root / arduino-1.0 / libraries / Firmata / Boards.h @ 58d82c77
History | View | Annotate | Download (14.6 KB)
1 | 58d82c77 | Tom Mullins | /* 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 */ |