COSA
An Object-Oriented Platform for Arduino Programming
GPIO.hh
Go to the documentation of this file.
1 
21 #ifndef COSA_GPIO_HH
22 #define COSA_GPIO_HH
23 
24 #include "Cosa/Types.h"
25 
30 class GPIO {
31 public:
35  enum Mode {
36  OUTPUT_MODE, // Output pin mode.
37  INPUT_MODE, // Input pin mode.
38  PULLUP_INPUT_MODE // Input pin with pullup mode.
39  };
40 
49  GPIO(Board::DigitalPin pin, Mode mode = INPUT_MODE, bool value = 0) :
50  m_sfr(Board::SFR(pin)),
51  m_mask(MASK(pin))
52  {
53  synchronized {
54  if (mode == OUTPUT_MODE) {
55  *DDR() |= m_mask;
56  }
57  else {
58  *DDR() &= ~m_mask;
59  }
60  if (value || (mode == PULLUP_INPUT_MODE)) {
61  *PORT() |= m_mask;
62  }
63  else {
64  *PORT() &= ~m_mask;
65  }
66  }
67  }
68 
74  void mode(Mode mode) const
75  __attribute__((always_inline))
76  {
77  synchronized {
78  if (mode == OUTPUT_MODE)
79  *DDR() |= m_mask;
80  else {
81  *DDR() &= ~m_mask;
82  if (mode == PULLUP_INPUT_MODE)
83  *PORT() |= m_mask;
84  }
85  }
86  }
87 
92  Mode mode() const
93  __attribute__((always_inline))
94  {
95  if ((*DDR() & m_mask) != 0)
96  return (OUTPUT_MODE);
97  if ((*PORT() & m_mask) != 0)
98  return (PULLUP_INPUT_MODE);
99  return (INPUT_MODE);
100  }
101 
106  operator bool() const
107  __attribute__((always_inline))
108  {
109  return ((*PIN() & m_mask) != 0);
110  }
111 
117  GPIO& operator=(bool value)
118  __attribute__((always_inline))
119  {
120  synchronized {
121  if (value) {
122  *PORT() |= m_mask;
123  }
124  else {
125  *PORT() &= ~m_mask;
126  }
127  }
128  return (*this);
129  }
130 
136  GPIO& operator=(const GPIO& rhs)
137  __attribute__((always_inline))
138  {
139  bool value = rhs;
140  synchronized {
141  if (value) {
142  *PORT() |= m_mask;
143  }
144  else {
145  *PORT() &= ~m_mask;
146  }
147  }
148  return (*this);
149  }
150 
155  void operator~() const
156  __attribute__((always_inline))
157  {
158  *PIN() = m_mask;
159  }
160 
166  static void mode(Board::DigitalPin pin, Mode mode)
167  __attribute__((always_inline))
168  {
169  const uint8_t mask = MASK(pin);
170  synchronized {
171  if (mode == OUTPUT_MODE)
172  *DDR(pin) |= mask;
173  else {
174  *DDR(pin) &= ~mask;
175  if (mode == PULLUP_INPUT_MODE)
176  *PORT(pin) |= mask;
177  }
178  }
179  }
180 
186  __attribute__((always_inline))
187  {
188  const uint8_t mask = MASK(pin);
189  if ((*DDR(pin) & mask) != 0)
190  return (OUTPUT_MODE);
191  if ((*PORT(pin) & mask) != 0)
192  return (PULLUP_INPUT_MODE);
193  return (INPUT_MODE);
194  }
195 
202  static bool read(Board::DigitalPin pin)
203  __attribute__((always_inline))
204  {
205  return ((*PIN(pin) & MASK(pin)) != 0);
206  }
207 
215  static void write(Board::DigitalPin pin, bool value)
216  __attribute__((always_inline))
217  {
218  volatile uint8_t* port = PORT(pin);
219  const uint8_t mask = MASK(pin);
220 #if (ARDUINO > 150)
221  // Synchronized not needed when constant values (and lower ports)
222 #if defined(PORTH)
223  if (((int) port < PORTH)
224  && __builtin_constant_p(pin)
225  && __builtin_constant_p(value)) {
226 #else
227  if (__builtin_constant_p(pin) && __builtin_constant_p(value)) {
228 #endif
229  if (value) {
230  *port |= mask;
231  }
232  else {
233  *port &= ~mask;
234  }
235  }
236  else
237 #endif
238  synchronized {
239  if (value) {
240  *port |= mask;
241  }
242  else {
243  *port &= ~mask;
244  }
245  }
246  }
247 
254  static void toggle(Board::DigitalPin pin)
255  __attribute__((always_inline))
256  {
257  volatile uint8_t* port = PIN(pin);
258  const uint8_t mask = MASK(pin);
259 #if (ARDUINO > 150)
260  // Synchronized not needed when constant values (and lower ports)
261 #if defined(PORTH)
262  if (((int) port < PORTH) && __builtin_constant_p(pin))
263 #else
264  if (__builtin_constant_p(pin))
265 #endif
266  *port = mask;
267  else
268 #endif
269  synchronized {
270  *port = mask;
271  }
272  }
273 
274 protected:
276  volatile uint8_t* const m_sfr;
277 
279  const uint8_t m_mask;
280 
285  volatile uint8_t* PIN() const
286  {
287  return (m_sfr);
288  }
289 
294  volatile uint8_t* DDR() const
295  {
296  return (m_sfr + 1);
297  }
298 
303  volatile uint8_t* PORT() const
304  {
305  return (m_sfr + 2);
306  }
307 
308 public:
314  static uint8_t MASK(uint8_t pin)
315  __attribute__((always_inline))
316  {
317  return (_BV(Board::BIT(pin)));
318  }
324  static volatile uint8_t* PIN(uint8_t pin)
325  __attribute__((always_inline))
326  {
327  return (Board::SFR(pin));
328  }
329 
336  static volatile uint8_t* DDR(uint8_t pin)
337  __attribute__((always_inline))
338  {
339  return (Board::SFR(pin) + 1);
340  }
341 
347  static volatile uint8_t* PORT(uint8_t pin)
348  __attribute__((always_inline))
349  {
350  return (Board::SFR(pin) + 2);
351  }
352 };
353 
354 #endif
volatile uint8_t *const m_sfr
Definition: GPIO.hh:276
void operator~() const
Definition: GPIO.hh:155
static void toggle(Board::DigitalPin pin)
Definition: GPIO.hh:254
static Mode mode(Board::DigitalPin pin)
Definition: GPIO.hh:185
GPIO(Board::DigitalPin pin, Mode mode=INPUT_MODE, bool value=0)
Definition: GPIO.hh:49
volatile uint8_t * DDR() const
Definition: GPIO.hh:294
void mode(Mode mode) const
Definition: GPIO.hh:74
static void write(Board::DigitalPin pin, bool value)
Definition: GPIO.hh:215
GPIO & operator=(bool value)
Definition: GPIO.hh:117
static bool read(Board::DigitalPin pin)
Definition: GPIO.hh:202
volatile uint8_t * PORT() const
Definition: GPIO.hh:303
const uint8_t m_mask
Definition: GPIO.hh:279
static volatile uint8_t * PIN(uint8_t pin)
Definition: GPIO.hh:324
static uint8_t MASK(uint8_t pin)
Definition: GPIO.hh:314
Mode mode() const
Definition: GPIO.hh:92
static void mode(Board::DigitalPin pin, Mode mode)
Definition: GPIO.hh:166
static volatile uint8_t * DDR(uint8_t pin)
Definition: GPIO.hh:336
Definition: GPIO.hh:30
volatile uint8_t * PIN() const
Definition: GPIO.hh:285
GPIO & operator=(const GPIO &rhs)
Definition: GPIO.hh:136
static volatile uint8_t * PORT(uint8_t pin)
Definition: GPIO.hh:347
Mode
Definition: GPIO.hh:35