wpi-32u4-library
FastGPIO.h
Go to the documentation of this file.
1// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2
44#pragma once
45#include <avr/io.h>
46#include <stdint.h>
47
49#define _FG_SBI(mem_addr, bit) asm volatile("sbi %0, %1\n" : \
50 : "I" (mem_addr - __SFR_OFFSET), "I" (bit))
51#define _FG_CBI(mem_addr, bit) asm volatile("cbi %0, %1\n" : \
52 : "I" (mem_addr - __SFR_OFFSET), "I" (bit))
53#define _FG_PIN(port, bit) { _SFR_MEM_ADDR(PIN##port), _SFR_MEM_ADDR(PORT##port), \
54 _SFR_MEM_ADDR(DDR##port), bit }
57namespace FastGPIO
58{
65 typedef struct IOStruct
66 {
67 uint8_t pinAddr;
68 uint8_t portAddr;
69 uint8_t ddrAddr;
70 uint8_t bit;
71
72 volatile uint8_t * pin() const
73 {
74 return (volatile uint8_t *)(uint16_t)pinAddr;
75 }
76
77 volatile uint8_t * port() const
78 {
79 return (volatile uint8_t *)(uint16_t)portAddr;
80 }
81
82 volatile uint8_t * ddr() const
83 {
84 return (volatile uint8_t *)(uint16_t)ddrAddr;
85 }
86 } IOStruct;
89#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
90
91 const IOStruct pinStructs[] = {
92 _FG_PIN(D, 0),
93 _FG_PIN(D, 1),
94 _FG_PIN(D, 2),
95 _FG_PIN(D, 3),
96 _FG_PIN(D, 4),
97 _FG_PIN(D, 5),
98 _FG_PIN(D, 6),
99 _FG_PIN(D, 7),
100 _FG_PIN(B, 0),
101 _FG_PIN(B, 1),
102 _FG_PIN(B, 2),
103 _FG_PIN(B, 3),
104 _FG_PIN(B, 4),
105 _FG_PIN(B, 5),
106 _FG_PIN(C, 0),
107 _FG_PIN(C, 1),
108 _FG_PIN(C, 2),
109 _FG_PIN(C, 3),
110 _FG_PIN(C, 4),
111 _FG_PIN(C, 5),
112 _FG_PIN(C, 6),
113 _FG_PIN(C, 7), // Null pin (IO_NONE)
114 };
115
116#define IO_D0 0
117#define IO_D1 1
118#define IO_D2 2
119#define IO_D3 3
120#define IO_D4 4
121#define IO_D5 5
122#define IO_D6 6
123#define IO_D7 7
124#define IO_B0 8
125#define IO_B1 9
126#define IO_B2 10
127#define IO_B3 11
128#define IO_B4 12
129#define IO_B5 13
130#define IO_C0 14
131#define IO_C1 15
132#define IO_C2 16
133#define IO_C3 17
134#define IO_C4 18
135#define IO_C5 19
136#define IO_C6 20
137#define IO_NONE 21
138
139#elif defined(__AVR_ATmega32U4__)
140
141 const IOStruct pinStructs[] = {
142 _FG_PIN(D, 2),
143 _FG_PIN(D, 3),
144 _FG_PIN(D, 1),
145 _FG_PIN(D, 0),
146 _FG_PIN(D, 4),
147 _FG_PIN(C, 6),
148 _FG_PIN(D, 7),
149 _FG_PIN(E, 6),
150
151 _FG_PIN(B, 4),
152 _FG_PIN(B, 5),
153 _FG_PIN(B, 6),
154 _FG_PIN(B, 7),
155 _FG_PIN(D, 6),
156 _FG_PIN(C, 7),
157
158 _FG_PIN(B, 3),
159 _FG_PIN(B, 1),
160 _FG_PIN(B, 2),
161 _FG_PIN(B, 0),
162
163 _FG_PIN(F, 7),
164 _FG_PIN(F, 6),
165 _FG_PIN(F, 5),
166 _FG_PIN(F, 4),
167 _FG_PIN(F, 1),
168 _FG_PIN(F, 0),
169
170 _FG_PIN(D, 4),
171 _FG_PIN(D, 7),
172 _FG_PIN(B, 4),
173 _FG_PIN(B, 5),
174 _FG_PIN(B, 6),
175 _FG_PIN(D, 6),
176
177 // Extra pins added by this library and not supported by the
178 // Arduino GPIO functions:
179 _FG_PIN(D, 5),
180 _FG_PIN(E, 2),
181
182 _FG_PIN(E, 0) // Null pin (IO_NONE)
183 };
184
185#define IO_D2 0
186#define IO_D3 1
187#define IO_D1 2
188#define IO_D0 3
189#define IO_D4 4
190#define IO_C6 5
191#define IO_D7 6
192#define IO_E6 7
193#define IO_B4 8
194#define IO_B5 9
195#define IO_B6 10
196#define IO_B7 11
197#define IO_D6 12
198#define IO_C7 13
199#define IO_B3 14
200#define IO_B1 15
201#define IO_B2 16
202#define IO_B0 17
203#define IO_F7 18
204#define IO_F6 19
205#define IO_F5 20
206#define IO_F4 21
207#define IO_F1 22
208#define IO_F0 23
209#define IO_D5 30
210#define IO_E2 31
211#define IO_NONE 32
212
213#else
214#error FastGPIO does not support this board.
215#endif
216
217 template<uint8_t pin> class Pin
218 {
219 public:
226 static inline void setOutputLow() __attribute__((always_inline))
227 {
228 _FG_CBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
229 _FG_SBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
230 }
231
238 static inline void setOutputHigh() __attribute__((always_inline))
239 {
240 _FG_SBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
241 _FG_SBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
242 }
243
246 static inline void setOutputToggle() __attribute__((always_inline))
247 {
249 _FG_SBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
250 }
251
260 static inline void setOutput(bool value) __attribute__((always_inline))
261 {
262 setOutputValue(value);
263 _FG_SBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
264 }
265
274 static inline void setOutputValueLow() __attribute__((always_inline))
275 {
276 _FG_CBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
277 }
278
287 static inline void setOutputValueHigh() __attribute__((always_inline))
288 {
289 _FG_SBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
290 }
291
302 static inline void setOutputValueToggle() __attribute__((always_inline))
303 {
304 _FG_SBI(pinStructs[pin].pinAddr, pinStructs[pin].bit);
305 }
306
318 static inline void setOutputValue(bool value) __attribute__((always_inline))
319 {
320 if (value)
321 {
322 _FG_SBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
323 }
324 else
325 {
326 _FG_CBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
327 }
328 }
329
333 static inline void setInput() __attribute__((always_inline))
334 {
335 _FG_CBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
336 _FG_CBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
337 }
338
342 static inline void setInputPulledUp() __attribute__((always_inline))
343 {
344 _FG_CBI(pinStructs[pin].ddrAddr, pinStructs[pin].bit);
345 _FG_SBI(pinStructs[pin].portAddr, pinStructs[pin].bit);
346 }
347
352 static inline bool isInputHigh() __attribute__((always_inline))
353 {
354 return *pinStructs[pin].pin() >> pinStructs[pin].bit & 1;
355
356 /* This is another option but it is less efficient in code
357 like "if (isInputHigh()) { ... }":
358 bool value;
359 asm volatile(
360 "ldi %0, 0\n"
361 "sbic %2, %1\n"
362 "ldi %0, 1\n"
363 : "=d" (value)
364 : "I" (pinStructs[pin].bit),
365 "I" (pinStructs[pin].pinAddr - __SFR_OFFSET));
366 return value;
367 */
368 }
369
374 static inline bool isOutput() __attribute__((always_inline))
375 {
376 return *pinStructs[pin].ddr() >> pinStructs[pin].bit & 1;
377 }
378
385 static inline bool isOutputValueHigh() __attribute__((always_inline))
386 {
387 return *pinStructs[pin].port() >> pinStructs[pin].bit & 1;
388 }
389
396 static uint8_t getState()
397 {
398 uint8_t state;
399 asm volatile(
400 "ldi %0, 0\n"
401 "sbic %2, %1\n"
402 "ori %0, 1\n" // Set state bit 0 to 1 if PORT bit is set.
403 "sbic %3, %1\n"
404 "ori %0, 2\n" // Set state bit 1 to 1 if DDR bit is set.
405 : "=a" (state)
406 : "I" (pinStructs[pin].bit),
407 "I" (pinStructs[pin].portAddr - __SFR_OFFSET),
408 "I" (pinStructs[pin].ddrAddr - __SFR_OFFSET));
409 return state;
410
411 /* Equivalent C++ code:
412 return isOutput() << 1 | isOutputValueHigh();
413 */
414 }
415
428 static void setState(uint8_t state)
429 {
430 asm volatile(
431 "bst %0, 1\n" // Set DDR to 0 if needed
432 "brts .+2\n"
433 "cbi %3, %1\n"
434 "bst %0, 0\n" // Copy state bit 0 to PORT bit
435 "brts .+2\n"
436 "cbi %2, %1\n"
437 "brtc .+2\n"
438 "sbi %2, %1\n"
439 "bst %0, 1\n" // Set DDR to 1 if needed
440 "brtc .+2\n"
441 "sbi %3, %1\n"
442 :
443 : "a" (state),
444 "I" (pinStructs[pin].bit),
445 "I" (pinStructs[pin].portAddr - __SFR_OFFSET),
446 "I" (pinStructs[pin].ddrAddr - __SFR_OFFSET));
447 }
448 };
449
484 template<uint8_t pin> class PinLoan
485 {
486 public:
488 uint8_t state;
489
491 {
493 }
494
496 {
498 }
499 };
500};
501
502#undef _FG_PIN
503#undef _FG_CBI
504#undef _FG_SBI
uint8_t state
The state of the pin as returned from FastGPIO::Pin::getState.
Definition: FastGPIO.h:488
static bool isOutputValueHigh() __attribute__((always_inline))
Returns the output value of the pin.
Definition: FastGPIO.h:385
static void setOutputValue(bool value) __attribute__((always_inline))
Sets the output value of the pin.
Definition: FastGPIO.h:318
static void setInputPulledUp() __attribute__((always_inline))
Sets a pin to be a digital input with the internal pull-up resistor enabled.
Definition: FastGPIO.h:342
static void setOutputLow() __attribute__((always_inline))
Configures the pin to be an output driving low.
Definition: FastGPIO.h:226
static void setOutputValueToggle() __attribute__((always_inline))
Toggles the output value of the pin.
Definition: FastGPIO.h:302
static void setOutputValueHigh() __attribute__((always_inline))
Sets the output value of the pin to 1.
Definition: FastGPIO.h:287
static void setState(uint8_t state)
Sets the full 2-bit state of the pin.
Definition: FastGPIO.h:428
static uint8_t getState()
Returns the full 2-bit state of the pin.
Definition: FastGPIO.h:396
static void setInput() __attribute__((always_inline))
Sets a pin to be a digital input with the internal pull-up resistor disabled.
Definition: FastGPIO.h:333
static void setOutput(bool value) __attribute__((always_inline))
Sets the pin as an output.
Definition: FastGPIO.h:260
static void setOutputHigh() __attribute__((always_inline))
Configures the pin to be an output driving high.
Definition: FastGPIO.h:238
static void setOutputToggle() __attribute__((always_inline))
Configures the pin to be an output and toggles it.
Definition: FastGPIO.h:246
static bool isInputHigh() __attribute__((always_inline))
Reads the input value of the pin.
Definition: FastGPIO.h:352
static void setOutputValueLow() __attribute__((always_inline))
Sets the output value of the pin to 0.
Definition: FastGPIO.h:274
static bool isOutput() __attribute__((always_inline))
Returns 1 if the pin is configured as an output.
Definition: FastGPIO.h:374