1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-11-29 10:24:12 +01:00

updated Firmata library to version 2.3.5 and moved to the new library format

This commit is contained in:
Fede85 2013-07-04 13:29:15 +02:00
parent 38c3bbbd3c
commit 10a4241ba7
18 changed files with 162 additions and 316 deletions

View File

@ -1,14 +0,0 @@
- make Firmata a subclass of HardwareSerial
- per-pin digital callback, since the per-port callback is a bit complicated
for beginners (maybe Firmata is not for beginners...)
- simplify SimpleDigitalFirmata, take out the code that checks to see if the
data has changed, since it is a bit complicated for this example. Ideally
this example would be based on a call
- turn current SimpleDigitalFirmata into DigitalPortFirmata for a more complex
example using the code which checks for changes before doing anything
- test integration with Wiring

View File

@ -1,228 +0,0 @@
/*
* Firmata is a generic protocol for communicating with microcontrollers
* from software on a host computer. It is intended to work with
* 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.
*
* http://firmata.org/wiki/Download
*/
/*
Copyright (C) 2009 Jeff Hoefs. All rights reserved.
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See file LICENSE.txt for further informations on licensing terms.
*/
#include <Wire.h>
#include <Firmata.h>
#define I2C_WRITE B00000000
#define I2C_READ B00001000
#define I2C_READ_CONTINUOUSLY B00010000
#define I2C_STOP_READING B00011000
#define I2C_READ_WRITE_MODE_MASK B00011000
#define MAX_QUERIES 8
unsigned long currentMillis; // store the current value from millis()
unsigned long previousMillis; // for comparison with currentMillis
unsigned int samplingInterval = 32; // default sampling interval is 33ms
unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom()
unsigned int powerPinsEnabled = 0; // use as boolean to prevent enablePowerPins from being called more than once
#define MINIMUM_SAMPLING_INTERVAL 10
#define REGISTER_NOT_SPECIFIED -1
struct i2c_device_info {
byte addr;
byte reg;
byte bytes;
};
i2c_device_info query[MAX_QUERIES];
byte i2cRxData[32];
boolean readingContinuously = false;
byte queryIndex = 0;
void readAndReportData(byte address, int theRegister, byte numBytes)
{
if (theRegister != REGISTER_NOT_SPECIFIED) {
Wire.beginTransmission(address);
Wire.write((byte)theRegister);
Wire.endTransmission();
delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck
}
else {
theRegister = 0; // fill the register with a dummy value
}
Wire.requestFrom(address, numBytes);
// check to be sure correct number of bytes were returned by slave
if(numBytes == Wire.available()) {
i2cRxData[0] = address;
i2cRxData[1] = theRegister;
for (int i = 0; i < numBytes; i++) {
i2cRxData[2 + i] = Wire.read();
}
// send slave address, register and received bytes
Firmata.sendSysex(I2C_REPLY, numBytes + 2, i2cRxData);
}
else {
if(numBytes > Wire.available()) {
Firmata.sendString("I2C Read Error: Too many bytes received");
} else {
Firmata.sendString("I2C Read Error: Too few bytes received");
}
}
}
void sysexCallback(byte command, byte argc, byte *argv)
{
byte mode;
byte slaveAddress;
byte slaveRegister;
byte data;
int delayTime;
if (command == I2C_REQUEST) {
mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
slaveAddress = argv[0];
switch(mode) {
case I2C_WRITE:
Wire.beginTransmission(slaveAddress);
for (byte i = 2; i < argc; i += 2) {
data = argv[i] + (argv[i + 1] << 7);
Wire.write(data);
}
Wire.endTransmission();
delayMicroseconds(70); // TODO is this needed?
break;
case I2C_READ:
if (argc == 6) {
// a slave register is specified
slaveRegister = argv[2] + (argv[3] << 7);
data = argv[4] + (argv[5] << 7); // bytes to read
readAndReportData(slaveAddress, (int)slaveRegister, data);
}
else {
// a slave register is NOT specified
data = argv[2] + (argv[3] << 7); // bytes to read
readAndReportData(slaveAddress, (int)REGISTER_NOT_SPECIFIED, data);
}
break;
case I2C_READ_CONTINUOUSLY:
if ((queryIndex + 1) >= MAX_QUERIES) {
// too many queries, just ignore
Firmata.sendString("too many queries");
break;
}
query[queryIndex].addr = slaveAddress;
query[queryIndex].reg = argv[2] + (argv[3] << 7);
query[queryIndex].bytes = argv[4] + (argv[5] << 7);
readingContinuously = true;
queryIndex++;
break;
case I2C_STOP_READING:
readingContinuously = false;
queryIndex = 0;
break;
default:
break;
}
}
else if (command == SAMPLING_INTERVAL) {
samplingInterval = argv[0] + (argv[1] << 7);
if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
samplingInterval = MINIMUM_SAMPLING_INTERVAL;
}
samplingInterval -= 1;
Firmata.sendString("sampling interval");
}
else if (command == I2C_CONFIG) {
delayTime = (argv[4] + (argv[5] << 7)); // MSB
delayTime = (delayTime << 8) + (argv[2] + (argv[3] << 7)); // add LSB
if((argv[0] + (argv[1] << 7)) > 0) {
enablePowerPins(PORTC3, PORTC2);
}
if(delayTime > 0) {
i2cReadDelayTime = delayTime;
}
if(argc > 6) {
// If you extend I2C_Config, handle your data here
}
}
}
void systemResetCallback()
{
readingContinuously = false;
queryIndex = 0;
}
/* reference: BlinkM_funcs.h by Tod E. Kurt, ThingM, http://thingm.com/ */
// Enables Pins A2 and A3 to be used as GND and Power
// so that I2C devices can be plugged directly
// into Arduino header (pins A2 - A5)
static void enablePowerPins(byte pwrpin, byte gndpin)
{
if(powerPinsEnabled == 0) {
DDRC |= _BV(pwrpin) | _BV(gndpin);
PORTC &=~ _BV(gndpin);
PORTC |= _BV(pwrpin);
powerPinsEnabled = 1;
Firmata.sendString("Power pins enabled");
delay(100);
}
}
void setup()
{
Firmata.setFirmwareVersion(2, 0);
Firmata.attach(START_SYSEX, sysexCallback);
Firmata.attach(SYSTEM_RESET, systemResetCallback);
for (int i = 0; i < TOTAL_PINS; ++i) {
pinMode(i, OUTPUT);
}
Firmata.begin(57600);
Wire.begin();
}
void loop()
{
while (Firmata.available()) {
Firmata.processInput();
}
currentMillis = millis();
if (currentMillis - previousMillis > samplingInterval) {
previousMillis += samplingInterval;
for (byte i = 0; i < queryIndex; i++) {
readAndReportData(query[i].addr, query[i].reg, query[i].bytes);
}
}
}

