root / arduino-1.0 / libraries / Firmata / Boards.h @ 58d82c77
History | View | Annotate | Download (14.6 KB)
1 |
/* Boards.h - Hardware Abstraction Layer for Firmata library */
|
---|---|
2 |
|
3 |
#ifndef Firmata_Boards_h
|
4 |
#define Firmata_Boards_h
|
5 |
|
6 |
#include <inttypes.h> |
7 |
|
8 |
#if defined(ARDUINO) && ARDUINO >= 100 |
9 |
#include "Arduino.h" // for digitalRead, digitalWrite, etc |
10 |
#else
|
11 |
#include "WProgram.h" |
12 |
#endif
|
13 |
|
14 |
// Normally Servo.h must be included before Firmata.h (which then includes
|
15 |
// this file). If Servo.h wasn't included, this allows the code to still
|
16 |
// compile, but without support for any Servos. Hopefully that's what the
|
17 |
// user intended by not including Servo.h
|
18 |
#ifndef MAX_SERVOS
|
19 |
#define MAX_SERVOS 0 |
20 |
#endif
|
21 |
|
22 |
/*
|
23 |
Firmata Hardware Abstraction Layer
|
24 |
|
25 |
Firmata is built on top of the hardware abstraction functions of Arduino,
|
26 |
specifically digitalWrite, digitalRead, analogWrite, analogRead, and
|
27 |
pinMode. While these functions offer simple integer pin numbers, Firmata
|
28 |
needs more information than is provided by Arduino. This file provides
|
29 |
all other hardware specific details. To make Firmata support a new board,
|
30 |
only this file should require editing.
|
31 |
|
32 |
The key concept is every "pin" implemented by Firmata may be mapped to
|
33 |
any pin as implemented by Arduino. Usually a simple 1-to-1 mapping is
|
34 |
best, but such mapping should not be assumed. This hardware abstraction
|
35 |
layer allows Firmata to implement any number of pins which map onto the
|
36 |
Arduino implemented pins in almost any arbitrary way.
|
37 |
|
38 |
|
39 |
General Constants:
|
40 |
|
41 |
These constants provide basic information Firmata requires.
|
42 |
|
43 |
TOTAL_PINS: The total number of pins Firmata implemented by Firmata.
|
44 |
Usually this will match the number of pins the Arduino functions
|
45 |
implement, including any pins pins capable of analog or digital.
|
46 |
However, Firmata may implement any number of pins. For example,
|
47 |
on Arduino Mini with 8 analog inputs, 6 of these may be used
|
48 |
for digital functions, and 2 are analog only. On such boards,
|
49 |
Firmata can implement more pins than Arduino's pinMode()
|
50 |
function, in order to accommodate those special pins. The
|
51 |
Firmata protocol supports a maximum of 128 pins, so this
|
52 |
constant must not exceed 128.
|
53 |
|
54 |
TOTAL_ANALOG_PINS: The total number of analog input pins implemented.
|
55 |
The Firmata protocol allows up to 16 analog inputs, accessed
|
56 |
using offsets 0 to 15. Because Firmata presents the analog
|
57 |
inputs using different offsets than the actual pin numbers
|
58 |
(a legacy of Arduino's analogRead function, and the way the
|
59 |
analog input capable pins are physically labeled on all
|
60 |
Arduino boards), the total number of analog input signals
|
61 |
must be specified. 16 is the maximum.
|
62 |
|
63 |
VERSION_BLINK_PIN: When Firmata starts up, it will blink the version
|
64 |
number. This constant is the Arduino pin number where a
|
65 |
LED is connected.
|
66 |
|
67 |
|
68 |
Pin Mapping Macros:
|
69 |
|
70 |
These macros provide the mapping between pins as implemented by
|
71 |
Firmata protocol and the actual pin numbers used by the Arduino
|
72 |
functions. Even though such mappings are often simple, pin
|
73 |
numbers received by Firmata protocol should always be used as
|
74 |
input to these macros, and the result of the macro should be
|
75 |
used with with any Arduino function.
|
76 |
|
77 |
When Firmata is extended to support a new pin mode or feature,
|
78 |
a pair of macros should be added and used for all hardware
|
79 |
access. For simple 1:1 mapping, these macros add no actual
|
80 |
overhead, yet their consistent use allows source code which
|
81 |
uses them consistently to be easily adapted to all other boards
|
82 |
with different requirements.
|
83 |
|
84 |
IS_PIN_XXXX(pin): The IS_PIN macros resolve to true or non-zero
|
85 |
if a pin as implemented by Firmata corresponds to a pin
|
86 |
that actually implements the named feature.
|
87 |
|
88 |
PIN_TO_XXXX(pin): The PIN_TO macros translate pin numbers as
|
89 |
implemented by Firmata to the pin numbers needed as inputs
|
90 |
to the Arduino functions. The corresponding IS_PIN macro
|
91 |
should always be tested before using a PIN_TO macro, so
|
92 |
these macros only need to handle valid Firmata pin
|
93 |
numbers for the named feature.
|
94 |
|
95 |
|
96 |
Port Access Inline Funtions:
|
97 |
|
98 |
For efficiency, Firmata protocol provides access to digital
|
99 |
input and output pins grouped by 8 bit ports. When these
|
100 |
groups of 8 correspond to actual 8 bit ports as implemented
|
101 |
by the hardware, these inline functions can provide high
|
102 |
speed direct port access. Otherwise, a default implementation
|
103 |
using 8 calls to digitalWrite or digitalRead is used.
|
104 |
|
105 |
When porting Firmata to a new board, it is recommended to
|
106 |
use the default functions first and focus only on the constants
|
107 |
and macros above. When those are working, if optimized port
|
108 |
access is desired, these inline functions may be extended.
|
109 |
The recommended approach defines a symbol indicating which
|
110 |
optimization to use, and then conditional complication is
|
111 |
used within these functions.
|
112 |
|
113 |
readPort(port, bitmask): Read an 8 bit port, returning the value.
|
114 |
port: The port number, Firmata pins port*8 to port*8+7
|
115 |
bitmask: The actual pins to read, indicated by 1 bits.
|
116 |
|
117 |
writePort(port, value, bitmask): Write an 8 bit port.
|
118 |
port: The port number, Firmata pins port*8 to port*8+7
|
119 |
value: The 8 bit value to write
|
120 |
bitmask: The actual pins to write, indicated by 1 bits.
|
121 |
*/
|
122 |
|
123 |
/*==============================================================================
|
124 |
* Board Specific Configuration
|
125 |
*============================================================================*/
|
126 |
|
127 |
#ifndef digitalPinHasPWM
|
128 |
#define digitalPinHasPWM(p) IS_PIN_DIGITAL(p)
|
129 |
#endif
|
130 |
|
131 |
// Arduino Duemilanove, Diecimila, and NG
|
132 |
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
|
133 |
#if defined(NUM_ANALOG_INPUTS) && NUM_ANALOG_INPUTS == 6 |
134 |
#define TOTAL_ANALOG_PINS 6 |
135 |
#define TOTAL_PINS 20 // 14 digital + 6 analog |
136 |
#else
|
137 |
#define TOTAL_ANALOG_PINS 8 |
138 |
#define TOTAL_PINS 22 // 14 digital + 8 analog |
139 |
#endif
|
140 |
#define VERSION_BLINK_PIN 13 |
141 |
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19) |
142 |
#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS) |
143 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
144 |
#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) |
145 |
#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) |
146 |
#define PIN_TO_DIGITAL(p) (p)
|
147 |
#define PIN_TO_ANALOG(p) ((p) - 14) |
148 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
149 |
#define PIN_TO_SERVO(p) ((p) - 2) |
150 |
#define ARDUINO_PINOUT_OPTIMIZE 1 |
151 |
|
152 |
|
153 |
// Wiring (and board)
|
154 |
#elif defined(WIRING)
|
155 |
#define VERSION_BLINK_PIN WLED
|
156 |
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) |
157 |
#define IS_PIN_ANALOG(p) ((p) >= FIRST_ANALOG_PIN && (p) < (FIRST_ANALOG_PIN+TOTAL_ANALOG_PINS))
|
158 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
159 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
160 |
#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
|
161 |
#define PIN_TO_DIGITAL(p) (p)
|
162 |
#define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN)
|
163 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
164 |
#define PIN_TO_SERVO(p) (p)
|
165 |
|
166 |
|
167 |
// old Arduinos
|
168 |
#elif defined(__AVR_ATmega8__)
|
169 |
#define TOTAL_ANALOG_PINS 6 |
170 |
#define TOTAL_PINS 20 // 14 digital + 6 analog |
171 |
#define VERSION_BLINK_PIN 13 |
172 |
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19) |
173 |
#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19) |
174 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
175 |
#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) |
176 |
#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) |
177 |
#define PIN_TO_DIGITAL(p) (p)
|
178 |
#define PIN_TO_ANALOG(p) ((p) - 14) |
179 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
180 |
#define PIN_TO_SERVO(p) ((p) - 2) |
181 |
#define ARDUINO_PINOUT_OPTIMIZE 1 |
182 |
|
183 |
|
184 |
// Arduino Mega
|
185 |
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
186 |
#define TOTAL_ANALOG_PINS 16 |
187 |
#define TOTAL_PINS 70 // 54 digital + 16 analog |
188 |
#define VERSION_BLINK_PIN 13 |
189 |
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) |
190 |
#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) |
191 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
192 |
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) |
193 |
#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) |
194 |
#define PIN_TO_DIGITAL(p) (p)
|
195 |
#define PIN_TO_ANALOG(p) ((p) - 54) |
196 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
197 |
#define PIN_TO_SERVO(p) ((p) - 2) |
198 |
|
199 |
|
200 |
// Teensy 1.0
|
201 |
#elif defined(__AVR_AT90USB162__)
|
202 |
#define TOTAL_ANALOG_PINS 0 |
203 |
#define TOTAL_PINS 21 // 21 digital + no analog |
204 |
#define VERSION_BLINK_PIN 6 |
205 |
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) |
206 |
#define IS_PIN_ANALOG(p) (0) |
207 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
208 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
209 |
#define IS_PIN_I2C(p) (0) |
210 |
#define PIN_TO_DIGITAL(p) (p)
|
211 |
#define PIN_TO_ANALOG(p) (0) |
212 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
213 |
#define PIN_TO_SERVO(p) (p)
|
214 |
|
215 |
|
216 |
// Teensy 2.0
|
217 |
#elif defined(__AVR_ATmega32U4__)
|
218 |
#define TOTAL_ANALOG_PINS 12 |
219 |
#define TOTAL_PINS 25 // 11 digital + 12 analog |
220 |
#define VERSION_BLINK_PIN 11 |
221 |
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) |
222 |
#define IS_PIN_ANALOG(p) ((p) >= 11 && (p) <= 22) |
223 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
224 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
225 |
#define IS_PIN_I2C(p) ((p) == 5 || (p) == 6) |
226 |
#define PIN_TO_DIGITAL(p) (p)
|
227 |
#define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11) |
228 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
229 |
#define PIN_TO_SERVO(p) (p)
|
230 |
|
231 |
|
232 |
// Teensy++ 1.0 and 2.0
|
233 |
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
234 |
#define TOTAL_ANALOG_PINS 8 |
235 |
#define TOTAL_PINS 46 // 38 digital + 8 analog |
236 |
#define VERSION_BLINK_PIN 6 |
237 |
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) |
238 |
#define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS) |
239 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
240 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
241 |
#define IS_PIN_I2C(p) ((p) == 0 || (p) == 1) |
242 |
#define PIN_TO_DIGITAL(p) (p)
|
243 |
#define PIN_TO_ANALOG(p) ((p) - 38) |
244 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
245 |
#define PIN_TO_SERVO(p) (p)
|
246 |
|
247 |
|
248 |
// Sanguino
|
249 |
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
250 |
#define TOTAL_ANALOG_PINS 8 |
251 |
#define TOTAL_PINS 32 // 24 digital + 8 analog |
252 |
#define VERSION_BLINK_PIN 0 |
253 |
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) |
254 |
#define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS) |
255 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
256 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
257 |
#define IS_PIN_I2C(p) ((p) == 16 || (p) == 17) |
258 |
#define PIN_TO_DIGITAL(p) (p)
|
259 |
#define PIN_TO_ANALOG(p) ((p) - 24) |
260 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
261 |
#define PIN_TO_SERVO(p) ((p) - 2) |
262 |
|
263 |
|
264 |
// Illuminato
|
265 |
#elif defined(__AVR_ATmega645__)
|
266 |
#define TOTAL_ANALOG_PINS 6 |
267 |
#define TOTAL_PINS 42 // 36 digital + 6 analog |
268 |
#define VERSION_BLINK_PIN 13 |
269 |
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) |
270 |
#define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS) |
271 |
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
|
272 |
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) |
273 |
#define IS_PIN_I2C(p) ((p) == 4 || (p) == 5) |
274 |
#define PIN_TO_DIGITAL(p) (p)
|
275 |
#define PIN_TO_ANALOG(p) ((p) - 36) |
276 |
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
|
277 |
#define PIN_TO_SERVO(p) ((p) - 2) |
278 |
|
279 |
|
280 |
// anything else
|
281 |
#else
|
282 |
#error "Please edit Boards.h with a hardware abstraction for this board" |
283 |
#endif
|
284 |
|
285 |
|
286 |
/*==============================================================================
|
287 |
* readPort() - Read an 8 bit port
|
288 |
*============================================================================*/
|
289 |
|
290 |
static inline unsigned char readPort(byte, byte) __attribute__((always_inline, unused)); |
291 |
static inline unsigned char readPort(byte port, byte bitmask) |
292 |
{ |
293 |
#if defined(ARDUINO_PINOUT_OPTIMIZE)
|
294 |
if (port == 0) return (PIND & 0xFC) & bitmask; // ignore Rx/Tx 0/1 |
295 |
if (port == 1) return ((PINB & 0x3F) | ((PINC & 0x03) << 6)) & bitmask; |
296 |
if (port == 2) return ((PINC & 0x3C) >> 2) & bitmask; |
297 |
return 0; |
298 |
#else
|
299 |
unsigned char out=0, pin=port*8; |
300 |
if (IS_PIN_DIGITAL(pin+0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(pin+0))) out |= 0x01; |
301 |
if (IS_PIN_DIGITAL(pin+1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(pin+1))) out |= 0x02; |
302 |
if (IS_PIN_DIGITAL(pin+2) && (bitmask & 0x04) && digitalRead(PIN_TO_DIGITAL(pin+2))) out |= 0x04; |
303 |
if (IS_PIN_DIGITAL(pin+3) && (bitmask & 0x08) && digitalRead(PIN_TO_DIGITAL(pin+3))) out |= 0x08; |
304 |
if (IS_PIN_DIGITAL(pin+4) && (bitmask & 0x10) && digitalRead(PIN_TO_DIGITAL(pin+4))) out |= 0x10; |
305 |
if (IS_PIN_DIGITAL(pin+5) && (bitmask & 0x20) && digitalRead(PIN_TO_DIGITAL(pin+5))) out |= 0x20; |
306 |
if (IS_PIN_DIGITAL(pin+6) && (bitmask & 0x40) && digitalRead(PIN_TO_DIGITAL(pin+6))) out |= 0x40; |
307 |
if (IS_PIN_DIGITAL(pin+7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(pin+7))) out |= 0x80; |
308 |
return out;
|
309 |
#endif
|
310 |
} |
311 |
|
312 |
/*==============================================================================
|
313 |
* writePort() - Write an 8 bit port, only touch pins specified by a bitmask
|
314 |
*============================================================================*/
|
315 |
|
316 |
static inline unsigned char writePort(byte, byte, byte) __attribute__((always_inline, unused)); |
317 |
static inline unsigned char writePort(byte port, byte value, byte bitmask) |
318 |
{ |
319 |
#if defined(ARDUINO_PINOUT_OPTIMIZE)
|
320 |
if (port == 0) { |
321 |
bitmask = bitmask & 0xFC; // do not touch Tx & Rx pins |
322 |
byte valD = value & bitmask; |
323 |
byte maskD = ~bitmask; |
324 |
cli(); |
325 |
PORTD = (PORTD & maskD) | valD; |
326 |
sei(); |
327 |
} else if (port == 1) { |
328 |
byte valB = (value & bitmask) & 0x3F;
|
329 |
byte valC = (value & bitmask) >> 6;
|
330 |
byte maskB = ~(bitmask & 0x3F);
|
331 |
byte maskC = ~((bitmask & 0xC0) >> 6); |
332 |
cli(); |
333 |
PORTB = (PORTB & maskB) | valB; |
334 |
PORTC = (PORTC & maskC) | valC; |
335 |
sei(); |
336 |
} else if (port == 2) { |
337 |
bitmask = bitmask & 0x0F;
|
338 |
byte valC = (value & bitmask) << 2;
|
339 |
byte maskC = ~(bitmask << 2);
|
340 |
cli(); |
341 |
PORTC = (PORTC & maskC) | valC; |
342 |
sei(); |
343 |
} |
344 |
#else
|
345 |
byte pin=port*8;
|
346 |
if ((bitmask & 0x01)) digitalWrite(PIN_TO_DIGITAL(pin+0), (value & 0x01)); |
347 |
if ((bitmask & 0x02)) digitalWrite(PIN_TO_DIGITAL(pin+1), (value & 0x02)); |
348 |
if ((bitmask & 0x04)) digitalWrite(PIN_TO_DIGITAL(pin+2), (value & 0x04)); |
349 |
if ((bitmask & 0x08)) digitalWrite(PIN_TO_DIGITAL(pin+3), (value & 0x08)); |
350 |
if ((bitmask & 0x10)) digitalWrite(PIN_TO_DIGITAL(pin+4), (value & 0x10)); |
351 |
if ((bitmask & 0x20)) digitalWrite(PIN_TO_DIGITAL(pin+5), (value & 0x20)); |
352 |
if ((bitmask & 0x40)) digitalWrite(PIN_TO_DIGITAL(pin+6), (value & 0x40)); |
353 |
if ((bitmask & 0x80)) digitalWrite(PIN_TO_DIGITAL(pin+7), (value & 0x80)); |
354 |
#endif
|
355 |
} |
356 |
|
357 |
|
358 |
|
359 |
|
360 |
#ifndef TOTAL_PORTS
|
361 |
#define TOTAL_PORTS ((TOTAL_PINS + 7) / 8) |
362 |
#endif
|
363 |
|
364 |
|
365 |
#endif /* Firmata_Boards_h */ |
366 |
|