# Photon and the PIN\_MAP\[\] challenge!

**URL:** <https://community.particle.io/t/photon-and-the-pin-map-challenge/12223>\
**Category:** Firmware\
**Created:** [June 1, 2015, 2:57am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223 "2015-06-01T02:57:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 1, 2015, 2:57am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/1 "2015-06-01T02:57:38Z")

</div>

Folks, with the Photon being so new, a lot of new functionality is being introduced to the firmware, including the HAL (Hardware Abstraction Layer) and the modular system/user code. These changes are impacting library code that was adapted specifically for the Core when future products were not known. Well, now that we know that future, it is time to generalize libraries for all Particle devices including the future Electron.

One key function used for doing faster bit I/O uses the PIN\_MAP reference. Until @mdma can formalize a method (API, macros) for using PIN\_MAP to set and reset pins faster than using (the safer) digitalWrite() command, the following code may be used to implement the functions:

The solution to the PIN\_MAP issue is a little more complex due to the differences in the bit set and reset registers on the STM32F103 (core) and the STM32F205 (photon). Here is a set of macros I used to port the SparkIntervalTimer library:

```
#if defined(PLATFORM_ID) //Only defined if a Particle device
  #include "application.h"
  STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // Pointer required for highest access speed
#if (PLATFORM_ID == 0) // Core
  #define pinLO(_pin) (PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin)
  #define pinHI(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin)
#elif (PLATFORM_ID == 6) // Photon
  #define pinLO(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRRH = PIN_MAP[_pin].gpio_pin)
  #define pinHI(_pin) (PIN_MAP[_pin].gpio_peripheral->BSRRL = PIN_MAP[_pin].gpio_pin)
#else
  #error " ***PLATFORM_ID not supported by this library. PLATFORM should be Core or Photon***"
#endif
#endif

```

You will need to replace any PIN\_MAP operation in the code with pinHI and pinLO if you want the code to be common for both the Core and the Photon (and future Electron). 😄

**UPDATE** : including pinmap\_impl.h is not necessary it seems

---

<div class="post-metadata">

**Author:** ![mdma](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mdma/32/1924_2.png) [@mdma](https://community.particle.io/u/mdma)\
**Post date:** [June 1, 2015, 8:18am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/2 "2015-06-01T08:18:50Z")

</div>

With your permission, I’d like to work on this header a little then include it in the firmware, so that we have one copy to maintain, along with any other library compatibility tweaks that people need.

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 1, 2015, 10:40am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/3 "2015-06-01T10:40:44Z")

</div>

@mdma, I was hoping you would say that! 😁

---

<div class="post-metadata">

**Author:** ![mdma](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mdma/32/1924_2.png) [@mdma](https://community.particle.io/u/mdma)\
**Post date:** [June 1, 2015, 11:23am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/4 "2015-06-01T11:23:08Z")

</div>

> [@peekay123](#):
>
> @mdma, I was hoping you would say that!

Excellent!

Ok, so some things we can discuss:

- use of macros vs inline functions?
- naming: any suggestions for a name other than pinHI/pinLO?
- what other things do we need in a library compatibility layer?

Here's my take on these:

- macros: I'd prefer not to use macros since they can cause very confusing messages if a library also happens to use the same name. (We are gradually phasing out macros in favor of regular C/C++ constructs.) The alternative is to use inline functions. The compiler can optimize these to give as good as performance as macros.
- naming: How about `fastDigitalWrite(pin, value)` ?

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 1, 2015, 12:05pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/5 "2015-06-01T12:05:58Z")

</div>

@mdma, I totally agree on inline vs macros so let’s use inline. There is some precedence in the Arduino world for creating a “fastDigitalWrite()” function. However, there is more than setting single bits to consider. At the low level we should also have:

fastDigitalRead(pin)  
fastPortWrite(port, value)  
fastPortRead(port)

😄

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [June 1, 2015, 12:58pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/6 "2015-06-01T12:58:07Z")

</div>

In addition to the `digitalFastWrite(pin,value)` (and of course @peekay123’s suggestions) where speed is an issue `fastPinSet(pin)` and `fastPinReset(pin)` might be useful too.

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 1, 2015, 1:00pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/7 "2015-06-01T13:00:51Z")

</div>

@ScruffR, good point though I thought those would just be a macro using the fastDigitalWrite() “root” function. 😄

---

<div class="post-metadata">

**Author:** ![wesner0019](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wesner0019](https://community.particle.io/u/wesner0019)\
**Post date:** [June 1, 2015, 3:34pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/8 "2015-06-01T15:34:16Z")

</div>

@mdma, @peekay123, Hi this is great news on for getting this implemented! Do you have any idea of a time line for an updated firmware?

Is there any thing we can do in the mean time to implement this into our existing code?

Thanks!

---

<div class="post-metadata">

**Author:** ![mdma](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mdma/32/1924_2.png) [@mdma](https://community.particle.io/u/mdma)\
**Post date:** [June 1, 2015, 6:02pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/9 "2015-06-01T18:02:51Z")

</div>

You could use the existing header file until it’s implemented in firmware, and provide a forward compatibility layer, mapping from the proposed function names to the existing ones:

something like:

```auto
#define fastDigitalWrite(pin, value) (value ? pinHI(pin) : pinLO(pin))

```

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [June 1, 2015, 6:31pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/10 "2015-06-01T18:31:06Z")

</div>

A thought on macros vs inline functions:

We should test the speed difference, since this is supposed to be useful for the _fastest_ GPIO writing, if it’s not… then people that need it SUPAFAST will still break out and do things manually.

Make sure people can breakaway and do things manually anyway.

I would prefer the naming be digitalWriteFast() so that when we add [intellisense](http://en.wikipedia.org/wiki/Intelligent_code_completion) to the IDE’s both versions of the function come up intuitively 😄

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [June 1, 2015, 7:40pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/11 "2015-06-01T19:40:18Z")

</div>

> [@peekay123](#):
>
> macro using the fastDigitalWrite() "root" function.

In this case the (admittedly minor) impact of the compare instruction would counteract the intended speed gain and with inlining you'd add some additional flash usage for the instruction which will never be called each time you'd use one of these macros (I guess, since I doubt that the optimizer will kill the respective branch).  
I'd rather turn that logic round and implement the set/reset functions a priori and use these in a third function or macro depending on the value - as pointed out in @mdma's macro.

---

<div class="post-metadata">

**Author:** ![wesner0019](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wesner0019](https://community.particle.io/u/wesner0019)\
**Post date:** [June 2, 2015, 2:42am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/12 "2015-06-02T02:42:47Z")

</div>

@peekay123, I used your macros in two libraries in my code. I now get the following errors.  
error: redefinition of 'STM32\_Pin\_Info\* PIN\_MAP  
error: ‘STM32\_Pin\_Info\* PIN\_MAP’ previously declared here

Not sure what is causing it. I tried reading up on that error but can’t figure it out. Any suggestions?

In file included from /spark/compile\_service/shared/workspace/6\_hal\_12\_0/firmware-privaili9341\_testing.cpp:7:0:  
/spark/compile\_service/shared/workspace/6\_hal\_12\_0/firmware-privaTouch\_4Wire.h:16:18:  
error: redefinition of 'STM32\_Pin\_Info\* PIN\_MAP’  
STM32\_Pin\_Info\* PIN\_MAP = HAL\_Pin\_Map(); // Pointer required for highest access speed

In file included from /spark/compile\_service/shared/workspace/6\_hal\_12\_0/firmware-privaili9341\_testing.cpp:4:0:  
/spark/compile\_service/shared/workspace/6\_hal\_12\_0/firmware-privaAdafruit\_ILI9341.h:27:17:  
error: ‘STM32\_Pin\_Info\* PIN\_MAP’ previously declared here  
STM32\_Pin\_Info\* PIN\_MAP = HAL\_Pin\_Map(); // Pointer required for highest access speed

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [June 2, 2015, 5:14am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/13 "2015-06-02T05:14:37Z")

</div>

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

```auto
#ifndef _ADAFRUIT_TOUCH4WIRE_H_
#define _ADAFRUIT_TOUCH4WIRE_H_

...

#endif

```

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

```auto
#ifndef _PHOTON_SPEED_MACROS_
#define _PHOTON_SPEED_MACROS_
... 
#endif

```

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 😊

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [June 2, 2015, 5:53am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/14 "2015-06-02T05:53:18Z")

</div>

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 😉

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [June 2, 2015, 9:58am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/15 "2015-06-02T09:58:15Z")

</div>

@mdma, can you remember this one 😉

> [@On another topic](https://community.particle.io/t/8846/4):
>
> I like this idea, but not sure a forum is the right place for this file. I'm thinking it might be best as part of the firmware repo.

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 👍

_(Link not publicly available)_  
[http://community.particle.io/t/some-reusable-macros-and-stuff/8846](http://community.particle.io/t/some-reusable-macros-and-stuff/8846)

---

<div class="post-metadata">

**Author:** ![mdma](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mdma/32/1924_2.png) [@mdma](https://community.particle.io/u/mdma)\
**Post date:** [June 2, 2015, 11:54am UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/16 "2015-06-02T11:54:48Z")

</div>

> [@ScruffR](#):
>
> In this case the (admittedly minor) impact of the compare instruction would counteract the intended speed gain and with inlining you'd add some additional flash usage for the instruction which will never be called each time you'd use one of these macros (I guess, since I doubt that the optimizer will kill the respective branch).

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.)

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 2, 2015, 12:43pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/17 "2015-06-02T12:43:28Z")

</div>

@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. 😀

---

<div class="post-metadata">

**Author:** ![wesner0019](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wesner0019](https://community.particle.io/u/wesner0019)\
**Post date:** [June 2, 2015, 1:54pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/18 "2015-06-02T13:54:46Z")

</div>

@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?

```auto
../../../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:

```auto
#ifndef _ADAFRUIT_TOUCH4WIRE_H_
#define _ADAFRUIT_TOUCH4WIRE_H_

#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);
  }

  delay(100);
}

```

* * *

_Edited by ScruffR: I’ve reformatted your code sections (have a look at “[Forum Tips and Tricks](http://community.particle.io/t/forum-tips-and-tricks/3999)” to see how to do that)_

---

<div class="post-metadata">

**Author:** ![wesner0019](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wesner0019](https://community.particle.io/u/wesner0019)\
**Post date:** [June 2, 2015, 2:14pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/19 "2015-06-02T14:14:57Z")

</div>

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 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

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [June 2, 2015, 2:19pm UTC](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223/20 "2015-06-02T14:19:37Z")

</div>

@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).

[Next page](https://community.particle.io/t/photon-and-the-pin-map-challenge/12223.md?page=2)
