source: rtos_arduino/trunk/arduino_lib/libraries/Firmata/examples/StandardFirmata/StandardFirmata.ino@ 224

Last change on this file since 224 was 224, checked in by ertl-honda, 8 years ago

1.7.10のファイルに更新

File size: 27.2 KB
Line 
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 list of Firmata client libraries your default browser.
8
9 https://github.com/firmata/arduino#firmata-client-libraries
10
11 Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
12 Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
13 Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
14 Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
15
16 This library is free software; you can redistribute it and/or
17 modify it under the terms of the GNU Lesser General Public
18 License as published by the Free Software Foundation; either
19 version 2.1 of the License, or (at your option) any later version.
20
21 See file LICENSE.txt for further informations on licensing terms.
22
23 Last updated by Jeff Hoefs: January 10th, 2016
24*/
25
26#include <Servo.h>
27#include <Wire.h>
28#include <Firmata.h>
29
30#define I2C_WRITE B00000000
31#define I2C_READ B00001000
32#define I2C_READ_CONTINUOUSLY B00010000
33#define I2C_STOP_READING B00011000
34#define I2C_READ_WRITE_MODE_MASK B00011000
35#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
36#define I2C_END_TX_MASK B01000000
37#define I2C_STOP_TX 1
38#define I2C_RESTART_TX 0
39#define I2C_MAX_QUERIES 8
40#define I2C_REGISTER_NOT_SPECIFIED -1
41
42// the minimum interval for sampling analog input
43#define MINIMUM_SAMPLING_INTERVAL 1
44
45
46/*==============================================================================
47 * GLOBAL VARIABLES
48 *============================================================================*/
49
50#ifdef FIRMATA_SERIAL_FEATURE
51SerialFirmata serialFeature;
52#endif
53
54/* analog inputs */
55int analogInputsToReport = 0; // bitwise array to store pin reporting
56
57/* digital input ports */
58byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
59byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
60
61/* pins configuration */
62byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
63
64/* timer variables */
65unsigned long currentMillis; // store the current value from millis()
66unsigned long previousMillis; // for comparison with currentMillis
67unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
68
69/* i2c data */
70struct i2c_device_info {
71 byte addr;
72 int reg;
73 byte bytes;
74 byte stopTX;
75};
76
77/* for i2c read continuous more */
78i2c_device_info query[I2C_MAX_QUERIES];
79
80byte i2cRxData[64];
81boolean isI2CEnabled = false;
82signed char queryIndex = -1;
83// default delay time between i2c read request and Wire.requestFrom()
84unsigned int i2cReadDelayTime = 0;
85
86Servo servos[MAX_SERVOS];
87byte servoPinMap[TOTAL_PINS];
88byte detachedServos[MAX_SERVOS];
89byte detachedServoCount = 0;
90byte servoCount = 0;
91
92boolean isResetting = false;
93
94
95/* utility functions */
96void wireWrite(byte data)
97{
98#if ARDUINO >= 100
99 Wire.write((byte)data);
100#else
101 Wire.send(data);
102#endif
103}
104
105byte wireRead(void)
106{
107#if ARDUINO >= 100
108 return Wire.read();
109#else
110 return Wire.receive();
111#endif
112}
113
114/*==============================================================================
115 * FUNCTIONS
116 *============================================================================*/
117
118void attachServo(byte pin, int minPulse, int maxPulse)
119{
120 if (servoCount < MAX_SERVOS) {
121 // reuse indexes of detached servos until all have been reallocated
122 if (detachedServoCount > 0) {
123 servoPinMap[pin] = detachedServos[detachedServoCount - 1];
124 if (detachedServoCount > 0) detachedServoCount--;
125 } else {
126 servoPinMap[pin] = servoCount;
127 servoCount++;
128 }
129 if (minPulse > 0 && maxPulse > 0) {
130 servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
131 } else {
132 servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
133 }
134 } else {
135 Firmata.sendString("Max servos attached");
136 }
137}
138
139void detachServo(byte pin)
140{
141 servos[servoPinMap[pin]].detach();
142 // if we're detaching the last servo, decrement the count
143 // otherwise store the index of the detached servo
144 if (servoPinMap[pin] == servoCount && servoCount > 0) {
145 servoCount--;
146 } else if (servoCount > 0) {
147 // keep track of detached servos because we want to reuse their indexes
148 // before incrementing the count of attached servos
149 detachedServoCount++;
150 detachedServos[detachedServoCount - 1] = servoPinMap[pin];
151 }
152
153 servoPinMap[pin] = 255;
154}
155
156void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
157 // allow I2C requests that don't require a register read
158 // for example, some devices using an interrupt pin to signify new data available
159 // do not always require the register read so upon interrupt you call Wire.requestFrom()
160 if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
161 Wire.beginTransmission(address);
162 wireWrite((byte)theRegister);
163 Wire.endTransmission(stopTX); // default = true
164 // do not set a value of 0
165 if (i2cReadDelayTime > 0) {
166 // delay is necessary for some devices such as WiiNunchuck
167 delayMicroseconds(i2cReadDelayTime);
168 }
169 } else {
170 theRegister = 0; // fill the register with a dummy value
171 }
172
173 Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
174
175 // check to be sure correct number of bytes were returned by slave
176 if (numBytes < Wire.available()) {
177 Firmata.sendString("I2C: Too many bytes received");
178 } else if (numBytes > Wire.available()) {
179 Firmata.sendString("I2C: Too few bytes received");
180 }
181
182 i2cRxData[0] = address;
183 i2cRxData[1] = theRegister;
184
185 for (int i = 0; i < numBytes && Wire.available(); i++) {
186 i2cRxData[2 + i] = wireRead();
187 }
188
189 // send slave address, register and received bytes
190 Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
191}
192
193void outputPort(byte portNumber, byte portValue, byte forceSend)
194{
195 // pins not configured as INPUT are cleared to zeros
196 portValue = portValue & portConfigInputs[portNumber];
197 // only send if the value is different than previously sent
198 if (forceSend || previousPINs[portNumber] != portValue) {
199 Firmata.sendDigitalPort(portNumber, portValue);
200 previousPINs[portNumber] = portValue;
201 }
202}
203
204/* -----------------------------------------------------------------------------
205 * check all the active digital inputs for change of state, then add any events
206 * to the Serial output queue using Serial.print() */
207void checkDigitalInputs(void)
208{
209 /* Using non-looping code allows constants to be given to readPort().
210 * The compiler will apply substantial optimizations if the inputs
211 * to readPort() are compile-time constants. */
212 if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
213 if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
214 if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
215 if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
216 if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
217 if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
218 if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
219 if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
220 if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
221 if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
222 if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
223 if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
224 if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
225 if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
226 if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
227 if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
228}
229
230// -----------------------------------------------------------------------------
231
232/* disable the i2c pins so they can be used for other functions */
233void disableI2CPins() {
234 isI2CEnabled = false;
235 // disable read continuous mode for all devices
236 queryIndex = -1;
237}
238
239/* sets bits in a bit array (int) to toggle the reporting of the analogIns
240 */
241//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
242//}
243void reportAnalogCallback(byte analogPin, int value)
244{
245 if (analogPin < TOTAL_ANALOG_PINS) {
246 if (value == 0) {
247 analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
248 } else {
249 analogInputsToReport = analogInputsToReport | (1 << analogPin);
250 // prevent during system reset or all analog pin values will be reported
251 // which may report noise for unconnected analog pins
252 if (!isResetting) {
253 // Send pin value immediately. This is helpful when connected via
254 // ethernet, wi-fi or bluetooth so pin states can be known upon
255 // reconnecting.
256 Firmata.sendAnalog(analogPin, analogRead(analogPin));
257 }
258 }
259 }
260 // TODO: save status to EEPROM here, if changed
261}
262
263// -----------------------------------------------------------------------------
264/* sets the pin mode to the correct state and sets the relevant bits in the
265 * two bit-arrays that track Digital I/O and PWM status
266 */
267void setPinModeCallback(byte pin, int mode)
268{
269 if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
270 return;
271
272 if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
273 // disable i2c so pins can be used for other functions
274 // the following if statements should reconfigure the pins properly
275 disableI2CPins();
276 }
277 if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
278 if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
279 detachServo(pin);
280 }
281 }
282 if (IS_PIN_ANALOG(pin)) {
283 reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
284 }
285 if (IS_PIN_DIGITAL(pin)) {
286 if (mode == INPUT || mode == PIN_MODE_PULLUP) {
287 portConfigInputs[pin / 8] |= (1 << (pin & 7));
288 } else {
289 portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
290 }
291 }
292 Firmata.setPinState(pin, 0);
293 switch (mode) {
294 case PIN_MODE_ANALOG:
295 if (IS_PIN_ANALOG(pin)) {
296 if (IS_PIN_DIGITAL(pin)) {
297 pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
298#if ARDUINO <= 100
299 // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
300 digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
301#endif
302 }
303 Firmata.setPinMode(pin, PIN_MODE_ANALOG);
304 }
305 break;
306 case INPUT:
307 if (IS_PIN_DIGITAL(pin)) {
308 pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
309#if ARDUINO <= 100
310 // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
311 digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
312#endif
313 Firmata.setPinMode(pin, INPUT);
314 }
315 break;
316 case PIN_MODE_PULLUP:
317 if (IS_PIN_DIGITAL(pin)) {
318 pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
319 Firmata.setPinMode(pin, PIN_MODE_PULLUP);
320 Firmata.setPinState(pin, 1);
321 }
322 break;
323 case OUTPUT:
324 if (IS_PIN_DIGITAL(pin)) {
325 digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
326 pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
327 Firmata.setPinMode(pin, OUTPUT);
328 }
329 break;
330 case PIN_MODE_PWM:
331 if (IS_PIN_PWM(pin)) {
332 pinMode(PIN_TO_PWM(pin), OUTPUT);
333 analogWrite(PIN_TO_PWM(pin), 0);
334 Firmata.setPinMode(pin, PIN_MODE_PWM);
335 }
336 break;
337 case PIN_MODE_SERVO:
338 if (IS_PIN_DIGITAL(pin)) {
339 Firmata.setPinMode(pin, PIN_MODE_SERVO);
340 if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
341 // pass -1 for min and max pulse values to use default values set
342 // by Servo library
343 attachServo(pin, -1, -1);
344 }
345 }
346 break;
347 case PIN_MODE_I2C:
348 if (IS_PIN_I2C(pin)) {
349 // mark the pin as i2c
350 // the user must call I2C_CONFIG to enable I2C for a device
351 Firmata.setPinMode(pin, PIN_MODE_I2C);
352 }
353 break;
354 case PIN_MODE_SERIAL:
355#ifdef FIRMATA_SERIAL_FEATURE
356 serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
357#endif
358 break;
359 default:
360 Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
361 }
362 // TODO: save status to EEPROM here, if changed
363}
364
365/*
366 * Sets the value of an individual pin. Useful if you want to set a pin value but
367 * are not tracking the digital port state.
368 * Can only be used on pins configured as OUTPUT.
369 * Cannot be used to enable pull-ups on Digital INPUT pins.
370 */
371void setPinValueCallback(byte pin, int value)
372{
373 if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
374 if (Firmata.getPinMode(pin) == OUTPUT) {
375 Firmata.setPinState(pin, value);
376 digitalWrite(PIN_TO_DIGITAL(pin), value);
377 }
378 }
379}
380
381void analogWriteCallback(byte pin, int value)
382{
383 if (pin < TOTAL_PINS) {
384 switch (Firmata.getPinMode(pin)) {
385 case PIN_MODE_SERVO:
386 if (IS_PIN_DIGITAL(pin))
387 servos[servoPinMap[pin]].write(value);
388 Firmata.setPinState(pin, value);
389 break;
390 case PIN_MODE_PWM:
391 if (IS_PIN_PWM(pin))
392 analogWrite(PIN_TO_PWM(pin), value);
393 Firmata.setPinState(pin, value);
394 break;
395 }
396 }
397}
398
399void digitalWriteCallback(byte port, int value)
400{
401 byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
402
403 if (port < TOTAL_PORTS) {
404 // create a mask of the pins on this port that are writable.
405 lastPin = port * 8 + 8;
406 if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
407 for (pin = port * 8; pin < lastPin; pin++) {
408 // do not disturb non-digital pins (eg, Rx & Tx)
409 if (IS_PIN_DIGITAL(pin)) {
410 // do not touch pins in PWM, ANALOG, SERVO or other modes
411 if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
412 pinValue = ((byte)value & mask) ? 1 : 0;
413 if (Firmata.getPinMode(pin) == OUTPUT) {
414 pinWriteMask |= mask;
415 } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
416 // only handle INPUT here for backwards compatibility
417#if ARDUINO > 100
418 pinMode(pin, INPUT_PULLUP);
419#else
420 // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
421 pinWriteMask |= mask;
422#endif
423 }
424 Firmata.setPinState(pin, pinValue);
425 }
426 }
427 mask = mask << 1;
428 }
429 writePort(port, (byte)value, pinWriteMask);
430 }
431}
432
433
434// -----------------------------------------------------------------------------
435
436void reportDigitalCallback(byte port, int value)
437{
438 if (port < TOTAL_PORTS) {
439 reportPINs[port] = (byte)value;
440 // Send port value immediately. This is helpful when connected via
441 // ethernet, wi-fi or bluetooth so pin states can be known upon
442 // reconnecting.
443 if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
444 }
445 // do not disable analog reporting on these 8 pins, to allow some
446 // pins used for digital, others analog. Instead, allow both types
447 // of reporting to be enabled, but check if the pin is configured
448 // as analog when sampling the analog inputs. Likewise, while
449 // scanning digital pins, portConfigInputs will mask off values from any
450 // pins configured as analog
451}
452
453// -----------------------------------------------------------------------------
454
455void enableI2CPins()
456{
457 byte i;
458 // is there a faster way to do this? would probaby require importing
459 // Arduino.h to get SCL and SDA pins
460 for (i = 0; i < TOTAL_PINS; i++) {
461 if (IS_PIN_I2C(i)) {
462 // mark pins as i2c so they are ignore in non i2c data requests
463 setPinModeCallback(i, PIN_MODE_I2C);
464 }
465 }
466
467 isI2CEnabled = true;
468
469 Wire.begin();
470}
471
472/*==============================================================================
473 * SYSEX-BASED commands
474 *============================================================================*/
475
476void sysexCallback(byte command, byte argc, byte *argv)
477{
478 byte mode;
479 byte stopTX;
480 byte slaveAddress;
481 byte data;
482 int slaveRegister;
483 unsigned int delayTime;
484
485 switch (command) {
486 case I2C_REQUEST:
487 mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
488 if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
489 Firmata.sendString("10-bit addressing not supported");
490 return;
491 }
492 else {
493 slaveAddress = argv[0];
494 }
495
496 // need to invert the logic here since 0 will be default for client
497 // libraries that have not updated to add support for restart tx
498 if (argv[1] & I2C_END_TX_MASK) {
499 stopTX = I2C_RESTART_TX;
500 }
501 else {
502 stopTX = I2C_STOP_TX; // default
503 }
504
505 switch (mode) {
506 case I2C_WRITE:
507 Wire.beginTransmission(slaveAddress);
508 for (byte i = 2; i < argc; i += 2) {
509 data = argv[i] + (argv[i + 1] << 7);
510 wireWrite(data);
511 }
512 Wire.endTransmission();
513 delayMicroseconds(70);
514 break;
515 case I2C_READ:
516 if (argc == 6) {
517 // a slave register is specified
518 slaveRegister = argv[2] + (argv[3] << 7);
519 data = argv[4] + (argv[5] << 7); // bytes to read
520 }
521 else {
522 // a slave register is NOT specified
523 slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
524 data = argv[2] + (argv[3] << 7); // bytes to read
525 }
526 readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
527 break;
528 case I2C_READ_CONTINUOUSLY:
529 if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
530 // too many queries, just ignore
531 Firmata.sendString("too many queries");
532 break;
533 }
534 if (argc == 6) {
535 // a slave register is specified
536 slaveRegister = argv[2] + (argv[3] << 7);
537 data = argv[4] + (argv[5] << 7); // bytes to read
538 }
539 else {
540 // a slave register is NOT specified
541 slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
542 data = argv[2] + (argv[3] << 7); // bytes to read
543 }
544 queryIndex++;
545 query[queryIndex].addr = slaveAddress;
546 query[queryIndex].reg = slaveRegister;
547 query[queryIndex].bytes = data;
548 query[queryIndex].stopTX = stopTX;
549 break;
550 case I2C_STOP_READING:
551 byte queryIndexToSkip;
552 // if read continuous mode is enabled for only 1 i2c device, disable
553 // read continuous reporting for that device
554 if (queryIndex <= 0) {
555 queryIndex = -1;
556 } else {
557 queryIndexToSkip = 0;
558 // if read continuous mode is enabled for multiple devices,
559 // determine which device to stop reading and remove it's data from
560 // the array, shifiting other array data to fill the space
561 for (byte i = 0; i < queryIndex + 1; i++) {
562 if (query[i].addr == slaveAddress) {
563 queryIndexToSkip = i;
564 break;
565 }
566 }
567
568 for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
569 if (i < I2C_MAX_QUERIES) {
570 query[i].addr = query[i + 1].addr;
571 query[i].reg = query[i + 1].reg;
572 query[i].bytes = query[i + 1].bytes;
573 query[i].stopTX = query[i + 1].stopTX;
574 }
575 }
576 queryIndex--;
577 }
578 break;
579 default:
580 break;
581 }
582 break;
583 case I2C_CONFIG:
584 delayTime = (argv[0] + (argv[1] << 7));
585
586 if (delayTime > 0) {
587 i2cReadDelayTime = delayTime;
588 }
589
590 if (!isI2CEnabled) {
591 enableI2CPins();
592 }
593
594 break;
595 case SERVO_CONFIG:
596 if (argc > 4) {
597 // these vars are here for clarity, they'll optimized away by the compiler
598 byte pin = argv[0];
599 int minPulse = argv[1] + (argv[2] << 7);
600 int maxPulse = argv[3] + (argv[4] << 7);
601
602 if (IS_PIN_DIGITAL(pin)) {
603 if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
604 detachServo(pin);
605 }
606 attachServo(pin, minPulse, maxPulse);
607 setPinModeCallback(pin, PIN_MODE_SERVO);
608 }
609 }
610 break;
611 case SAMPLING_INTERVAL:
612 if (argc > 1) {
613 samplingInterval = argv[0] + (argv[1] << 7);
614 if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
615 samplingInterval = MINIMUM_SAMPLING_INTERVAL;
616 }
617 } else {
618 //Firmata.sendString("Not enough data");
619 }
620 break;
621 case EXTENDED_ANALOG:
622 if (argc > 1) {
623 int val = argv[1];
624 if (argc > 2) val |= (argv[2] << 7);
625 if (argc > 3) val |= (argv[3] << 14);
626 analogWriteCallback(argv[0], val);
627 }
628 break;
629 case CAPABILITY_QUERY:
630 Firmata.write(START_SYSEX);
631 Firmata.write(CAPABILITY_RESPONSE);
632 for (byte pin = 0; pin < TOTAL_PINS; pin++) {
633 if (IS_PIN_DIGITAL(pin)) {
634 Firmata.write((byte)INPUT);
635 Firmata.write(1);
636 Firmata.write((byte)PIN_MODE_PULLUP);
637 Firmata.write(1);
638 Firmata.write((byte)OUTPUT);
639 Firmata.write(1);
640 }
641 if (IS_PIN_ANALOG(pin)) {
642 Firmata.write(PIN_MODE_ANALOG);
643 Firmata.write(10); // 10 = 10-bit resolution
644 }
645 if (IS_PIN_PWM(pin)) {
646 Firmata.write(PIN_MODE_PWM);
647 Firmata.write(8); // 8 = 8-bit resolution
648 }
649 if (IS_PIN_DIGITAL(pin)) {
650 Firmata.write(PIN_MODE_SERVO);
651 Firmata.write(14);
652 }
653 if (IS_PIN_I2C(pin)) {
654 Firmata.write(PIN_MODE_I2C);
655 Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
656 }
657#ifdef FIRMATA_SERIAL_FEATURE
658 serialFeature.handleCapability(pin);
659#endif
660 Firmata.write(127);
661 }
662 Firmata.write(END_SYSEX);
663 break;
664 case PIN_STATE_QUERY:
665 if (argc > 0) {
666 byte pin = argv[0];
667 Firmata.write(START_SYSEX);
668 Firmata.write(PIN_STATE_RESPONSE);
669 Firmata.write(pin);
670 if (pin < TOTAL_PINS) {
671 Firmata.write(Firmata.getPinMode(pin));
672 Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
673 if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
674 if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
675 }
676 Firmata.write(END_SYSEX);
677 }
678 break;
679 case ANALOG_MAPPING_QUERY:
680 Firmata.write(START_SYSEX);
681 Firmata.write(ANALOG_MAPPING_RESPONSE);
682 for (byte pin = 0; pin < TOTAL_PINS; pin++) {
683 Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
684 }
685 Firmata.write(END_SYSEX);
686 break;
687
688 case SERIAL_MESSAGE:
689#ifdef FIRMATA_SERIAL_FEATURE
690 serialFeature.handleSysex(command, argc, argv);
691#endif
692 break;
693 }
694}
695
696
697/*==============================================================================
698 * SETUP()
699 *============================================================================*/
700
701void systemResetCallback()
702{
703 isResetting = true;
704
705 // initialize a defalt state
706 // TODO: option to load config from EEPROM instead of default
707
708#ifdef FIRMATA_SERIAL_FEATURE
709 serialFeature.reset();
710#endif
711
712 if (isI2CEnabled) {
713 disableI2CPins();
714 }
715
716 for (byte i = 0; i < TOTAL_PORTS; i++) {
717 reportPINs[i] = false; // by default, reporting off
718 portConfigInputs[i] = 0; // until activated
719 previousPINs[i] = 0;
720 }
721
722 for (byte i = 0; i < TOTAL_PINS; i++) {
723 // pins with analog capability default to analog input
724 // otherwise, pins default to digital output
725 if (IS_PIN_ANALOG(i)) {
726 // turns off pullup, configures everything
727 setPinModeCallback(i, PIN_MODE_ANALOG);
728 } else if (IS_PIN_DIGITAL(i)) {
729 // sets the output to 0, configures portConfigInputs
730 setPinModeCallback(i, OUTPUT);
731 }
732
733 servoPinMap[i] = 255;
734 }
735 // by default, do not report any analog inputs
736 analogInputsToReport = 0;
737
738 detachedServoCount = 0;
739 servoCount = 0;
740
741 /* send digital inputs to set the initial state on the host computer,
742 * since once in the loop(), this firmware will only send on change */
743 /*
744 TODO: this can never execute, since no pins default to digital input
745 but it will be needed when/if we support EEPROM stored config
746 for (byte i=0; i < TOTAL_PORTS; i++) {
747 outputPort(i, readPort(i, portConfigInputs[i]), true);
748 }
749 */
750 isResetting = false;
751}
752
753void setup()
754{
755 Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
756
757 Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
758 Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
759 Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
760 Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
761 Firmata.attach(SET_PIN_MODE, setPinModeCallback);
762 Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
763 Firmata.attach(START_SYSEX, sysexCallback);
764 Firmata.attach(SYSTEM_RESET, systemResetCallback);
765
766 // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
767 // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
768 // Serial1.begin(57600);
769 // Firmata.begin(Serial1);
770 // However do not do this if you are using SERIAL_MESSAGE
771
772 Firmata.begin(57600);
773 while (!Serial) {
774 ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
775 }
776
777 systemResetCallback(); // reset to default config
778}
779
780/*==============================================================================
781 * LOOP()
782 *============================================================================*/
783void loop()
784{
785 byte pin, analogPin;
786
787 /* DIGITALREAD - as fast as possible, check for changes and output them to the
788 * FTDI buffer using Serial.print() */
789 checkDigitalInputs();
790
791 /* STREAMREAD - processing incoming messagse as soon as possible, while still
792 * checking digital inputs. */
793 while (Firmata.available())
794 Firmata.processInput();
795
796 // TODO - ensure that Stream buffer doesn't go over 60 bytes
797
798 currentMillis = millis();
799 if (currentMillis - previousMillis > samplingInterval) {
800 previousMillis += samplingInterval;
801 /* ANALOGREAD - do all analogReads() at the configured sampling interval */
802 for (pin = 0; pin < TOTAL_PINS; pin++) {
803 if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
804 analogPin = PIN_TO_ANALOG(pin);
805 if (analogInputsToReport & (1 << analogPin)) {
806 Firmata.sendAnalog(analogPin, analogRead(analogPin));
807 }
808 }
809 }
810 // report i2c data for all device with read continuous mode enabled
811 if (queryIndex > -1) {
812 for (byte i = 0; i < queryIndex + 1; i++) {
813 readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
814 }
815 }
816 }
817
818#ifdef FIRMATA_SERIAL_FEATURE
819 serialFeature.update();
820#endif
821}
Note: See TracBrowser for help on using the repository browser.