diff --git a/Firmata.h b/Firmata.h index bda1364e..1d1dce23 100644 --- a/Firmata.h +++ b/Firmata.h @@ -41,6 +41,7 @@ // extended command set using sysex (0-127/0x00-0x7F) /* 0x00-0x0F reserved for user-defined commands */ +#define TONE_DATA 0x5F // send a tone or noTone command #define ENCODER_DATA 0x61 // reply with encoders current positions #define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq #define STRING_DATA 0x71 // a string message with 14-bits per char @@ -79,8 +80,9 @@ #define ONEWIRE 0x07 // pin configured for 1-wire #define STEPPER 0x08 // pin configured for stepper motor #define ENCODER 0x09 // pin configured for rotary encoders +#define TONE 0x0A // pin configured for tone function #define IGNORE 0x7F // pin configured to be ignored by digitalWrite and capabilityResponse -#define TOTAL_PIN_MODES 11 +#define TOTAL_PIN_MODES 12 extern "C" { // callback function types diff --git a/examples/StandardFirmata/StandardFirmata.ino b/examples/StandardFirmata/StandardFirmata.ino index 9dfb8c4f..42005c02 100644 --- a/examples/StandardFirmata/StandardFirmata.ino +++ b/examples/StandardFirmata/StandardFirmata.ino @@ -27,6 +27,9 @@ #include #include +#define TONE_TONE 0x00 +#define TONE_NO_TONE 0x01 + #define I2C_WRITE B00000000 #define I2C_READ B00001000 #define I2C_READ_CONTINUOUSLY B00010000 @@ -229,6 +232,9 @@ void setPinModeCallback(byte pin, int mode) if (pinConfig[pin] == IGNORE) return; + if (pinConfig[pin] == TONE && mode != TONE) { + noTone(pin); + } if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) { // disable i2c so pins can be used for other functions // the following if statements should reconfigure the pins properly @@ -298,6 +304,13 @@ void setPinModeCallback(byte pin, int mode) pinConfig[pin] = I2C; } break; + case TONE: + if (IS_PIN_DIGITAL(pin)) { + digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM + pinMode(PIN_TO_DIGITAL(pin), OUTPUT); + pinConfig[pin] = TONE; + } + break; default: Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM } @@ -402,6 +415,23 @@ void sysexCallback(byte command, byte argc, byte *argv) unsigned int delayTime; switch (command) { + case TONE_DATA: + if (argc > 1) { + byte toneCommand = argv[0]; + byte pin = argv[1]; + + if (toneCommand == TONE_TONE && argc > 5) { + unsigned int frequency = argv[2] + (argv[3] << 7); + // duration is currently limited to 16,383 ms + unsigned int duration = argv[4] + (argv[5] << 7); + setPinModeCallback(pin, TONE); + tone(pin, frequency, duration); + } + if (toneCommand == TONE_NO_TONE) { + noTone(pin); + } + } + break; case I2C_REQUEST: mode = argv[1] & I2C_READ_WRITE_MODE_MASK; if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) { @@ -555,6 +585,10 @@ void sysexCallback(byte command, byte argc, byte *argv) Firmata.write(SERVO); Firmata.write(14); } + if (IS_PIN_DIGITAL(pin)) { + Firmata.write(TONE); + Firmata.write(14); // 14 bit frequency value + } if (IS_PIN_I2C(pin)) { Firmata.write(I2C); Firmata.write(1); // TODO: could assign a number to map to SCL or SDA