From 8c2b5b979a75d109ae7cc306afc50d7ffe1e0366 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 4 Jan 2012 15:14:51 +0100 Subject: Moved libraries folder inside platform folder. Now libraries and examples are searched per board/platform --- libraries/Firmata/Firmata.cpp | 444 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 libraries/Firmata/Firmata.cpp (limited to 'libraries/Firmata/Firmata.cpp') diff --git a/libraries/Firmata/Firmata.cpp b/libraries/Firmata/Firmata.cpp new file mode 100644 index 0000000..e81c10b --- /dev/null +++ b/libraries/Firmata/Firmata.cpp @@ -0,0 +1,444 @@ +/* + Firmata.cpp - Firmata library + 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) +{ + FirmataSerial.write(value & B01111111); // LSB + FirmataSerial.write(value >> 7 & B01111111); // MSB +} + +void FirmataClass::startSysex(void) +{ + FirmataSerial.write(START_SYSEX); +} + +void FirmataClass::endSysex(void) +{ + FirmataSerial.write(END_SYSEX); +} + +//****************************************************************************** +//* Constructors +//****************************************************************************** + +FirmataClass::FirmataClass(Stream &s) : FirmataSerial(s) +{ + firmwareVersionCount = 0; + systemReset(); +} + +//****************************************************************************** +//* Public Methods +//****************************************************************************** + +/* begin method for overriding default serial bitrate */ +void FirmataClass::begin(void) +{ + begin(57600); +} + +/* begin method for overriding default serial bitrate */ +void FirmataClass::begin(long speed) +{ + Serial.begin(speed); + FirmataSerial = Serial; + blinkVersion(); + printVersion(); + printFirmwareVersion(); +} + +void FirmataClass::begin(Stream &s) +{ + FirmataSerial = s; + systemReset(); + printVersion(); + printFirmwareVersion(); +} + +// output the protocol version message to the serial port +void FirmataClass::printVersion(void) { + FirmataSerial.write(REPORT_VERSION); + FirmataSerial.write(FIRMATA_MAJOR_VERSION); + FirmataSerial.write(FIRMATA_MINOR_VERSION); +} + +void FirmataClass::blinkVersion(void) +{ + // flash the pin with the protocol version + pinMode(VERSION_BLINK_PIN,OUTPUT); + pin13strobe(FIRMATA_MAJOR_VERSION, 40, 210); + delay(250); + pin13strobe(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(); + FirmataSerial.write(REPORT_FIRMWARE); + FirmataSerial.write(firmwareVersionVector[0]); // major version number + FirmataSerial.write(firmwareVersionVector[1]); // minor version number + for(i=2; i 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; // two data bytes 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 + FirmataSerial.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. The DIGITAL_MESSAGE sends 14 bits at a time, but it is + * probably easier to send 8 bit ports for any board with more than 14 + * digital pins. + */ + + // 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) +{ + FirmataSerial.write(DIGITAL_MESSAGE | (portNumber & 0xF)); + FirmataSerial.write((byte)portData % 128); // Tx bits 0-6 + FirmataSerial.write(portData >> 7); // Tx bits 7-13 +} + + +void FirmataClass::sendSysex(byte command, byte bytec, byte* bytev) +{ + byte i; + startSysex(); + FirmataSerial.write(command); + for(i=0; i