View File

@ -15,8 +15,6 @@
*/ */
#include <Firmata.h> #include <Firmata.h>
byte analogPin;
void stringCallback(char *myString) void stringCallback(char *myString)
{ {
Firmata.sendString(myString); Firmata.sendString(myString);

View File

@ -99,7 +99,11 @@ void readAndReportData(byte address, int theRegister, byte numBytes) {
Wire.send((byte)theRegister); Wire.send((byte)theRegister);
#endif #endif
Wire.endTransmission(); Wire.endTransmission();
delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck // do not set a value of 0
if (i2cReadDelayTime > 0) {
// delay is necessary for some devices such as WiiNunchuck
delayMicroseconds(i2cReadDelayTime);
}
} else { } else {
theRegister = 0; // fill the register with a dummy value theRegister = 0; // fill the register with a dummy value
} }
@ -455,57 +459,57 @@ void sysexCallback(byte command, byte argc, byte *argv)
} }
break; break;
case CAPABILITY_QUERY: case CAPABILITY_QUERY:
Serial.write(START_SYSEX); Firmata.write(START_SYSEX);
Serial.write(CAPABILITY_RESPONSE); Firmata.write(CAPABILITY_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) { for (byte pin=0; pin < TOTAL_PINS; pin++) {
if (IS_PIN_DIGITAL(pin)) { if (IS_PIN_DIGITAL(pin)) {
Serial.write((byte)INPUT); Firmata.write((byte)INPUT);
Serial.write(1); Firmata.write(1);
Serial.write((byte)OUTPUT); Firmata.write((byte)OUTPUT);
Serial.write(1); Firmata.write(1);
} }
if (IS_PIN_ANALOG(pin)) { if (IS_PIN_ANALOG(pin)) {
Serial.write(ANALOG); Firmata.write(ANALOG);
Serial.write(10); Firmata.write(10);
} }
if (IS_PIN_PWM(pin)) { if (IS_PIN_PWM(pin)) {
Serial.write(PWM); Firmata.write(PWM);
Serial.write(8); Firmata.write(8);
} }
if (IS_PIN_SERVO(pin)) { if (IS_PIN_SERVO(pin)) {
Serial.write(SERVO); Firmata.write(SERVO);
Serial.write(14); Firmata.write(14);
} }
if (IS_PIN_I2C(pin)) { if (IS_PIN_I2C(pin)) {
Serial.write(I2C); Firmata.write(I2C);
Serial.write(1); // to do: determine appropriate value Firmata.write(1); // to do: determine appropriate value
} }
Serial.write(127); Firmata.write(127);
} }
Serial.write(END_SYSEX); Firmata.write(END_SYSEX);
break; break;
case PIN_STATE_QUERY: case PIN_STATE_QUERY:
if (argc > 0) { if (argc > 0) {
byte pin=argv[0]; byte pin=argv[0];
Serial.write(START_SYSEX); Firmata.write(START_SYSEX);
Serial.write(PIN_STATE_RESPONSE); Firmata.write(PIN_STATE_RESPONSE);
Serial.write(pin); Firmata.write(pin);
if (pin < TOTAL_PINS) { if (pin < TOTAL_PINS) {
Serial.write((byte)pinConfig[pin]); Firmata.write((byte)pinConfig[pin]);
Serial.write((byte)pinState[pin] & 0x7F); Firmata.write((byte)pinState[pin] & 0x7F);
if (pinState[pin] & 0xFF80) Serial.write((byte)(pinState[pin] >> 7) & 0x7F); if (pinState[pin] & 0xFF80) Firmata.write((byte)(pinState[pin] >> 7) & 0x7F);
if (pinState[pin] & 0xC000) Serial.write((byte)(pinState[pin] >> 14) & 0x7F); if (pinState[pin] & 0xC000) Firmata.write((byte)(pinState[pin] >> 14) & 0x7F);
} }
Serial.write(END_SYSEX); Firmata.write(END_SYSEX);
} }
break; break;
case ANALOG_MAPPING_QUERY: case ANALOG_MAPPING_QUERY:
Serial.write(START_SYSEX); Firmata.write(START_SYSEX);
Serial.write(ANALOG_MAPPING_RESPONSE); Firmata.write(ANALOG_MAPPING_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) { for (byte pin=0; pin < TOTAL_PINS; pin++) {
Serial.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127); Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
} }
Serial.write(END_SYSEX); Firmata.write(END_SYSEX);
break; break;
} }
} }

