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