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

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

1.7.10のファイルに更新

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