Libraries and Example of mbed parallel bus using I2C port expanders
Dependencies: HDSP253X mbed PCF8574_Bus
Diff: Host_Coms.cpp
- Revision:
- 6:aaefa04f06be
- Parent:
- 5:38b853bb1afa
- Child:
- 7:8680b8b718c8
--- a/Host_Coms.cpp Fri Aug 26 20:35:11 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,526 +0,0 @@ -/* Host_Coms - Communications with Host PC - * - * Copyright (c) 2011 Wim Huiskamp - * - * Released under the MIT License: http://mbed.org/license/mit - * - * version 0.2 Initial Release -*/ -#include "mbed.h" -#include "Host_Coms.h" - - -/** Create a Host Coms object connected to the proper channel - * - * @param Serial serial channel to connect to - * @brief -*/ -Host_Coms::Host_Coms(Serial &hostChannel) : _hostChannel(hostChannel) { - - _init(); -} - - -/** Send a formatted string to the Host PC - * @param - * @returns int message length - */ -int Host_Coms::sendString(char * format, ...) { - va_list args; - va_start (args, format); - int rv; - - rv = _hostChannel.printf(format, args); - - va_end (args); - - return rv; -} - - - -/** Send a formatted message to the Host PC - * @param - * @returns int message length - */ -int Host_Coms::sendMessage(char * format, ...) { - va_list args; - va_start (args, format); - int rv=vsprintf (_sendBuffer, format, args); - -// _hostChannel.printf("%s:len=%d\r\n", _sendBuffer, strlen(_sendBuffer)); - - _hostChannel.printf("%s*%02X\r\n", _sendBuffer, _calcChecksum()); - - va_end (args); - - return (rv + 5); // length + * + checksum + <CR> + <NL> -} - -/** Compute the XOR checksum on the message - * @param - * @returns int checksum - */ -int Host_Coms::_calcChecksum() { - int checksum = 0; - int i, last; - - //_sendBuffer[0] should be '$' and is ignored in checksum - last = strlen(_sendBuffer); - for (i=1; i<last; i++) { - checksum ^= (int) _sendBuffer[i]; - } - - return checksum; -} - - -/** Parse the LFRNG message and decode the fields - * @param - * @returns bool valid message - * @brief - */ -bool Host_Coms::_parseLFRNG(char *data) { - char *token; - int tokenfield; - bool result=true; - -// char hostmessage[] = "1234,5678,0"; -// strcpy(hostmessage, "1234,5678,0"); - - token = strtok(data, ","); // get first token, separator is ',' - tokenfield = 1; - - while ((token != NULL) && (tokenfield <= 3)) { - switch (tokenfield) { - case 1: - // Range First - _hostChannel.printf("#%d: %s\r\n", tokenfield, token); - - // Convert and perform sanity check - rangeFirst = atoi(token); - if ((rangeFirst < 0) || (rangeFirst > 9999)) { - rangeFirst = 0; - result=false; - } - _hostChannel.printf("#%d: int=%04d\r\n", tokenfield, rangeFirst); - break; - - case 2: - // Range Last - _hostChannel.printf("#%d: %s\r\n", tokenfield, token); - - // Convert and perform sanity check - rangeLast = atoi(token); - if ((rangeLast < 0) || (rangeLast > 9999)) { - rangeLast = 0; - result=false; - } - - _hostChannel.printf("#%d: int=%04d\r\n", tokenfield, rangeLast); - break; - - case 3: - // Multiple Returns - _hostChannel.printf("#%d: %s\r\n", tokenfield, token); - - // Convert and perform sanity check - mult = atoi(token); - if ((mult < 0) || (mult > 1)) { - mult = 0; - result=false; - } - - _hostChannel.printf("#%d: int=%1d\r\n", tokenfield, mult); - break; - - default: - break; - } // switch - - token = strtok(NULL, ","); // Get next token - tokenfield++; - } // while - - // Could do additional sanity check on correct number of fields - - return result; -} - -/** Parse the LFRES message and decode the fields - * @param - * @returns bool valid message - * @brief - */ -bool Host_Coms::_parseLFRES(char *data) { - char *token; - int tokenfield; - int STANAG_Code; - bool result=true; - - token = strtok(data, ","); // get first token, separator is ',' - tokenfield = 1; - - while ((token != NULL) && (tokenfield <= D_HOST_STANAG_CODES)) { - switch (tokenfield) { - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - _hostChannel.printf("#%d: %s\r\n", tokenfield, token); - - // STANAG_Code[i] and sanity check - STANAG_Code = atoi(token); - if ((STANAG_Code < 0) || (STANAG_Code > 9999)) { -// if (STANAG_Code < 0) || (STANAG_Code > 1999) { // Check on limited code value - STANAG_Code = 0; - result = false; - } - - STANAG_Codes[tokenfield - 1] = STANAG_Code; - - _hostChannel.printf("#%d: %s\r\n", tokenfield, STANAG_Codes[tokenfield - 1]); - - break; - - default: - break; - } // switch - - token = strtok(NULL, ","); // Get next token - tokenfield++; - } // while - - // Could do additonal sanity check on correct number of fields - - return result; -} - - -/** Receive and Parse the Host message - * @param - * @returns Host_Mess message type that was received - * @brief - * Check LF28A Host channel and Parse received data for valid messages. - * Since the parser is a state machine, partial data may - * be supplied where the next time this method is called, the - * rest of the partial data will complete the message and - * parsing will begin. A typical message is constructed as: - * - * $LFCMD,DDDD,DDDD,....DD*CS<CR><LF> - * - * Where: - * '$' Hex 24 (Start of Message) - * 'LFCMD' LF28A command or data - * ',DDDD' Zero or more data fields - * '*CS' Checksum field (optional) - * <CR><LF> Hex 0D 0A (End of Message) - * - * When a complete message is received, this function sends the - * LF28A command and data to the parseCommand methods for - * individual field parsing. The received data will be stored - * in a datastructure. The return value informs the caller which - * command has been received to decide on proper action. - */ -Host_Mess Host_Coms::parseMessage() { - char data; - static int cmdIdx = 0; // index for received command - static int datIdx = 0; // index for received data - static int computedChecksum = 0; // computed from the received data - static int receivedChecksum = 0; // checksum that was part of the received data - static bool checksumReceived = false; // received data included the optional checksum - static bool messageComplete = false; // message has been received that is ready for decoding - Host_Mess messageType; // valid decoded message type - static LFP_State parseState = LFP_STATE_SOM; - - // init while loop, no valid decoded message is available initially - messageType = HOST_CMD_NONE; - - // Continue reading from host as long as data is available or until a - // valid message has been received that needs to be processed first. - while ((_hostChannel.readable()) && (messageType == HOST_CMD_NONE)) { - data = _hostChannel.getc(); - - // The main state machine which processes individual characters - // until a complete message has been received that is ready for decoding. - switch(parseState) { - // Search for start of message '$' - case LFP_STATE_SOM : - if(data == '$') { - cmdIdx = 0; // reset index - computedChecksum = 0; // reset checksum - receivedChecksum = 0; - messageComplete = false; // restart - checksumReceived = false; // restart - parseState = LFP_STATE_CMD; // next state - -_hostChannel.printf("#start cmd\r\n"); - } - - - break; - - // Retrieve command field - case LFP_STATE_CMD : - switch (data) { - case ',': - // terminate command - _command[cmdIdx] = '\0'; - - // update checksum - computedChecksum ^= (int) data; - - // goto get data state - datIdx = 0; // reset index - parseState = LFP_STATE_DATA; -_hostChannel.printf("#, end cmd\r\n"); - break; - case '*': - // terminate command - _command[cmdIdx] = '\0'; - - // goto get checksum state - checksumReceived = true; - parseState = LFP_STATE_CS1; -_hostChannel.printf("#* end cmd\r\n"); - break; - - case '\r': - case '\n': - // terminate command - _command[cmdIdx] = '\0'; - - // done, decode data and restart - messageComplete = true; - parseState = LFP_STATE_SOM; -_hostChannel.printf("#cr nl end cmd\r\n"); - break; - - case '$' : - // unexpected restart - cmdIdx = 0; // reset index - computedChecksum = 0; // reset checksum -_hostChannel.printf("#$ restart cmd\r\n"); - break; - - default : - // store command - _command[cmdIdx++] = data; - - // update checksum - computedChecksum ^= (int) data; - - // Check for command overflow - if (cmdIdx > D_HOST_MAX_CMD_LEN) { - parseState = LFP_STATE_SOM; // something went wrong, restart - } - -_hostChannel.printf("#in cmd\r\n"); - break; - - } // switch (data) - break; - - // Store data and check for end of sentence or checksum flag - case LFP_STATE_DATA : - switch (data) { - case '*': - // terminate data - _data[datIdx] = '\0'; - - // goto get checksum state - checksumReceived = true; - parseState = LFP_STATE_CS1; -_hostChannel.printf("#* end data\r\n"); - break; - - case '\r': - case '\n': - // terminate data - _data[datIdx] = '\0'; - - // done, decode data and restart - messageComplete = true; - parseState = LFP_STATE_SOM; -_hostChannel.printf("#cr nl end data\r\n"); - break; - - case '$' : - // unexpected restart - cmdIdx = 0; // reset index - computedChecksum = 0; // reset checksum - - parseState = LFP_STATE_CMD; // restart -_hostChannel.printf("#$ in data, restart cmd\r\n"); - break; - - default : - // store data - _data[datIdx++] = data; - - // update checksum - computedChecksum ^= (int) data; - - // Check for data overflow - if (datIdx > D_HOST_MAX_DATA_LEN) { - parseState = LFP_STATE_SOM; // something went wrong, restart - } - -_hostChannel.printf("#in data\r\n"); - break; - - } // switch (data) - break; - - // Handle checksum (part1) from sentence - case LFP_STATE_CS1 : - - if ((data >= '0') && (data <= '9')) { - receivedChecksum = (data - '0') << 4; - parseState = LFP_STATE_CS2; - } - else if ((data >= 'a') && (data <= 'f')) { - receivedChecksum = ((data - 'a') + 10) << 4; - parseState = LFP_STATE_CS2; - } - else if ((data >= 'A') && (data <= 'F')) { - receivedChecksum = ((data - 'A') + 10) << 4; - parseState = LFP_STATE_CS2; - } - else { - // not a valid checksum - parseState = LFP_STATE_SOM; // something went wrong, restart - } - - break; - - // Handle checksum (part2) from sentence - case LFP_STATE_CS2 : - - if ((data >= '0') && (data <= '9')) { - receivedChecksum |= (data - '0'); - - // done, decode data and restart - messageComplete = true; - parseState = LFP_STATE_SOM; - } - else if ((data >= 'a') && (data <= 'f')) { - receivedChecksum |= (data - 'a') + 10; - - // done, decode data and restart - messageComplete = true; - parseState = LFP_STATE_SOM; - } - else if ((data >= 'A') && (data <= 'F')) { - receivedChecksum |= (data - 'A') + 10; - parseState = LFP_STATE_SOM; - - // done, decode data and restart - messageComplete = true; - parseState = LFP_STATE_SOM; - } - else { - // not a valid checksum - parseState = LFP_STATE_SOM; // something went wrong, restart - } - - break; - - - // Something went wrong, restart - default : - parseState = LFP_STATE_SOM; - } // switch (_parseState) - - - // Check if done with this message - if (messageComplete) { -_hostChannel.printf("#complete\r\n"); - if (!checksumReceived) { - // No checksum received, process message - messageType = _parseCommand(_command, _data); - } - else if (computedChecksum == receivedChecksum) { - // Correct checksum, process message - messageType = _parseCommand(_command, _data); - } - else { - // Ignore messages with an invalid checksum - messageType = HOST_CMD_NONE; - } - - // done processing this received message - messageComplete = false; - } - - - } // while readable and no valid message available - - - // inform the caller when a valid message is available - return messageType; -} // _parseMessage - - -/** Receive and Parse the Host command from the message - * @param - * @returns Host_Mess valid command type - * @brief - * Process LFCMD message - Use the _command and _data strings to call the - * appropriate command sentence data processor. - * Return which command has been received to let caller decide on proper action !! -*/ -Host_Mess Host_Coms::_parseCommand(char *command, char *data) { - Host_Mess result = HOST_CMD_NONE; - - // - // LFRES - // - if (strcmp(command, "LFRES") == NULL) { - if (_parseLFRES(data)) - result = HOST_CMD_RES; - } - // - // LFRNG - // - else if (strcmp(command, "LFRNG") == NULL) { - if (_parseLFRNG(data)) - result = HOST_CMD_RNG; - } - - return result; -} - - - -/** Init Host_Coms - * @param - * @returns - */ -void Host_Coms::_init(void) { - int i; - - rangeFirst=0; - rangeLast=0; - mult=0; - - for (i=0; i<D_HOST_STANAG_CODES; i++) { - STANAG_Codes[i]=0; - } -}