/* Firmata.cpp - Firmata library Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Modified for Adafruit_BLE_Uart by Limor Fried/Kevin Townsend for Adafruit Industries, 2014 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 "Adafruit_BLE_Firmata.h" extern "C" { #include #include } //****************************************************************************** //* Support Functions //****************************************************************************** void Adafruit_BLE_FirmataClass::sendValueAsTwo7bitBytes(int value) { FirmataSerial.write(value & B01111111); // LSB FirmataSerial.write(value >> 7 & B01111111); // MSB } void Adafruit_BLE_FirmataClass::startSysex(void) { FirmataSerial.write(START_SYSEX); } void Adafruit_BLE_FirmataClass::endSysex(void) { FirmataSerial.write(END_SYSEX); } //****************************************************************************** //* Constructors //****************************************************************************** Adafruit_BLE_FirmataClass::Adafruit_BLE_FirmataClass(Adafruit_BLE_UART &s) : FirmataSerial(s) { firmwareVersionCount = 0; systemReset(); } //****************************************************************************** //* Public Methods //****************************************************************************** /* begin method for overriding default serial bitrate */ void Adafruit_BLE_FirmataClass::begin(void) { blinkVersion(); printVersion(); printFirmwareVersion(); } void Adafruit_BLE_FirmataClass::begin(Adafruit_BLE_UART &s) { FirmataSerial = s; systemReset(); printVersion(); printFirmwareVersion(); } // output the protocol version message to the serial port void Adafruit_BLE_FirmataClass::printVersion(void) { FirmataSerial.write(REPORT_VERSION); FirmataSerial.write(FIRMATA_MAJOR_VERSION); FirmataSerial.write(FIRMATA_MINOR_VERSION); } void Adafruit_BLE_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 Adafruit_BLE_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; #ifdef BLE_DEBUG Serial.print(F(" 0x")); Serial.print(inputData, HEX); #endif if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message #ifdef BLE_DEBUG Serial.println(); #endif 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 { #ifdef BLE_DEBUG Serial.print(F("\tReceived 0x")); Serial.print(inputData, HEX); #endif // 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: printVersion(); break; } } return inputData; } //------------------------------------------------------------------------------ // Serial Send Handling // send an analog message void Adafruit_BLE_FirmataClass::sendAnalog(byte pin, int value) { // create a three byte buffer uint8_t sendbuffer[3]; // pin can only be 0-15, so chop higher bits //FirmataSerial.write(ANALOG_MESSAGE | (pin & 0xF)); sendbuffer[0] = ANALOG_MESSAGE | (pin & 0xF); //sendValueAsTwo7bitBytes(value); sendbuffer[1] = value % 128; // Tx bits 0-6 sendbuffer[2] = (value >> 7) &0x7F; // Tx bits 7-13 FirmataSerial.write(sendbuffer, 3); } // send a single digital pin in a digital message void Adafruit_BLE_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 Adafruit_BLE_FirmataClass::sendDigitalPort(byte portNumber, int portData) { // create a three byte buffer uint8_t sendbuffer[3]; sendbuffer[0] = DIGITAL_MESSAGE | (portNumber & 0xF); sendbuffer[1] = (byte)portData % 128; // Tx bits 0-6 sendbuffer[2] = portData >> 7; // Tx bits 7-13 FirmataSerial.write(sendbuffer, 3); } void Adafruit_BLE_FirmataClass::sendSysex(byte command, byte bytec, byte* bytev) { byte i; startSysex(); FirmataSerial.write(command); for(i=0; i