Libraries and Example of mbed parallel bus using I2C port expanders
Dependencies: HDSP253X mbed PCF8574_Bus
Revision 5:38b853bb1afa, committed 2011-08-26
- Comitter:
- wim
- Date:
- Fri Aug 26 20:35:11 2011 +0000
- Parent:
- 4:745fbbd5e4e5
- Child:
- 6:aaefa04f06be
- Commit message:
- Included Messages to Host
Changed in this revision
--- a/HDSP253X_Display.cpp Tue Aug 23 20:26:05 2011 +0000 +++ b/HDSP253X_Display.cpp Fri Aug 26 20:35:11 2011 +0000 @@ -162,7 +162,7 @@ | | Parameters: address - full address in bits 0-5 (bit 5 is flash) | - | Returns: data - data byte read in + | Returns: data - data byte read in (Note that D7 is masked out) | \*---------------------------------------------------------------------------*/ @@ -174,8 +174,7 @@ _databus.busdir(READ); // Switch databus buffer to inputs _controlbus.busdir(READ); - - + // Write out the address on to the addressbus and wait _addressbus.write(address); wait_ms(HDSP253X_1TCY_WAIT_MS); @@ -189,7 +188,10 @@ wait_ms(HDSP253X_1TCY_WAIT_MS); // Read the data byte from databus - data = _databus.read(); + // Mask out the not-readable D7 bit, this mask is needed for my specific targetboard ! + // Reading the unconnected D7 bit results in 'H' level. A RMW cycle on the Ctrl register + // would then always result in a Clearscreen ! + data = _databus.read() & HDSP253X_CTRL_MASK; // set RD high and wait _controlbus.RD(HIGH); @@ -263,8 +265,6 @@ udc_char |= HDSP253X_UDC_SEL; // add in top bit to specify UDC _write(HDSP253X_ADDR_CHAR_BASE + char_pos, udc_char); } -#endif - /*---------------------------------------------------------------------------*\ @@ -339,7 +339,7 @@ _write(HDSP253X_ADDR_CHAR_BASE + i, char_value); } } - +#endif /*---------------------------------------------------------------------------*\ |
--- a/HDSP253X_Display.h Tue Aug 23 20:26:05 2011 +0000 +++ b/HDSP253X_Display.h Fri Aug 26 20:35:11 2011 +0000 @@ -141,6 +141,10 @@ #define HDSP253X_CTRL_SELFTEST_MASK 0x40 #define HDSP253X_CTRL_CLEAR_MASK 0x80 +// Masks for register read, Bit 7 not readable in the target hardware +#define HDSP253X_CTRL_MASK 0x7F + + // display brightness definitions, indicating percentage brightness #define HDSP253X_BRIGHT_100 0x00 #define HDSP253X_BRIGHT_80 0x01 @@ -161,30 +165,7 @@ // default display brightness -#define HDSP253X_DEF_DISPLAY_BRIGHT HDSP253X_BRIGHT_53 - -#if(0) -// static array of display brightness to index number setting -static byte disp_bright_lookup[] = -{ - HDSP253X_BRIGHT_100, // 0 - HDSP253X_BRIGHT_13, // 1 - HDSP253X_BRIGHT_20, // 2 - HDSP253X_BRIGHT_27, // 3 - HDSP253X_BRIGHT_40, // 4 - HDSP253X_BRIGHT_53, // 5 - HDSP253X_BRIGHT_53, // 6 - HDSP253X_BRIGHT_80, // 7 - HDSP253X_BRIGHT_80, // 8 - HDSP253X_BRIGHT_100 // 9 -}; -#endif - -#if (0) -//Enums for HDSP253X Display -enum HDSP253X_Brightness { HDSP253X_Bright_0, HDSP253X_Bright_13, HDSP253X_Bright_20, HDSP253X_Bright_27, - HDSP253X_Bright_40, HDSP253X_Bright_53, HDSP253X_Bright_80, HDSP253X_Bright_100 }; -#endif +#define HDSP253X_DEF_DISPLAY_BRIGHT HDSP253X_BRIGHT_100 /** Create an HDSP253X_Display object connected to the proper busses @@ -231,8 +212,8 @@ void _init(); // void _display_ascii_char(char ascii_char, uint8_t char_pos); // void _display_udc_char(char udc_char, uint8_t char_pos); - void _display_part_string(const char *disp_string, uint8_t start_pos, uint8_t end_pos); - void _display_fixed_string(const char *disp_string, uint8_t start_pos); +// void _display_part_string(const char *disp_string, uint8_t start_pos, uint8_t end_pos); +// void _display_fixed_string(const char *disp_string, uint8_t start_pos); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Host_Coms.cpp Fri Aug 26 20:35:11 2011 +0000 @@ -0,0 +1,526 @@ +/* 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Host_Coms.h Fri Aug 26 20:35:11 2011 +0000 @@ -0,0 +1,70 @@ +/* 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 +*/ +#ifndef _HOST_COMS_H +#define _HOST_COMS_H + +#include <stdarg.h> +#include <string.h> + +/*****************************************************************************/ +/********************* DEFINITIONS FOR HOST_COMS ***************************/ +/*****************************************************************************/ + +// Definitions for Host Comms +#define D_HOST_MAX_MESS_LEN 255 +#define D_HOST_MAX_DATA_LEN 255 +#define D_HOST_MAX_TOKEN_LEN 4 +#define D_HOST_MAX_CMD_LEN 5 +#define D_HOST_STANAG_CODES 20 + +// Masks + +// Enums +enum LFP_State {LFP_STATE_SOM, LFP_STATE_CMD, LFP_STATE_DATA, LFP_STATE_CS1, LFP_STATE_CS2}; // Message Parser States +enum Host_Mess {HOST_CMD_NONE, HOST_CMD_RES, HOST_CMD_RNG, // Message Types Host to LF28A Mockup + HOST_MESS_NONE, HOST_MESS_RDY1, HOST_MESS_RDY2, HOST_MESS_STATE}; // Message Types LF28A to Host + + +/** Create a Host Coms object connected to the proper channel + * + * @param Serial serial channel to connect to + * @brief +*/ +class Host_Coms { + +public: + Host_Coms(Serial &hostChannel); + int sendString(char * format, ...); + int sendMessage(char * format, ...); + Host_Mess parseMessage(); + + int rangeFirst, rangeLast, mult; + int STANAG_Codes[D_HOST_STANAG_CODES]; + + char _data[D_HOST_MAX_DATA_LEN + 1]; // leave room for '\0' + + bool _parseLFRNG(char *data); + bool _parseLFRES(char *data); + Host_Mess _parseCommand(char *command, char *data); + +protected: + Serial &_hostChannel; + char _sendBuffer[D_HOST_MAX_MESS_LEN + 1]; // leave room for '\0' +// char _receiveBuffer[D_HOST_MAX_MESS_LEN + 1]; // leave room for '\0' + char _command[D_HOST_MAX_CMD_LEN + 1]; // leave room for '\0' + + void _init(); + int _calcChecksum(); +}; + + +#endif +/*****************************************************************************/ +/****************************** END OF FILE ********************************/ +/*****************************************************************************/
--- a/Keyboard.cpp Tue Aug 23 20:26:05 2011 +0000 +++ b/Keyboard.cpp Fri Aug 26 20:35:11 2011 +0000 @@ -50,21 +50,7 @@ _KeyReady = true; // Get the switchvalue and decode it - data = _read() & D_KEYBOARD_MASK; - switch (data) { - case D_KEYBOARD_MODE: _KeyCode = KEY_MODE; - break; - case D_KEYBOARD_EDIT_PATH: _KeyCode = KEY_EDIT_PATH; - break; - case D_KEYBOARD_BRIGHT: _KeyCode = KEY_BRIGHT; - break; - case D_KEYBOARD_GRAT_RT: _KeyCode = KEY_GRAT_RT; - break; - case D_KEYBOARD_F_L_UP: _KeyCode = KEY_F_L_UP; - break; - default: _KeyCode = KEY_NONE; - break; - } + _KeyCode = getswitch(); } if (_controlbus.FIRE() == HIGH) { @@ -95,6 +81,36 @@ } +/** Get keycode for pressed switch + * + * @param none + * @returns keycode +*/ +Key_Code Keyboard::getswitch() { + uint8_t data = 0; + Key_Code code; + + // Get the switchvalue and decode it + data = _read() & D_KEYBOARD_MASK; + switch (data) { + case D_KEYBOARD_MODE: code = KEY_MODE; + break; + case D_KEYBOARD_EDIT_PATH: code = KEY_EDIT_PATH; + break; + case D_KEYBOARD_BRIGHT: code = KEY_BRIGHT; + break; + case D_KEYBOARD_GRAT_RT: code = KEY_GRAT_RT; + break; + case D_KEYBOARD_F_L_UP: code = KEY_F_L_UP; + break; + default: code = KEY_NONE; + break; + } + + return code; +} + + /** Read switch value * * @param none
--- a/Keyboard.h Tue Aug 23 20:26:05 2011 +0000 +++ b/Keyboard.h Fri Aug 26 20:35:11 2011 +0000 @@ -43,6 +43,7 @@ PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus); bool readable (); Key_Code getkey(); + Key_Code getswitch(); protected: PCF8574_DataBus &_databus;
--- a/Status_Display.cpp Tue Aug 23 20:26:05 2011 +0000 +++ b/Status_Display.cpp Fri Aug 26 20:35:11 2011 +0000 @@ -172,10 +172,10 @@ // The LED is controlled from this class because it is more convenient and logical if (NoGo_state == LED_ON) { - _enablebus.nogo(HIGH); // NoGo LED On + _enablebus.nogo(LOW); // NoGo LED On } else { - _enablebus.nogo(LOW); // NoGo LED Off + _enablebus.nogo(HIGH); // NoGo LED Off } }
--- a/Status_Display.h Tue Aug 23 20:26:05 2011 +0000 +++ b/Status_Display.h Fri Aug 26 20:35:11 2011 +0000 @@ -54,10 +54,15 @@ #define STATUS_LED_BRIGHT_MASK 0x07 // Display brightness modes -#define D_STATUS_LED_BRIGHT_OFF D_STATUS_LED_BRIGHT_000 -#define D_STATUS_LED_BRIGHT_LOW D_STATUS_LED_BRIGHT_053 +//#define D_STATUS_LED_BRIGHT_OFF D_STATUS_LED_BRIGHT_000 +//#define D_STATUS_LED_BRIGHT_LOW D_STATUS_LED_BRIGHT_053 +//#define D_STATUS_LED_BRIGHT_MED D_STATUS_LED_BRIGHT_570 +//#define D_STATUS_LED_BRIGHT_HGH D_STATUS_LED_BRIGHT_360 +//Test values +#define D_STATUS_LED_BRIGHT_OFF D_STATUS_LED_BRIGHT_053 +#define D_STATUS_LED_BRIGHT_LOW D_STATUS_LED_BRIGHT_112 #define D_STATUS_LED_BRIGHT_MED D_STATUS_LED_BRIGHT_570 -#define D_STATUS_LED_BRIGHT_HGH D_STATUS_LED_BRIGHT_360 +#define D_STATUS_LED_BRIGHT_HGH D_STATUS_LED_BRIGHT_129 // default display brightness #define D_STATUS_LED_BRIGHT_DEF D_STATUS_LED_BRIGHT_LOW
--- a/Testloop.h Tue Aug 23 20:26:05 2011 +0000 +++ b/Testloop.h Fri Aug 26 20:35:11 2011 +0000 @@ -59,6 +59,9 @@ show_LEDS(); show_menu(); +//make sure we see something + LF28A_status.set_brightness(BRT_MED); + while(running) { if(pc.readable()) { @@ -316,8 +319,8 @@ wait(0.5); LF28A_status.set_brightness(BRT_MED); wait(0.5); - LF28A_status.set_brightness(BRT_HIGH); - wait(0.5); +// LF28A_status.set_brightness(BRT_HIGH); +// wait(0.5); LF28A_status.set_brightness(BRT_OFF); wait(0.5); } @@ -441,7 +444,8 @@ case 'N' : pc.printf("Test STANAG\r"); - + + STANAG_codes.setDigitIdx(0); pc.printf("Code = %04d; CodeIdx=%d; DigitIdx=%d;\r", STANAG_codes.getCode(), STANAG_codes.getCodeIdx(), STANAG_codes.getDigitIdx() ); LF28A_display.locate (0);
--- a/main.cpp Tue Aug 23 20:26:05 2011 +0000 +++ b/main.cpp Fri Aug 26 20:35:11 2011 +0000 @@ -15,12 +15,13 @@ #include "Status_Display.h" #include "Keyboard.h" #include "STANAG_Codes.h" +#include "Host_Coms.h" // Debug stuff #define __DEBUG #include "Dbg.h" -#define __TESTCODE +//#define __TESTCODE // Software version @@ -29,14 +30,24 @@ #define LF28A_SW_VERSION_MINOR 2 #define LF28A_COPYRIGHT_DESCRIPTOR "(C)TNO 2011" +// Laser Time-out in Seconds +//#define LF28A_RANGE_TIME_OUT_S 1 +//#define LF28A_DESIG_TIME_OUT_S (3*60 + 20) +//Test only: +#define LF28A_RANGE_TIME_OUT_S 5 +#define LF28A_DESIG_TIME_OUT_S 10 + // mbed Interface Hardware definitions DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut heartbeatLED(LED4); +// Host PC Communication channels Serial pc(USBTX, USBRX); +Host_Coms host_coms(pc); +//I2C Bus I2C i2c(D_SDA, D_SCL); // CDA Interface Hardware definitions @@ -63,7 +74,8 @@ enum RangeSelect { RNG_F, RNG_L }; -enum MessageToHost { LFPON, LFRDY_0, LFRDY_1, LFSTA, LFIDL }; +enum MessageToHost { LFPON, LFRDY_0, LFRDY_1, LFSTA_D, LFSTA_R, LFSTA_C, LFSTA_A, LFSTA_F, LFSTA_P, LFIDL }; +//enum MessageToHost { LFPON, LFRDY_0, LFRDY_1, LFSTA, LFIDL }; enum MessageFromHost { LFRES, LFRNG }; //Typedef for Laser Range finder data @@ -78,7 +90,7 @@ Brightness brightness, graticule; Key_Code keycode; Range_t range; -bool laser; +bool laser; // Laser On/Off bool hostResetCmd; MessageToHost messageToHost; STANAG_Codes STANAG_codes; @@ -87,6 +99,13 @@ Ticker heartbeat; bool heartbeatflag=false; +// Laser Time-out +Timer timer; + +// Cycle Timer +Timer cycletimer; +int cyclecount = 0; +const int maxcount = 1000000; // Local functions void clear_screen() { @@ -125,7 +144,38 @@ myled1 = 1; DBG("Init Interfaces Done, Main, Step = %d\r", 10); } + +void BITE() { + int count; + + LF28A_status.set_brightness(BRT_MED); + LF28A_status.NoGo(LED_ON); + + for (count=0; count<5; count++) { + LF28A_display.locate(0); + LF28A_display.printf("BITE - "); + LF28A_display.locate(0); + LF28A_display.printf("BITE \ "); + LF28A_display.locate(0); + LF28A_display.printf("BITE | "); + LF28A_display.locate(0); + LF28A_display.printf("BITE / "); + LF28A_display.locate(0); + LF28A_display.printf("BITE - "); + }; + LF28A_display.locate(0); + LF28A_display.printf("BITE OK"); + LF28A_status.NoGo(LED_OFF); + + wait(2.0); + + LF28A_display.cls(); +// LF28A_status.set_brightness(D_STATUS_LED_BRIGHT_OFF); + + //Done, Tell me about it + DBG("BITE Done, Main, Step = %d\r", 30); +} void lamp_test() { LF28A_status.set_brightness(BRT_LOW); @@ -142,24 +192,9 @@ // LF28A_status.set_brightness(D_STATUS_LED_BRIGHT_OFF); //Done, Tell me about it - DBG("Lamp Test Done, Main, Step = %d\r", 20); + //DBG("Lamp Test Done, Main, Step = %d\r", 20); } - -void BITE() { - LF28A_status.set_brightness(BRT_LOW); - LF28A_status.NoGo(LED_OFF); - - LF28A_display.locate(0); - LF28A_display.printf("--------"); - - wait(0.5); - - LF28A_display.cls(); -// LF28A_status.set_brightness(D_STATUS_LED_BRIGHT_OFF); - //Done, Tell me about it - DBG("BITE Done, Main, Step = %d\r", 30); -} void init_state() { // Default modes and settings after Power On or Host Reset @@ -171,6 +206,8 @@ range.select = RNG_F; laser = false; + timer.stop(); + timer.reset(); // Read Config File if needed.. // Reload STANAG Codes ? @@ -184,10 +221,10 @@ // Init Alphanumeric Display LF28A_display.cls(); // Clear display and Cursor home - LF28A_display.set_flash_mode(true); // Enable flashing digits + LF28A_display.set_flash_mode(false); // Disable flashing digits //Done, Tell me about it - DBG("Init Done, Originator = %d\r", hostResetCmd); + //DBG("Init Done, Originator = %d\r", hostResetCmd); } @@ -210,7 +247,7 @@ } //end switch //Done, Tell me about it - DBG("Graticule Brightness Change, current val = %d\r", graticule); + //DBG("Grat Bright Chnge, val = %d\r", graticule); } void disp_bright_selector() { @@ -237,7 +274,7 @@ } //end switch //Done, Tell me about it - DBG("Display Brightness Change, current val = %d\r", brightness); + //DBG("Disp Bright Chng, val = %d\r", brightness); } void range_selector() { @@ -255,7 +292,7 @@ } //end switch //Done, Tell me about it - DBG("Range Change, current val = %d\r", range.select); + //DBG("Rng Chng, val = %d\r", range.select); } // Heartbeat monitor @@ -273,6 +310,56 @@ heartbeatflag = false; } +// Construct and Send messages to Host PC. Need to complete this !! +void SendHostMessage(MessageToHost messageToHost) { + int result; + + switch (messageToHost) { + case LFPON: host_coms.sendMessage("$LFPON"); + break; + + case LFRDY_0: // No hostResetCmd + host_coms.sendMessage("$LFRDY,0"); + //pc.printf("$LFRDY,0*00\r\n"); + break; + + case LFRDY_1: // hostResetCmd + host_coms.sendMessage("$LFRDY,1"); +// pc.printf("$LFRDY,1*00\r\n"); + break; + + case LFSTA_D: // Designate + host_coms.sendMessage("$LFSTA,D,%1d,%04d,%1d", laser, STANAG_codes.getCode(), graticule); +// pc.printf("$LFSTA,D,0,1234,1*00\r\n"); + break; + + case LFSTA_R: // Range + host_coms.sendMessage("$LFSTA,R,%1d,%04d,%1d", laser, STANAG_codes.getCode(), graticule); +// pc.printf("$LFSTA,D,0,1234,1*00\r\n"); + break; + + case LFSTA_C: // Code + host_coms.sendMessage("$LFSTA,C,%1d,%04d,%1d", laser, STANAG_codes.getCode(), graticule); +// pc.printf("$LFSTA,D,0,1234,1*00\r\n"); + break; + + case LFSTA_A: + case LFSTA_F: + case LFSTA_P: + case LFIDL: // No Message + break; + + default: // Oops, we should never end up here.... + + result = -1; + break; + } //end switch + + //Done, Tell me about it + //DBG("To Host Msg, type = %d\r", messageToHost); +} + + //------------------------------------------------------------// // Testing Stuff // //------------------------------------------------------------// @@ -284,39 +371,6 @@ //------------------------------------------------------------// -// Construct and Send messages to Host PC. Need to complete this !! -void SendHostMessage(MessageToHost messageToHost) { - int result; - - switch (messageToHost) { - case LFPON : pc.printf("$LFPON*00\r\n"); - break; - - case LFRDY_0 : // No hostResetCmd - pc.printf("$LFRDY,0*00\r\n"); - break; - - case LFRDY_1 : // hostResetCmd - pc.printf("$LFRDY,1*00\r\n"); - break; - - case LFSTA : pc.printf("$LFSTA,D,0,1234,1*00\r\n"); - break; - - case LFIDL : // No Message - break; - - default: // Oops, we should never end up here.... - - result = -1; - break; - } //end switch - - //Done, Tell me about it - DBG("Message, current val = %d\r", messageToHost); -} - - int main() { int address, result; @@ -325,7 +379,7 @@ heartbeat_start(); clear_screen(); - version_string(); + version_string(); #ifndef __TESTCODE lamp_test(); @@ -338,6 +392,10 @@ mode = INIT_ENTRY; // Start with Init hostResetCmd = false; // Start with regular PowerOn reset +//Test cycletime + cycletimer.start(); + cycletimer.reset(); + // Main Controlloop: // Check keyboard input and respond as required in the current device mode // Check Host commands and respond as required @@ -355,14 +413,14 @@ init_state(); // Inform Host that Init has completed - if (!hostResetCmd) { - // Regular PowerOn Reset - SendHostMessage(LFRDY_0); + if (hostResetCmd) { + // Host initiated a Reset + SendHostMessage(LFRDY_1); + hostResetCmd = false; } else { - // Host initiated a Reset - SendHostMessage(LFRDY_1); - hostResetCmd = false; + // Regular PowerOn Reset + SendHostMessage(LFRDY_0); } mode = INIT_EXIT; @@ -383,7 +441,7 @@ LF28A_display.printf (" %04d",STANAG_codes.getCode() ); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_D); mode = DESIG_DISP; break; @@ -396,25 +454,77 @@ switch (keycode) { case KEY_GRAT_RT: grat_bright_selector(); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_D); break; case KEY_BRIGHT: disp_bright_selector(); break; case KEY_MODE: mode = DESIG_EXIT; + break; + + case KEY_FIRE: // Check and handle Fire key + + // Toggle Laser On/Off + if (laser) { + // Laser is On, Switch Off + laser=false; + timer.stop(); // Stop time-out timer + timer.reset(); + + // Status LEDs + LF28A_status.LED(LED_LASER, LED_OFF); + } + else { + // Laser is Off, Switch On + laser=true; + timer.start(); // Start time-out timer + + // Status LEDs + LF28A_status.LED(LED_LASER, LED_ON); + }; + + // Inform Host of change (laser on/off) + SendHostMessage(LFSTA_D); + break; + default: // Ignore other keys break; }; //End Keyswitch }; // End Keyread - // Check and handle Fire key + // Check Automatic Time-out for Laser + if (laser) { + // Laser is On, Test Time-out to Switch Off + if (timer.read() > LF28A_DESIG_TIME_OUT_S) { + laser=false; // Laser Off + timer.stop(); // Stop time-out timer + timer.reset(); + // Status LEDs + LF28A_status.LED(LED_LASER, LED_OFF); + + // Inform Host of change (laser off) + SendHostMessage(LFSTA_D); + } + }; + break; case DESIG_EXIT: // Transitional state + + // Check Laser + if (laser) { + // Laser is On, Switch Off + laser=false; // Laser Off + timer.stop(); // Stop time-out timer + timer.reset(); + + // Status LEDs + LF28A_status.LED(LED_LASER, LED_OFF); + }; // Status LEDs LF28A_status.LED(LED_DESIG, LED_OFF); @@ -433,7 +543,7 @@ LF28A_display.printf (" %04d",STANAG_codes.getCode() ); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_R); mode = RANGE_DISP; break; @@ -447,7 +557,7 @@ case KEY_GRAT_RT: grat_bright_selector(); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_R); break; @@ -467,7 +577,7 @@ } else { LF28A_display.locate (0); - LF28A_display.printf ("F %04d", range.last); + LF28A_display.printf ("L %04d", range.last); }; // Inform Host of change ?? @@ -475,29 +585,29 @@ break; - case KEY_FIRE: // Check and handle Fire key // Toggle Laser On/Off if (laser) { // Laser is On, Switch Off + laser=false; + timer.stop(); // Stop time-out timer + timer.reset(); // Status LEDs - LF28A_status.LED(LED_LASER, LED_ON); - + LF28A_status.LED(LED_LASER, LED_OFF); } else { - // Laser is Off, Switch On + // Laser is Off, Switch On + laser=true; + timer.start(); // Start time-out timer // Status LEDs - LF28A_status.LED(LED_LASER, LED_ON); - - // Automatic Time-out needed - + LF28A_status.LED(LED_LASER, LED_ON); }; // Inform Host of change (laser on/off) - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_R); break; @@ -506,26 +616,37 @@ }; //End Keyswitch }; // End Keyread -#if (0) - // tbd Check Automatic Time-out for Laser - Timer.stop() - laser = false; - // Status LEDs - LF28A_status.LED(LED_LASER, LED_ON); -#endif + // Check Automatic Time-out for Laser + if (laser) { + // Laser is On, Test Time-out to Switch Off + if (timer.read() > LF28A_RANGE_TIME_OUT_S) { + laser=false; // Laser Off + timer.stop(); // Stop time-out timer + timer.reset(); + + // Status LEDs + LF28A_status.LED(LED_LASER, LED_OFF); + + // Inform Host of change (laser off) + SendHostMessage(LFSTA_R); + } + }; break; case RANGE_EXIT: // Transitional state -#if (0) - // tbd Check Automatic Time-out for Laser - Timer.stop() - laser = false; - // Status LEDs - LF28A_status.LED(LED_LASER, LED_ON); -#endif - + // Check Laser + if (laser) { + // Laser is On, Switch Off + laser=false; // Laser Off + timer.stop(); // Stop time-out timer + timer.reset(); + + // Status LEDs + LF28A_status.LED(LED_LASER, LED_OFF); + }; + // Status LEDs LF28A_status.LED(LED_RANGE, LED_OFF); @@ -547,7 +668,7 @@ LF28A_display.printf (" %04d",STANAG_codes.getCode() ); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_C); mode = CODE_DISP; break; @@ -561,7 +682,7 @@ case KEY_GRAT_RT: grat_bright_selector(); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_C); break; @@ -626,7 +747,7 @@ LF28A_display.set_char_flash_state(false, 4 + STANAG_codes.getDigitIdx()); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_C); mode = CODE_EXIT; @@ -638,14 +759,14 @@ LF28A_display.set_char_flash_state(false, 4 + STANAG_codes.getDigitIdx()); // Inform Host of change - SendHostMessage(LFSTA); + SendHostMessage(LFSTA_C); mode = CODE_DISP; break; case KEY_F_L_UP : //Incr current digit - STANAG_codes.incDigitIdx(); + STANAG_codes.incDigit(); // Display Current STANAG Code LF28A_display.locate (0); @@ -701,8 +822,16 @@ // Reset command // Range data -// Just for Info, lets see how fast this cycle is... -// +#if(0) + // Just for Info, lets see how fast this cycle is... + cyclecount++; + if (cyclecount == maxcount) { + pc.printf("Freq = %d Hz\r", (cyclecount * 1000) / cycletimer.read_ms()); + cyclecount = 0; + cycletimer.reset(); + } +#endif + } // end while(1)