framework2
1826 строк · 45.6 Кб
1/*
2* 11/5/15:
3* - updated for arduino 2.5.0 and configurable firmata
4*
5* 1/9/13:
6* - Fixed issue where digitalPinchange
7*
8* 9/28/11:
9* - updated to be Firmata 2.3/Arduino 1.0 compatible
10* - fixed ability to use analog pins as digital inputs
11*
12* 3/5/11:
13* - added servo support for firmata 2.2 and greater (should be
14* backwards compatible with Erik Sjodin's older firmata servo
15* implementation)
16*
17*
18* Copyright 2007-2008 (c) Erik Sjodin, eriksjodin.net
19* Wiring version 2011 (c) Carlos Mario Rodriguez and Hernando Barragan
20* Updates 2015 (c) Dom Amato
21*
22* Devloped at: The Interactive Institutet / Art and Technology,
23* OF Lab / Ars Electronica
24*
25* Permission is hereby granted, free of charge, to any person
26* obtaining a copy of this software and associated documentation
27* files (the "Software"), to deal in the Software without
28* restriction, including without limitation the rights to use,
29* copy, modify, merge, publish, distribute, sublicense, and/or sell
30* copies of the Software, and to permit persons to whom the
31* Software is furnished to do so, subject to the following
32* conditions:
33*
34* The above copyright notice and this permission notice shall be
35* included in all copies or substantial _portions of the Software.
36*
37* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
39* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
40* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
41* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44* OTHER DEALINGS IN THE SOFTWARE.
45*/
46
47#include "ofArduino.h"48#include "ofUtils.h"49#include "ofMath.h"50#include "ofLog.h"51#include <climits>52
53using std::vector;54using std::string;55using std::list;56using std::pair;57
58
59// TODO thread it?60// TODO throw event or exception if the serial port goes down...61//---------------------------------------------------------------------------62ofArduino::ofArduino() {63_portStatus = -1;64_waitForData = 0;65_analogHistoryLength = 2;66_digitalHistoryLength = 2;67_stringHistoryLength = 1;68_sysExHistoryLength = 1;69_initialized = false;70_totalDigitalPins = 0;71_executeMultiByteCommand = 0x00; // 0x00 a pin mode (input), not a command in Firmata -> fail hard72_multiByteChannel = 0;73_firstAnalogPin = -1;74
75for (unsigned char & e : _storedInputData) {76e = UCHAR_MAX;77}78for (int & e : _digitalPinMode) {79e = INT_MAX;80}81for (int & e : _digitalPinValue) {82e = INT_MAX;83}84for (int & e : _digitalPortValue) {85e = INT_MAX;86}87for (int & e : _digitalPortReporting) {88e = INT_MAX;89}90for (int & e : _digitalPinReporting) {91e = INT_MAX;92}93for (int & e : _analogPinReporting) {94e = INT_MAX;95}96for (int & e : _servoValue) {97e = INT_MAX;98}99connected = false;100connectTime = 0.0f;101
102_majorFirmwareVersion = 0;103_minorFirmwareVersion = 0;104_firmwareName = "Unknown";105
106bUseDelay = true;107}
108
109ofArduino::~ofArduino() {110_port.close();111}
112
113// initialize pins once we get the Firmata version back from the Arduino board
114// the version is sent automatically by the Arduino board on startup
115void ofArduino::initPins() {116
117if (_initialized) {118return; // already initialized119}120
121_digitalHistory.resize(_totalDigitalPins + 1);122_digitalPinMode.resize(_totalDigitalPins + 1);123_digitalPinValue.resize(_totalDigitalPins + 1);124_digitalPinReporting.resize(_totalDigitalPins + 1);125_servoValue.resize(_totalDigitalPins + 1);126
127_analogHistory.resize(_totalDigitalPins - _firstAnalogPin + 1);128_analogPinReporting.resize(_totalDigitalPins - _firstAnalogPin + 1);129
130// ports131for (int i = 0; i < ARD_TOTAL_PORTS; ++i) {132_digitalPortValue[i] = 0;133_digitalPortReporting[i] = ARD_OFF;134}135
136// digital pins137for (int i = 0; i < _firstAnalogPin; ++i) {138_digitalPinValue[i] = -1;139_digitalPinMode[i] = ARD_OUTPUT;140_digitalPinReporting[i] = ARD_OFF;141}142
143// analog in pins144for (int i = _firstAnalogPin; i < _totalDigitalPins; ++i) {145_analogPinReporting[i - _firstAnalogPin] = ARD_OFF;146// analog pins used as digital147_digitalPinMode[i] = ARD_ANALOG;148_digitalPinValue[i] = -1;149}150
151for (int i = 0; i < _totalDigitalPins; ++i) {152_servoValue[i] = -1;153}154
155_initialized = true;156ofNotifyEvent(EInitialized, _majorFirmwareVersion, this);157}
158
159bool ofArduino::connect(const std::string & device, int baud) {160connectTime = ofGetElapsedTimef();161_initialized = false;162connected = _port.setup(device.c_str(), baud);163sendFirmwareVersionRequest();164return connected;165}
166
167// this method is not recommended
168// the preferred method is to listen for the EInitialized event in your application
169bool ofArduino::isArduinoReady() {170if (bUseDelay) {171if (!_initialized && (ofGetElapsedTimef() - connectTime) > OF_ARDUINO_DELAY_LENGTH) {172sendPinCapabilityRequest();173connected = true;174}175}176return connected;177}
178
179void ofArduino::setUseDelay(bool bDelay) {180bUseDelay = bDelay;181}
182
183void ofArduino::setDigitalHistoryLength(int length) {184if (length >= 2) {185_digitalHistoryLength = length;186}187}
188
189void ofArduino::setAnalogHistoryLength(int length) {190if (length >= 2) {191_analogHistoryLength = length;192}193}
194
195void ofArduino::setSysExHistoryLength(int length) {196if (length >= 1) {197_sysExHistoryLength = length;198}199}
200
201void ofArduino::setStringHistoryLength(int length) {202if (length >= 1) {203_stringHistoryLength = length;204}205}
206
207void ofArduino::disconnect() {208_port.close();209}
210
211void ofArduino::update() {212vector <unsigned char> bytesToProcess;213int bytesToRead = _port.available();214if (bytesToRead > 0) {215bytesToProcess.resize(bytesToRead);216//its possible we dont get all the bytes217int bytesRead = _port.readBytes(&bytesToProcess[0], bytesToRead);218for (int i = 0; i < bytesRead; i++) {219processData((char)(bytesToProcess[i]));220}221}222}
223
224int ofArduino::getAnalog(int pin) const {225if (!isAnalogPin(pin)) {226return -1;227}228if (_digitalPinMode[convertAnalogPinToDigital(pin)] != ARD_ANALOG) {229ofLogError("ofArduino") << "Analog Input has not been configured for pin " << pin;230return -1;231}232pin = convertDigitalPinToAnalog(pin);233if (_analogHistory[pin].size() > 0) {234return _analogHistory[pin].front();235}236else {237return -1;238}239}
240
241int ofArduino::getDigital(int pin) const {242if (!isPin(pin)) {243return -1;244}245if ((_digitalPinMode[pin] == ARD_INPUT || _digitalPinMode[pin] == ARD_INPUT_PULLUP) && _digitalHistory[pin].size() > 0) {246return _digitalHistory[pin].front();247}248else if (_digitalPinMode[pin] == ARD_OUTPUT) {249return _digitalPinValue[pin];250}251else {252return -1;253}254}
255
256int ofArduino::getPwm(int pin) const {257if (!isPin(pin)) {258return -1;259}260if (!pinCapabilities[pin].pwmSupported) {261ofLogError("ofArduino") << "PWM is not supported for pin " << pin;262return -1;263}264if (_digitalPinMode[pin] == ARD_PWM) {265return _digitalPinValue[pin];266}267else {268return -1;269}270}
271
272vector <unsigned char> ofArduino::getSysEx() const {273return _sysExHistory.front();274}
275
276string ofArduino::getString() const {277return _stringHistory.front();278}
279
280int ofArduino::getDigitalPinMode(int pin) const {281if (!isPin(pin)) {282return -1;283}284return _digitalPinMode[pin];285}
286
287void ofArduino::sendDigital(int pin, int value, bool force) {288if (!isPin(pin)) {289return;290}291if ((_digitalPinMode[pin] == ARD_INPUT || _digitalPinMode[pin] == ARD_INPUT_PULLUP || _digitalPinMode[pin] == ARD_OUTPUT) && (_digitalPinValue[pin] != value || force)) {292
293_digitalPinValue[pin] = value;294
295// set the bit296int port = (pin >> 3) & 0x0F;297
298if (value == 1)299_digitalPortValue[port] |= (1 << (pin & 0x07));300
301// clear the bit302if (value == 0)303_digitalPortValue[port] &= ~(1 << (pin & 0x07));304
305sendByte(DIGITAL_MESSAGE | port);306sendValueAsTwo7bitBytes(_digitalPortValue[port]);307
308}309}
310
311void ofArduino::sendPwm(int pin, int value, bool force) {312if (!isPin(pin)) {313return;314}315if (!pinCapabilities[pin].pwmSupported) {316ofLogError("ofArduino") << "PWM is not supported for pin " << pin;317return;318}319if (_digitalPinMode[pin] == ARD_PWM && (_digitalPinValue[pin] != value || force)) {320sendByte(ANALOG_MESSAGE | pin);321sendValueAsTwo7bitBytes(value);322_digitalPinValue[pin] = value;323}324}
325
326void ofArduino::sendSysEx(int command, vector <unsigned char> data) {327sendByte(START_SYSEX);328sendByte(command);329vector <unsigned char>::iterator it = data.begin();330while (it != data.end()) {331sendValueAsTwo7bitBytes(*it);332it++;333}334sendByte(END_SYSEX);335}
336
337void ofArduino::sendSysExBegin() {338sendByte(START_SYSEX);339}
340
341void ofArduino::sendSysExEnd() {342sendByte(END_SYSEX);343}
344
345void ofArduino::sendString(string str) {346sendByte(START_SYSEX);347sendByte(STRING_DATA);348string::iterator it = str.begin();349while (it != str.end()) {350sendValueAsTwo7bitBytes(*it);351it++;352}353sendByte(END_SYSEX);354}
355
356void ofArduino::sendProtocolVersionRequest() {357sendByte(REPORT_VERSION);358}
359
360void ofArduino::sendFirmwareVersionRequest() {361sendByte(START_SYSEX);362sendByte(REPORT_FIRMWARE);363sendByte(END_SYSEX);364}
365
366//this currently isn't supported as the resonse is not mapped
367void ofArduino::sendPinCofigurationRequest() {368sendByte(START_SYSEX);369sendByte(PIN_STATE_QUERY);370sendByte(END_SYSEX);371}
372
373void ofArduino::sendPinCapabilityRequest() {374sendByte(START_SYSEX);375sendByte(CAPABILITY_QUERY);376sendByte(END_SYSEX);377}
378
379void ofArduino::sendAnalogMappingRequest()380{
381sendByte(START_SYSEX);382sendByte(ANALOG_MAPPING_QUERY);383sendByte(END_SYSEX);384}
385
386void ofArduino::sendPinStateQuery(int pin)387{
388sendByte(START_SYSEX);389sendByte(PIN_STATE_QUERY);390sendByte(pin & 0x7f);391sendByte(END_SYSEX);392}
393
394void ofArduino::sendReset() {395sendByte(SYSTEM_RESET);396}
397
398void ofArduino::sendAnalogPinReporting(int pin, int mode) {399if (!isAnalogPin(pin)) {400return;401}402
403//the digital pin mode needs the digital pin #404_digitalPinMode[convertAnalogPinToDigital(pin)] = ARD_ANALOG;405
406//the sent message needs the analog pin #407sendByte(REPORT_ANALOG | convertDigitalPinToAnalog(pin));408sendByte(mode);409_analogPinReporting[convertDigitalPinToAnalog(pin)] = mode;410}
411
412void ofArduino::sendDigitalPinMode(int pin, int mode) {413if (!isPin(pin)) {414return;415}416switch (mode) {417case ARD_INPUT:418case ARD_INPUT_PULLUP:419if (!pinCapabilities[pin].inputSupported) {420ofLogError("ofArduino") << "Input is not supported for pin " << pin;421return;422}423break;424case ARD_OUTPUT:425if (!pinCapabilities[pin].outputSupported) {426ofLogError("ofArduino") << "Output is not supported for pin " << pin;427return;428}429break;430case ARD_ANALOG:431if (!pinCapabilities[pin].analogSupported) {432ofLogError("ofArduino") << "Analog is not supported for pin " << pin;433return;434}435break;436case ARD_PWM:437if (!pinCapabilities[pin].pwmSupported) {438ofLogError("ofArduino") << "PWM is not supported for pin " << pin;439return;440}441break;442case ARD_SERVO:443if (!pinCapabilities[pin].servoSupported) {444ofLogError("ofArduino") << "Servo Control is not supported for pin " << pin;445return;446}447break;448case ARD_I2C:449if (!pinCapabilities[pin].i2cSupported) {450ofLogError("ofArduino") << "I2C is not supported for pin " << pin;451return;452}453break;454case ARD_ONEWIRE:455if (!pinCapabilities[pin].onewireSupported) {456ofLogError("ofArduino") << "Onewire is not supported for pin " << pin;457return;458}459break;460case ARD_STEPPER:461if (!pinCapabilities[pin].stepperSupported) {462ofLogError("ofArduino") << "Stepper Control is not supported for pin " << pin;463return;464}465break;466case ARD_ENCODER:467if (!pinCapabilities[pin].encoderSupported) {468ofLogError("ofArduino") << "Encoder Control is not supported for pin " << pin;469return;470}471break;472case ARD_SERIAL:473if (!pinCapabilities[pin].serialSupported) {474ofLogError("ofArduino") << "Serial is not supported for pin" + ofToString(pin);475return;476}477break;478default:479ofLogError("ofArduino") << "Mode is not supported";480return;481break;482}483sendByte(SET_PIN_MODE);484sendByte(pin); // Tx pins 0-6485sendByte(mode);486_digitalPinMode[pin] = mode;487
488// turn on or off reporting on the port489
490if (mode == ARD_INPUT || mode == ARD_INPUT_PULLUP) {491sendDigitalPinReporting(pin, ARD_ON);492}493else {494sendDigitalPinReporting(pin, ARD_OFF);495}496
497}
498
499int ofArduino::getAnalogPinReporting(int pin) const {500if (!isAnalogPin(pin)) {501return -1;502}503if (_digitalPinMode[convertAnalogPinToDigital(pin)] != ARD_ANALOG) {504ofLogError("ofArduino") << "Analog Input has not been configured for pin " << pin;505return -1;506}507//these are just safety checks508pin = convertDigitalPinToAnalog(pin);509return _analogPinReporting[pin];510}
511
512list <int> * ofArduino::getAnalogHistory(int pin) {513if (!isAnalogPin(pin)) {514return NULL;515}516if (_digitalPinMode[convertAnalogPinToDigital(pin)] != ARD_ANALOG) {517ofLogError("ofArduino") << "Analog Input has not been configured for pin " << pin;518return NULL;519}520pin = convertDigitalPinToAnalog(pin);521return &_analogHistory[pin];522}
523
524list <int> * ofArduino::getDigitalHistory(int pin) {525if (!isPin(pin)) {526return NULL;527}528return &_digitalHistory[pin];529}
530
531list <vector <unsigned char> > * ofArduino::getSysExHistory() {532return &_sysExHistory;533}
534
535list <string> * ofArduino::getStringHistory() {536return &_stringHistory;537}
538
539int ofArduino::getMajorFirmwareVersion() const {540return _majorFirmwareVersion;541}
542
543int ofArduino::getMinorFirmwareVersion() const {544return _minorFirmwareVersion;545}
546
547string ofArduino::getFirmwareName() const {548return _firmwareName;549}
550
551bool ofArduino::isInitialized() const {552return _initialized;553}
554
555bool ofArduino::isAttached() {556//should return false if there is a serial error thus the arduino is not attached557return _port.writeByte(static_cast<unsigned char>(END_SYSEX));558}
559
560// ------------------------------ private functions
561
562void ofArduino::processData(unsigned char inputData) {563ofLog() << "Received Byte: " << inputData;564
565// we have command data566if (_waitForData > 0 && inputData < 128) {567_waitForData--;568
569// collect the data570_storedInputData[_waitForData] = inputData;571
572// we have all data executeMultiByteCommand573if (_waitForData == 0) {574switch (_executeMultiByteCommand) {575case DIGITAL_MESSAGE:576processDigitalPort(_multiByteChannel, (_storedInputData[0] << 7) | _storedInputData[1]);577break;578
579case REPORT_VERSION: // report version580_majorFirmwareVersion = _storedInputData[1];581_minorFirmwareVersion = _storedInputData[0];582ofNotifyEvent(EFirmwareVersionReceived, _majorFirmwareVersion, this);583break;584
585case ANALOG_MESSAGE:586if (_initialized) {587if (_analogHistory[_multiByteChannel].size() > 0) {588int previous = _analogHistory[_multiByteChannel].front();589
590_analogHistory[_multiByteChannel].push_front((_storedInputData[0] << 7) | _storedInputData[1]);591if ((int)_analogHistory[_multiByteChannel].size() > _analogHistoryLength) {592_analogHistory[_multiByteChannel].pop_back();593}594
595// trigger an event if the pin has changed value596if (_analogHistory[_multiByteChannel].front() != previous) {597ofNotifyEvent(EAnalogPinChanged, _multiByteChannel, this);598}599}600else {601_analogHistory[_multiByteChannel].push_front((_storedInputData[0] << 7) | _storedInputData[1]);602if ((int)_analogHistory[_multiByteChannel].size() > _analogHistoryLength) {603_analogHistory[_multiByteChannel].pop_back();604}605}606}607break;608}609
610}611}612// we have SysEx command data613else if (_waitForData < 0) {614
615// we have all sysex data616if (inputData == END_SYSEX) {617_waitForData = 0;618processSysExData(_sysExData);619_sysExData.clear();620}621// still have data, collect it622else {623_sysExData.push_back((unsigned char)inputData);624}625}626// we have a command627else {628
629int command;630
631// extract the command and channel info from a byte if it is less than 0xF0632if (inputData < 0xF0) {633command = inputData & 0xF0;634_multiByteChannel = inputData & 0x0F;635}636else {637// commands in the 0xF* range don't use channel data638command = inputData;639}640
641switch (command) {642case REPORT_VERSION:643case DIGITAL_MESSAGE:644case ANALOG_MESSAGE:645_waitForData = 2; // 2 bytes needed646_executeMultiByteCommand = command;647break;648
649case START_SYSEX:650_sysExData.clear();651_waitForData = -1; // n bytes needed, -1 is used to indicate sysex message652_executeMultiByteCommand = command;653break;654}655
656}657}
658
659// sysex data is assumed to be 8-bit bytes split into two 7-bit bytes.
660void ofArduino::processSysExData(vector <unsigned char> data) {661
662string str;663
664vector <unsigned char>::iterator it;665unsigned char buffer;666//int i = 1;667
668// act on reserved sysEx messages (extended commands) or trigger SysEx event...669switch (data.front()) { //first byte in buffer is command670case REPORT_FIRMWARE:671ofLogVerbose("ofArduino") << "Recieved Firmware Report";672it = data.begin();673it++; // skip the first byte, which is the firmware version command674_majorFirmwareVersion = *it;675it++;676_minorFirmwareVersion = *it;677it++;678
679while (it != data.end()) {680buffer = *it;681it++;682buffer += *it << 7;683it++;684str += buffer;685}686_firmwareName = str;687
688ofNotifyEvent(EFirmwareVersionReceived, _majorFirmwareVersion, this);689
690// trigger the initialization event691if (!_initialized) {692sendPinCapabilityRequest();693}694
695break;696
697case STRING_DATA:698ofLogVerbose("ofArduino") << "Recieved Firamta String";699it = data.begin();700it++; // skip the first byte, which is the string command701while (it != data.end()) {702buffer = *it;703it++;704buffer += *it << 7;705it++;706str += buffer;707}708
709_stringHistory.push_front(str);710if ((int)_stringHistory.size() > _stringHistoryLength) {711_stringHistory.pop_back();712}713
714ofNotifyEvent(EStringReceived, str, this);715break;716case I2C_REPLY:717ofLogVerbose("ofArduino") << "Recieved I2C Reply";718if (data.size() > 7 && (data.size() - 5) % 2 == 0) {719Firmata_I2C_Data i2creply;720it = data.begin();721
722i2creply.address = *++it | (*++it << 7);723i2creply.reg = *++it | (*++it << 7);724
725it++;726while (it != data.end()) {727str += *it | (*++it << 7);728it++;729}730i2creply.data = str;731ofNotifyEvent(EI2CDataRecieved, i2creply, this);732}733else {734ofLogError("Arduino I2C") << "Incorrect Number of Bytes recieved, possible buffer overflow";735purge();736}737break;738case ENCODER_DATA:739ofLogVerbose("ofArduino") << "Recieved Encoder Data";740if (data.size() % 5 == 1) {741
742vector<Firmata_Encoder_Data> encoderReply;743Firmata_Encoder_Data tempEncoderReply;744int encoderPos = 0;745unsigned char encBuffer[4];746
747it = data.begin();748it++; // skip the first byte, which is the string command749
750while (it != data.end()) {751tempEncoderReply.ID = (*it & ENCODER_CHANNEL_MASK);752tempEncoderReply.direction = (*it & ENCODER_DIRECTION_MASK);753
754it++;755
756encBuffer[0] = *it++ & 0x7F;757encBuffer[1] = *it++ & 0x7F;758encBuffer[2] = *it++ & 0x7F;759encBuffer[3] = *it++ & 0x7F;760
761encoderPos = encBuffer[3];762encoderPos <<= 7;763encoderPos |= encBuffer[2];764encoderPos <<= 7;765encoderPos |= encBuffer[1];766encoderPos <<= 7;767encoderPos |= encBuffer[0];768
769tempEncoderReply.position = encoderPos;770encoderReply.push_back(tempEncoderReply);771}772ofNotifyEvent(EEncoderDataReceived, encoderReply, this);773}774else {775ofLogError("Arduino Encoder") << "Incorrect Number of Bytes recieved, possible buffer overflow";776purge();777}778
779break;780case SERIAL_MESSAGE:781{782ofLogVerbose("ofArduino") << "Recieved Serial Message";783Firmata_Serial_Data reply;784
785it = data.begin();786//unsigned char command = *it & 0xF0;787unsigned char portId = *it & 0x0F;788it++; // skip the first byte, which is the command and port789
790while (it != data.end()) {791buffer = *it;792it++;793buffer += *it << 7;794it++;795str += buffer;796}797switch (portId) {798case HW_SERIAL0:799reply.portID = HW_SERIAL0;800break;801case HW_SERIAL1:802reply.portID = HW_SERIAL1;803break;804case HW_SERIAL2:805reply.portID = HW_SERIAL2;806break;807case HW_SERIAL3:808reply.portID = HW_SERIAL3;809break;810case SW_SERIAL0:811reply.portID = SW_SERIAL0;812break;813case SW_SERIAL1:814reply.portID = SW_SERIAL1;815break;816case SW_SERIAL2:817reply.portID = SW_SERIAL2;818break;819case SW_SERIAL3:820reply.portID = SW_SERIAL3;821break;822default:823ofLogError("Arduino Serial") << "Port does not exist or is not defined";824}825reply.data = str;826ofNotifyEvent(ESerialDataReceived, reply, this);827}828break;829case CAPABILITY_RESPONSE:830{831ofLogVerbose("ofArduino") << "Recieved Capability Response";832it = data.begin();833it += 2; // skip the first byte, which is the string command834
835int pin = 1;836
837firmataInputSupported = false;838firmataOutputSupported = false;839firmataAnalogSupported = false;840firmataPwmSupported = false;841firmataServoSupported = false;842firmataI2cSupported = false;843firmataSerialSupported = false;844firmataOnewireSupported = false;845firmataStepperSupported = false;846firmataEncoderSupported = false;847
848while (it != data.end()) {849switch (*it) {850case ARD_INPUT:851pinCapabilities[pin].inputSupported = true;852pinCapabilities[pin].outputSupported = true;853firmataInputSupported = true;854firmataOutputSupported = true;855it += 6;856break;857case ARD_ANALOG:858pinCapabilities[pin].analogSupported = true;859it += 2;860if (!firmataAnalogSupported)861_firstAnalogPin = pin;862firmataAnalogSupported = true;863break;864case ARD_PWM:865pinCapabilities[pin].pwmSupported = true;866firmataPwmSupported = true;867it += 2;868break;869case ARD_SERVO:870pinCapabilities[pin].servoSupported = true;871firmataServoSupported = true;872it += 2;873break;874case ARD_I2C:875pinCapabilities[pin].i2cSupported = true;876firmataI2cSupported = true;877it += 2;878break;879case ARD_SERIAL:880pinCapabilities[pin].serialSupported = true;881firmataI2cSupported = true;882it += 2;883break;884case ARD_ONEWIRE:885pinCapabilities[pin].onewireSupported = true;886firmataOnewireSupported = true;887it += 2;888break;889case ARD_STEPPER:890pinCapabilities[pin].stepperSupported = true;891firmataStepperSupported = true;892it += 2;893break;894case ARD_ENCODER:895pinCapabilities[pin].encoderSupported = true;896firmataEncoderSupported = true;897it += 2;898break;899default:900it++;901if (it != data.end()) {902supportedPinTypes temp;903pinCapabilities.emplace(++pin, temp);904}905break;906}907}908_totalDigitalPins = pin;909if (!_initialized) {910sendAnalogMappingRequest();911}912}913break;914case ANALOG_MAPPING_RESPONSE:915{916ofLogVerbose("ofArduino") << "Recieved Analog Map Query Response";917it = data.begin();918int pin = 0;919bool fAPin = false;920it++; // skip the first byte, which is the string command921_totalAnalogPins = 0;922while (it != data.end()) {923//from the firmata protocol924//analog channel corresponding to pin x, or 127 if pin x does not support analog925if (*it != 127) {926analogPinMap.emplace(int(*it), pin);927_totalAnalogPins++;928//these should be set by the capability query but just incase929pinCapabilities[pin].analogSupported = true;930if (!firmataAnalogSupported)931firmataAnalogSupported = true;932
933//lets also make sure that the capability response and this match up934if (!fAPin) {935if (pin != _firstAnalogPin)936ofLogNotice("ofArduino") << "Capabaility Query and Analog Map don't match up";937_firstAnalogPin = pin;938fAPin = true;939}940}941pin++;942*it++;943}944if (!_initialized) {945initPins();946}947}948break;949case PIN_STATE_RESPONSE:950{951ofLogVerbose("ofArduino") << "Recieved Pin State Query Response";952it = data.begin();953it++; // skip the first byte, which is the string command954int pin = *it++;955Firmata_Pin_Modes mode{Firmata_Pin_Modes::MODE_INPUT};956switch (*it++) {957case ARD_INPUT:958mode = Firmata_Pin_Modes::MODE_INPUT;959break;960case ARD_INPUT_PULLUP:961mode = Firmata_Pin_Modes::MODE_INPUT_PULLUP;962break;963case ARD_OUTPUT:964mode = Firmata_Pin_Modes::MODE_OUTPUT;965break;966case ARD_ANALOG:967mode = Firmata_Pin_Modes::MODE_ANALOG;968break;969case ARD_PWM:970mode = Firmata_Pin_Modes::MODE_PWM;971break;972case ARD_SERVO:973mode = Firmata_Pin_Modes::MODE_SERVO;974break;975case ARD_I2C:976mode = Firmata_Pin_Modes::MODE_I2C;977break;978case ARD_SERIAL:979mode = Firmata_Pin_Modes::MODE_SERIAL;980break;981case ARD_ONEWIRE:982mode = Firmata_Pin_Modes::MODE_ONEWIRE;983break;984case ARD_STEPPER:985mode = Firmata_Pin_Modes::MODE_STEPPER;986break;987case ARD_ENCODER:988mode = Firmata_Pin_Modes::MODE_ENCODER;989break;990}991
992pair<int, Firmata_Pin_Modes> reply(pin, mode);993ofNotifyEvent(EPinStateResponseReceived, reply, this);994}995break;996default: // the message isn't in Firmatas extended command set997ofLogVerbose("ofArduino") << "This message isn't in Firmatas extended command set";998_sysExHistory.push_front(data);999if ((int)_sysExHistory.size() > _sysExHistoryLength) {1000_sysExHistory.pop_back();1001}1002ofNotifyEvent(ESysExReceived, data, this);1003break;1004
1005}1006}
1007
1008void ofArduino::processDigitalPort(int port, unsigned char value) {1009
1010if (!_initialized)1011return;1012unsigned char mask;1013int previous;1014int pin;1015
1016for (int i = 0; i < 8; ++i) {1017pin = i + (port * 8);1018if (pin <= _totalDigitalPins && (_digitalPinMode[pin] == ARD_INPUT || _digitalPinMode[pin] == ARD_INPUT_PULLUP)) {1019if (!_digitalHistory[pin].empty())1020previous = _digitalHistory[pin].front();1021else previous = 0;1022
1023mask = 1 << i;1024_digitalHistory[pin].push_front((value & mask) >> i);1025
1026if ((int)_digitalHistory[pin].size() > _digitalHistoryLength)1027_digitalHistory[pin].pop_back();1028
1029// trigger an event if the pin has changed value1030if (_digitalHistory[pin].front() != previous) {1031ofNotifyEvent(EDigitalPinChanged, pin, this);1032}1033}1034}1035}
1036
1037void ofArduino::sendDigitalPortReporting(int port, int mode) {1038sendByte(REPORT_DIGITAL | port);1039sendByte(mode);1040_digitalPortReporting[port] = mode;1041}
1042
1043void ofArduino::sendDigitalPinReporting(int pin, int mode) {1044
1045int port = floor(pin / 8);1046if (mode == ARD_OFF || mode == ARD_ON) {1047_digitalPinReporting[pin] = mode;1048sendDigitalPortReporting(port, mode);1049}1050}
1051
1052void ofArduino::sendByte(unsigned char byte) {1053_port.writeByte(byte);1054}
1055
1056// in Firmata (and MIDI) data bytes are 7-bits. The 8th bit serves as a flag to mark a byte as either command or data.
1057// therefore you need two data bytes to send 8-bits (a char).
1058void ofArduino::sendValueAsTwo7bitBytes(int value) {1059sendByte(value & 127); // LSB1060sendByte(value >> 7 & 127); // MSB1061}
1062
1063// SysEx data is sent as 8-bit bytes split into two 7-bit bytes, this function merges two 7-bit bytes back into one 8-bit byte.
1064int ofArduino::getValueFromTwo7bitBytes(unsigned char lsb, unsigned char msb) {1065return (msb << 7) | lsb;1066}
1067
1068int ofArduino::getInvertedValueFromTwo7bitBytes(unsigned char lsb, unsigned char msb) {1069return msb | (lsb << 7);1070}
1071
1072/********************************************
1073*
1074*
1075* Servo Functions
1076*
1077*
1078********************************************/
1079
1080void ofArduino::sendServoAttach(int pin, int minPulse, int maxPulse) {1081if (!isPin(pin)) {1082return;1083}1084if (!pinCapabilities[pin].servoSupported) {1085ofLogError("ofArduino") << "Servo Control is not supported for pin" + ofToString(pin);1086return;1087}1088sendByte(START_SYSEX);1089sendByte(SERVO_CONFIG);1090sendByte(pin);1091sendValueAsTwo7bitBytes(minPulse);1092sendValueAsTwo7bitBytes(maxPulse);1093sendByte(END_SYSEX);1094_digitalPinMode[pin] = ARD_SERVO;1095}
1096
1097void ofArduino::sendServo(int pin, int value, bool force) {1098if (!isPin(pin)) {1099return;1100}1101if (!pinCapabilities[pin].servoSupported) {1102ofLogError("ofArduino") << "Servo Control is not supported for pin " + ofToString(pin);1103return;1104}1105if (_digitalPinMode[pin] != ARD_SERVO) {1106ofLogError("ofArduino") << "Servo Control is not configured for pin " + ofToString(pin) + ". Did you send a servo attach message?";1107return;1108}1109if (_digitalPinValue[pin] != value || force) {1110if (pin > 15) {1111sendByte(START_SYSEX);1112sendByte(EXTENDED_ANALOG);1113sendByte(pin);1114sendValueAsTwo7bitBytes(value);1115sendByte(END_SYSEX);1116
1117}1118else {1119sendByte(ANALOG_MESSAGE | pin);1120sendValueAsTwo7bitBytes(value);1121_digitalPinValue[pin] = value;1122}1123}1124}
1125
1126int ofArduino::getServo(int pin) const {1127if (!isPin(pin)) {1128return -1;1129}1130if (!pinCapabilities[pin].servoSupported) {1131ofLogError("ofArduino") << "Servo Control is not supported for pin" + ofToString(pin);1132return -1;1133}1134if (_digitalPinMode[pin] == ARD_SERVO) {1135return _digitalPinValue[pin];1136}1137else {1138return -1;1139}1140}
1141
1142/********************************************
1143*
1144*
1145* Stepper Functions
1146*
1147*
1148********************************************/
1149
1150void ofArduino::sendStepper2Wire(int dirPin, int stepPin, int stepsPerRev) {1151if (!isPin(dirPin)) {1152return;1153}1154if (!isPin(stepPin)) {1155return;1156}1157if (!pinCapabilities[dirPin].stepperSupported) {1158ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(dirPin);1159return;1160}1161if (!pinCapabilities[stepPin].stepperSupported) {1162ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(stepPin);1163return;1164}1165if (_numSteppers < MAX_STEPPERS) {1166sendByte(START_SYSEX);1167sendByte(STEPPER_DATA);1168sendByte(STEPPER_CONFIG);1169sendByte(_numSteppers);1170sendByte(FIRMATA_STEPPER_DRIVER);1171sendValueAsTwo7bitBytes(stepsPerRev);1172sendByte(dirPin);1173sendByte(stepPin);1174sendByte(END_SYSEX);1175_digitalPinMode[dirPin] = ARD_STEPPER;1176_digitalPinMode[stepPin] = ARD_STEPPER;1177_numSteppers++;1178}1179else {1180ofLogNotice("Arduino") << "Reached max number of steppers";1181}1182}
1183
1184void ofArduino::sendStepper4Wire(int pin1, int pin2, int pin3, int pin4, int stepsPerRev) {1185if (!isPin(pin1)) {1186return;1187}1188if (!isPin(pin2)) {1189return;1190}1191if (!isPin(pin3)) {1192return;1193}1194if (!isPin(pin4)) {1195return;1196}1197if (!pinCapabilities[pin1].stepperSupported) {1198ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(pin1);1199return;1200}1201if (!pinCapabilities[pin2].stepperSupported) {1202ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(pin2);1203return;1204}1205if (!pinCapabilities[pin3].stepperSupported) {1206ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(pin3);1207return;1208}1209if (!pinCapabilities[pin4].stepperSupported) {1210ofLogError("ofArduino") << "Stepper Control is not supported for pin" + ofToString(pin4);1211return;1212}1213if (_numSteppers < MAX_STEPPERS) {1214sendByte(START_SYSEX);1215sendByte(STEPPER_DATA);1216sendByte(STEPPER_CONFIG);1217sendByte(_numSteppers);1218sendByte(FIRMATA_STEPPER_FOUR_WIRE);1219sendValueAsTwo7bitBytes(stepsPerRev);1220sendByte(pin1);1221sendByte(pin2);1222sendByte(pin3);1223sendByte(pin4);1224sendByte(END_SYSEX);1225
1226_digitalPinMode[pin1] = ARD_STEPPER;1227_digitalPinMode[pin2] = ARD_STEPPER;1228_digitalPinMode[pin3] = ARD_STEPPER;1229_digitalPinMode[pin4] = ARD_STEPPER;1230_numSteppers++;1231}1232else {1233ofLogNotice("Arduino") << "Reached max number of steppers";1234}1235
1236}
1237
1238void ofArduino::sendStepperMove(int stepperID, int direction, int numSteps, int speed, float acceleration, float deceleration) {1239
1240if (stepperID <= _numSteppers && stepperID >= 0) {1241unsigned char steps[3] = { static_cast<unsigned char>(abs(numSteps) & 0x0000007F), static_cast<unsigned char>((abs(numSteps) >> 7) & 0x0000007F), static_cast<unsigned char>((abs(numSteps) >> 14) & 0x0000007F) };1242
1243// the stepper interface expects decimal expressed an an integer1244if (acceleration != 0 && deceleration != 0) {1245int accel = floor(acceleration * 100);1246int decel = floor(deceleration * 100);1247
1248sendByte(START_SYSEX);1249sendByte(STEPPER_DATA);1250sendByte(STEPPER_STEP);1251sendByte(stepperID);1252sendByte(direction);1253sendByte(steps[0]);1254sendByte(steps[1]);1255sendByte(steps[2]);1256sendValueAsTwo7bitBytes(speed);1257sendValueAsTwo7bitBytes(accel);1258sendValueAsTwo7bitBytes(decel);1259sendByte(END_SYSEX);1260
1261}1262else {1263sendByte(START_SYSEX);1264sendByte(STEPPER_DATA);1265sendByte(STEPPER_STEP);1266sendByte(stepperID);1267sendByte(direction);1268sendByte(steps[0]);1269sendByte(steps[1]);1270sendByte(steps[2]);1271sendValueAsTwo7bitBytes(speed);1272sendByte(END_SYSEX);1273}1274}1275}
1276
1277
1278/********************************************
1279*
1280*
1281* I2C Functions
1282*
1283*
1284********************************************/
1285
1286void ofArduino::sendI2CConfig(int delay) {1287sendByte(START_SYSEX);1288sendByte(I2C_CONFIG);1289sendByte(delay & 0xFF);1290sendByte((delay >> 8) & 0xFF);1291sendByte(END_SYSEX);1292
1293_i2cConfigured = true;1294}
1295
1296void ofArduino::sendI2CWriteRequest(char slaveAddress, unsigned char * bytes, int numOfBytes, int reg) {1297
1298if (_i2cConfigured) {1299sendByte(START_SYSEX);1300sendByte(I2C_REQUEST);1301sendByte(slaveAddress);1302sendByte(FIRMATA_I2C_WRITE << 3);1303if (reg >= 0) {1304sendValueAsTwo7bitBytes(reg);1305}1306for (int i = 0, length = numOfBytes; i < length; i++) {1307sendValueAsTwo7bitBytes(bytes[i]);1308}1309
1310sendByte(END_SYSEX);1311}1312else {1313ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1314}1315}
1316
1317void ofArduino::sendI2CWriteRequest(char slaveAddress, char * bytes, int numOfBytes, int reg) {1318if (_i2cConfigured) {1319sendByte(START_SYSEX);1320sendByte(I2C_REQUEST);1321sendByte(slaveAddress);1322sendByte(FIRMATA_I2C_WRITE << 3);1323if (reg >= 0) {1324sendValueAsTwo7bitBytes(reg);1325}1326for (int i = 0, length = numOfBytes; i < length; i++) {1327sendValueAsTwo7bitBytes(bytes[i]);1328}1329
1330sendByte(END_SYSEX);1331}1332else {1333ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1334}1335}
1336
1337void ofArduino::sendI2CWriteRequest(char slaveAddress, const char * bytes, int numOfBytes, int reg) {1338if (_i2cConfigured) {1339sendByte(START_SYSEX);1340sendByte(I2C_REQUEST);1341sendByte(slaveAddress);1342sendByte(FIRMATA_I2C_WRITE << 3);1343if (reg >= 0) {1344sendValueAsTwo7bitBytes(reg);1345}1346for (int i = 0, length = numOfBytes; i < length; i++) {1347sendValueAsTwo7bitBytes(bytes[i]);1348}1349
1350sendByte(END_SYSEX);1351}1352else {1353ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1354}1355}
1356
1357void ofArduino::sendI2CWriteRequest(char slaveAddress, vector<char> bytes, int reg) {1358
1359if (_i2cConfigured) {1360sendByte(START_SYSEX);1361sendByte(I2C_REQUEST);1362sendByte(slaveAddress);1363sendByte(FIRMATA_I2C_WRITE << 3);1364if (reg >= 0) {1365sendValueAsTwo7bitBytes(reg);1366}1367for (int i = 0, length = bytes.size(); i < length; i++) {1368sendValueAsTwo7bitBytes(bytes[i]);1369}1370
1371sendByte(END_SYSEX);1372}1373else {1374ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1375}1376}
1377
1378void ofArduino::sendI2CReadRequest(char address, int numBytes, int reg) {1379
1380if (_i2cConfigured) {1381sendByte(START_SYSEX);1382sendByte(I2C_REQUEST);1383sendByte(address);1384sendByte(FIRMATA_I2C_READ << 3);1385if (reg >= 0) {1386sendValueAsTwo7bitBytes(reg);1387}1388sendValueAsTwo7bitBytes(numBytes);1389sendByte(END_SYSEX);1390}1391else {1392ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1393}1394}
1395
1396void ofArduino::sendI2ContinuousReadRequest(char address, int numBytes, int reg) {1397if (_i2cConfigured) {1398sendByte(START_SYSEX);1399sendByte(I2C_REQUEST);1400sendByte(address);1401sendByte(FIRMATA_I2C_CONTINUOUS_READ << 3);1402if (reg >= 0) {1403sendValueAsTwo7bitBytes(reg);1404}1405sendValueAsTwo7bitBytes(numBytes);1406sendByte(END_SYSEX);1407}1408else {1409ofLogError("Arduino") << "I2C was not configured, did you send an I2C config request?";1410}1411}
1412
1413bool ofArduino::isI2CConfigured() {1414return _i2cConfigured;1415}
1416
1417// CONTINUOUS_READ
1418
1419/********************************************
1420*
1421*
1422* One Wire Functions
1423*
1424*
1425********************************************/
1426
1427void ofArduino::sendOneWireConfig(int pin, bool enableParasiticPower) {1428if (!isPin(pin)) {1429return;1430}1431if (!pinCapabilities[pin].onewireSupported) {1432ofLogError("ofArduino") << "Onewire is not supported for pin " << pin;1433return;1434}1435sendByte(START_SYSEX);1436sendByte(ONEWIRE_DATA);1437sendByte(ONEWIRE_CONFIG_REQUEST);1438sendByte(pin);1439sendByte(enableParasiticPower ? 0x01 : 0x00);1440sendByte(END_SYSEX);1441};1442
1443void ofArduino::sendOneWireSearch(int pin) {1444sendOneWireSearch(ONEWIRE_SEARCH_REQUEST, pin);1445};1446
1447void ofArduino::sendOneWireAlarmsSearch(int pin) {1448sendOneWireSearch(ONEWIRE_SEARCH_ALARMS_REQUEST, pin);1449};1450
1451//needs to notify event handler
1452void ofArduino::sendOneWireSearch(char type, int pin) {1453if (!isPin(pin)) {1454return;1455}1456if (!pinCapabilities[pin].onewireSupported) {1457ofLogError("ofArduino") << "Onewire is not supported for pin " << pin;1458return;1459}1460sendByte(START_SYSEX);1461sendByte(ONEWIRE_DATA);1462sendByte(type);1463sendByte(pin);1464sendByte(END_SYSEX);1465}
1466
1467void ofArduino::sendOneWireRead(int pin, vector<unsigned char> devices, int numBytesToRead) {1468int correlationId = floor(ofRandomuf() * 255);1469vector<unsigned char> b;1470sendOneWireRequest(pin, ONEWIRE_READ_REQUEST_BIT, devices, numBytesToRead, correlationId, 0, b);1471}
1472
1473void ofArduino::sendOneWireReset(int pin) {1474vector<unsigned char> a, b;1475sendOneWireRequest(pin, ONEWIRE_RESET_REQUEST_BIT, a, 0, 0, 0, b);1476};1477
1478void ofArduino::sendOneWireWrite(int pin, vector<unsigned char> devices, vector<unsigned char> data) {1479sendOneWireRequest(pin, ONEWIRE_WRITE_REQUEST_BIT, devices, 0, 0, 0, data);1480};1481
1482void ofArduino::sendOneWireDelay(int pin, unsigned int delay) {1483vector<unsigned char> a, b;1484sendOneWireRequest(pin, ONEWIRE_DELAY_REQUEST_BIT, a, 0, 0, delay, b);1485};1486
1487void ofArduino::sendOneWireWriteAndRead(int pin, vector<unsigned char> devices, vector<unsigned char> data, int numBytesToRead) {1488int correlationId = floor(ofRandomuf() * 255);1489sendOneWireRequest(pin, ONEWIRE_WRITE_REQUEST_BIT | ONEWIRE_READ_REQUEST_BIT, devices, numBytesToRead, correlationId, 0, data);1490}
1491
1492//// see http://firmata.org/wiki/Proposals#OneWire_Proposal
1493void ofArduino::sendOneWireRequest(int pin, unsigned char subcommand, vector<unsigned char> devices, int numBytesToRead, unsigned char correlationId, unsigned int delay, vector<unsigned char> dataToWrite) {1494if (!isPin(pin)) {1495return;1496}1497if (!pinCapabilities[pin].onewireSupported) {1498ofLogError("ofArduino") << "Onewire is not supported for pin " << pin;1499return;1500}1501vector<unsigned char> bytes;1502bytes.resize(16);1503
1504if (devices.size() > 0 || numBytesToRead > 0 || correlationId || delay > 0 || dataToWrite.size() > 0) {1505subcommand = subcommand | ONEWIRE_WITHDATA_REQUEST_BITS;1506}1507
1508if (devices.size() > 0) {1509for (size_t i = 0; i < devices.size(); i++) {1510bytes[i] = devices[i];1511}1512}1513
1514if (numBytesToRead > 0) {1515bytes[8] = numBytesToRead & 0xFF;1516bytes[9] = (numBytesToRead >> 8) & 0xFF;1517}1518
1519if (correlationId) {1520bytes[10] = correlationId & 0xFF;1521bytes[11] = (correlationId >> 8) & 0xFF;1522}1523
1524if (delay > 0) {1525bytes[12] = delay & 0xFF;1526bytes[13] = (delay >> 8) & 0xFF;1527bytes[14] = (delay >> 16) & 0xFF;1528bytes[15] = (delay >> 24) & 0xFF;1529}1530
1531if (dataToWrite.size() > 0) {1532for (size_t i = 0; i < dataToWrite.size(); i++) {1533bytes.push_back(dataToWrite[i]);1534}1535}1536
1537sendByte(START_SYSEX);1538sendByte(ONEWIRE_DATA);1539sendByte(subcommand);1540sendByte(pin);1541int shift = 0;1542int previous = 0;1543//i dont think this is safe1544for (size_t i = 0; i < bytes.size(); i++) {1545if (shift == 0) {1546sendByte(bytes[i] & 0x7f);1547shift++;1548previous = bytes[i] >> 7;1549}1550else {1551sendByte(((bytes[i] << shift) & 0x7f) | previous);1552if (shift == 6) {1553sendByte(bytes[i] >> 1);1554shift = 0;1555}1556else {1557shift++;1558previous = bytes[i] >> (8 - shift);1559}1560}1561}1562if (shift > 0) {1563sendByte(previous);1564}1565
1566sendByte(END_SYSEX);1567}
1568
1569/********************************************
1570*
1571*
1572* Encoder Functions
1573*
1574*
1575********************************************/
1576
1577void ofArduino::attachEncoder(int pinA, int pinB) {1578if (!isPin(pinA)) {1579return;1580}1581if (!isPin(pinB)) {1582return;1583}1584if (!pinCapabilities[pinA].encoderSupported) {1585ofLogError("ofArduino") << "Encoder Control is not supported for pin " + ofToString(pinA);1586return;1587}1588if (!pinCapabilities[pinB].encoderSupported) {1589ofLogError("ofArduino") << "Encoder Control is not supported for pin " + ofToString(pinB);1590return;1591}1592if (_encoderID < MAX_ENCODERS) {1593sendByte(START_SYSEX);1594sendByte(ENCODER_DATA);1595sendByte(ENCODER_ATTACH);1596sendByte(_encoderID);1597sendByte(pinA);1598sendByte(pinB);1599sendByte(END_SYSEX);1600_encoderID++;1601}1602
1603}
1604void ofArduino::getEncoderPosition(int encoderID) {1605if (encoderID <= _encoderID && encoderID >= 0) {1606sendByte(START_SYSEX);1607sendByte(ENCODER_DATA);1608sendByte(ENCODER_REPORT_POSITION);1609sendByte(encoderID);1610sendByte(END_SYSEX);1611}1612}
1613void ofArduino::getAllEncoderPositions() {1614sendByte(START_SYSEX);1615sendByte(ENCODER_DATA);1616sendByte(ENCODER_REPORT_POSITIONS);1617sendByte(END_SYSEX);1618}
1619void ofArduino::resetEncoderPosition(int encoderID) {1620if (encoderID <= _encoderID && encoderID >= 0) {1621sendByte(START_SYSEX);1622sendByte(ENCODER_DATA);1623sendByte(ENCODER_RESET_POSITION);1624sendByte(encoderID);1625sendByte(END_SYSEX);1626}1627}
1628void ofArduino::enableEncoderReporting() {1629sendByte(START_SYSEX);1630sendByte(ENCODER_DATA);1631sendByte(ENCODER_REPORT_AUTO);1632sendByte(1);1633sendByte(END_SYSEX);1634}
1635void ofArduino::disableEncoderReporting() {1636sendByte(START_SYSEX);1637sendByte(ENCODER_DATA);1638sendByte(ENCODER_REPORT_AUTO);1639sendByte(0);1640sendByte(END_SYSEX);1641}
1642void ofArduino::detachEncoder(int encoderID) {1643if (encoderID <= _encoderID && encoderID >= 0) {1644sendByte(START_SYSEX);1645sendByte(ENCODER_DATA);1646sendByte(ENCODER_DETACH);1647sendByte(encoderID);1648sendByte(END_SYSEX);1649_encoderID--;1650}1651}
1652
1653//if the buffer gets out of sync we have to purge everything to get back on track
1654void ofArduino::purge() {1655while (_port.readByte() != -1);1656for (int i = 0; i < 5; i++)1657sendByte(END_SYSEX);1658}
1659
1660/********************************************
1661*
1662*
1663* Serial Functions
1664*
1665*
1666********************************************/
1667
1668void ofArduino::sendSerialConfig(Firmata_Serial_Ports portID, int baud, int rxPin, int txPin) {1669
1670if (portID > 7 && rxPin < 0 && txPin < 0) {1671ofLogError("ofArduino") << "Both RX and TX pins must be defined when using Software Serial.";1672return;1673}1674
1675sendByte(START_SYSEX);1676sendByte(SERIAL_MESSAGE);1677sendByte(SERIAL_CONFIG | portID);1678sendByte(baud & 0x007F);1679sendByte((baud >> 7) & 0x007F);1680sendByte((baud >> 14) & 0x007F);1681
1682if (portID > 7 && rxPin >= 0 && txPin >= 0) {1683sendByte(rxPin);1684sendByte(txPin);1685}1686else if (portID > 7) {1687ofLogError("ofArduino") << "Both RX and TX pins must be defined when using Software Serial.";1688}1689
1690sendByte(END_SYSEX);1691};1692
1693void ofArduino::serialWrite(Firmata_Serial_Ports portID, unsigned char * bytes, int numOfBytes) {1694sendByte(START_SYSEX);1695sendByte(SERIAL_MESSAGE);1696sendByte(SERIAL_WRITE | portID);1697for (int i = 0; i < numOfBytes; i++) {1698sendValueAsTwo7bitBytes(bytes[i]);1699}1700sendByte(END_SYSEX);1701};1702
1703void ofArduino::serialRead(Firmata_Serial_Ports portID, int maxBytesToRead) {1704sendByte(START_SYSEX);1705sendByte(SERIAL_MESSAGE);1706sendByte(SERIAL_READ | portID);1707sendByte(FIRMATA_SERIAL_READ_CONTINUOUS);1708
1709if (maxBytesToRead > 0) {1710sendValueAsTwo7bitBytes(maxBytesToRead);1711}1712
1713sendByte(END_SYSEX);1714};1715
1716void ofArduino::serialStop(Firmata_Serial_Ports portID) {1717sendByte(START_SYSEX);1718sendByte(SERIAL_MESSAGE);1719sendByte(SERIAL_READ | portID);1720sendByte(FIRMATA_SERIAL_STOP_READING);1721sendByte(END_SYSEX);1722};1723
1724void ofArduino::serialClose(Firmata_Serial_Ports portID) {1725sendByte(START_SYSEX);1726sendByte(SERIAL_MESSAGE);1727sendByte(SERIAL_CLOSE | portID);1728sendByte(END_SYSEX);1729};1730
1731void ofArduino::serialFlush(Firmata_Serial_Ports portID) {1732sendByte(START_SYSEX);1733sendByte(SERIAL_MESSAGE);1734sendByte(SERIAL_FLUSH | portID);1735sendByte(END_SYSEX);1736};1737
1738void ofArduino::serialListen(Firmata_Serial_Ports portID) {1739// listen only applies to software serial ports1740if (portID < 8) {1741return;1742}1743sendByte(START_SYSEX);1744sendByte(SERIAL_MESSAGE);1745sendByte(SERIAL_LISTEN | portID);1746sendByte(END_SYSEX);1747};1748
1749
1750
1751//this is mostly safe except for the teensy 2.0, it has 12 analog outs starting at 22 going down to 11
1752//the problem arises if they mean digital pin 11 or analog pin 11 which are not the same
1753//digital pin 11 is analog pin 10 and analog pin 11 is digital pin 22
1754bool ofArduino::isAnalogPin(int pin) const1755{
1756if (isPin(convertAnalogPinToDigital(pin))) {1757if (pin < _firstAnalogPin) // this probably means they are using the Analog pin #1758{1759if (analogPinMap.count(pin) < 1) { //the pin doesnt exist in the analog pin mapping1760ofLogError("ofArduino") << "Analog is not supported for pin " + ofToString(pin);1761return false;1762}1763return true;1764}1765else //they are using the digital pin #1766{1767if (pinCapabilities.count(pin) < 1) {1768ofLogError("ofArduino") << "Analog is not supported for pin " + ofToString(pin);1769return false;1770}1771return true;1772}1773}1774return false;1775}
1776
1777
1778//this should only be false if the pin is negative or greater than the number of pins on the board
1779//just incase we check against the pin capability map if for some reason a pin doesn't exist
1780//pin 0 & 1 are outliers because they dont exist in the capability query but technically exist
1781//we cant really use pin 0 & 1 though as it messes up the serial communication
1782bool ofArduino::isPin(int pin) const1783{
1784if (pin < 0 || pin > _totalDigitalPins) {1785ofLogError("ofArduino") << "Pin " + ofToString(pin) + " does not exist on the current board";1786return false;1787}1788if (pinCapabilities.count(pin) < 1) {1789ofLogError("ofArduino") << "Pin " + ofToString(pin) + " does not exist on the current board";1790return false;1791}1792return true;1793}
1794
1795//this returns the pin if its already not within the analog pin map
1796//we need this to check between digital and analog pin mappings
1797int ofArduino::convertAnalogPinToDigital(size_t pin) const1798{
1799if (pin < analogPinMap.size()) {1800if (analogPinMap.count(pin) > 0) {1801return analogPinMap[pin];1802}1803else {1804ofLogError("ofArduino") << "Pin " + ofToString(pin) + " is not an Analog Pin";1805return -1;1806}1807}1808return pin;1809}
1810
1811//this returns the pin if its already within the analog pin map
1812//we need this to check between digital and analog pin mappings
1813int ofArduino::convertDigitalPinToAnalog(size_t pin) const1814{
1815if (pin > analogPinMap.size()) {1816for (auto aPin : analogPinMap)1817if (aPin.second == (int)pin) {1818return aPin.first;1819}1820ofLogError("ofArduino") << "Pin " + ofToString(pin) + " is not an Analog Pin";1821return -1;1822}1823return pin; //this pin is already in the range of analog pins1824}
1825
1826//these functions can't really account for user error
1827