diff options
Diffstat (limited to 'OpenModelicaArduino/Firmware/Tiva C/StandardFirmata/FirmataParser.cpp')
-rw-r--r-- | OpenModelicaArduino/Firmware/Tiva C/StandardFirmata/FirmataParser.cpp | 480 |
1 files changed, 0 insertions, 480 deletions
diff --git a/OpenModelicaArduino/Firmware/Tiva C/StandardFirmata/FirmataParser.cpp b/OpenModelicaArduino/Firmware/Tiva C/StandardFirmata/FirmataParser.cpp deleted file mode 100644 index d402fdf..0000000 --- a/OpenModelicaArduino/Firmware/Tiva C/StandardFirmata/FirmataParser.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* - FirmataParser.cpp - Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved. - Copyright (C) 2009-2016 Jeff Hoefs. 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 "FirmataParser.h" - -#include "FirmataConstants.h" - -using namespace firmata; - -//****************************************************************************** -//* Constructors -//****************************************************************************** - -/** - * The FirmataParser class. - * @param dataBuffer A pointer to an external buffer used to store parsed data - * @param dataBufferSize The size of the external buffer - */ -FirmataParser::FirmataParser(uint8_t * const dataBuffer, size_t dataBufferSize) -: - dataBuffer(dataBuffer), - dataBufferSize(dataBufferSize), - executeMultiByteCommand(0), - multiByteChannel(0), - waitForData(0), - parsingSysex(false), - sysexBytesRead(0), - currentAnalogCallbackContext((void *)NULL), - currentDigitalCallbackContext((void *)NULL), - currentReportAnalogCallbackContext((void *)NULL), - currentReportDigitalCallbackContext((void *)NULL), - currentPinModeCallbackContext((void *)NULL), - currentPinValueCallbackContext((void *)NULL), - currentReportFirmwareCallbackContext((void *)NULL), - currentReportVersionCallbackContext((void *)NULL), - currentDataBufferOverflowCallbackContext((void *)NULL), - currentStringCallbackContext((void *)NULL), - currentSysexCallbackContext((void *)NULL), - currentSystemResetCallbackContext((void *)NULL), - currentAnalogCallback((callbackFunction)NULL), - currentDigitalCallback((callbackFunction)NULL), - currentReportAnalogCallback((callbackFunction)NULL), - currentReportDigitalCallback((callbackFunction)NULL), - currentPinModeCallback((callbackFunction)NULL), - currentPinValueCallback((callbackFunction)NULL), - currentDataBufferOverflowCallback((dataBufferOverflowCallbackFunction)NULL), - currentStringCallback((stringCallbackFunction)NULL), - currentSysexCallback((sysexCallbackFunction)NULL), - currentReportFirmwareCallback((versionCallbackFunction)NULL), - currentReportVersionCallback((systemCallbackFunction)NULL), - currentSystemResetCallback((systemCallbackFunction)NULL) -{ - allowBufferUpdate = ((uint8_t *)NULL == dataBuffer); -} - -//****************************************************************************** -//* Public Methods -//****************************************************************************** - -//------------------------------------------------------------------------------ -// Serial Receive Handling - -/** - * Parse data from the input stream. - * @param inputData A single byte to be added to the parser. - */ -void FirmataParser::parse(uint8_t inputData) -{ - uint8_t command; - - if (parsingSysex) { - if (inputData == END_SYSEX) { - //stop sysex byte - parsingSysex = false; - //fire off handler function - processSysexMessage(); - } else { - //normal data byte - add to buffer - bufferDataAtPosition(inputData, sysexBytesRead); - ++sysexBytesRead; - } - } else if ( (waitForData > 0) && (inputData < 128) ) { - --waitForData; - bufferDataAtPosition(inputData, waitForData); - if ( (waitForData == 0) && executeMultiByteCommand ) { // got the whole message - switch (executeMultiByteCommand) { - case ANALOG_MESSAGE: - if (currentAnalogCallback) { - (*currentAnalogCallback)(currentAnalogCallbackContext, - multiByteChannel, - (dataBuffer[0] << 7) - + dataBuffer[1]); - } - break; - case DIGITAL_MESSAGE: - if (currentDigitalCallback) { - (*currentDigitalCallback)(currentDigitalCallbackContext, - multiByteChannel, - (dataBuffer[0] << 7) - + dataBuffer[1]); - } - break; - case SET_PIN_MODE: - if (currentPinModeCallback) - (*currentPinModeCallback)(currentPinModeCallbackContext, dataBuffer[1], dataBuffer[0]); - break; - case SET_DIGITAL_PIN_VALUE: - if (currentPinValueCallback) - (*currentPinValueCallback)(currentPinValueCallbackContext, dataBuffer[1], dataBuffer[0]); - break; - case REPORT_ANALOG: - if (currentReportAnalogCallback) - (*currentReportAnalogCallback)(currentReportAnalogCallbackContext, multiByteChannel, dataBuffer[0]); - break; - case REPORT_DIGITAL: - if (currentReportDigitalCallback) - (*currentReportDigitalCallback)(currentReportDigitalCallbackContext, multiByteChannel, dataBuffer[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: - case SET_DIGITAL_PIN_VALUE: - 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: - if (currentReportVersionCallback) - (*currentReportVersionCallback)(currentReportVersionCallbackContext); - break; - } - } -} - -/** - * @return Returns true if the parser is actively parsing data. - */ -bool FirmataParser::isParsingMessage(void) -const -{ - return (waitForData > 0 || parsingSysex); -} - -/** - * Provides a mechanism to either set or update the working buffer of the parser. - * The method will be enabled when no buffer has been provided, or an overflow - * condition exists. - * @param dataBuffer A pointer to an external buffer used to store parsed data - * @param dataBufferSize The size of the external buffer - */ -int FirmataParser::setDataBufferOfSize(uint8_t * dataBuffer, size_t dataBufferSize) -{ - int result; - - if ( !allowBufferUpdate ) { - result = __LINE__; - } else if ((uint8_t *)NULL == dataBuffer) { - result = __LINE__; - } else { - this->dataBuffer = dataBuffer; - this->dataBufferSize = dataBufferSize; - allowBufferUpdate = false; - result = 0; - } - - return result; -} - -/** - * Attach a generic sysex callback function to a command (options are: ANALOG_MESSAGE, - * DIGITAL_MESSAGE, REPORT_ANALOG, REPORT DIGITAL, SET_PIN_MODE and SET_DIGITAL_PIN_VALUE). - * @param command The ID of the command to attach a callback function to. - * @param newFunction A reference to the callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(uint8_t command, callbackFunction newFunction, void * context) -{ - switch (command) { - case ANALOG_MESSAGE: - currentAnalogCallback = newFunction; - currentAnalogCallbackContext = context; - break; - case DIGITAL_MESSAGE: - currentDigitalCallback = newFunction; - currentDigitalCallbackContext = context; - break; - case REPORT_ANALOG: - currentReportAnalogCallback = newFunction; - currentReportAnalogCallbackContext = context; - break; - case REPORT_DIGITAL: - currentReportDigitalCallback = newFunction; - currentReportDigitalCallbackContext = context; - break; - case SET_PIN_MODE: - currentPinModeCallback = newFunction; - currentPinModeCallbackContext = context; - break; - case SET_DIGITAL_PIN_VALUE: - currentPinValueCallback = newFunction; - currentPinValueCallbackContext = context; - break; - } -} - -/** - * Attach a version callback function (supported option: REPORT_FIRMWARE). - * @param command The ID of the command to attach a callback function to. - * @param newFunction A reference to the callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(uint8_t command, versionCallbackFunction newFunction, void * context) -{ - switch (command) { - case REPORT_FIRMWARE: - currentReportFirmwareCallback = newFunction; - currentReportFirmwareCallbackContext = context; - break; - } -} - -/** - * Attach a system callback function (supported options are: SYSTEM_RESET, REPORT_VERSION). - * @param command The ID of the command to attach a callback function to. - * @param newFunction A reference to the callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(uint8_t command, systemCallbackFunction newFunction, void * context) -{ - switch (command) { - case REPORT_VERSION: - currentReportVersionCallback = newFunction; - currentReportVersionCallbackContext = context; - break; - case SYSTEM_RESET: - currentSystemResetCallback = newFunction; - currentSystemResetCallbackContext = context; - break; - } -} - -/** - * Attach a callback function for the STRING_DATA command. - * @param command Must be set to STRING_DATA or it will be ignored. - * @param newFunction A reference to the string callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(uint8_t command, stringCallbackFunction newFunction, void * context) -{ - switch (command) { - case STRING_DATA: - currentStringCallback = newFunction; - currentStringCallbackContext = context; - break; - } -} - -/** - * Attach a generic sysex callback function to sysex command. - * @param command The ID of the command to attach a callback function to. - * @param newFunction A reference to the sysex callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(uint8_t command, sysexCallbackFunction newFunction, void * context) -{ - (void)command; - currentSysexCallback = newFunction; - currentSysexCallbackContext = context; -} - -/** - * Attach a buffer overflow callback - * @param newFunction A reference to the buffer overflow callback function to attach. - * @param context An optional context to be provided to the callback function (NULL by default). - * @note The context parameter is provided so you can pass a parameter, by reference, to - * your callback function. - */ -void FirmataParser::attach(dataBufferOverflowCallbackFunction newFunction, void * context) -{ - currentDataBufferOverflowCallback = newFunction; - currentDataBufferOverflowCallbackContext = context; -} - -/** - * Detach a callback function for a specified command (such as SYSTEM_RESET, STRING_DATA, - * ANALOG_MESSAGE, DIGITAL_MESSAGE, etc). - * @param command The ID of the command to detatch the callback function from. - */ -void FirmataParser::detach(uint8_t command) -{ - switch (command) { - case REPORT_FIRMWARE: - attach(command, (versionCallbackFunction)NULL, NULL); - break; - case REPORT_VERSION: - case SYSTEM_RESET: - attach(command, (systemCallbackFunction)NULL, NULL); - break; - case STRING_DATA: - attach(command, (stringCallbackFunction)NULL, NULL); - break; - case START_SYSEX: - attach(command, (sysexCallbackFunction)NULL, NULL); - break; - default: - attach(command, (callbackFunction)NULL, NULL); - break; - } -} - -/** - * Detach the buffer overflow callback - * @param <unused> Any pointer of type dataBufferOverflowCallbackFunction. - */ -void FirmataParser::detach(dataBufferOverflowCallbackFunction) -{ - currentDataBufferOverflowCallback = (dataBufferOverflowCallbackFunction)NULL; - currentDataBufferOverflowCallbackContext = (void *)NULL; -} - -//****************************************************************************** -//* Private Methods -//****************************************************************************** - -/** - * Buffer abstraction to prevent memory corruption - * @param data The byte to put into the buffer - * @param pos The position to insert the byte into the buffer - * @return writeError A boolean to indicate if an error occured - * @private - */ -bool FirmataParser::bufferDataAtPosition(const uint8_t data, const size_t pos) -{ - bool bufferOverflow = (pos >= dataBufferSize); - - // Notify of overflow condition - if ( bufferOverflow - && ((dataBufferOverflowCallbackFunction)NULL != currentDataBufferOverflowCallback) ) - { - allowBufferUpdate = true; - currentDataBufferOverflowCallback(currentDataBufferOverflowCallbackContext); - // Check if overflow was resolved during callback - bufferOverflow = (pos >= dataBufferSize); - } - - // Write data to buffer if no overflow condition persist - if ( !bufferOverflow ) - { - dataBuffer[pos] = data; - } - - return bufferOverflow; -} - -/** - * Transform 7-bit firmata message into 8-bit stream - * @param bytec The encoded data byte length of the message (max: 16383). - * @param bytev A pointer to the encoded array of data bytes. - * @return The length of the decoded data. - * @note The conversion will be done in place on the provided buffer. - * @private - */ -size_t FirmataParser::decodeByteStream(size_t bytec, uint8_t * bytev) { - size_t decoded_bytes, i; - - for ( i = 0, decoded_bytes = 0 ; i < bytec ; ++decoded_bytes, ++i ) { - bytev[decoded_bytes] = bytev[i]; - bytev[decoded_bytes] |= (uint8_t)(bytev[++i] << 7); - } - - return decoded_bytes; -} - -/** - * Process incoming sysex messages. Handles REPORT_FIRMWARE and STRING_DATA internally. - * Calls callback function for STRING_DATA and all other sysex messages. - * @private - */ -void FirmataParser::processSysexMessage(void) -{ - switch (dataBuffer[0]) { //first byte in buffer is command - case REPORT_FIRMWARE: - if (currentReportFirmwareCallback) { - const size_t major_version_offset = 1; - const size_t minor_version_offset = 2; - const size_t string_offset = 3; - // Test for malformed REPORT_FIRMWARE message (used to query firmware prior to Firmata v3.0.0) - if ( 3 > sysexBytesRead ) { - (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext, 0, 0, (const char *)NULL); - } else { - const size_t end_of_string = (string_offset + decodeByteStream((sysexBytesRead - string_offset), &dataBuffer[string_offset])); - bufferDataAtPosition('\0', end_of_string); // NULL terminate the string - (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext, (size_t)dataBuffer[major_version_offset], (size_t)dataBuffer[minor_version_offset], (const char *)&dataBuffer[string_offset]); - } - } - break; - case STRING_DATA: - if (currentStringCallback) { - const size_t string_offset = 1; - const size_t end_of_string = (string_offset + decodeByteStream((sysexBytesRead - string_offset), &dataBuffer[string_offset])); - bufferDataAtPosition('\0', end_of_string); // NULL terminate the string - (*currentStringCallback)(currentStringCallbackContext, (const char *)&dataBuffer[string_offset]); - } - break; - default: - if (currentSysexCallback) - (*currentSysexCallback)(currentSysexCallbackContext, dataBuffer[0], sysexBytesRead - 1, dataBuffer + 1); - } -} - -/** - * Resets the system state upon a SYSTEM_RESET message from the host software. - * @private - */ -void FirmataParser::systemReset(void) -{ - size_t 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 < dataBufferSize; ++i) { - dataBuffer[i] = 0; - } - - parsingSysex = false; - sysexBytesRead = 0; - - if (currentSystemResetCallback) - (*currentSystemResetCallback)(currentSystemResetCallbackContext); -} |