diff --git a/Firmata.cpp b/Firmata.cpp index 7ecead8c..2737e523 100644 --- a/Firmata.cpp +++ b/Firmata.cpp @@ -1,5 +1,5 @@ /* - Firmata.cpp - Firmata library v2.4.3 - 2015-4-11 + Firmata.cpp - Firmata library v2.5.0.beta1 - 2015-5-17 Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved. This library is free software; you can redistribute it and/or @@ -238,6 +238,10 @@ void FirmataClass::processInput(void) if (currentPinModeCallback) (*currentPinModeCallback)(storedInputData[1], storedInputData[0]); break; + case SET_DIGITAL_PIN_VALUE: + if (currentPinValueCallback) + (*currentPinValueCallback)(storedInputData[1], storedInputData[0]); + break; case REPORT_ANALOG: if (currentReportAnalogCallback) (*currentReportAnalogCallback)(multiByteChannel, storedInputData[0]); @@ -262,6 +266,7 @@ void FirmataClass::processInput(void) case ANALOG_MESSAGE: case DIGITAL_MESSAGE: case SET_PIN_MODE: + case SET_DIGITAL_PIN_VALUE: waitForData = 2; // two data bytes needed executeMultiByteCommand = command; break; @@ -369,6 +374,7 @@ void FirmataClass::attach(byte command, callbackFunction newFunction) case REPORT_ANALOG: currentReportAnalogCallback = newFunction; break; case REPORT_DIGITAL: currentReportDigitalCallback = newFunction; break; case SET_PIN_MODE: currentPinModeCallback = newFunction; break; + case SET_DIGITAL_PIN_VALUE: currentPinValueCallback = newFunction; break; } } diff --git a/Firmata.h b/Firmata.h index bda1364e..ab2ef271 100644 --- a/Firmata.h +++ b/Firmata.h @@ -1,5 +1,5 @@ /* - Firmata.h - Firmata library v2.4.3 - 2015-4-11 + Firmata.h - Firmata library v2.5.0.beta1 - 2015-5-17 Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved. This library is free software; you can redistribute it and/or @@ -20,19 +20,21 @@ * software can test whether it will be compatible with the currently * installed firmware. */ #define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes -#define FIRMATA_MINOR_VERSION 4 // for backwards compatible changes -#define FIRMATA_BUGFIX_VERSION 3 // for bugfix releases +#define FIRMATA_MINOR_VERSION 5 // for backwards compatible changes +#define FIRMATA_BUGFIX_VERSION 0 // for bugfix releases #define MAX_DATA_BYTES 64 // max number of data bytes in incoming messages // message command bytes (128-255/0x80-0xFF) -#define DIGITAL_MESSAGE 0x90 // send data for a digital pin +#define DIGITAL_MESSAGE 0x90 // send data for a digital port (collection of 8 pins) #define ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM) #define REPORT_ANALOG 0xC0 // enable analog input by pin # #define REPORT_DIGITAL 0xD0 // enable digital input by port pair // #define SET_PIN_MODE 0xF4 // set a pin to INPUT/OUTPUT/PWM/etc // +#define SET_DIGITAL_PIN_VALUE 0xF5 // set value of an individual digital pin +// #define REPORT_VERSION 0xF9 // report protocol version #define SYSTEM_RESET 0xFF // reset from MIDI // @@ -69,8 +71,8 @@ #define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL // pin modes -//#define INPUT 0x00 // defined in wiring.h -//#define OUTPUT 0x01 // defined in wiring.h +//#define INPUT 0x00 // defined in Arduino.h +//#define OUTPUT 0x01 // defined in Arduino.h #define ANALOG 0x02 // analog pin in analogInput mode #define PWM 0x03 // digital pin in PWM output mode #define SERVO 0x04 // digital pin in Servo output mode @@ -148,6 +150,7 @@ class FirmataClass callbackFunction currentReportAnalogCallback; callbackFunction currentReportDigitalCallback; callbackFunction currentPinModeCallback; + callbackFunction currentPinValueCallback; systemResetCallbackFunction currentSystemResetCallback; stringCallbackFunction currentStringCallback; sysexCallbackFunction currentSysexCallback; diff --git a/examples/StandardFirmata/StandardFirmata.ino b/examples/StandardFirmata/StandardFirmata.ino index 9dfb8c4f..384935b7 100644 --- a/examples/StandardFirmata/StandardFirmata.ino +++ b/examples/StandardFirmata/StandardFirmata.ino @@ -20,7 +20,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated by Jeff Hoefs: April 11, 2015 + Last updated by Jeff Hoefs: May 17, 2015 */ #include @@ -33,8 +33,8 @@ #define I2C_STOP_READING B00011000 #define I2C_READ_WRITE_MODE_MASK B00011000 #define I2C_10BIT_ADDRESS_MODE_MASK B00100000 -#define MAX_QUERIES 8 -#define REGISTER_NOT_SPECIFIED -1 +#define I2C_MAX_QUERIES 8 +#define I2C_REGISTER_NOT_SPECIFIED -1 // the minimum interval for sampling analog input #define MINIMUM_SAMPLING_INTERVAL 10 @@ -69,7 +69,7 @@ struct i2c_device_info { }; /* for i2c read continuous more */ -i2c_device_info query[MAX_QUERIES]; +i2c_device_info query[I2C_MAX_QUERIES]; byte i2cRxData[32]; boolean isI2CEnabled = false; @@ -150,7 +150,7 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // allow I2C requests that don't require a register read // for example, some devices using an interrupt pin to signify new data available // do not always require the register read so upon interrupt you call Wire.requestFrom() - if (theRegister != REGISTER_NOT_SPECIFIED) { + if (theRegister != I2C_REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); wireWrite((byte)theRegister); Wire.endTransmission(); @@ -304,6 +304,20 @@ void setPinModeCallback(byte pin, int mode) // TODO: save status to EEPROM here, if changed } +/* + * Sets the value of an individual pin. + * Useful if you want to set a pin value but are not tracking the digital port state. + */ +void setPinValueCallback(byte pin, int value) +{ + if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) { + if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) { + pinState[pin] = value; + digitalWrite(PIN_TO_DIGITAL(pin), value); + } + } +} + void analogWriteCallback(byte pin, int value) { if (pin < TOTAL_PINS) { @@ -430,13 +444,13 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = REGISTER_NOT_SPECIFIED; + slaveRegister = I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } readAndReportData(slaveAddress, (int)slaveRegister, data); break; case I2C_READ_CONTINUOUSLY: - if ((queryIndex + 1) >= MAX_QUERIES) { + if ((queryIndex + 1) >= I2C_MAX_QUERIES) { // too many queries, just ignore Firmata.sendString("too many queries"); break; @@ -448,7 +462,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = (int)REGISTER_NOT_SPECIFIED; + slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } queryIndex++; @@ -474,7 +488,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) { - if (i < MAX_QUERIES) { + if (i < I2C_MAX_QUERIES) { query[i].addr = query[i + 1].addr; query[i].reg = query[i + 1].reg; query[i].bytes = query[i + 1].bytes; @@ -674,6 +688,7 @@ void setup() Firmata.attach(REPORT_ANALOG, reportAnalogCallback); Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); Firmata.attach(SET_PIN_MODE, setPinModeCallback); + Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback); Firmata.attach(START_SYSEX, sysexCallback); Firmata.attach(SYSTEM_RESET, systemResetCallback); diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index cc5fdb0f..d2a2aa1a 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -20,7 +20,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated by Jeff Hoefs: April 11, 2015 + Last updated by Jeff Hoefs: May 17, 2015 */ /* @@ -417,6 +417,20 @@ void setPinModeCallback(byte pin, int mode) // TODO: save status to EEPROM here, if changed } +/* + * Sets the value of an individual pin. + * Useful if you want to set a pin value but are not tracking the digital port state. + */ +void setPinValueCallback(byte pin, int value) +{ + if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) { + if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) { + pinState[pin] = value; + digitalWrite(PIN_TO_DIGITAL(pin), value); + } + } +} + void analogWriteCallback(byte pin, int value) { if (pin < TOTAL_PINS) { @@ -801,6 +815,7 @@ void setup() Firmata.attach(REPORT_ANALOG, reportAnalogCallback); Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); Firmata.attach(SET_PIN_MODE, setPinModeCallback); + Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback); Firmata.attach(START_SYSEX, sysexCallback); Firmata.attach(SYSTEM_RESET, systemResetCallback); diff --git a/examples/StandardFirmataYun/StandardFirmataYun.ino b/examples/StandardFirmataYun/StandardFirmataYun.ino index 9391fb93..274aea53 100644 --- a/examples/StandardFirmataYun/StandardFirmataYun.ino +++ b/examples/StandardFirmataYun/StandardFirmataYun.ino @@ -4,14 +4,14 @@ any host computer software package. To download a host software package, please clink on the following link - to open the download page in your default browser. + to open the list of Firmata client libraries your default browser. https://github.com/firmata/arduino#firmata-client-libraries Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. - Copyright (C) 2009-2014 Jeff Hoefs. All rights reserved. + Copyright (C) 2009-2015 Jeff Hoefs. All rights reserved. Copyright (C) 2014 Alan Yorinks. All rights reserved. This library is free software; you can redistribute it and/or @@ -21,7 +21,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated by Jeff Hoefs: April 11, 2015 + Last updated by Jeff Hoefs: May 17, 2015 */ /* @@ -45,8 +45,8 @@ #define I2C_STOP_READING B00011000 #define I2C_READ_WRITE_MODE_MASK B00011000 #define I2C_10BIT_ADDRESS_MODE_MASK B00100000 -#define MAX_QUERIES 8 -#define REGISTER_NOT_SPECIFIED -1 +#define I2C_MAX_QUERIES 8 +#define I2C_REGISTER_NOT_SPECIFIED -1 // the minimum interval for sampling analog input #define MINIMUM_SAMPLING_INTERVAL 10 @@ -81,7 +81,7 @@ struct i2c_device_info { }; /* for i2c read continuous more */ -i2c_device_info query[MAX_QUERIES]; +i2c_device_info query[I2C_MAX_QUERIES]; byte i2cRxData[32]; boolean isI2CEnabled = false; @@ -162,7 +162,7 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // allow I2C requests that don't require a register read // for example, some devices using an interrupt pin to signify new data available // do not always require the register read so upon interrupt you call Wire.requestFrom() - if (theRegister != REGISTER_NOT_SPECIFIED) { + if (theRegister != I2C_REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); wireWrite((byte)theRegister); Wire.endTransmission(); @@ -316,6 +316,20 @@ void setPinModeCallback(byte pin, int mode) // TODO: save status to EEPROM here, if changed } +/* + * Sets the value of an individual pin. + * Useful if you want to set a pin value but are not tracking the digital port state. + */ +void setPinValueCallback(byte pin, int value) +{ + if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) { + if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) { + pinState[pin] = value; + digitalWrite(PIN_TO_DIGITAL(pin), value); + } + } +} + void analogWriteCallback(byte pin, int value) { if (pin < TOTAL_PINS) { @@ -442,13 +456,13 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = REGISTER_NOT_SPECIFIED; + slaveRegister = I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } readAndReportData(slaveAddress, (int)slaveRegister, data); break; case I2C_READ_CONTINUOUSLY: - if ((queryIndex + 1) >= MAX_QUERIES) { + if ((queryIndex + 1) >= I2C_MAX_QUERIES) { // too many queries, just ignore Firmata.sendString("too many queries"); break; @@ -460,7 +474,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = (int)REGISTER_NOT_SPECIFIED; + slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } queryIndex++; @@ -486,7 +500,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) { - if (i < MAX_QUERIES) { + if (i < I2C_MAX_QUERIES) { query[i].addr = query[i + 1].addr; query[i].reg = query[i + 1].reg; query[i].bytes = query[i + 1].bytes; @@ -698,6 +712,7 @@ void setup() Firmata.attach(REPORT_ANALOG, reportAnalogCallback); Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); Firmata.attach(SET_PIN_MODE, setPinModeCallback); + Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback); Firmata.attach(START_SYSEX, sysexCallback); Firmata.attach(SYSTEM_RESET, systemResetCallback); diff --git a/extras/revisions.txt b/extras/revisions.txt index 9a933d24..3f320097 100644 --- a/extras/revisions.txt +++ b/extras/revisions.txt @@ -1,3 +1,11 @@ +FIRMATA 2.5.0.beta1 - May 17, 2015 + +[core library] +* Added SET_DIGITAL_PIN_VALUE (0xF5) to enable setting an individual digital pin value + +[StandardFirmata (all variations)] +* Implement SET_DIGITAL_PIN_VALUE + FIRMATA 2.4.3 - Apr 11, 2015 [core library] diff --git a/library.properties b/library.properties index fd9eea05..f898de0d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Firmata -version=2.4.3 +version=2.5.0 author=Firmata Developers maintainer=https://github.com/firmata/arduino sentence=Enables the communication with computer apps using a standard serial protocol. For all Arduino boards. diff --git a/release.sh b/release.sh index 49c43802..b1296390 100644 --- a/release.sh +++ b/release.sh @@ -16,7 +16,7 @@ cd temp find . -name "*.DS_Store" -type f -delete zip -r Firmata.zip ./Firmata/ cd .. -mv ./temp/Firmata.zip Firmata-2.4.3.zip +mv ./temp/Firmata.zip Firmata-2.5.0.beta1.zip #package for Arduino 1.6.x cp library.properties temp/Firmata @@ -31,5 +31,5 @@ cd .. find . -name "*.DS_Store" -type f -delete zip -r Firmata.zip ./Firmata/ cd .. -mv ./temp/Firmata.zip Arduino-1.6.x-Firmata-2.4.3.zip +mv ./temp/Firmata.zip Arduino-1.6.x-Firmata-2.5.0.beta1.zip rm -r ./temp