diff --git a/Firmata.cpp b/Firmata.cpp deleted file mode 100644 index 5289e07..0000000 --- a/Firmata.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* - Firmata.cpp - Firmata library v2.4.4 - 2015-8-9 - Copyright (c) 2006-2008 Hans-Christoph Steiner. 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. -*/ - -//****************************************************************************** -//* Includes -//****************************************************************************** - -#include "Firmata.h" -#include "HardwareSerial.h" - -extern "C" { -#include -#include -} - -//****************************************************************************** -//* Support Functions -//****************************************************************************** - -void FirmataClass::sendValueAsTwo7bitBytes(int value) -{ - FirmataStream->write(value & B01111111); // LSB - FirmataStream->write(value >> 7 & B01111111); // MSB -} - -void FirmataClass::startSysex(void) -{ - FirmataStream->write(START_SYSEX); -} - -void FirmataClass::endSysex(void) -{ - FirmataStream->write(END_SYSEX); -} - -//****************************************************************************** -//* Constructors -//****************************************************************************** - -FirmataClass::FirmataClass() -{ - firmwareVersionCount = 0; - firmwareVersionVector = 0; - systemReset(); -} - -//****************************************************************************** -//* Public Methods -//****************************************************************************** - -/* begin method with default serial bitrate */ -void FirmataClass::begin(void) -{ - begin(57600); -} - -/* begin method for overriding default serial bitrate */ -void FirmataClass::begin(long speed) -{ - Serial.begin(speed); - FirmataStream = &Serial; - blinkVersion(); - printVersion(); - printFirmwareVersion(); -} - -/* begin method for overriding default stream */ -void FirmataClass::begin(Stream &s) -{ - FirmataStream = &s; - // do not call blinkVersion() here because some hardware such as the - // Ethernet shield use pin 13 - printVersion(); - printFirmwareVersion(); -} - -// output the protocol version message to the serial port -void FirmataClass::printVersion(void) -{ - FirmataStream->write(REPORT_VERSION); - FirmataStream->write(FIRMATA_MAJOR_VERSION); - FirmataStream->write(FIRMATA_MINOR_VERSION); -} - -void FirmataClass::blinkVersion(void) -{ - // flash the pin with the protocol version - pinMode(VERSION_BLINK_PIN, OUTPUT); - strobeBlinkPin(FIRMATA_MAJOR_VERSION, 40, 210); - delay(250); - strobeBlinkPin(FIRMATA_MINOR_VERSION, 40, 210); - delay(125); -} - -void FirmataClass::printFirmwareVersion(void) -{ - byte i; - - if (firmwareVersionCount) { // make sure that the name has been set before reporting - startSysex(); - FirmataStream->write(REPORT_FIRMWARE); - FirmataStream->write(firmwareVersionVector[0]); // major version number - FirmataStream->write(firmwareVersionVector[1]); // minor version number - for (i = 2; i < firmwareVersionCount; ++i) { - sendValueAsTwo7bitBytes(firmwareVersionVector[i]); - } - endSysex(); - } -} - -void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte minor) -{ - const char *firmwareName; - const char *extension; - - // parse out ".cpp" and "applet/" that comes from using __FILE__ - extension = strstr(name, ".cpp"); - firmwareName = strrchr(name, '/'); - - if (!firmwareName) { - // windows - firmwareName = strrchr(name, '\\'); - } - if (!firmwareName) { - // user passed firmware name - firmwareName = name; - } else { - firmwareName ++; - } - - if (!extension) { - firmwareVersionCount = strlen(firmwareName) + 2; - } else { - firmwareVersionCount = extension - firmwareName + 2; - } - - // in case anyone calls setFirmwareNameAndVersion more than once - free(firmwareVersionVector); - - firmwareVersionVector = (byte *) malloc(firmwareVersionCount + 1); - firmwareVersionVector[firmwareVersionCount] = 0; - firmwareVersionVector[0] = major; - firmwareVersionVector[1] = minor; - strncpy((char *)firmwareVersionVector + 2, firmwareName, firmwareVersionCount - 2); -} - -//------------------------------------------------------------------------------ -// Serial Receive Handling - -int FirmataClass::available(void) -{ - return FirmataStream->available(); -} - - -void FirmataClass::processSysexMessage(void) -{ - switch (storedInputData[0]) { //first byte in buffer is command - case REPORT_FIRMWARE: - printFirmwareVersion(); - break; - case STRING_DATA: - if (currentStringCallback) { - byte bufferLength = (sysexBytesRead - 1) / 2; - byte i = 1; - byte j = 0; - while (j < bufferLength) { - // The string length will only be at most half the size of the - // stored input buffer so we can decode the string within the buffer. - storedInputData[j] = storedInputData[i]; - i++; - storedInputData[j] += (storedInputData[i] << 7); - i++; - j++; - } - // Make sure string is null terminated. This may be the case for data - // coming from client libraries in languages that don't null terminate - // strings. - if (storedInputData[j - 1] != '\0') { - storedInputData[j] = '\0'; - } - (*currentStringCallback)((char *)&storedInputData[0]); - } - break; - default: - if (currentSysexCallback) - (*currentSysexCallback)(storedInputData[0], sysexBytesRead - 1, storedInputData + 1); - } -} - -void FirmataClass::processInput(void) -{ - int inputData = FirmataStream->read(); // this is 'int' to handle -1 when no data - int command; - - // TODO make sure it handles -1 properly - - if (parsingSysex) { - if (inputData == END_SYSEX) { - //stop sysex byte - parsingSysex = false; - //fire off handler function - processSysexMessage(); - } else { - //normal data byte - add to buffer - storedInputData[sysexBytesRead] = inputData; - sysexBytesRead++; - } - } else if ( (waitForData > 0) && (inputData < 128) ) { - waitForData--; - storedInputData[waitForData] = inputData; - if ( (waitForData == 0) && executeMultiByteCommand ) { // got the whole message - switch (executeMultiByteCommand) { - case ANALOG_MESSAGE: - if (currentAnalogCallback) { - (*currentAnalogCallback)(multiByteChannel, - (storedInputData[0] << 7) - + storedInputData[1]); - } - break; - case DIGITAL_MESSAGE: - if (currentDigitalCallback) { - (*currentDigitalCallback)(multiByteChannel, - (storedInputData[0] << 7) - + storedInputData[1]); - } - break; - case SET_PIN_MODE: - if (currentPinModeCallback) - (*currentPinModeCallback)(storedInputData[1], storedInputData[0]); - break; - case REPORT_ANALOG: - if (currentReportAnalogCallback) - (*currentReportAnalogCallback)(multiByteChannel, storedInputData[0]); - break; - case REPORT_DIGITAL: - if (currentReportDigitalCallback) - (*currentReportDigitalCallback)(multiByteChannel, storedInputData[0]); - break; - } - executeMultiByteCommand = 0; - } - } else { - // remove channel info from command byte if less than 0xF0 - if (inputData < 0xF0) { - command = inputData & 0xF0; - multiByteChannel = inputData & 0x0F; - } else { - command = inputData; - // commands in the 0xF* range don't use channel data - } - switch (command) { - case ANALOG_MESSAGE: - case DIGITAL_MESSAGE: - case SET_PIN_MODE: - waitForData = 2; // two data bytes needed - executeMultiByteCommand = command; - break; - case REPORT_ANALOG: - case REPORT_DIGITAL: - waitForData = 1; // one data byte needed - executeMultiByteCommand = command; - break; - case START_SYSEX: - parsingSysex = true; - sysexBytesRead = 0; - break; - case SYSTEM_RESET: - systemReset(); - break; - case REPORT_VERSION: - Firmata.printVersion(); - break; - } - } -} - -//------------------------------------------------------------------------------ -// Serial Send Handling - -// send an analog message -void FirmataClass::sendAnalog(byte pin, int value) -{ - // pin can only be 0-15, so chop higher bits - FirmataStream->write(ANALOG_MESSAGE | (pin & 0xF)); - sendValueAsTwo7bitBytes(value); -} - -// send a single digital pin in a digital message -void FirmataClass::sendDigital(byte pin, int value) -{ - /* TODO add single pin digital messages to the protocol, this needs to - * track the last digital data sent so that it can be sure to change just - * one bit in the packet. This is complicated by the fact that the - * numbering of the pins will probably differ on Arduino, Wiring, and - * other boards. - */ - - // TODO: the digital message should not be sent on the serial port every - // time sendDigital() is called. Instead, it should add it to an int - // which will be sent on a schedule. If a pin changes more than once - // before the digital message is sent on the serial port, it should send a - // digital message for each change. - - // if(value == 0) - // sendDigitalPortPair(); -} - - -// send 14-bits in a single digital message (protocol v1) -// send an 8-bit port in a single digital message (protocol v2) -void FirmataClass::sendDigitalPort(byte portNumber, int portData) -{ - FirmataStream->write(DIGITAL_MESSAGE | (portNumber & 0xF)); - FirmataStream->write((byte)portData % 128); // Tx bits 0-6 - FirmataStream->write(portData >> 7); // Tx bits 7-13 -} - - -void FirmataClass::sendSysex(byte command, byte bytec, byte *bytev) -{ - byte i; - startSysex(); - FirmataStream->write(command); - for (i = 0; i < bytec; i++) { - sendValueAsTwo7bitBytes(bytev[i]); - } - endSysex(); -} - -void FirmataClass::sendString(byte command, const char *string) -{ - sendSysex(command, strlen(string), (byte *)string); -} - - -// send a string as the protocol string type -void FirmataClass::sendString(const char *string) -{ - sendString(STRING_DATA, string); -} - -// expose the write method -void FirmataClass::write(byte c) -{ - FirmataStream->write(c); -} - - -// Internal Actions///////////////////////////////////////////////////////////// - -// generic callbacks -void FirmataClass::attach(byte command, callbackFunction newFunction) -{ - switch (command) { - case ANALOG_MESSAGE: currentAnalogCallback = newFunction; break; - case DIGITAL_MESSAGE: currentDigitalCallback = newFunction; break; - case REPORT_ANALOG: currentReportAnalogCallback = newFunction; break; - case REPORT_DIGITAL: currentReportDigitalCallback = newFunction; break; - case SET_PIN_MODE: currentPinModeCallback = newFunction; break; - } -} - -void FirmataClass::attach(byte command, systemResetCallbackFunction newFunction) -{ - switch (command) { - case SYSTEM_RESET: currentSystemResetCallback = newFunction; break; - } -} - -void FirmataClass::attach(byte command, stringCallbackFunction newFunction) -{ - switch (command) { - case STRING_DATA: currentStringCallback = newFunction; break; - } -} - -void FirmataClass::attach(byte command, sysexCallbackFunction newFunction) -{ - currentSysexCallback = newFunction; -} - -void FirmataClass::detach(byte command) -{ - switch (command) { - case SYSTEM_RESET: currentSystemResetCallback = NULL; break; - case STRING_DATA: currentStringCallback = NULL; break; - case START_SYSEX: currentSysexCallback = NULL; break; - default: - attach(command, (callbackFunction)NULL); - } -} - -// sysex callbacks -/* - * this is too complicated for analogReceive, but maybe for Sysex? - void FirmataClass::attachSysex(sysexFunction newFunction) - { - byte i; - byte tmpCount = analogReceiveFunctionCount; - analogReceiveFunction* tmpArray = analogReceiveFunctionArray; - analogReceiveFunctionCount++; - analogReceiveFunctionArray = (analogReceiveFunction*) calloc(analogReceiveFunctionCount, sizeof(analogReceiveFunction)); - for(i = 0; i < tmpCount; i++) { - analogReceiveFunctionArray[i] = tmpArray[i]; - } - analogReceiveFunctionArray[tmpCount] = newFunction; - free(tmpArray); - } -*/ - -//****************************************************************************** -//* Private Methods -//****************************************************************************** - - - -// resets the system state upon a SYSTEM_RESET message from the host software -void FirmataClass::systemReset(void) -{ - byte i; - - waitForData = 0; // this flag says the next serial input will be data - executeMultiByteCommand = 0; // execute this after getting multi-byte data - multiByteChannel = 0; // channel data for multiByteCommands - - for (i = 0; i < MAX_DATA_BYTES; i++) { - storedInputData[i] = 0; - } - - parsingSysex = false; - sysexBytesRead = 0; - - if (currentSystemResetCallback) - (*currentSystemResetCallback)(); -} - - - -// ============================================================================= -// used for flashing the pin for the version number -void FirmataClass::strobeBlinkPin(int count, int onInterval, int offInterval) -{ - byte i; - pinMode(VERSION_BLINK_PIN, OUTPUT); - for (i = 0; i < count; i++) { - delay(offInterval); - digitalWrite(VERSION_BLINK_PIN, HIGH); - delay(onInterval); - digitalWrite(VERSION_BLINK_PIN, LOW); - } -} - - -// make one instance for the user to use -FirmataClass Firmata; diff --git a/Firmata.h b/Firmata.h deleted file mode 100644 index 5b8a3f4..0000000 --- a/Firmata.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - Firmata.h - Firmata library v2.4.4 - 2015-8-9 - Copyright (c) 2006-2008 Hans-Christoph Steiner. 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. -*/ - -#ifndef Firmata_h -#define Firmata_h - -#include "Boards.h" /* Hardware Abstraction Layer + Wiring/Arduino */ - -/* Version numbers for the protocol. The protocol is still changing, so these - * version numbers are important. This number can be queried so that host - * 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 4 // 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 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 REPORT_VERSION 0xF9 // report protocol version -#define SYSTEM_RESET 0xFF // reset from MIDI -// -#define START_SYSEX 0xF0 // start a MIDI Sysex message -#define END_SYSEX 0xF7 // end a MIDI Sysex message - -// extended command set using sysex (0-127/0x00-0x7F) -/* 0x00-0x0F reserved for user-defined commands */ -#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 -#define STEPPER_DATA 0x72 // control a stepper motor -#define ONEWIRE_DATA 0x73 // send an OneWire read/write/reset/select/skip/search request -#define SHIFT_DATA 0x75 // a bitstream to/from a shift register -#define I2C_REQUEST 0x76 // send an I2C read/write request -#define I2C_REPLY 0x77 // a reply to an I2C read request -#define I2C_CONFIG 0x78 // config I2C settings such as delay times and power pins -#define EXTENDED_ANALOG 0x6F // analog write (PWM, Servo, etc) to any pin -#define PIN_STATE_QUERY 0x6D // ask for a pin's current mode and value -#define PIN_STATE_RESPONSE 0x6E // reply with pin's current mode and value -#define CAPABILITY_QUERY 0x6B // ask for supported modes and resolution of all pins -#define CAPABILITY_RESPONSE 0x6C // reply with supported modes and resolution -#define ANALOG_MAPPING_QUERY 0x69 // ask for mapping of analog to pin numbers -#define ANALOG_MAPPING_RESPONSE 0x6A // reply with mapping info -#define REPORT_FIRMWARE 0x79 // report name and version of the firmware -#define SAMPLING_INTERVAL 0x7A // set the poll rate of the main loop -#define SCHEDULER_DATA 0x7B // send a createtask/deletetask/addtotask/schedule/querytasks/querytask request to the scheduler -#define SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages -#define SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages -// these are DEPRECATED to make the naming more consistent -#define FIRMATA_STRING 0x71 // same as STRING_DATA -#define SYSEX_I2C_REQUEST 0x76 // same as I2C_REQUEST -#define SYSEX_I2C_REPLY 0x77 // same as I2C_REPLY -#define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL - -// pin modes -//#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 -#define SHIFT 0x05 // shiftIn/shiftOut mode -#define I2C 0x06 // pin included in I2C setup -#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 IGNORE 0x7F // pin configured to be ignored by digitalWrite and capabilityResponse -#define TOTAL_PIN_MODES 11 - -extern "C" { - // callback function types - typedef void (*callbackFunction)(byte, int); - typedef void (*systemResetCallbackFunction)(void); - typedef void (*stringCallbackFunction)(char *); - typedef void (*sysexCallbackFunction)(byte command, byte argc, byte *argv); -} - - -// TODO make it a subclass of a generic Serial/Stream base class -class FirmataClass -{ - public: - FirmataClass(); - /* Arduino constructors */ - void begin(); - void begin(long); - void begin(Stream &s); - /* querying functions */ - void printVersion(void); - void blinkVersion(void); - void printFirmwareVersion(void); - //void setFirmwareVersion(byte major, byte minor); // see macro below - void setFirmwareNameAndVersion(const char *name, byte major, byte minor); - /* serial receive handling */ - int available(void); - void processInput(void); - /* serial send handling */ - void sendAnalog(byte pin, int value); - void sendDigital(byte pin, int value); // TODO implement this - void sendDigitalPort(byte portNumber, int portData); - void sendString(const char *string); - void sendString(byte command, const char *string); - void sendSysex(byte command, byte bytec, byte *bytev); - void write(byte c); - /* attach & detach callback functions to messages */ - void attach(byte command, callbackFunction newFunction); - void attach(byte command, systemResetCallbackFunction newFunction); - void attach(byte command, stringCallbackFunction newFunction); - void attach(byte command, sysexCallbackFunction newFunction); - void detach(byte command); - - /* utility methods */ - void sendValueAsTwo7bitBytes(int value); - void startSysex(void); - void endSysex(void); - - private: - Stream *FirmataStream; - /* firmware name and version */ - byte firmwareVersionCount; - byte *firmwareVersionVector; - /* input message handling */ - byte waitForData; // this flag says the next serial input will be data - byte executeMultiByteCommand; // execute this after getting multi-byte data - byte multiByteChannel; // channel data for multiByteCommands - byte storedInputData[MAX_DATA_BYTES]; // multi-byte data - /* sysex */ - boolean parsingSysex; - int sysexBytesRead; - /* callback functions */ - callbackFunction currentAnalogCallback; - callbackFunction currentDigitalCallback; - callbackFunction currentReportAnalogCallback; - callbackFunction currentReportDigitalCallback; - callbackFunction currentPinModeCallback; - systemResetCallbackFunction currentSystemResetCallback; - stringCallbackFunction currentStringCallback; - sysexCallbackFunction currentSysexCallback; - - /* private methods ------------------------------ */ - void processSysexMessage(void); - void systemReset(void); - void strobeBlinkPin(int count, int onInterval, int offInterval); -}; - -extern FirmataClass Firmata; - -/*============================================================================== - * MACROS - *============================================================================*/ - -/* shortcut for setFirmwareNameAndVersion() that uses __FILE__ to set the - * firmware name. It needs to be a macro so that __FILE__ is included in the - * firmware source file rather than the library source file. - */ -#define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y) - -#endif /* Firmata_h */