Project

General

Profile

Statistics
| Branch: | Revision:

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 */