View File

@ -0,0 +1,10 @@
name=Firmata
author=Hans-Christoph Steiner
email=Hans-Christoph Steiner <hans@at.or.at> (author), Paul Stoffregen <paul@pjrc.com> (maintainer)
sentence=This library implements the Firmata protocol and allows you to control the Arduino board from the an application on the computer.
paragraph=The Firmata library implements the Firmata protocol for communicating with software on the host computer. This allows you to write custom firmware without having to create your own protocol and objects for the programming environment that you are using.
url=http://arduino.cc/en/Reference/Firmata</br>http://firmata.org
architectures=avr, sam
version=1.0
dependencies= SoftwareSerial
core-dependencies=arduino (>=1.5.0)

View File

@ -143,6 +143,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 14) #define PIN_TO_ANALOG(p) ((p) - 14)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -158,6 +159,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL) #define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN) #define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -191,6 +193,23 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 54)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) ((p) - 2)
// Arduino DUE
#elif defined(__SAM3X8E__)
#define TOTAL_ANALOG_PINS 12
#define TOTAL_PINS 66 // 54 digital + 12 analog
#define VERSION_BLINK_PIN 13
#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) // 70 71
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 54) #define PIN_TO_ANALOG(p) ((p) - 54)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -207,6 +226,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) (0)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) (0) #define PIN_TO_ANALOG(p) (0)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -214,7 +234,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
// Teensy 2.0 // Teensy 2.0
#elif defined(__AVR_ATmega32U4__) #elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
#define TOTAL_ANALOG_PINS 12 #define TOTAL_ANALOG_PINS 12
#define TOTAL_PINS 25 // 11 digital + 12 analog #define TOTAL_PINS 25 // 11 digital + 12 analog
#define VERSION_BLINK_PIN 11 #define VERSION_BLINK_PIN 11
@ -223,12 +243,29 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 5 || (p) == 6) #define IS_PIN_I2C(p) ((p) == 5 || (p) == 6)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11) #define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) (p) #define PIN_TO_SERVO(p) (p)
// Teensy 3.0
#elif defined(__MK20DX128__)
#define TOTAL_ANALOG_PINS 14
#define TOTAL_PINS 38 // 24 digital + 10 analog-digital + 4 analog
#define VERSION_BLINK_PIN 13
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 34)
#define IS_PIN_ANALOG(p) (((p) >= 14 && (p) <= 23) || ((p) >= 34 && (p) <= 38))
#define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
#define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) (((p)<=23)?(p)-14:(p)-24)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) (p)
// Teensy++ 1.0 and 2.0 // Teensy++ 1.0 and 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define TOTAL_ANALOG_PINS 8 #define TOTAL_ANALOG_PINS 8
@ -239,12 +276,30 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_PWM(p) digitalPinHasPWM(p) #define IS_PIN_PWM(p) digitalPinHasPWM(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 0 || (p) == 1) #define IS_PIN_I2C(p) ((p) == 0 || (p) == 1)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 38) #define PIN_TO_ANALOG(p) ((p) - 38)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) (p) #define PIN_TO_SERVO(p) (p)
// Leonardo
#elif defined(__AVR_ATmega32U4__)
#define TOTAL_ANALOG_PINS 12
#define TOTAL_PINS 30 // 14 digital + 12 analog + 4 SPI (D14-D17 on ISP header)
#define VERSION_BLINK_PIN 13
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
#define IS_PIN_ANALOG(p) ((p) >= 18 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11 || (p) == 13)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == 2 || (p) == 3)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) (p) - 18
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) (p)
// Sanguino // Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TOTAL_ANALOG_PINS 8 #define TOTAL_ANALOG_PINS 8
@ -282,6 +337,10 @@ writePort(port, value, bitmask): Write an 8 bit port.
#error "Please edit Boards.h with a hardware abstraction for this board" #error "Please edit Boards.h with a hardware abstraction for this board"
#endif #endif
// as long this is not defined for all boards:
#ifndef IS_PIN_SPI(p)
#define IS_PIN_SPI(p) 0
#endif
/*============================================================================== /*==============================================================================
* readPort() - Read an 8 bit port * readPort() - Read an 8 bit port

View File

@ -28,27 +28,28 @@ extern "C" {
void FirmataClass::sendValueAsTwo7bitBytes(int value) void FirmataClass::sendValueAsTwo7bitBytes(int value)
{ {
FirmataSerial.write(value & B01111111); // LSB FirmataSerial->write(value & B01111111); // LSB
FirmataSerial.write(value >> 7 & B01111111); // MSB FirmataSerial->write(value >> 7 & B01111111); // MSB
} }
void FirmataClass::startSysex(void) void FirmataClass::startSysex(void)
{ {
FirmataSerial.write(START_SYSEX); FirmataSerial->write(START_SYSEX);
} }
void FirmataClass::endSysex(void) void FirmataClass::endSysex(void)
{ {
FirmataSerial.write(END_SYSEX); FirmataSerial->write(END_SYSEX);
} }
//****************************************************************************** //******************************************************************************
//* Constructors //* Constructors
//****************************************************************************** //******************************************************************************
FirmataClass::FirmataClass(Stream &s) : FirmataSerial(s) FirmataClass::FirmataClass()
{ {
firmwareVersionCount = 0; firmwareVersionCount = 0;
firmwareVersionVector = 0;
systemReset(); systemReset();
} }
@ -56,7 +57,7 @@ FirmataClass::FirmataClass(Stream &s) : FirmataSerial(s)
//* Public Methods //* Public Methods
//****************************************************************************** //******************************************************************************
/* begin method for overriding default serial bitrate */ /* begin method with default serial bitrate */
void FirmataClass::begin(void) void FirmataClass::begin(void)
{ {
begin(57600); begin(57600);
@ -66,34 +67,32 @@ void FirmataClass::begin(void)
void FirmataClass::begin(long speed) void FirmataClass::begin(long speed)
{ {
Serial.begin(speed); Serial.begin(speed);
FirmataSerial = Serial; begin(Serial);
blinkVersion(); blinkVersion();
printVersion();
printFirmwareVersion();
} }
/* begin method for overriding default stream */
void FirmataClass::begin(Stream &s) void FirmataClass::begin(Stream &s)
{ {
FirmataSerial = s; FirmataSerial = &s;
systemReset();
printVersion(); printVersion();
printFirmwareVersion(); printFirmwareVersion();
} }
// output the protocol version message to the serial port // output the protocol version message to the serial port
void FirmataClass::printVersion(void) { void FirmataClass::printVersion(void) {
FirmataSerial.write(REPORT_VERSION); FirmataSerial->write(REPORT_VERSION);
FirmataSerial.write(FIRMATA_MAJOR_VERSION); FirmataSerial->write(FIRMATA_MAJOR_VERSION);
FirmataSerial.write(FIRMATA_MINOR_VERSION); FirmataSerial->write(FIRMATA_MINOR_VERSION);
} }
void FirmataClass::blinkVersion(void) void FirmataClass::blinkVersion(void)
{ {
// flash the pin with the protocol version // flash the pin with the protocol version
pinMode(VERSION_BLINK_PIN,OUTPUT); pinMode(VERSION_BLINK_PIN,OUTPUT);
pin13strobe(FIRMATA_MAJOR_VERSION, 40, 210); strobeBlinkPin(FIRMATA_MAJOR_VERSION, 40, 210);
delay(250); delay(250);
pin13strobe(FIRMATA_MINOR_VERSION, 40, 210); strobeBlinkPin(FIRMATA_MINOR_VERSION, 40, 210);
delay(125); delay(125);
} }
@ -103,9 +102,9 @@ void FirmataClass::printFirmwareVersion(void)
if(firmwareVersionCount) { // make sure that the name has been set before reporting if(firmwareVersionCount) { // make sure that the name has been set before reporting
startSysex(); startSysex();
FirmataSerial.write(REPORT_FIRMWARE); FirmataSerial->write(REPORT_FIRMWARE);
FirmataSerial.write(firmwareVersionVector[0]); // major version number FirmataSerial->write(firmwareVersionVector[0]); // major version number
FirmataSerial.write(firmwareVersionVector[1]); // minor version number FirmataSerial->write(firmwareVersionVector[1]); // minor version number
for(i=2; i<firmwareVersionCount; ++i) { for(i=2; i<firmwareVersionCount; ++i) {
sendValueAsTwo7bitBytes(firmwareVersionVector[i]); sendValueAsTwo7bitBytes(firmwareVersionVector[i]);
} }
@ -128,6 +127,9 @@ void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte
firmwareVersionCount = strlen(name) + 2; firmwareVersionCount = strlen(name) + 2;
filename = name; filename = name;
} }
free(firmwareVersionVector);
firmwareVersionVector = (byte *) malloc(firmwareVersionCount); firmwareVersionVector = (byte *) malloc(firmwareVersionCount);
firmwareVersionVector[firmwareVersionCount] = 0; firmwareVersionVector[firmwareVersionCount] = 0;
firmwareVersionVector[0] = major; firmwareVersionVector[0] = major;
@ -138,12 +140,20 @@ void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte
// (char)major, (char)minor, firmwareVersionVector); // (char)major, (char)minor, firmwareVersionVector);
} }
// this method is only used for unit testing
// void FirmataClass::unsetFirmwareVersion()
// {
// firmwareVersionCount = 0;
// free(firmwareVersionVector);
// firmwareVersionVector = 0;
// }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Serial Receive Handling // Serial Receive Handling
int FirmataClass::available(void) int FirmataClass::available(void)
{ {
return FirmataSerial.available(); return FirmataSerial->available();
} }
@ -177,11 +187,11 @@ void FirmataClass::processSysexMessage(void)
void FirmataClass::processInput(void) void FirmataClass::processInput(void)
{ {
int inputData = FirmataSerial.read(); // this is 'int' to handle -1 when no data int inputData = FirmataSerial->read(); // this is 'int' to handle -1 when no data
int command; int command;
// TODO make sure it handles -1 properly // TODO make sure it handles -1 properly
if (parsingSysex) { if (parsingSysex) {
if(inputData == END_SYSEX) { if(inputData == END_SYSEX) {
//stop sysex byte //stop sysex byte
@ -245,7 +255,7 @@ void FirmataClass::processInput(void)
break; break;
case REPORT_ANALOG: case REPORT_ANALOG:
case REPORT_DIGITAL: case REPORT_DIGITAL:
waitForData = 1; // one data byte needed waitForData = 1; // two data bytes needed
executeMultiByteCommand = command; executeMultiByteCommand = command;
break; break;
case START_SYSEX: case START_SYSEX:
@ -269,7 +279,7 @@ void FirmataClass::processInput(void)
void FirmataClass::sendAnalog(byte pin, int value) void FirmataClass::sendAnalog(byte pin, int value)
{ {
// pin can only be 0-15, so chop higher bits // pin can only be 0-15, so chop higher bits
FirmataSerial.write(ANALOG_MESSAGE | (pin & 0xF)); FirmataSerial->write(ANALOG_MESSAGE | (pin & 0xF));
sendValueAsTwo7bitBytes(value); sendValueAsTwo7bitBytes(value);
} }
@ -300,9 +310,9 @@ void FirmataClass::sendDigital(byte pin, int value)
// send an 8-bit port in a single digital message (protocol v2) // send an 8-bit port in a single digital message (protocol v2)
void FirmataClass::sendDigitalPort(byte portNumber, int portData) void FirmataClass::sendDigitalPort(byte portNumber, int portData)
{ {
FirmataSerial.write(DIGITAL_MESSAGE | (portNumber & 0xF)); FirmataSerial->write(DIGITAL_MESSAGE | (portNumber & 0xF));
FirmataSerial.write((byte)portData % 128); // Tx bits 0-6 FirmataSerial->write((byte)portData % 128); // Tx bits 0-6
FirmataSerial.write(portData >> 7); // Tx bits 7-13 FirmataSerial->write(portData >> 7); // Tx bits 7-13
} }
@ -310,7 +320,7 @@ void FirmataClass::sendSysex(byte command, byte bytec, byte* bytev)
{ {
byte i; byte i;
startSysex(); startSysex();
FirmataSerial.write(command); FirmataSerial->write(command);
for(i=0; i<bytec; i++) { for(i=0; i<bytec; i++) {
sendValueAsTwo7bitBytes(bytev[i]); sendValueAsTwo7bitBytes(bytev[i]);
} }
@ -329,6 +339,12 @@ void FirmataClass::sendString(const char* string)
sendString(STRING_DATA, string); sendString(STRING_DATA, string);
} }
// expose the write method
void FirmataClass::write(byte c)
{
FirmataSerial->write(c);
}
// Internal Actions///////////////////////////////////////////////////////////// // Internal Actions/////////////////////////////////////////////////////////////
@ -407,7 +423,6 @@ void FirmataClass::systemReset(void)
executeMultiByteCommand = 0; // execute this after getting multi-byte data executeMultiByteCommand = 0; // execute this after getting multi-byte data
multiByteChannel = 0; // channel data for multiByteCommands multiByteChannel = 0; // channel data for multiByteCommands
for(i=0; i<MAX_DATA_BYTES; i++) { for(i=0; i<MAX_DATA_BYTES; i++) {
storedInputData[i] = 0; storedInputData[i] = 0;
} }
@ -425,7 +440,7 @@ void FirmataClass::systemReset(void)
// ============================================================================= // =============================================================================
// used for flashing the pin for the version number // used for flashing the pin for the version number
void FirmataClass::pin13strobe(int count, int onInterval, int offInterval) void FirmataClass::strobeBlinkPin(int count, int onInterval, int offInterval)
{ {
byte i; byte i;
pinMode(VERSION_BLINK_PIN, OUTPUT); pinMode(VERSION_BLINK_PIN, OUTPUT);
@ -439,6 +454,6 @@ void FirmataClass::pin13strobe(int count, int onInterval, int offInterval)
// make one instance for the user to use // make one instance for the user to use
FirmataClass Firmata(Serial); FirmataClass Firmata;

View File

@ -21,7 +21,7 @@
* installed firmware. */ * installed firmware. */
#define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes #define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes
#define FIRMATA_MINOR_VERSION 3 // for backwards compatible changes #define FIRMATA_MINOR_VERSION 3 // for backwards compatible changes
#define FIRMATA_BUGFIX_VERSION 1 // for bugfix releases #define FIRMATA_BUGFIX_VERSION 5 // for bugfix releases
#define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages #define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages
@ -87,27 +87,29 @@ extern "C" {
class FirmataClass class FirmataClass
{ {
public: public:
FirmataClass(Stream &s); FirmataClass();
/* Arduino constructors */ /* Arduino constructors */
void begin(); void begin();
void begin(long); void begin(long);
void begin(Stream &s); void begin(Stream &s);
/* querying functions */ /* querying functions */
void printVersion(void); void printVersion(void);
void blinkVersion(void); void blinkVersion(void);
void printFirmwareVersion(void); void printFirmwareVersion(void);
//void setFirmwareVersion(byte major, byte minor); // see macro below //void setFirmwareVersion(byte major, byte minor); // see macro below
void setFirmwareNameAndVersion(const char *name, byte major, byte minor); void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
//void unsetFirmwareVersion(); // only used for unit test
/* serial receive handling */ /* serial receive handling */
int available(void); int available(void);
void processInput(void); void processInput(void);
/* serial send handling */ /* serial send handling */
void sendAnalog(byte pin, int value); void sendAnalog(byte pin, int value);
void sendDigital(byte pin, int value); // TODO implement this void sendDigital(byte pin, int value); // TODO implement this
void sendDigitalPort(byte portNumber, int portData); void sendDigitalPort(byte portNumber, int portData);
void sendString(const char* string); void sendString(const char* string);
void sendString(byte command, const char* string); void sendString(byte command, const char* string);
void sendSysex(byte command, byte bytec, byte* bytev); void sendSysex(byte command, byte bytec, byte* bytev);
void write(byte c);
/* attach & detach callback functions to messages */ /* attach & detach callback functions to messages */
void attach(byte command, callbackFunction newFunction); void attach(byte command, callbackFunction newFunction);
void attach(byte command, systemResetCallbackFunction newFunction); void attach(byte command, systemResetCallbackFunction newFunction);
@ -116,7 +118,7 @@ public:
void detach(byte command); void detach(byte command);
private: private:
Stream &FirmataSerial; Stream *FirmataSerial;
/* firmware name and version */ /* firmware name and version */
byte firmwareVersionCount; byte firmwareVersionCount;
byte *firmwareVersionVector; byte *firmwareVersionVector;
@ -140,8 +142,8 @@ private:
/* private methods ------------------------------ */ /* private methods ------------------------------ */
void processSysexMessage(void); void processSysexMessage(void);
void systemReset(void); void systemReset(void);
void pin13strobe(int count, int onInterval, int offInterval); void strobeBlinkPin(int count, int onInterval, int offInterval);
void sendValueAsTwo7bitBytes(int value); void sendValueAsTwo7bitBytes(int value);
void startSysex(void); void startSysex(void);
void endSysex(void); void endSysex(void);