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

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

1.7.10のファイルに更新

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