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