Photon and the PIN_MAP[] challenge!

Some (most) definitions/declarations are not allowed to be made twice.
For this reason header files usually have some way to prevent this to happen by means of conditional compiling like this




So you could either remove the second definition/declaration or wrap each of these blocks in a conditional compiling “envelope” like


But unfortunately I have called the respective macros pinSetHigh() and pinSetLow() in my port of Touch_4Wire.
So you’d need to adapt @peekay123’s macros or replace all occurences of my macro names with his - sorry :blush:

If your libraries depend on each other, you can put the macros in the lowest level, and just use PIN_MAP, pinHI( ), pinLO( ) in the top level library.

If that doesn’t work, just name the pointer PIN_MAP2 in one of the libraries :wink:

@mdma, can you remember this one :wink:

Now we are back in the forum with this topic - even public.
But I’d like to renew my proposal for a porting toolset including most of the collected macros (or even more) - if these should become inline functions, even better :+1:

(Link not publicly available)

When the value argument is constant, such as fastDigitalWrite(A0, LOW) then the compiler will indeed optimize out the conditional and simply inline the appropriate branch. Even so, we can implement fastDigitalSet directly if it makes people happy. (We’d probably get others asking the same question about efficiency.)

1 Like

@mdma, @ScruffR, I think I stirred the pot a little to much with this topic! I get the feeling it is causing more problems then not. What I do know is that deploying a solid set of extended functions for fast I/O is crucial to get a lot of libraries ported over to the Photon, especially given folks are receiving their them and have certain “expectations”.

Macros or inline, the timing difference between the “safe” digitalWrite() and the “unsafe” digitalWriteFast (or whatever we call it) is huge. Whatever we do, let’s get something out that we can test and optimize, as long as the outward facing “functions” remain the same. I just want to remind everyone that we need both fast bit and port set/reset capabilities. :grinning:

1 Like

@scruff R
I’m now just trying to get the touch4wire to compile to reduce complexity. When just using this library I get this error: Seems like this is being defined somewhere else not within the libraries?

../../../build/target/user/platform-6/libuser.a(touchscreen.o): In function `setup':
 /spark/compile_service/shared/workspace/6_hal_12_0/firmware-privatouchscreen.cpp:9: multiple definition of `PIN_MAP'
../../../build/target/user/platform-6/libuser.a(Touch_4Wire.o):/spark/compile_service/shared/workspace/6_hal_12_0/firmware-privaTouch_4Wire.cpp:27: first defined here collect2: error: ld returned 1 exit status

Below is the updated macro in the. h file:


#include "application.h"
#define ADC_MAX_VALUE (0x0FFF)
#define XY_TOLERANCE 15
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // Pointer required for highest access speed
#define pinSetLow(pin) PIN_MAP[pin].gpio_peripheral->BSRRH = PIN_MAP[pin].gpio_pin
#define pinSetHigh(pin) PIN_MAP[pin].gpio_peripheral->BSRRL = PIN_MAP[pin].gpio_pin
#define pinSet(pin, HILO) (HILO) ? pinSetHigh(pin) : pinSetLow(pin)

And here is the .ino file
#include "Touch_4Wire.h"
#define YP A0  // must be an analog pin, use "An" notation!
#define XM A1  // must be an analog pin, use "An" notation!
#define YM D0  // can be a digital pin
#define XP D1  // can be a digital pin

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void) {
 // Serial.begin(9600);

void loop(void) {
  TSPoint p = ts.getPoint();

  if (p.z > ts.pressureThreshhold) {
     Serial.print("X = "); Serial.print(p.x);
     Serial.print("\tY = "); Serial.print(p.y);
     Serial.print("\tPressure = "); Serial.println(p.z);


Edited by ScruffR: I’ve reformatted your code sections (have a look at “Forum Tips and Tricks” to see how to do that)

If I comment out the setup function. i get the below error:

Where is this _GLOBAL__sub_I_PIN_MAP function?

./…/…/build/target/user/platform-6/libuser.a(touchscreen.o): In function _GLOBAL__sub_I_PIN_MAP': /spark/compile_service/shared/workspace/6_hal_12_0/firmware-privatouchscreen.cpp:13: multiple definition ofPIN_MAP’
first defined here

@wesner0019, I had the same problem when trying to port my RGBPongClock code. I ended up putting the macros in the only .cpp file that used PIN_MAP. When I tried putting it in the include file, I got errors even though I had compiles flags setup to only compile that .h file once. Separating the file to a different included file did not help either.

This is why I think it may be worth waiting for the firmware based GPIO stuff that @mdma will be adding (soon).

Could this be due to application.h including a definition of PIN_MAP via some of the nested headers?
On the Core PIN_MAP worked without the need for an explicit declaration in user code, so it must be there somewhere.

This made me think, if this

 STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // Pointer required for highest access speed

should not be put inside the PLATFORM_ID == 6 block.

1 Like

I moved the line,

STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // Pointer required for highest access speed

to the .cpp file and it compiled! yeah!

I did the same for my code with multiple instances of the PIN_MAP. So I had to move the PIN_MAP (above) to the cpp file and on the second instance had to rename the second PIN_MAP as:

STM32_Pin_Info* PIN_MAP2 = HAL_Pin_Map();

and the rename the .h file definitions as below:

#define pinSetLow(pin) PIN_MAP2[pin].gpio_peripheral->BSRRH = PIN_MAP2[pin].gpio_pin
#define pinSetHigh(pin) PIN_MAP2[pin].gpio_peripheral->BSRRL = PIN_MAP2[pin].gpio_pin

@ScruffR, the defines I used are really meant for the new 4.x firmware which introduces the HAL for both the Core and the Photon. However, using the cloud compile (IDE, CLI, DEV), the code will not work since the Core is still compiling against v3.4 of the firmware. :flushed:

1 Like

@wesner0019, ouch! Obviously, having the functions in the system firmware will make things a lot simpler. IMO we should not do any “official” library ports until everything settles which should be soon.

1 Like

I moved 7 posts to an existing topic: Touch_4Wire library not yet ported for Photon

1 Like

Has there been a final consensus over this topic already?
I’ve seen this OneWire thread where some HAL functions were already applied - is this the way to go, or is there still some decision making to do?

If it’s still in the rough, I’ve got one more thought to throw in (in connection with Core/Photon unifiability ;-))

#define pinSet(pin, hilo) PIN_MAP2[pin].gpio_peripheral->BSRR = (PIN_MAP2[pin].gpio_pin << (hilo ? 0 : 16))

does work on both (I’m convinced until proven wrong :wink: - since I can’t test on a Photon)

I have tested the code from Beebs. With a tiny modification it seems to compile both for a core and photon. See: Libraries to Update for the Photon .

Here’s a PR of our work in process. Comments, tests and general praise for @peekay123 for kicking off this whole thing welcome :smile:


I don’t see a link, is this it?

Ooops yep! That’s the one!

I have read this post and I still don’t know if a conclusion has been reached ?
Is there a replacement for PIN_MAP ?

I’m getting this error on my Photon build :

function_pulseIn.h: In function 'long unsigned int pulseIn(uint16_t, uint8_t)':
function_pulseIn.h:42:31: error: 'PIN_MAP' was not declared in this scope
 GPIO_TypeDef* portMask = (PIN_MAP[pin].gpio_peripheral); // Cache the target's peripheral mask to speed up the loops.