MySensors Library & Examples  2.3.2-62-ge298769
PJON_IO.h
1 
2 /* Faster digitalWrite, digitalRead, pinMode for Arduino
3  https://codebender.cc/library/digitalWriteFast#bonus%2FdigitalWrite%2Fdigital_write_macros.h
4  - Basic scheme was developed by Paul Stoffregen with digitalWrite.
5  - Extended to pinMode by John Raines
6  - Extended to digitalRead by John Raines with considerable assistance
7  by William Westfield
8  Copyright (c) 2008-2010 PJRC.COM, LLC
9 
10  List of supported MCUs:
11  - ATmega8/88/168/328/1280/1284P/2560 (Duemilanove, Uno, Nano, Mini, Pro, Mega)
12  - ATmega16U4/32U4 (Leonardo, Micro)
13  - ATtiny44/84/44A/84A Added by Wilfried Klaas
14  - ATtiny45/85 (Trinket, Digispark)
15  - SAMD21G18A (Arduino Zero) Added by Esben Soeltoft 03/09/2016
16 
17 Renamed since v7.0 to avoid naming collisions and so subtle bugs and anomalies
18 if used along with third-party software using older/different versions of
19 digitalWriteFast. All methods are defined in uppercase style to implicitly
20 inform the reader of their definition as macros in the global scope.
21  ______________________________________________________________________________
22 
23  Permission is hereby granted, free of charge, to any person obtaining a copy
24  of this software and associated documentation files (the "Software"), to deal
25  in the Software without restriction, including without limitation the rights
26  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27  copies of the Software, and to permit persons to whom the Software is
28  furnished to do so, subject to the following conditions:
29 
30  The above copyright notice and this permission notice shall be included in
31  all copies or substantial portions of the Software.
32 
33  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39  THE SOFTWARE. */
40 
41 #pragma once
42 
43 /* AVR ATmega1280/2560 - Arduino Mega ------------------------------------- */
44 
45 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
46 #define PJON_IO_PIN_TO_PORT_REG(P) \
47  ((P >= 22 && P <= 29) ? &PORTA : \
48  (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &PORTB : \
49  ((P >= 30 && P <= 37) ? &PORTC : \
50  (((P >= 18 && P <= 21) || P == 38) ? &PORTD : \
51  (((P <= 3) || P == 5) ? &PORTE : \
52  ((P >= 54 && P <= 61) ? &PORTF : \
53  (((P >= 39 && P <= 41) || P == 4) ? &PORTG : \
54  (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &PORTH : \
55  ((P == 14 || P == 15) ? &PORTJ : \
56  ((P >= 62 && P <= 69) ? &PORTK : &PORTL))))))))))
57 
58 #define PJON_IO_PIN_TO_DDR_REG(P) \
59  ((P >= 22 && P <= 29) ? &DDRA : \
60  (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &DDRB : \
61  ((P >= 30 && P <= 37) ? &DDRC : \
62  (((P >= 18 && P <= 21) || P == 38) ? &DDRD : \
63  (((P <= 3) || P == 5) ? &DDRE : \
64  ((P >= 54 && P <= 61) ? &DDRF : \
65  (((P >= 39 && P <= 41) || P == 4) ? &DDRG : \
66  (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &DDRH : \
67  ((P == 14 || P == 15) ? &DDRJ : \
68  ((P >= 62 && P <= 69) ? &DDRK : &DDRL))))))))))
69 
70 #define PJON_IO_PIN_TO_PIN_REG(P) \
71  ((P >= 22 && P <= 29) ? &PINA : \
72  (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &PINB : \
73  ((P >= 30 && P <= 37) ? &PINC : \
74  (((P >= 18 && P <= 21) || P == 38) ? &PIND : \
75  (((P <= 3) || P == 5) ? &PINE : \
76  ((P >= 54 && P <= 61) ? &PINF : \
77  (((P >= 39 && P <= 41) || P == 4) ? &PING : \
78  (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &PINH : \
79  ((P == 14 || P == 15) ? &PINJ : \
80  ((P >= 62 && P <= 69) ? &PINK : &PINL))))))))))
81 
82 #ifndef PJON_IO_PIN_TO_BIT
83 #define PJON_IO_PIN_TO_BIT(P) \
84  ((P >= 7 && P <= 9) ? P - 3 : ((P >= 10 && P <= 13) ? P - 6 : \
85  ((P >= 22 && P <= 29) ? P - 22 : ((P >= 30 && P <= 37) ? 37 - P : \
86  ((P >= 39 && P <= 41) ? 41 - P : ((P >= 42 && P <= 49) ? 49 - P : \
87  ((P >= 50 && P <= 53) ? 53 - P : ((P >= 54 && P <= 61) ? P - 54 : \
88  ((P >= 62 && P <= 69) ? P - 62 : ((P == 0 || P == 15 || P == 17 || P == 21) \
89  ? 0 : ((P == 1 || P == 14 || P == 16 || P == 20) ? 1 : ((P == 19) ? 2 : \
90  ((P == 5 || P == 6 || P == 18) ? 3 : ((P == 2) ? 4 : \
91  ((P == 3 || P == 4) ? 5 : 7)))))))))))))))
92 #endif
93 #endif
94 
95 /* AVR ATmega88/168/328/328P - Arduino Duemilanove, Uno, Nano, Mini, Pro -- */
96 
97 #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || \
98  defined(__AVR_ATmega168P__)|| \
99  defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || \
100  defined(__AVR_ATmega328PB__)
101 #define PJON_IO_PIN_TO_PORT_REG(P) \
102  ((P <= 7) ? &PORTD : ((P >= 8 && P <= 13) ? &PORTB : &PORTC))
103 #define PJON_IO_PIN_TO_DDR_REG(P) \
104  ((P <= 7) ? &DDRD : ((P >= 8 && P <= 13) ? &DDRB : &DDRC))
105 #define PJON_IO_PIN_TO_PIN_REG(P) \
106  ((P <= 7) ? &PIND : ((P >= 8 && P <= 13) ? &PINB : &PINC))
107 #ifndef PJON_IO_PIN_TO_BIT
108 #define PJON_IO_PIN_TO_BIT(P) \
109  ((P <= 7) ? P : ((P >= 8 && P <= 13) ? P - 8 : P - 14))
110 #endif
111 #endif
112 
113 /* AVR ATmega16U4/32U4 - Arduino Leonardo, Micro -------------------------- */
114 
115 #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
116 #define PJON_IO_PIN_TO_PORT_REG(P) \
117  (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
118  ? &PORTD : ((P == 5 || P == 13) ? &PORTC : ((P >= 18 && P <= 23)) ? &PORTF : \
119  ((P == 7) ? &PORTE : &PORTB)))
120 #define PJON_IO_PIN_TO_DDR_REG(P) \
121  (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
122  ? &DDRD : ((P == 5 || P == 13) ? &DDRC : ((P >= 18 && P <= 23)) ? \
123  &DDRF : ((P == 7) ? &DDRE : &DDRB)))
124 #define PJON_IO_PIN_TO_PIN_REG(P) \
125  (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
126  ? &PIND : ((P == 5 || P == 13) ? &PINC : ((P >= 18 && P <= 23)) ? \
127  &PINF : ((P == 7) ? &PINE : &PINB)))
128 #ifndef PJON_IO_PIN_TO_BIT
129 #define PJON_IO_PIN_TO_BIT(P) \
130  ((P >= 8 && P <= 11) ? P - 4 : ((P >= 18 && P <= 21) ? 25 - P : \
131  ((P == 0) ? 2 : ((P == 1) ? 3 : ((P == 2) ? 1 : ((P == 3) ? 0 : \
132  ((P == 4) ? 4 : ((P == 6) ? 7 : ((P == 13) ? 7 : ((P == 14) ? 3 : \
133  ((P == 15) ? 1 : ((P == 16) ? 2 : ((P == 17) ? 0 : ((P == 22) ? 1 : \
134  ((P == 23) ? 0 : ((P == 24) ? 4 : ((P == 25) ? 7 : ((P == 26) ? 4 : \
135  ((P == 27) ? 5 : 6 )))))))))))))))))))
136 #endif
137 #endif
138 
139 /* AVR ATtiny45/85 - Trinket, Digispark ----------------------------------- */
140 
141 #if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
142 #define PJON_IO_PIN_TO_PORT_REG(P) &PORTB
143 #define PJON_IO_PIN_TO_DDR_REG(P) &DDRB
144 #define PJON_IO_PIN_TO_PIN_REG(P) &PINB
145 #ifndef PJON_IO_PIN_TO_BIT
146 #define PJON_IO_PIN_TO_BIT(P) P
147 #endif
148 #endif
149 
150 /* AVR ATMEGA1284P -------------------------------------------------------- */
151 
152 #if defined(__AVR_ATmega1284P__)
153 #define PJON_IO_PIN_TO_PORT_REG(P) \
154  (P >= 24 ? &PORTA : (P <= 7 ? &PORTB : ((P >= 8 && P <=15) ? &PORTD : &PORTC)))
155 #define PJON_IO_PIN_TO_DDR_REG(P) \
156  (P >= 24 ? &DDRA : (P <= 7 ? &DDRB : ((P >= 8 && P <=15) ? &DDRD : &DDRC)))
157 #define PJON_IO_PIN_TO_PIN_REG(P) \
158  (P >= 24 ? &PINA : (P <= 7 ? &PINB : ((P >= 8 && P <=15) ? &PIND : &PINC)))
159 #ifndef PJON_IO_PIN_TO_BIT
160 #define PJON_IO_PIN_TO_BIT(P) \
161  (P >= 24 ? P-24 : (P <= 7 ? P : ((P >= 8 && P <=15) ? P-8 : P-16 ) ) )
162 #endif
163 #endif
164 
165 /* AVR ATtiny44/84/44A/84A ------------------------------------------------ */
166 #if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || \
167  defined(__AVR_ATtiny44A__) || defined(__AVR_ATtiny84A__)
168 #define PJON_IO_PIN_TO_PORT_REG(P) \
169  ((P <= 7) ? &PORTA : &PORTB )
170 #define PJON_IO_PIN_TO_DDR_REG(P) \
171  ((P <= 7) ? &DDRA : &DDRB )
172 #define PJON_IO_PIN_TO_PIN_REG(P) \
173  ((P <= 7) ? &PINA : &PINB)
174 #ifndef PJON_IO_PIN_TO_BIT
175 #define PJON_IO_PIN_TO_BIT(P) \
176  ((P <= 7) ? P : ((P == 8) ? 2 : ( (P == 9) ? 3 : ( (P == 10) ? 1 : 0))))
177 #endif
178 #endif
179 
180 /* SAMD21G18A - Arduino Zero ---------------------------------------------- */
181 
182 #if defined(__SAMD21G18A__) || defined(ARDUINO_SAM_ZERO) // Arduino Zero pins
183 #define PJON_IO_PIN_TO_PORT_BIT(P) \
184  ((P == 0) ? PORT_PA11 : ((P == 1) ? PORT_PA10 : ((P == 2) ? PORT_PA14 : \
185  ((P == 3) ? PORT_PA09 : ((P == 4) ? PORT_PA08 : ((P == 5) ? PORT_PA15 : \
186  ((P == 6) ? PORT_PA20 : ((P == 7) ? PORT_PA21 : ((P == 8) ? PORT_PA06 : \
187  ((P == 9) ? PORT_PA07 : ((P == 10) ? PORT_PA18 : ((P == 11) ? PORT_PA16 : \
188  ((P == 12) ? PORT_PA19 : ((P == 13) ? PORT_PA17 : ((P == A0) ? PORT_PA02 : \
189  ((P == A1) ? PORT_PB08 : ((P == A2) ? PORT_PB09 : ((P == A3) ? PORT_PA04 : \
190  ((P == A4) ? PORT_PA05 : ((P == A5) ? PORT_PB02 : ((P == SCK) ? PORT_PB11 : \
191  ((P == MISO) ? PORT_PA12 : ((P == MOSI) ? PORT_PB10 : ((P == PIN_WIRE_SCL) ? \
192  PORT_PA23 : ((P == PIN_WIRE_SDA) ? PORT_PA22 : PORT_PA13 \
193  )))))))))))))))))))))))))
194 
195 #define PJON_IO_PIN_TO_PORT_REG(P) \
196  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? PORTB : PORTA )
197 #define PJON_IO_PIN_TO_PORT_REGOUT(P) \
198  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
199  REG_PORT_OUT1 : REG_PORT_OUT0)
200 #define PJON_IO_PIN_TO_PORT_REGOUTSET(P) \
201  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
202  REG_PORT_OUTSET1 : REG_PORT_OUTSET0)
203 #define PJON_IO_PIN_TO_PORT_REGOUTCLR(P) \
204  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
205  REG_PORT_OUTCLR1 : REG_PORT_OUTCLR0)
206 #define PJON_IO_PIN_TO_PORT_REGPINCFG(P) \
207  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
208  REG_PORT_PINCFG1 : REG_PORT_PINCFG0)
209 #define PJON_IO_PIN_TO_PORT_REGDIRSET(P) \
210  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
211  REG_PORT_DIRSET1 : REG_PORT_DIRSET0)
212 #define PJON_IO_PIN_TO_PORT_REGDIRCLR(P) \
213  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
214  REG_PORT_DIRCLR1 : REG_PORT_DIRCLR0)
215 #define PJON_IO_PIN_TO_PORT_IN_REG(P) \
216  ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
217  REG_PORT_IN1 : REG_PORT_IN0)
218 
219 /* functions for read/write/pinmode fast for SAMD chips
220  PWM pins 3, 4, 5, 6, 8, 9, 10, 11, 12, 13 provide 8-bit PWM output with the
221  analogWrite() function analogWrite works on all analog pins and all digital
222  PWM pins. You can supply it any value between 0 and 255. analog pins provide
223  12bits resolution and provide a value between 0-4096.
224 
225  INPUT (0x0),
226  OUTPUT (0x1),
227  INPUT_PULLUP (0x2) Set pin to input mode with pull-up resistor enabled,
228  INPUT_PULLDOWN (0x3) */
229 
230 #define PJON_IO_MODE(P, V) \
231  do { if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
232  if(V == 0x0) { \
233  PJON_IO_PIN_TO_PORT_REGPINCFG(P) = (uint8_t)(PORT_PINCFG_INEN); \
234  PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
235  } else if(V == 0x2) { \
236  PORT->Group[PJON_IO_PIN_TO_PORT_REG(11)].PINCFG[g_APinDescription[11].ulPin].reg = \
237  (uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN); \
238  PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
239  PJON_IO_PIN_TO_PORT_REGOUTSET(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
240  } else if(V == 0x3) { \
241  PORT->Group[g_APinDescription[11].ulPort].PINCFG[g_APinDescription[11].ulPin].reg = \
242  (uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ; \
243  PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
244  PJON_IO_PIN_TO_PORT_REGOUTCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
245  } else { \
246  PJON_IO_PIN_TO_PORT_REGPINCFG(P) &= ~(uint8_t)(PORT_PINCFG_INEN); \
247  PJON_IO_PIN_TO_PORT_REGDIRSET(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
248  } \
249  } else pinMode(P, V); \
250  } while (0)
251 
252 #define PJON_IO_READ(P) ( (int) _PJON_IO_READ_(P) )
253 #define _PJON_IO_READ_(P) \
254  (__builtin_constant_p(P)) ? \
255  (PJON_IO_PIN_TO_PORT_IN_REG(P) & PJON_IO_PIN_TO_PORT_BIT(P)) : digitalRead(P)
256 
257 #define PJON_IO_WRITE(P, V) \
258  do { if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
259  if(V) PJON_IO_PIN_TO_PORT_REGOUTSET(P) = PJON_IO_PIN_TO_PORT_BIT(P); \
260  else PJON_IO_PIN_TO_PORT_REGOUTCLR(P) = PJON_IO_PIN_TO_PORT_BIT(P); \
261  } else digitalWrite(P, V); \
262  } while(0)
263 
264 #define PJON_IO_PULL_DOWN(P) \
265  do { if(__builtin_constant_p(P)) { \
266  PJON_IO_MODE(P, INPUT_PULLDOWN); \
267  } else pinMode(P, INPUT_PULLDOWN); \
268  } while(0)
269 #endif
270 
271 /* AVR related ------------------------------------------------------------ */
272 
273 #ifdef __AVR__
274 #define PJON_IO_ATOMIC_WRITE(A, P, V) \
275  if ((int)(A) < 0x40) { bitWrite(*(A), PJON_IO_PIN_TO_BIT(P), V); } \
276  else { \
277  uint8_t register saveSreg = SREG; \
278  cli(); \
279  bitWrite(*(A), PJON_IO_PIN_TO_BIT(P), V); \
280  sei(); \
281  SREG = saveSreg; \
282  }
283 
284 #ifndef PJON_IO_WRITE
285 #define PJON_IO_WRITE(P, V) \
286  do { \
287  if(__builtin_constant_p(P) && __builtin_constant_p(V)) \
288  PJON_IO_ATOMIC_WRITE((uint8_t*) PJON_IO_PIN_TO_PORT_REG(P), P, V) \
289  else digitalWrite(P, V); \
290  } while(0)
291 #endif
292 
293 #ifndef PJON_IO_MODE
294 #define PJON_IO_MODE(P, V) \
295  do { \
296  if(__builtin_constant_p(P) && __builtin_constant_p(V)) \
297  PJON_IO_ATOMIC_WRITE((uint8_t*) PJON_IO_PIN_TO_DDR_REG(P), P, V) \
298  else pinMode(P, V); \
299  } while(0)
300 #endif
301 
302 #ifndef PJON_IO_READ
303 #define PJON_IO_READ(P) ((int) _PJON_IO_READ_(P))
304 #define _PJON_IO_READ_(P) \
305  (__builtin_constant_p(P)) ? ( \
306  ((((*PJON_IO_PIN_TO_PIN_REG(P)) >> (PJON_IO_PIN_TO_BIT(P))) & 0x01))) : \
307  digitalRead(P)
308 #endif
309 
310 #define PJON_IO_PULL_DOWN(P) \
311  do { if(__builtin_constant_p(P)) { \
312  PJON_IO_WRITE(P, LOW); \
313  PJON_IO_MODE(P, INPUT); \
314  } else { \
315  digitalWrite(P, LOW); \
316  pinMode(P, INPUT); \
317  } \
318  } while(0)
319 #endif