Digital IO
DigitalPin.h
Go to the documentation of this file.
1 /* Arduino DigitalIO Library
2  * Copyright (C) 2013 by William Greiman
3  *
4  * This file is part of the Arduino DigitalIO Library
5  *
6  * This Library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with the Arduino DigitalIO Library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
28 #ifndef DigitalPin_h
29 #define DigitalPin_h
30 #if defined(__AVR__) || defined(DOXYGEN)
31 #include <avr/io.h>
33 struct GpioPinMap_t {
34  volatile uint8_t* pin;
35  volatile uint8_t* ddr;
36  volatile uint8_t* port;
37  uint8_t mask;
38 };
39 
41 #define GPIO_PIN(reg, bit) {&PIN##reg, &DDR##reg, &PORT##reg, 1 << bit}
42 
43 // Include pin map for current board.
44 #include "boards/GpioPinMap.h"
45 //------------------------------------------------------------------------------
47 void badPinNumber(void)
48  __attribute__((error("Pin number is too large or not a constant")));
49 //------------------------------------------------------------------------------
53 static inline __attribute__((always_inline))
54 void badPinCheck(uint8_t pin) {
55  if (!__builtin_constant_p(pin) || pin >= NUM_DIGITAL_PINS) {
56  badPinNumber();
57  }
58 }
59 //------------------------------------------------------------------------------
64 static inline __attribute__((always_inline))
65 volatile uint8_t* ddrReg(uint8_t pin) {
66  badPinCheck(pin);
67  return GpioPinMap[pin].ddr;
68 }
69 //------------------------------------------------------------------------------
74 static inline __attribute__((always_inline))
75 uint8_t pinMask(uint8_t pin) {
76  badPinCheck(pin);
77  return GpioPinMap[pin].mask;
78 }
79 //------------------------------------------------------------------------------
84 static inline __attribute__((always_inline))
85 volatile uint8_t* pinReg(uint8_t pin) {
86  badPinCheck(pin);
87  return GpioPinMap[pin].pin;
88 }
89 //------------------------------------------------------------------------------
94 static inline __attribute__((always_inline))
95 volatile uint8_t* portReg(uint8_t pin) {
96  badPinCheck(pin);
97  return GpioPinMap[pin].port;
98 }
99 //------------------------------------------------------------------------------
105 static inline __attribute__((always_inline))
106 void fastBitWriteSafe(volatile uint8_t* address, uint8_t mask, bool level) {
107  uint8_t s;
108  if (address > reinterpret_cast<uint8_t*>(0X3F)) {
109  s = SREG;
110  cli();
111  }
112  if (level) {
113  *address |= mask;
114  } else {
115  *address &= ~mask;
116  }
117  if (address > reinterpret_cast<uint8_t*>(0X3F)) {
118  SREG = s;
119  }
120 }
121 //------------------------------------------------------------------------------
126 static inline __attribute__((always_inline))
127 bool fastDigitalRead(uint8_t pin) {
128  return *pinReg(pin) & pinMask(pin);
129 }
130 //------------------------------------------------------------------------------
137 static inline __attribute__((always_inline))
138 void fastDigitalToggle(uint8_t pin) {
139  if (pinReg(pin) > reinterpret_cast<uint8_t*>(0X3F)) {
140  // must write bit to high address port
141  *pinReg(pin) = pinMask(pin);
142  } else {
143  // will compile to sbi and PIN register will not be read.
144  *pinReg(pin) |= pinMask(pin);
145  }
146 }
147 //------------------------------------------------------------------------------
152 static inline __attribute__((always_inline))
153 void fastDigitalWrite(uint8_t pin, bool level) {
154  fastBitWriteSafe(portReg(pin), pinMask(pin), level);
155 }
156 //------------------------------------------------------------------------------
161 static inline __attribute__((always_inline))
162 void fastDdrWrite(uint8_t pin, bool level) {
163  fastBitWriteSafe(ddrReg(pin), pinMask(pin), level);
164 }
165 //------------------------------------------------------------------------------
173 static inline __attribute__((always_inline))
174 void fastPinMode(uint8_t pin, uint8_t mode) {
175  fastDdrWrite(pin, mode == OUTPUT);
176  if (mode != OUTPUT) {
177  fastDigitalWrite(pin, mode == INPUT_PULLUP);
178  }
179 }
180 #else // defined(__AVR__)
181 #if defined(CORE_TEENSY)
182 //------------------------------------------------------------------------------
187 static inline __attribute__((always_inline))
188 bool fastDigitalRead(uint8_t pin) {
189  return *portInputRegister(pin);
190 }
191 //------------------------------------------------------------------------------
196 static inline __attribute__((always_inline))
197 void fastDigitalWrite(uint8_t pin, bool value) {
198  if (value) {
199  *portSetRegister(pin) = 1;
200  } else {
201  *portClearRegister(pin) = 1;
202  }
203 }
204 #elif defined(__SAM3X8E__) || defined(__SAM3X8H__)
205 //------------------------------------------------------------------------------
210 static inline __attribute__((always_inline))
211 bool fastDigitalRead(uint8_t pin) {
212  return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
213 }
214 //------------------------------------------------------------------------------
219 static inline __attribute__((always_inline))
220 void fastDigitalWrite(uint8_t pin, bool value) {
221  if (value) {
222  g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
223  } else {
224  g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
225  }
226 }
227 #elif defined(ESP8266)
228 //------------------------------------------------------------------------------
233 static inline __attribute__((always_inline))
234 void fastDigitalWrite(uint8_t pin, uint8_t val) {
235  if (pin < 16) {
236  if (val) {
237  GPOS = (1 << pin);
238  } else {
239  GPOC = (1 << pin);
240  }
241  } else if (pin == 16) {
242  if (val) {
243  GP16O |= 1;
244  } else {
245  GP16O &= ~1;
246  }
247  }
248 }
249 //------------------------------------------------------------------------------
254 static inline __attribute__((always_inline))
255 bool fastDigitalRead(uint8_t pin) {
256  if (pin < 16) {
257  return GPIP(pin);
258  } else if (pin == 16) {
259  return GP16I & 0x01;
260  }
261  return 0;
262 }
263 #else // CORE_TEENSY
264 //------------------------------------------------------------------------------
265 inline void fastDigitalWrite(uint8_t pin, bool value) {
266  digitalWrite(pin, value);
267 }
268 //------------------------------------------------------------------------------
269 inline bool fastDigitalRead(uint8_t pin) {
270  return digitalRead(pin);
271 }
272 #endif // CORE_TEENSY
273 //------------------------------------------------------------------------------
274 inline void fastDigitalToggle(uint8_t pin) {
275  fastDigitalWrite(pin, !fastDigitalRead(pin));
276 }
277 //------------------------------------------------------------------------------
278 inline void fastPinMode(pin, mode) {
279  pinMode(pin, mode);
280 }
281 #endif // __AVR__
282 //------------------------------------------------------------------------------
289 #define fastPinConfig(pin, mode, level)\
290  {fastPinMode(pin, mode); fastDigitalWrite(pin, level);}
291 //==============================================================================
296 template<uint8_t PinNumber>
297 class DigitalPin {
298  public:
299  //----------------------------------------------------------------------------
302  //----------------------------------------------------------------------------
309  inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
310  write(value);
311  return *this;
312  }
313  //----------------------------------------------------------------------------
317  inline operator bool () const __attribute__((always_inline)) {
318  return read();
319  }
320  //----------------------------------------------------------------------------
326  inline __attribute__((always_inline))
327  void config(uint8_t mode, bool level) {
328  fastPinConfig(PinNumber, mode, level);
329  }
330  //----------------------------------------------------------------------------
334  inline __attribute__((always_inline))
335  void high() {write(true);}
336  //----------------------------------------------------------------------------
340  inline __attribute__((always_inline))
341  void low() {write(false);}
342  //----------------------------------------------------------------------------
350  inline __attribute__((always_inline))
351  void mode(uint8_t mode) {
352  fastPinMode(PinNumber, mode);
353  }
354  //----------------------------------------------------------------------------
356  inline __attribute__((always_inline))
357  bool read() const {
358  return fastDigitalRead(PinNumber);
359  }
360  //----------------------------------------------------------------------------
366  inline __attribute__((always_inline))
367  void toggle() {
368  fastDigitalToggle(PinNumber);
369  }
370  //----------------------------------------------------------------------------
375  inline __attribute__((always_inline))
376  void write(bool value) {
377  fastDigitalWrite(PinNumber, value);
378  }
379 };
380 #endif // DigitalPin_h
381 
void write(bool value)
Definition: DigitalPin.h:376
uint8_t mask
Definition: DigitalPin.h:37
void low()
Definition: DigitalPin.h:341
bool read() const
Definition: DigitalPin.h:357
DigitalPin & operator=(bool value)
Definition: DigitalPin.h:309
volatile uint8_t * port
Definition: DigitalPin.h:36
static volatile uint8_t * portReg(uint8_t pin)
Definition: DigitalPin.h:95
#define fastPinConfig(pin, mode, level)
Definition: DigitalPin.h:289
void config(uint8_t mode, bool level)
Definition: DigitalPin.h:327
void mode(uint8_t mode)
Definition: DigitalPin.h:351
Fast digital port I/O.
Definition: DigitalPin.h:297
static void fastDigitalWrite(uint8_t pin, bool level)
Definition: DigitalPin.h:153
static volatile uint8_t * pinReg(uint8_t pin)
Definition: DigitalPin.h:85
static bool fastDigitalRead(uint8_t pin)
Definition: DigitalPin.h:127
static volatile uint8_t * ddrReg(uint8_t pin)
Definition: DigitalPin.h:65
void high()
Definition: DigitalPin.h:335
static void fastDdrWrite(uint8_t pin, bool level)
Definition: DigitalPin.h:162
void badPinNumber(void)
static void fastDigitalToggle(uint8_t pin)
Definition: DigitalPin.h:138
static void fastPinMode(uint8_t pin, uint8_t mode)
Definition: DigitalPin.h:174
volatile uint8_t * pin
Definition: DigitalPin.h:34
volatile uint8_t * ddr
Definition: DigitalPin.h:35
static void badPinCheck(uint8_t pin)
Definition: DigitalPin.h:54
static void fastBitWriteSafe(volatile uint8_t *address, uint8_t mask, bool level)
Definition: DigitalPin.h:106
static uint8_t pinMask(uint8_t pin)
Definition: DigitalPin.h:75
void toggle()
Definition: DigitalPin.h:367