arduino_firmata 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,655 @@
1
+ /*
2
+ * Firmata is a generic protocol for communicating with microcontrollers
3
+ * from software on a host computer. It is intended to work with
4
+ * any host computer software package.
5
+ *
6
+ * To download a host software package, please clink on the following link
7
+ * to open the download page in your default browser.
8
+ *
9
+ * http://firmata.org/wiki/Download
10
+ */
11
+
12
+ /*
13
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
14
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
15
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
16
+ Copyright (C) 2009-2011 Jeff Hoefs. All rights reserved.
17
+ Copyright (C) 2013 Sho Hashimoto. All rights reserved.
18
+
19
+ This library is free software; you can redistribute it and/or
20
+ modify it under the terms of the GNU Lesser General Public
21
+ License as published by the Free Software Foundation; either
22
+ version 2.1 of the License, or (at your option) any later version.
23
+
24
+ See file LICENSE.txt for further informations on licensing terms.
25
+
26
+ formatted using the GNU C formatting and indenting
27
+ */
28
+
29
+ /*
30
+ * TODO: use Program Control to load stored profiles from EEPROM
31
+ */
32
+
33
+ #include <Servo.h>
34
+ #include <Wire.h>
35
+ #include <Firmata.h>
36
+
37
+ // move the following defines to Firmata.h?
38
+ #define I2C_WRITE B00000000
39
+ #define I2C_READ B00001000
40
+ #define I2C_READ_CONTINUOUSLY B00010000
41
+ #define I2C_STOP_READING B00011000
42
+ #define I2C_READ_WRITE_MODE_MASK B00011000
43
+ #define I2C_10BIT_ADDRESS_MODE_MASK B00100000
44
+
45
+ #define MAX_QUERIES 8
46
+ #define MINIMUM_SAMPLING_INTERVAL 10
47
+
48
+ #define REGISTER_NOT_SPECIFIED -1
49
+
50
+ /*==============================================================================
51
+ * GLOBAL VARIABLES
52
+ *============================================================================*/
53
+
54
+ /* analog inputs */
55
+ int analogInputsToReport = 0; // bitwise array to store pin reporting
56
+
57
+ /* digital input ports */
58
+ byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
59
+ byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
60
+
61
+ /* pins configuration */
62
+ byte pinConfig[TOTAL_PINS]; // configuration of every pin
63
+ byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
64
+ int pinState[TOTAL_PINS]; // any value that has been written
65
+
66
+ /* timer variables */
67
+ unsigned long currentMillis; // store the current value from millis()
68
+ unsigned long previousMillis; // for comparison with currentMillis
69
+ int samplingInterval = 19; // how often to run the main loop (in ms)
70
+
71
+ /* i2c data */
72
+ struct i2c_device_info {
73
+ byte addr;
74
+ byte reg;
75
+ byte bytes;
76
+ };
77
+
78
+ /* for i2c read continuous more */
79
+ i2c_device_info query[MAX_QUERIES];
80
+
81
+ byte i2cRxData[32];
82
+ boolean isI2CEnabled = false;
83
+ signed char queryIndex = -1;
84
+ unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom()
85
+
86
+ Servo servos[MAX_SERVOS];
87
+ /*==============================================================================
88
+ * FUNCTIONS
89
+ *============================================================================*/
90
+
91
+ void readAndReportData(byte address, int theRegister, byte numBytes) {
92
+ // allow I2C requests that don't require a register read
93
+ // for example, some devices using an interrupt pin to signify new data available
94
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
95
+ if (theRegister != REGISTER_NOT_SPECIFIED) {
96
+ Wire.beginTransmission(address);
97
+ #if ARDUINO >= 100
98
+ Wire.write((byte)theRegister);
99
+ #else
100
+ Wire.send((byte)theRegister);
101
+ #endif
102
+ Wire.endTransmission();
103
+ delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck
104
+ } else {
105
+ theRegister = 0; // fill the register with a dummy value
106
+ }
107
+
108
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
109
+
110
+ // check to be sure correct number of bytes were returned by slave
111
+ if(numBytes == Wire.available()) {
112
+ i2cRxData[0] = address;
113
+ i2cRxData[1] = theRegister;
114
+ for (int i = 0; i < numBytes; i++) {
115
+ #if ARDUINO >= 100
116
+ i2cRxData[2 + i] = Wire.read();
117
+ #else
118
+ i2cRxData[2 + i] = Wire.receive();
119
+ #endif
120
+ }
121
+ }
122
+ else {
123
+ if(numBytes > Wire.available()) {
124
+ Firmata.sendString("I2C Read Error: Too many bytes received");
125
+ } else {
126
+ Firmata.sendString("I2C Read Error: Too few bytes received");
127
+ }
128
+ }
129
+
130
+ // send slave address, register and received bytes
131
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
132
+ }
133
+
134
+ void outputPort(byte portNumber, byte portValue, byte forceSend)
135
+ {
136
+ // pins not configured as INPUT are cleared to zeros
137
+ portValue = portValue & portConfigInputs[portNumber];
138
+ // only send if the value is different than previously sent
139
+ if(forceSend || previousPINs[portNumber] != portValue) {
140
+ Firmata.sendDigitalPort(portNumber, portValue);
141
+ previousPINs[portNumber] = portValue;
142
+ }
143
+ }
144
+
145
+ /* -----------------------------------------------------------------------------
146
+ * check all the active digital inputs for change of state, then add any events
147
+ * to the Serial output queue using Serial.print() */
148
+ void checkDigitalInputs(void)
149
+ {
150
+ /* Using non-looping code allows constants to be given to readPort().
151
+ * The compiler will apply substantial optimizations if the inputs
152
+ * to readPort() are compile-time constants. */
153
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
154
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
155
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
156
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
157
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
158
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
159
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
160
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
161
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
162
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
163
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
164
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
165
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
166
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
167
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
168
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
169
+ }
170
+
171
+ // -----------------------------------------------------------------------------
172
+ /* sets the pin mode to the correct state and sets the relevant bits in the
173
+ * two bit-arrays that track Digital I/O and PWM status
174
+ */
175
+ void setPinModeCallback(byte pin, int mode)
176
+ {
177
+ if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) {
178
+ // disable i2c so pins can be used for other functions
179
+ // the following if statements should reconfigure the pins properly
180
+ disableI2CPins();
181
+ }
182
+ if (IS_PIN_SERVO(pin) && mode != SERVO && servos[PIN_TO_SERVO(pin)].attached()) {
183
+ servos[PIN_TO_SERVO(pin)].detach();
184
+ }
185
+ if (IS_PIN_ANALOG(pin)) {
186
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == ANALOG ? 1 : 0); // turn on/off reporting
187
+ }
188
+ if (IS_PIN_DIGITAL(pin)) {
189
+ if (mode == INPUT) {
190
+ portConfigInputs[pin/8] |= (1 << (pin & 7));
191
+ } else {
192
+ portConfigInputs[pin/8] &= ~(1 << (pin & 7));
193
+ }
194
+ }
195
+ pinState[pin] = 0;
196
+ switch(mode) {
197
+ case ANALOG:
198
+ if (IS_PIN_ANALOG(pin)) {
199
+ if (IS_PIN_DIGITAL(pin)) {
200
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
201
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
202
+ }
203
+ pinConfig[pin] = ANALOG;
204
+ }
205
+ break;
206
+ case INPUT:
207
+ if (IS_PIN_DIGITAL(pin)) {
208
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
209
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
210
+ pinConfig[pin] = INPUT;
211
+ }
212
+ break;
213
+ case OUTPUT:
214
+ if (IS_PIN_DIGITAL(pin)) {
215
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
216
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
217
+ pinConfig[pin] = OUTPUT;
218
+ }
219
+ break;
220
+ case PWM:
221
+ if (IS_PIN_PWM(pin)) {
222
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
223
+ analogWrite(PIN_TO_PWM(pin), 0);
224
+ pinConfig[pin] = PWM;
225
+ }
226
+ break;
227
+ case SERVO:
228
+ if (IS_PIN_SERVO(pin)) {
229
+ pinConfig[pin] = SERVO;
230
+ if (!servos[PIN_TO_SERVO(pin)].attached()) {
231
+ servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin));
232
+ }
233
+ }
234
+ break;
235
+ case I2C:
236
+ if (IS_PIN_I2C(pin)) {
237
+ // mark the pin as i2c
238
+ // the user must call I2C_CONFIG to enable I2C for a device
239
+ pinConfig[pin] = I2C;
240
+ }
241
+ break;
242
+ default:
243
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
244
+ }
245
+ // TODO: save status to EEPROM here, if changed
246
+ }
247
+
248
+ void analogWriteCallback(byte pin, int value)
249
+ {
250
+ if (pin < TOTAL_PINS) {
251
+ switch(pinConfig[pin]) {
252
+ case SERVO:
253
+ if (IS_PIN_SERVO(pin))
254
+ servos[PIN_TO_SERVO(pin)].write(value);
255
+ pinState[pin] = value;
256
+ break;
257
+ case PWM:
258
+ if (IS_PIN_PWM(pin))
259
+ analogWrite(PIN_TO_PWM(pin), value);
260
+ pinState[pin] = value;
261
+ break;
262
+ }
263
+ }
264
+ }
265
+
266
+ void digitalWriteCallback(byte port, int value)
267
+ {
268
+ byte pin, lastPin, mask=1, pinWriteMask=0;
269
+
270
+ if (port < TOTAL_PORTS) {
271
+ // create a mask of the pins on this port that are writable.
272
+ lastPin = port*8+8;
273
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
274
+ for (pin=port*8; pin < lastPin; pin++) {
275
+ // do not disturb non-digital pins (eg, Rx & Tx)
276
+ if (IS_PIN_DIGITAL(pin)) {
277
+ // only write to OUTPUT and INPUT (enables pullup)
278
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
279
+ if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
280
+ pinWriteMask |= mask;
281
+ pinState[pin] = ((byte)value & mask) ? 1 : 0;
282
+ }
283
+ }
284
+ mask = mask << 1;
285
+ }
286
+ writePort(port, (byte)value, pinWriteMask);
287
+ }
288
+ }
289
+
290
+
291
+ // -----------------------------------------------------------------------------
292
+ /* sets bits in a bit array (int) to toggle the reporting of the analogIns
293
+ */
294
+ //void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
295
+ //}
296
+ void reportAnalogCallback(byte analogPin, int value)
297
+ {
298
+ if (analogPin < TOTAL_ANALOG_PINS) {
299
+ if(value == 0) {
300
+ analogInputsToReport = analogInputsToReport &~ (1 << analogPin);
301
+ } else {
302
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
303
+ }
304
+ }
305
+ // TODO: save status to EEPROM here, if changed
306
+ }
307
+
308
+ void reportDigitalCallback(byte port, int value)
309
+ {
310
+ if (port < TOTAL_PORTS) {
311
+ reportPINs[port] = (byte)value;
312
+ }
313
+ // do not disable analog reporting on these 8 pins, to allow some
314
+ // pins used for digital, others analog. Instead, allow both types
315
+ // of reporting to be enabled, but check if the pin is configured
316
+ // as analog when sampling the analog inputs. Likewise, while
317
+ // scanning digital pins, portConfigInputs will mask off values from any
318
+ // pins configured as analog
319
+ }
320
+
321
+ /*==============================================================================
322
+ * SYSEX-BASED commands
323
+ *============================================================================*/
324
+
325
+ void sysexCallback(byte command, byte argc, byte *argv)
326
+ {
327
+ byte mode;
328
+ byte slaveAddress;
329
+ byte slaveRegister;
330
+ byte data;
331
+ unsigned int delayTime;
332
+
333
+ switch(command) {
334
+ case 0x01: // LED Blink Command
335
+ if(argc < 3) break;
336
+ byte blink_pin;
337
+ byte blink_count;
338
+ blink_pin = argv[0];
339
+ blink_count = argv[1];
340
+ delayTime = argv[2] * 100;
341
+
342
+ pinMode(blink_pin, OUTPUT);
343
+ byte i;
344
+ for(i = 0; i < blink_count; i++){
345
+ digitalWrite(blink_pin, true);
346
+ delay(delayTime);
347
+ digitalWrite(blink_pin, false);
348
+ delay(delayTime);
349
+ }
350
+ Firmata.sendSysex(command, argc, argv); // callback
351
+ break;
352
+ case I2C_REQUEST:
353
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
354
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
355
+ Firmata.sendString("10-bit addressing mode is not yet supported");
356
+ return;
357
+ }
358
+ else {
359
+ slaveAddress = argv[0];
360
+ }
361
+
362
+ switch(mode) {
363
+ case I2C_WRITE:
364
+ Wire.beginTransmission(slaveAddress);
365
+ for (byte i = 2; i < argc; i += 2) {
366
+ data = argv[i] + (argv[i + 1] << 7);
367
+ #if ARDUINO >= 100
368
+ Wire.write(data);
369
+ #else
370
+ Wire.send(data);
371
+ #endif
372
+ }
373
+ Wire.endTransmission();
374
+ delayMicroseconds(70);
375
+ break;
376
+ case I2C_READ:
377
+ if (argc == 6) {
378
+ // a slave register is specified
379
+ slaveRegister = argv[2] + (argv[3] << 7);
380
+ data = argv[4] + (argv[5] << 7); // bytes to read
381
+ readAndReportData(slaveAddress, (int)slaveRegister, data);
382
+ }
383
+ else {
384
+ // a slave register is NOT specified
385
+ data = argv[2] + (argv[3] << 7); // bytes to read
386
+ readAndReportData(slaveAddress, (int)REGISTER_NOT_SPECIFIED, data);
387
+ }
388
+ break;
389
+ case I2C_READ_CONTINUOUSLY:
390
+ if ((queryIndex + 1) >= MAX_QUERIES) {
391
+ // too many queries, just ignore
392
+ Firmata.sendString("too many queries");
393
+ break;
394
+ }
395
+ queryIndex++;
396
+ query[queryIndex].addr = slaveAddress;
397
+ query[queryIndex].reg = argv[2] + (argv[3] << 7);
398
+ query[queryIndex].bytes = argv[4] + (argv[5] << 7);
399
+ break;
400
+ case I2C_STOP_READING:
401
+ byte queryIndexToSkip;
402
+ // if read continuous mode is enabled for only 1 i2c device, disable
403
+ // read continuous reporting for that device
404
+ if (queryIndex <= 0) {
405
+ queryIndex = -1;
406
+ } else {
407
+ // if read continuous mode is enabled for multiple devices,
408
+ // determine which device to stop reading and remove it's data from
409
+ // the array, shifiting other array data to fill the space
410
+ for (byte i = 0; i < queryIndex + 1; i++) {
411
+ if (query[i].addr = slaveAddress) {
412
+ queryIndexToSkip = i;
413
+ break;
414
+ }
415
+ }
416
+
417
+ for (byte i = queryIndexToSkip; i<queryIndex + 1; i++) {
418
+ if (i < MAX_QUERIES) {
419
+ query[i].addr = query[i+1].addr;
420
+ query[i].reg = query[i+1].addr;
421
+ query[i].bytes = query[i+1].bytes;
422
+ }
423
+ }
424
+ queryIndex--;
425
+ }
426
+ break;
427
+ default:
428
+ break;
429
+ }
430
+ break;
431
+ case I2C_CONFIG:
432
+ delayTime = (argv[0] + (argv[1] << 7));
433
+
434
+ if(delayTime > 0) {
435
+ i2cReadDelayTime = delayTime;
436
+ }
437
+
438
+ if (!isI2CEnabled) {
439
+ enableI2CPins();
440
+ }
441
+
442
+ break;
443
+ case SERVO_CONFIG:
444
+ if(argc > 4) {
445
+ // these vars are here for clarity, they'll optimized away by the compiler
446
+ byte pin = argv[0];
447
+ int minPulse = argv[1] + (argv[2] << 7);
448
+ int maxPulse = argv[3] + (argv[4] << 7);
449
+
450
+ if (IS_PIN_SERVO(pin)) {
451
+ if (servos[PIN_TO_SERVO(pin)].attached())
452
+ servos[PIN_TO_SERVO(pin)].detach();
453
+ servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
454
+ setPinModeCallback(pin, SERVO);
455
+ }
456
+ }
457
+ break;
458
+ case SAMPLING_INTERVAL:
459
+ if (argc > 1) {
460
+ samplingInterval = argv[0] + (argv[1] << 7);
461
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
462
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
463
+ }
464
+ } else {
465
+ //Firmata.sendString("Not enough data");
466
+ }
467
+ break;
468
+ case EXTENDED_ANALOG:
469
+ if (argc > 1) {
470
+ int val = argv[1];
471
+ if (argc > 2) val |= (argv[2] << 7);
472
+ if (argc > 3) val |= (argv[3] << 14);
473
+ analogWriteCallback(argv[0], val);
474
+ }
475
+ break;
476
+ case CAPABILITY_QUERY:
477
+ Serial.write(START_SYSEX);
478
+ Serial.write(CAPABILITY_RESPONSE);
479
+ for (byte pin=0; pin < TOTAL_PINS; pin++) {
480
+ if (IS_PIN_DIGITAL(pin)) {
481
+ Serial.write((byte)INPUT);
482
+ Serial.write(1);
483
+ Serial.write((byte)OUTPUT);
484
+ Serial.write(1);
485
+ }
486
+ if (IS_PIN_ANALOG(pin)) {
487
+ Serial.write(ANALOG);
488
+ Serial.write(10);
489
+ }
490
+ if (IS_PIN_PWM(pin)) {
491
+ Serial.write(PWM);
492
+ Serial.write(8);
493
+ }
494
+ if (IS_PIN_SERVO(pin)) {
495
+ Serial.write(SERVO);
496
+ Serial.write(14);
497
+ }
498
+ if (IS_PIN_I2C(pin)) {
499
+ Serial.write(I2C);
500
+ Serial.write(1); // to do: determine appropriate value
501
+ }
502
+ Serial.write(127);
503
+ }
504
+ Serial.write(END_SYSEX);
505
+ break;
506
+ case PIN_STATE_QUERY:
507
+ if (argc > 0) {
508
+ byte pin=argv[0];
509
+ Serial.write(START_SYSEX);
510
+ Serial.write(PIN_STATE_RESPONSE);
511
+ Serial.write(pin);
512
+ if (pin < TOTAL_PINS) {
513
+ Serial.write((byte)pinConfig[pin]);
514
+ Serial.write((byte)pinState[pin] & 0x7F);
515
+ if (pinState[pin] & 0xFF80) Serial.write((byte)(pinState[pin] >> 7) & 0x7F);
516
+ if (pinState[pin] & 0xC000) Serial.write((byte)(pinState[pin] >> 14) & 0x7F);
517
+ }
518
+ Serial.write(END_SYSEX);
519
+ }
520
+ break;
521
+ case ANALOG_MAPPING_QUERY:
522
+ Serial.write(START_SYSEX);
523
+ Serial.write(ANALOG_MAPPING_RESPONSE);
524
+ for (byte pin=0; pin < TOTAL_PINS; pin++) {
525
+ Serial.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
526
+ }
527
+ Serial.write(END_SYSEX);
528
+ break;
529
+ }
530
+ }
531
+
532
+ void enableI2CPins()
533
+ {
534
+ byte i;
535
+ // is there a faster way to do this? would probaby require importing
536
+ // Arduino.h to get SCL and SDA pins
537
+ for (i=0; i < TOTAL_PINS; i++) {
538
+ if(IS_PIN_I2C(i)) {
539
+ // mark pins as i2c so they are ignore in non i2c data requests
540
+ setPinModeCallback(i, I2C);
541
+ }
542
+ }
543
+
544
+ isI2CEnabled = true;
545
+
546
+ // is there enough time before the first I2C request to call this here?
547
+ Wire.begin();
548
+ }
549
+
550
+ /* disable the i2c pins so they can be used for other functions */
551
+ void disableI2CPins() {
552
+ isI2CEnabled = false;
553
+ // disable read continuous mode for all devices
554
+ queryIndex = -1;
555
+ // uncomment the following if or when the end() method is added to Wire library
556
+ // Wire.end();
557
+ }
558
+
559
+ /*==============================================================================
560
+ * SETUP()
561
+ *============================================================================*/
562
+
563
+ void systemResetCallback()
564
+ {
565
+ // initialize a defalt state
566
+ // TODO: option to load config from EEPROM instead of default
567
+ if (isI2CEnabled) {
568
+ disableI2CPins();
569
+ }
570
+ for (byte i=0; i < TOTAL_PORTS; i++) {
571
+ reportPINs[i] = false; // by default, reporting off
572
+ portConfigInputs[i] = 0; // until activated
573
+ previousPINs[i] = 0;
574
+ }
575
+ // pins with analog capability default to analog input
576
+ // otherwise, pins default to digital output
577
+ for (byte i=0; i < TOTAL_PINS; i++) {
578
+ if (IS_PIN_ANALOG(i)) {
579
+ // turns off pullup, configures everything
580
+ setPinModeCallback(i, ANALOG);
581
+ } else {
582
+ // sets the output to 0, configures portConfigInputs
583
+ setPinModeCallback(i, OUTPUT);
584
+ }
585
+ }
586
+ // by default, do not report any analog inputs
587
+ analogInputsToReport = 0;
588
+
589
+ /* send digital inputs to set the initial state on the host computer,
590
+ * since once in the loop(), this firmware will only send on change */
591
+ /*
592
+ TODO: this can never execute, since no pins default to digital input
593
+ but it will be needed when/if we support EEPROM stored config
594
+ for (byte i=0; i < TOTAL_PORTS; i++) {
595
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
596
+ }
597
+ */
598
+ }
599
+
600
+ void setup()
601
+ {
602
+ Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);
603
+
604
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
605
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
606
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
607
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
608
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
609
+ Firmata.attach(START_SYSEX, sysexCallback);
610
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
611
+
612
+ Firmata.begin(57600);
613
+ systemResetCallback(); // reset to default config
614
+ }
615
+
616
+ /*==============================================================================
617
+ * LOOP()
618
+ *============================================================================*/
619
+ void loop()
620
+ {
621
+ byte pin, analogPin;
622
+
623
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
624
+ * FTDI buffer using Serial.print() */
625
+ checkDigitalInputs();
626
+
627
+ /* SERIALREAD - processing incoming messagse as soon as possible, while still
628
+ * checking digital inputs. */
629
+ while(Firmata.available())
630
+ Firmata.processInput();
631
+
632
+ /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
633
+ * 60 bytes. use a timer to sending an event character every 4 ms to
634
+ * trigger the buffer to dump. */
635
+
636
+ currentMillis = millis();
637
+ if (currentMillis - previousMillis > samplingInterval) {
638
+ previousMillis += samplingInterval;
639
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
640
+ for(pin=0; pin<TOTAL_PINS; pin++) {
641
+ if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) {
642
+ analogPin = PIN_TO_ANALOG(pin);
643
+ if (analogInputsToReport & (1 << analogPin)) {
644
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
645
+ }
646
+ }
647
+ }
648
+ // report i2c data for all device with read continuous mode enabled
649
+ if (queryIndex > -1) {
650
+ for (byte i = 0; i < queryIndex + 1; i++) {
651
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes);
652
+ }
653
+ }
654
+ }
655
+ }