Libraries and Example of mbed parallel bus using I2C port expanders
Dependencies: HDSP253X mbed PCF8574_Bus
Diff: main.cpp
- Revision:
- 2:1dab1089c332
- Child:
- 3:3fbfdec782f4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Aug 20 12:49:44 2011 +0000 @@ -0,0 +1,588 @@ +/* LF28A Simulator - Main + * Copyright (c) 2011 Wim Huiskamp + * + * Released under the MIT License: http://mbed.org/license/mit + * + * version 0.2 Initial Release +*/ +#include "mbed.h" +#include "BusDefines.h" +#include "PCF8574_DataBus.h" +#include "PCF8574_AddressBus.h" +#include "PCF8574_EnableBus.h" +#include "MBED_ControlBus.h" +#include "HDSP253X_Display.h" +#include "Status_Display.h" +#include "Keyboard.h" +#include "STANAG_Codes.h" + +// Debug stuff +#define __DEBUG +#include "Dbg.h" + +#define __TESTCODE + + +// Software version +#define LF28A_SOFTWARE_DESCRIPTOR "LF28A Testsoftware" +#define LF28A_SW_VERSION_MAJOR 0 +#define LF28A_SW_VERSION_MINOR 2 +#define LF28A_COPYRIGHT_DESCRIPTOR "(C)TNO 2011" + +// mbed Interface Hardware definitions +DigitalOut myled1(LED1); +DigitalOut myled2(LED2); +DigitalOut myled3(LED3); +DigitalOut heartbeatLED(LED4); + +Serial pc(USBTX, USBRX); + +I2C i2c(D_SDA, D_SCL); + +// CDA Interface Hardware definitions +PCF8574_DataBus databus = PCF8574_DataBus(i2c, D_I2C_DATA_BUS); //Copy constructors.. +PCF8574_AddressBus addressbus = PCF8574_AddressBus(i2c, D_I2C_ADDR_BUS); +PCF8574_EnableBus enablebus = PCF8574_EnableBus(i2c, D_I2C_ENA_BUS); +MBED_ControlBus controlbus = MBED_ControlBus(D_WR, D_RD, D_DTR, D_CDBUF, D_CDINT, D_FIRE); + +// CDA Hardware definitions +HDSP253X_Display LF28A_display = HDSP253X_Display(databus, addressbus, enablebus, controlbus); +Status_Display LF28A_status = Status_Display(databus, enablebus, controlbus); +Keyboard LF28A_keyboard = Keyboard(databus, enablebus, controlbus); + + +//Enums for LF28A Statemachines +enum Mode { IDLE, + INIT_ENTRY, INIT, INIT_EXIT, + DESIG_ENTRY, DESIG_DISP, DESIG_LASER, DESIG_EXIT, + RANGE_ENTRY, RANGE_DISP, RANGE_FIRE, RANGE_EXIT, + CODE_ENTRY, CODE_DISP, CODE_EDIT, CODE_EXIT, + ADDR_ENTRY, ADDR, ADDR_EXIT, + FREQ_ENTRY, FREQ, FREQ_EXIT, + PATH_ENTRY, PATH, PATH_EXIT }; + +enum RangeSelect { RNG_F, RNG_L }; + +enum MessageToHost { LFPON, LFRDY, LFSTA }; +enum MessageFromHost { LFRES, LFRNG }; + +//Typedef for Laser Range finder data +typedef struct { + uint16_t first; + uint16_t last; + RangeSelect select; +} Range_t; + +// Variables for Statemachine +Mode mode; +Brightness brightness, graticule; +Key_Code keycode; +Range_t range; +bool hostResetCmd; +MessageToHost messageToHost; +STANAG_Codes STANAG_codes; + +// Variables for Heartbeat and Status monitoring +Ticker heartbeat; +bool heartbeatflag=false; + + +// Local functions +void clear_screen() { +//ANSI Terminal Commands + pc.printf("\x1B[2J"); + pc.printf("\x1B[H"); +} + +void version_string() { + pc.printf("\r\r"); + pc.printf("%s\r", LF28A_SOFTWARE_DESCRIPTOR); + pc.printf("Version v%1d.%1d\r", LF28A_SW_VERSION_MAJOR, LF28A_SW_VERSION_MINOR); + pc.printf("Build on %s at %s\r", __DATE__, __TIME__); + pc.printf("%s\r", LF28A_COPYRIGHT_DESCRIPTOR); + pc.printf("\r\n"); +} + +void init_interfaces() { +// Init Host PC communication, default is 9600 + pc.baud(D_BAUDRATE); + +// Init LF28A CDA I/F hardware + i2c.frequency(100000); +// pc.printf("SCL0 H, L = 0x%x, 0x%x\r", LPC_I2C0->I2SCLH, LPC_I2C0->I2SCLL); +// pc.printf("SCL1 H, L = 0x%x, 0x%x\r", LPC_I2C1->I2SCLH, LPC_I2C1->I2SCLL); +// pc.printf("SCL2 H, L = 0x%x, 0x%x\r", LPC_I2C2->I2SCLH, LPC_I2C2->I2SCLL); + +// Reset LF28A CDA +// NOTE: On LF28A CDA the Reset* pin is connected to the Display and to the Latches. +// That implies they are all reset when the Reset* pin is used ! + enablebus.reset(LOW); + wait_ms(50); + enablebus.reset(HIGH); + + //Done, Tell me about it + myled1 = 1; + DBG("Init Interfaces Done, Main, Step = %d\r", 10); +} + + +void lamp_test() { + LF28A_status.set_brightness(BRT_LOW); + LF28A_status.lamptest(LED_ON); // All LEDs On, including Backlight and NoGo + + LF28A_display.locate(0); + LF28A_display.printf("XXXXXXXX"); + + wait(2.0); + + LF28A_status.lamptest(LED_OFF); // All LEDs Off, including Backlight and NoGo + + LF28A_display.cls(); +// LF28A_status.set_brightness(D_STATUS_LED_BRIGHT_OFF); + + //Done, Tell me about it + 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 + brightness = BRT_LOW; // Should be BRT_OFF, but then you dont see anything.. + graticule = BRT_LOW; // Should be BRT_OFF, but then you dont see anything.. + + range.last = 0; + range.first = 0; + range.select = RNG_F; + +// Read Config File if needed.. +// Reload STANAG Codes ? + STANAG_codes.setCodeIdx(0); + STANAG_codes.setDigitIdx(0); + + // Init Status LEDs + LF28A_status.lamptest(LED_OFF); // All LEDs off + LF28A_status.backlight(LED_ON); + LF28A_status.set_brightness(brightness); + + // Init Alphanumeric Display + LF28A_display.cls(); + + //Done, Tell me about it + DBG("Init Done, Originator = %d\r", hostResetCmd); +} + + +void grat_bright_selector() { + int result; + + switch (graticule) { + case BRT_OFF : graticule = BRT_LOW; + break; + case BRT_LOW : graticule = BRT_MED; + break; + case BRT_MED : graticule = BRT_HIGH; + break; + case BRT_HIGH : graticule = BRT_OFF; + break; + default: // Oops, we should never end up here.... + graticule = BRT_LOW; + result = -1; + break; + } //end switch + + //Done, Tell me about it + DBG("Graticule Brightness Change, current val = %d\r", graticule); +} + +void disp_bright_selector() { + int result; + + switch (brightness) { + case BRT_OFF : brightness = BRT_LOW; + LF28A_status.set_brightness(BRT_LOW); + break; + case BRT_LOW : brightness = BRT_MED; + LF28A_status.set_brightness(BRT_MED); + break; + case BRT_MED : brightness = BRT_HIGH; + LF28A_status.set_brightness(BRT_HIGH); + break; + case BRT_HIGH : brightness = BRT_OFF; + LF28A_status.set_brightness(BRT_OFF); + break; + default: // Oops, we should never end up here.... + brightness = BRT_LOW; + LF28A_status.set_brightness(BRT_LOW); + result = -1; + break; + } //end switch + + //Done, Tell me about it + DBG("Display Brightness Change, current val = %d\r", brightness); +} + +void range_selector() { + int result; + + switch (range.select) { + case RNG_F : range.select = RNG_L; + break; + case RNG_L : range.select = RNG_F; + break; + default: // Oops, we should never end up here.... + range.select = RNG_F; + result = -1; + break; + } //end switch + + //Done, Tell me about it + DBG("Range Change, current val = %d\r", range.select); +} + +// Heartbeat monitor +void pulse() { + heartbeatLED = !heartbeatLED; +} + +void heartbeat_start() { + heartbeat.attach(&pulse, 0.5); + heartbeatflag = true; +} + +void heartbeat_stop() { + heartbeat.detach(); + heartbeatflag = false; +} + +//------------------------------------------------------------// +// Testing Stuff // +//------------------------------------------------------------// +#ifdef __TESTCODE +#include "Testloop.h" +#endif +//------------------------------------------------------------// +// End Testing Stuff // +//------------------------------------------------------------// + + +// 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 : if (!hostResetCmd) { + pc.printf("$LFRDY,0*00\r\n"); + } + else { + pc.printf("$LFRDY,1*00\r\n"); + hostResetCmd = false; + } + break; + + case LFSTA : pc.printf("$LFSTA,D,0,1234,1*00\r\n"); + 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; + + init_interfaces(); + + heartbeat_start(); + + clear_screen(); + version_string(); + + lamp_test(); + + BITE(); + + DBG("Start Main Loop, Step = %d\r", 50); + + // Prepare main State Machine + mode = INIT_ENTRY; // Start with Init + hostResetCmd = false; // Start with regular PowerOn reset + + +#ifndef __TESTCODE + // Main Controlloop: + // Check keyboard input and respond as required in the current device mode + // Check Host commands and respond as required + while(1) { + + // Handle mode statemachine + switch (mode) { + + // INIT MODEs - Init LF28A after Power On or Host Reset + case INIT_ENTRY: // Transitional state + mode = INIT; + break; + + case INIT: // Init LF28A after Power On or Host Reset + init_state(); + + // Inform Host that Init has completed + SendHostMessage(LFRDY); + + mode = INIT_EXIT; + break; + + case INIT_EXIT: // Transitional state + mode = DESIG_ENTRY; + break; + + // DESIG MODEs - Laser Designator + case DESIG_ENTRY: // Transitional state + + //Display current STANAG Code + + // Inform Host of change + SendHostMessage(LFSTA); + + mode = DESIG_DISP; + break; + + case DESIG_DISP: + // Check and handle Keyboard + if (LF28A_keyboard.readable()) { + keycode = LF28A_keyboard.getkey(); + + switch (keycode) { + case KEY_GRAT_RT: grat_bright_selector(); + // Inform Host of change + SendHostMessage(LFSTA); + break; + + case KEY_BRIGHT: disp_bright_selector(); + break; + + case KEY_MODE: mode = DESIG_EXIT; + break; + + default: // Ignore other keys + break; + }; //End Keyswitch + }; // End Keyread + + // Check and handle Fire key + + break; + + case DESIG_EXIT: // Transitional state + + mode = RANGE_ENTRY; + break; + + // RANGE MODEs + case RANGE_ENTRY: // Transitional state + + //Display current STANAG Code + + // Inform Host of change + SendHostMessage(LFSTA); + + mode = RANGE_DISP; + break; + + case RANGE_DISP: + // Check and handle Keyboard + if (LF28A_keyboard.readable()) { + keycode = LF28A_keyboard.getkey(); + + switch (keycode) { + case KEY_GRAT_RT: grat_bright_selector(); + + // Inform Host of change + SendHostMessage(LFSTA); + + break; + + case KEY_BRIGHT: disp_bright_selector(); + break; + + case KEY_MODE: mode = RANGE_EXIT; + break; + + default: // Ignore other keys + break; + }; //End Keyswitch + }; // End Keyread + + // Check and handle Fire key + // Toggle Laser On/Off + // Update and show Range, Toggle First/Last Range + + break; + + case RANGE_EXIT: // Transitional state + + mode = CODE_ENTRY; + break; + + + // CODE MODEs + case CODE_ENTRY: // Transitional state + + //Display current STANAG Code + + // Inform Host of change + SendHostMessage(LFSTA); + + mode = CODE_DISP; + break; + + case CODE_DISP: + // Check and handle Keyboard + if (LF28A_keyboard.readable()) { + keycode = LF28A_keyboard.getkey(); + + switch (keycode) { + case KEY_GRAT_RT: grat_bright_selector(); + + // Inform Host of change + SendHostMessage(LFSTA); + + break; + + case KEY_BRIGHT: disp_bright_selector(); + break; + + case KEY_MODE: mode = CODE_EXIT; + break; + + case KEY_EDIT: mode = CODE_EDIT; + break; + + case KEY_F_L_UP : //Incr STANAG code idx + STANAG_code.incIdx(); + + //Display current STANAG Code + + // Inform Host of change ?? + //SendHostMessage(LFSTA); + + break; + + default: // Ignore other keys + break; + }; //End Keyswitch + }; //End Keyread + + break; + + case CODE_EDIT: + // Check and handle Keyboard + if (LF28A_keyboard.readable()) { + keycode = LF28A_keyboard.getkey(); + + switch (keycode) { + case KEY_GRAT_RT: //Cursor Right; + break; + + case KEY_BRIGHT: disp_bright_selector(); + break; + + case KEY_MODE: + // Inform Host of change + SendHostMessage(LFSTA); + + mode = CODE_EXIT; + + break; + + case KEY_EDIT: + // Inform Host of change + SendHostMessage(LFSTA); + + mode = CODE_DISP; + + break; + + case KEY_F_L_UP : //Incr current digit + STANAG_code.incDigitIdx(); + + // Inform Host of change ro wait untip done editing ?? + //SendHostMessage(LFSTA); + + break; + + default: // Ignore other keys + break; + }; //End Keyswitch + }; //End Keyread + + break; + + case CODE_EXIT: // Transitional state + + mode = DESIG_ENTRY; + break; + + // ADDR MODEs + case ADDR_ENTRY: // Transitional state + case ADDR: // Transitional state + case ADDR_EXIT: // Transitional state + // FREQ MODEs + case FREQ_ENTRY: // Transitional state + case FREQ: // Transitional state + case FREQ_EXIT: // Transitional state + // PATH MODEs + case PATH_ENTRY: // Transitional state + case PATH: // Transitional state + case PATH_EXIT: // Transitional state + + default: // Oops, we should never end up here....try to recover + mode = INIT_ENTRY; + hostResetCmd = false; + + result = -1; + DBG("Error - Result = %d\r", result); + break; + }; //End mode statemachine switch + + + // Handle Host commands + // Reset command + // Range data + +// Just for Info, lets see how fast this cycle is... +// + } // end while(1) + + +#else +//testing stuff + testloop(); + +#endif + + DBG("I'll be back...\r\r"); +}