Preprocessor #ifdef to Detect Platform Type (Core/Photon) at Compile Time

So this may be a soon to be irrelevant question, once 0.4.x goes live for the Core, but it appears that right now, 0.3.4 has a define SPARK in the makefile (this issue), but doesn’t define PLATFORM_ID. However, 0.4.x defines PLATFORM_ID (for use in differentiating Core from Photon from Electron, etc.) but has removed the definition of SPARK in the makefile, so a #ifdef SPARK statement will no longer work. This is somewhat annoying, and is there a better way to deal with it other than this?

#if defined(SPARK) || defined(PLATFORM_ID)
// Particle Device
#if defined(SPARK) || (defined(PLATFORM_ID) && PLATFORM_ID == 0)
// Particle Core
#elif (PLATFORM_ID == 6)
// Particle Photon
#endif
#endif

@mumblepins, I suspect the SPARK flag will get deprecated in the next Core release. As for the Core/Photon in the 0.4+ versions, there are two aspects to look at - hardware and system platforms. In the new firmware, there are two hardware related flags to differentiate between the STM32F10x of the Core (STM32F10X_MD) and the STM32F2xx of the Photon/Electron (STM32F2XX). These flags should be used to differentiate hardware environments like the Core having 5 hardware timers and the Photon/Electron having 15. Arduino code often differentiates between different processors (atmega168, 328, etc.).

#if defined (STM32F10X_MD)
// Core hardware specific code here
#endif

#if defined (STM32F2XX)
// Photon hardware specific code here
#endif

For system platform differentiation, the PLATFORM_ID flag should be used since there are some differences between the Core and the Photon/Electron. Arduino uses the #if defined (ARDUINO) && (ARDUINO > 100) for example to know which compile environment is being used.

The PLATFORM_ID would be used as follows:

#if (PLATFORM_ID == 0)
// Core code here
#elif (PLATFORM_ID == 6)
// Photon code here
#elif (PLATFORM_ID == ??)
//Electron or other Particle device code here
#endif

No need to test for (PLATFORM_ID) since the above will fail if PLATFORM_ID is not defined to begin with. :smile:

Yeah, I'm mainly using it for determining if the flash chip is there (AKA Core but not photon). However, I'm pretty sure that your last #if statement won't work as expected on Arduino or elsewhere where PLATFORM_ID is undefined, as according to this Stackoverflow thread:

From the C Standard:

(C99, 6.10.1p4) "After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0""

So, if PLATFORM_ID is undefined, the first one will be true. For example, try this, and you'll see the error:

#if (THIS_VARIABLE_IS_NOT_DEFINED == 0)
#error "uh oh"
#endif

but if you try this:

#if (THIS_VARIABLE_IS_NOT_DEFINED == 1)
#error "uh oh"
#endif

you won't

I would like to see a PARTICLE defined so you could test that before PLATFORM_ID since PLATFORM_ID is very generic and has been used for other non-Particle platforms.

What does @mdma think? Is there going to be a direct replacement for SPARK?

2 Likes

Well, perhaps I misunderstood @mdma regarding the compile flag testing! I believe a test is in order! The flag will always be defined in a Particle environment. HOWEVER, if a library is designed to also work on a different platform (eg Arduino) then yes, you are correct to test that way! DOH!

@bko, all of the code I have seen in the library uses either the hardware or platform flags. You’ll have to discuss with @mdma regarding a PARTICLE flag. I had pointed out in the past that I actually came across a library that used PLATFORM_ID for another processor. :smile:

1 Like

Yes, anything that is going to be used on other ecosystems outside Particle should wrap everything that is particle-specific in

#ifdef SPARK
// particle specific stuff
#endif

In due course we’ll naturally add PARTICLE as a define too. SPARK will be kept indefinitely for compatibility with existing code.

3 Likes

For some reason, none of the above code examples work in the Particle Dev IDE. It seems that I might as well write #if (false). Are these defines for the web IDE only?

@WebDust21 I tested this a few days ago and it worked for me then:

#ifdef SPARK
// particle specific stuff
#endif

I haven’t tried that, because I’m not writing portable code right now. What I was trying to get working was the #ifdef to determine whether the code was being compiled for Core or the Photon.

Please give this a try:

#if PLATFORM_ID == 0
    // Core code here
#elif PLATFORM_ID == 6
    // Photon code here
#else
    #error "*** PLATFORM_ID not supported by this library. PLATFORM should be Core or Photon ***"
#endif

I use this based on @mdma’s comments above:

#if defined(SPARK)
  #if defined(PLATFORM_ID)
    #if (PLATFORM_ID == 0)
	  //Core
    #elif (PLATFORM_ID == 6)
         //Photon
    #endif
  #endif  //PLATFORM_ID
#endif  //SPARK
2 Likes

@bdub That works. I don’t understand why it didn’t work when I tried the same code before posting in this thread, but it works now. (P.S. I did upgrade Particle Dev to 0.0.24, the latest version AFAIK.)

EDIT: I understand what I was doing wrong: I need to use #if PLATFORM_ID == 0. Can’t substitute #ifdef PLATFORM_ID == 0. Because, well, it is defined! My bad…and it’s perhaps unfortunate that my socks aren’t chocolate.

@mumblepins, This is a great question but I didn’t find it with the search button. The topic might be more widely helpful if it was retitled Detecting Platform Type (Core/Photon) at Compile Time.
As it stands it only comes up in a search if you know it is there or know the name of the pre-processor flag. @kennethlimcp kindly pointed out the answer when I couldn’t find it.

Done.

1 Like

Hello,
Sorry as I only have a vague understanding of this issue, but I am having trouble using a Neopixel library with my photon redboard, and it is giving me an error concerning my PLATFORM_ID. I was wondering if this thread is dealing with a similar issue and might shed light on how to resolve it.

Thanks,
Gary

Let us have a look at the respective code segment and the error messages.