Libraries and Example of mbed parallel bus using I2C port expanders

Dependencies:   HDSP253X mbed PCF8574_Bus

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Sat Aug 20 12:49:44 2011 +0000
Child:
3:3fbfdec782f4
Commit message:
First commit, testloop

Changed in this revision

BusDefines.h Show annotated file Show diff for this revision Revisions of this file
BusEnums.h Show annotated file Show diff for this revision Revisions of this file
ChangeLog.h Show annotated file Show diff for this revision Revisions of this file
Dbg.cpp Show annotated file Show diff for this revision Revisions of this file
Dbg.h Show annotated file Show diff for this revision Revisions of this file
HDSP253X_Display.cpp Show annotated file Show diff for this revision Revisions of this file
HDSP253X_Display.h Show annotated file Show diff for this revision Revisions of this file
Keyboard.cpp Show annotated file Show diff for this revision Revisions of this file
Keyboard.h Show annotated file Show diff for this revision Revisions of this file
MBED_ControlBus.cpp Show annotated file Show diff for this revision Revisions of this file
MBED_ControlBus.h Show annotated file Show diff for this revision Revisions of this file
PCF8574_AddressBus.cpp Show annotated file Show diff for this revision Revisions of this file
PCF8574_AddressBus.h Show annotated file Show diff for this revision Revisions of this file
PCF8574_DataBus.cpp Show annotated file Show diff for this revision Revisions of this file
PCF8574_DataBus.h Show annotated file Show diff for this revision Revisions of this file
PCF8574_EnableBus.cpp Show annotated file Show diff for this revision Revisions of this file
PCF8574_EnableBus.h Show annotated file Show diff for this revision Revisions of this file
PinDetect.h Show annotated file Show diff for this revision Revisions of this file
STANAG_Codes.cpp Show annotated file Show diff for this revision Revisions of this file
STANAG_Codes.h Show annotated file Show diff for this revision Revisions of this file
Status_Display.cpp Show annotated file Show diff for this revision Revisions of this file
Status_Display.h Show annotated file Show diff for this revision Revisions of this file
Testloop.h Show annotated file Show diff for this revision Revisions of this file
Utils.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BusDefines.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,39 @@
+/* BusDefines - Use the MBED Port pins and PCF8574s for controlling the Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _BUS_DEFINES_H
+#define _BUS_DEFINES_H
+
+
+//Pin Defines for MBED Control Bus (inputs)
+#define D_FIRE                 p19
+#define D_CDINT                p20
+//Pin Defines for MBED Control Bus (outputs)
+#define D_DTR                  p21
+#define D_CDBUF                p22
+#define D_RD                   p23
+#define D_WR                   p24
+
+#define D_CTRL_MSK             0xFF
+
+//Pin Defines for I2C Bus
+//#define D_SDA                  p9
+//#define D_SCL                  p10
+#define D_SDA                  p28
+#define D_SCL                  p27
+
+//I2C Bus Address Defines for PCF8574 slaves
+#define D_I2C_DATA_BUS        0x40
+#define D_I2C_ADDR_BUS        0x42
+#define D_I2C_ENA_BUS         0x44
+
+
+//Host PC Baudrate (Virtual Com Port on USB)
+#define D_BAUDRATE            9600
+//#define D_BAUDRATE            57600
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BusEnums.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,17 @@
+/* BusEnums - Use the MBED Port pins and PCF8574s for controlling the Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _BUS_ENUMS_H
+#define _BUS_ENUMS_H
+
+//Enums for Control Bus and Enable Bus
+enum Bit_Level { LOW, HIGH };
+enum Bus_Dir   { READ, WRITE };
+enum Bus_Ena   { ENABLE, DISABLE };
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChangeLog.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,12 @@
+/* LF28A Simulator - ChangeLog
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+/*  0.2        Jun 2011 - Testversion
+
+    0.1     23 Mar 2011 - Initial release.
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dbg.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,62 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define __DEBUG
+#include "Dbg.h"
+#include "mbed.h"
+#include <cstdarg>
+
+void DebugStream::debug(const char* format, ...)
+{ 
+  va_list argp;
+  
+  va_start(argp, format);
+  vprintf(format, argp);
+  va_end(argp);
+}
+
+void DebugStream::release()
+{
+
+}
+
+void DebugStream::breakPoint(const char* file, int line)
+{
+  printf("\r\nBREAK in %s at line %d\r\n", file, line);
+  fflush(stdout);
+  getchar();
+  fflush(stdin);
+}
+
+/*
+int snprintf(char *str, int size, const char *format, ...)
+{
+  va_list argp;
+  
+  va_start(argp, format);
+  vsprintf(str, format, argp);
+  va_end(argp);
+  
+  return strlen(str);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dbg.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,78 @@
+/** \file
+Debugging helpers header file
+*/
+
+/**
+ Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef DBG_H
+#define DBG_H
+
+/*!
+  Define to enable debugging in one file
+  #define __DEBUG  
+*/
+
+#ifdef __DEBUG
+
+#ifndef __DEBUGSTREAM
+#define __DEBUGSTREAM
+
+class DebugStream {
+  public:
+    static void debug(const char* format, ...);
+    static void release();
+    static void breakPoint(const char* file, int line);
+  private:
+ 
+};
+
+#undef DBG
+#undef DBGL
+#undef DBG_END
+#undef BREAK
+
+//Debug output (if enabled), same syntax as printf, with heading info
+//#define DBG(...) do{ DebugStream::debug("[%s:%s@%d] ", __FILE__, __FUNCTION__, __LINE__); DebugStream::debug(__VA_ARGS__); } while(0);
+#define DBG(...) do{ DebugStream::debug("[%s @%d] ", __FUNCTION__, __LINE__); DebugStream::debug(__VA_ARGS__); } while(0);
+
+//Debug output (if enabled), same syntax as printf, no heading info
+#define DBGL(...) do{ DebugStream::debug(__VA_ARGS__); } while(0);
+#define DBG_END DebugStream::release
+
+//Breakpoint using serial debug interface (if debug enabled)
+#define BREAK() DebugStream::breakPoint(__FILE__, __LINE__)
+#endif
+
+#else
+#undef DBG
+#undef DBGL
+#undef DBG_END
+#undef BREAK
+
+#define DBG(...)
+#define DBGL(...)
+#define DBG_END()
+#define BREAK()
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HDSP253X_Display.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,747 @@
+/* HDSP253X_Display - Intelligent 8 digit 5x7 LED matrix display
+ *
+ * Copyright (c) 2011 Wim Huiskamp
+ * Modified software based on sourcecode by RAC 06/08/2008
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+//#include "Utils.h"
+#include "PCF8574_DataBus.h"
+#include "PCF8574_AddressBus.h"
+#include "PCF8574_EnableBus.h"
+#include "MBED_ControlBus.h"
+#include "HDSP253X_Display.h"
+
+/** Create an HDSP253X_Display object connected to the proper busses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_AddressBus address addressbus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+HDSP253X_Display::HDSP253X_Display (PCF8574_DataBus &databus, PCF8574_AddressBus &addressbus, PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus) : 
+                                     _databus(databus), _addressbus(addressbus), _enablebus(enablebus), _controlbus(controlbus) {
+
+   _init();
+}    
+
+/** Init HDSP253X_Display
+ * @param
+ * @returns 
+ */
+void HDSP253X_Display::_init(void)
+{
+    // Apply reset
+    reset();  // Note that this also resets the LED status display. 
+ 
+    // Note: Brightness is 100% after reset
+    set_brightness(HDSP253X_DEF_DISPLAY_BRIGHT);
+ 
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*****************************************************************************/
+/*******************  LOW LEVEL HDSP253X SUPPORT FUNCTIONS  ******************/
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_reset
+ |
+ |  Description:    Reset routine for HDSP253X display, applying reset, 
+ |                  removing reset, then waiting for preset delay.
+ |                  With the internal clock, the delay should be around 1
+ |                  millisecond, but slower clocks will require longer delays.
+ |                  After reset the Char RAM and Flash RAM is cleared, the CTRL word is
+ |                  cleared (Blink Off, Flash Off, Brightness 100%). UDC RAM and address
+ |                  are unaffected.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing.
+ |
+\*---------------------------------------------------------------------------*/
+void HDSP253X_Display::reset(void)
+{
+//NOTE: On LF28A the Reset* pin is connected to the display and to the latches.
+//      That implies they are all reset when the Reset* pin is used !
+// 
+// Alternative for the Display may be SW reset instruction
+
+    // Apply the reset condition and then remove after short delay
+    _enablebus.chipselect(CS_DISP, HIGH);  
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+    _enablebus.reset(LOW);   
+    wait_ms(HDSP253X_1TCY_WAIT_MS);    
+    wait_ms(HDSP253X_1TCY_WAIT_MS);        
+    _enablebus.reset(HIGH);             
+    
+    // Wait for the preset delay to allow operation to complete
+    wait_ms(HDSP253X_RST_CLR_DELAY_MS);
+    
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_write
+ |
+ |  Description:    Low level data write routine for HDSP253X. Takes in data
+ |                  and address (including Flash as top bit) and writes
+ |                  it to the display. For simplicity, entire address byte
+ |                  is written, even though top two bits are unused inputs.
+ |                  After performing the operation, address lines are set
+ |                  all high, in order to eliminate current drain through
+ |                  pullup resistors (0.5mA per pin with 10K pullups)
+ |
+ |  Parameters:     address - full address in bits 0-5 (bit 5 is flash)
+ |                  data - data byte to write out
+ |
+ |  Returns:        Nothing.
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_write(uint8_t address, uint8_t data)
+{
+//    // Switch databus buffer to outputs
+//    _controlbus.busdir(WRITE);        
+//    // Switch databus to outputs
+//    _databus.busdir(WRITE);   
+
+    
+    // Write out the address on to the addressbus and wait
+    _addressbus.write(address);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE low and wait
+    _enablebus.chipselect(CS_DISP, LOW);  
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Write data to the databus
+    _databus.write(data);        
+ 
+    // Set WR low, wait, then set high and wait
+    _controlbus.WR(LOW);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    _controlbus.WR(HIGH);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_DISP, HIGH);  
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+//    // Switch databus back to inputs
+//    _databus.busdir(READ);        
+//    // Switch databus buffer back to inputs
+//    _controlbus.busdir(READ);  
+
+//    // Set address lines all high to minimise power through pullups
+//    _addressbus.write(HDSP253X_ADDR_LOW_POWER);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_read
+ |
+ |  Description:    Low level data read routine for HDSP253X. Takes in 
+ |                  address (including Flash as top bit) and reads data
+ |                  from the display. For simplicity, entire address byte
+ |                  is written, even though top two bits are unused inputs.
+ |                  After performing the operation, address lines are set
+ |                  all high, in order to eliminate current drain through
+ |                  pullup resistors (0.5mA per pin with 10K pullups)
+ |
+ |  Parameters:     address - full address in bits 0-5 (bit 5 is flash)
+ |
+ |  Returns:        data - data byte read in
+ |
+\*---------------------------------------------------------------------------*/
+
+uint8_t HDSP253X_Display::_read(uint8_t address)
+{
+    uint8_t data = 0;
+
+    // Switch databus to inputs
+    _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);
+
+    // Set CE low and wait
+    _enablebus.chipselect(CS_DISP, LOW);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set RD low and wait
+    _controlbus.RD(LOW);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+    
+    // Read the data byte from databus
+    data = _databus.read();
+
+    // set RD high and wait
+    _controlbus.RD(HIGH);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_DISP, HIGH);
+    wait_ms(HDSP253X_1TCY_WAIT_MS);
+
+//    // Set address lines all high to minimise power through pullups
+//    _addressbus.write(HDSP253X_ADDR_LOW_POWER);
+
+    // Switch databus buffer back to outputs
+    _controlbus.busdir(WRITE);        
+    // Switch databus to outputs
+    _databus.busdir(WRITE);   
+    
+    // Return read data to caller
+    return data;
+}
+
+
+/*****************************************************************************/
+/**************  HIGH LEVEL HDSP253X CHARACTER DISPLAY FUNCTIONS  ************/
+/*****************************************************************************/
+
+#if(0)
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_display_ascii_char
+ |
+ |  Description:    Displays specified character on the display at specified
+ |                  position.
+ |
+ |  Parameters:     disp_char - single character display
+ |                  char_pos - position on the display (0 to 7, Leftmost = 0)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_display_ascii_char(char ascii_char, char char_pos)
+{
+    // Write selected character to display at wrapped position
+    char_pos %= HDSP253X_NUM_CHARS;
+    ascii_char &= HDSP253X_CHAR_MASK;        // mask off unused bits
+    _write(HDSP253X_ADDR_CHAR_BASE + char_pos, ascii_char);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_display_udc_char
+ |
+ |  Description:    Displays specified UDC character on the display at specified
+ |                  position. Used defined characters use codes from 128-142.
+ |                  Note that the normal write routines can be used
+ |                  to set UDCs, using ASCII values 128 to 143 inclusive.
+ |
+ |  Parameters:     udc_char - UDC character, 15 possible UDC values from 128-142
+ |                  char_pos - position on the display (0 to 7, Leftmost = 0)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_display_udc_char(char udc_char, char char_pos)
+{
+    // Write selected UDC character to display at wrapped position
+    char_pos %= HDSP253X_NUM_CHARS;
+    udc_char &= HDSP253X_UDC_MASK;        // mask off unused bits
+    udc_char |= HDSP253X_UDC_SEL;         // add in top bit to specify UDC
+    _write(HDSP253X_ADDR_CHAR_BASE + char_pos, udc_char);
+}
+#endif
+
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_display_part_string
+ |
+ |  Description:    Displays specified string on the display, starting
+ |                  from specified position, up to end position or end of
+ |                  string, whichever is less. NOTE this function must
+ |                  NOT be used with read-only strings in program memory.
+ |
+ |  Parameters:     disp_string - character string to display
+ |                  start_pos - starting position on the display (0 to 7)
+ |                  end_pos - end position on the display (0 to 7)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_display_part_string(const char *disp_string, uint8_t start_pos, uint8_t end_pos)
+{
+    int i;
+    int string_len;
+
+    // loop round from start pos, writing characters until end reached
+    string_len = strlen(disp_string);   // obtain length of string
+    for (i = start_pos; (i < HDSP253X_NUM_CHARS) && ((i - start_pos) < string_len) && (i <= end_pos); i++)
+    {
+    // write selected character to display at selected position
+    _write(HDSP253X_ADDR_CHAR_BASE + i, disp_string[i - start_pos]);
+    }
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_display_fixed_string
+ |
+ |  Description:    Displays specified fixed string on the display, starting
+ |            from first character and filling in with spaces until specified
+ |            starting position. If string is shorter than remaining display,
+ |            extra characters will be filled with spaces. If string is longer,
+ |            remaining characters will not be displayed. NOTE this function 
+ |            must NOT be used with read-only strings in program memory.
+ |
+ |  Parameters:     disp_string - fixed character string to display
+ |            start_pos - starting position on the display (0 to 7)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::_display_fixed_string(const char *disp_string, uint8_t start_pos)
+{
+    int i;
+    int string_len;
+    uint8_t char_value;
+
+    // loop round, writing characters or spaces to whole display from start
+    string_len = strlen(disp_string);   // obtain length of string
+    for (i = 0; i < HDSP253X_NUM_CHARS; i++)
+    {
+    // work out whether to display a character or space
+    if ((i < start_pos) || ((i - start_pos) >= string_len))
+    {
+        // out of string range, so select space character
+        char_value = ' ';
+    }
+    else
+    {
+        // within string, so select string character
+        char_value = disp_string[i - start_pos];
+    }
+
+    // write selected character to display at selected position
+    _write(HDSP253X_ADDR_CHAR_BASE + i, char_value);
+    }
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_printf
+ |
+ |  Description:    Displays specified string on the display at current
+ |                  cursor position. Increments cursor.
+ |
+ |  Parameters:     format - format string
+ |                  args   - data
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::printf (char * format, ...) {
+   char buffer[40];
+   va_list args;
+   va_start (args, format);
+   int rv=vsprintf (buffer, format, args);
+//    ::printf("printing:'%s'\n", buffer);
+//   writeString (buffer);
+   va_end (args);
+
+// return rv;
+}
+
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_putc
+ |
+ |  Description:    Displays specified character on the display at current
+ |                  cursor position. Increments cursor.
+ |                  Position on the display (0 to 7, Leftmost = 0)
+ |
+ |  Parameters:     disp_char - single character to display
+ |                    - ASCII characters, 128 values between 0-127
+ |                    - UDC character, 15 possible UDC values from 128-142
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::putc(char disp_char)
+{
+    // Write selected character to display at current position
+   
+    if ((disp_char & HDSP253X_UDC_SEL) == HDSP253X_UDC_SEL) {      
+        // Write UDC character to display, code between 128-142
+        disp_char &= HDSP253X_UDC_MASK;        // mask off unused bits
+        disp_char |= HDSP253X_UDC_SEL;         // add in top bit to specify UDC        
+        _write(HDSP253X_ADDR_CHAR_BASE + _column, disp_char);
+    }
+    else {
+        // Write ASCII character, code between 0-127
+        disp_char &= HDSP253X_CHAR_MASK;        // mask off unused bits
+        _write(HDSP253X_ADDR_CHAR_BASE + _column, disp_char);        
+    }
+    
+    // Incr and wrap around cursorposition
+    _column = (_column++) % HDSP253X_NUM_CHARS;    
+}
+
+
+#if(0)
+     if (disp_char == '\n') {
+       _column = 0;
+       _row = (_row++) % HDSP253X_NUM_LINES;
+     }
+     else {
+       _putc(_column, _row, disp_char);
+       _column = (_column++) % HDSP253X_NUM_CHARS;    
+       if (_column == 0) {
+         _row = (_row++) % HDSP253X_NUM_LINES;
+       }
+
+
+char HDSP253X_Display::getc() {
+  return -1;
+}
+
+#endif
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_locate
+ |
+ |  Description:    Set the cursor address where the next character will be written. 
+ |
+ |  Parameters:     Cursor Column address
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::locate(uint8_t column)
+{
+//    _row = row % HDSP253X_NUM_ROWS;
+    _column = column % HDSP253X_NUM_CHARS;
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_cls
+ |
+ |  Description:    Clears the displayed data and flash RAM, but not the user
+ |                  defined characters. Waits for the preset delay to ensure the 
+ |                  display is ready for operation; with an internal clock,
+ |                  this delay needs to be around 1 millisecond. 
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::cls(void)
+{
+    uint8_t disp_data;
+
+    // Read in control word, modify and write back out
+    disp_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    disp_data |= HDSP253X_CTRL_CLEAR_MASK;
+    _write(HDSP253X_ADDR_CTRL_WORD, disp_data);
+
+    // Wait for the preset delay to allow operation to complete
+    wait_ms(HDSP253X_RST_CLR_DELAY_MS);
+
+    // Reset cursor 
+    locate(0);
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_brightness
+ |
+ |  Description:    Sets the brightness of the HDSP253X display, by performing
+ |                  a read-modify-write on the control register.
+ |
+ |  Parameters:     brightness - 3 bit brightness value
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_brightness(uint8_t brightness)
+{
+    uint8_t ctrl_data;
+
+    // Read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    ctrl_data &= ~HDSP253X_CTRL_BRIGHT_MASK;
+    ctrl_data |= (brightness & HDSP253X_CTRL_BRIGHT_MASK);
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_start_self_test
+ |
+ |  Description:    Starts the HDSP253X self test, setting the relevant 
+ |                  control word bit. The caller should then wait for 
+ |                  the required number of seconds before checking the result.
+ |                  With the internal display clock, the self test takes 
+ |                  around 5 seconds, so waiting for 6 seconds should
+ |                  be OK. Slower clocks will require longer delays.
+ |
+ |                  Note that some displays such as the Siemens HDSP2111
+ |                  appear to take longer than the official 4.5 seconds
+ |                  so it is advisable to wait for longer (say 6 seconds)
+ |                  before checking the result. Attempting to access the
+ |                  display before it is ready may result in the self test
+ |                  status failing to clear down.
+ |
+ |                  Also note that some display datasheets suggest that
+ |                  the display must be reset BEFORE running the self
+ |                  test routine, so this routine does this.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::start_self_test(void)
+{
+    // Reset the display to ensure it is ready for the self test
+    reset();
+
+    // Directly write the self test request, as control word is wiped at end
+    _write(HDSP253X_ADDR_CTRL_WORD, HDSP253X_CTRL_SELFTEST_MASK);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_finish_self_test
+ |
+ |  Description:    Reads the control register to determine the self test
+ |                  result. Then issues a display reset to ensure 
+ |                  that it is ready for operation afterwards. While such
+ |                  a reset should not be necessary if an adequate delay
+ |                  occurs between starting the self test and checking the 
+ |                  result, issuing a reset guarantees that the display will 
+ |                  be ready for operation. This also means that this function
+ |                  can be called early to prematurely terminate a self test.
+ |
+ |  Parameters:     None
+ |
+ |  Returns:        True if passed, False if failed
+ |
+\*---------------------------------------------------------------------------*/
+
+bool HDSP253X_Display::finish_self_test(void)
+{
+    uint8_t ctrl_data;
+    bool result;
+    
+    // Read back control word and obtain self test result
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    result = ((ctrl_data & HDSP253X_CTRL_STRESULT_MASK) != 0);
+
+    // Reset the display to ensure it is ready for normal operation
+    reset();
+
+    // Indicate the self test result
+    return result;
+}
+
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_blink_mode
+ |
+ |  Description:    Enables or disables the blinking function on the display.
+ |                  When enabled, blinking will flash the whole display 
+ |                  irrespective of the flash RAM. With the internal clock,
+ |                  the blink rate is 2Hz. Note that blink mode overrides 
+ |                  the normal flashing mode.
+ |
+ |  Parameters:     enable - true to enable, false to disable
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_blink_mode(bool enable)
+{
+    uint8_t ctrl_data;
+
+    // read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    if (enable)
+    {
+      ctrl_data |= HDSP253X_CTRL_BLINK_MASK;
+    }
+    else
+    {
+      ctrl_data &= ~HDSP253X_CTRL_BLINK_MASK;
+    }
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_flash_mode
+ |
+ |  Description:    Enables or disables the flashing function on the display.
+ |                  When enabled, characters with the flashing bit set in the 
+ |                  RAM will flash. With the internal clock, the flash rate is 2Hz.
+ |
+ |  Parameters:     enable - true to enable, false to disable
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_flash_mode(bool enable)
+{
+    uint8_t ctrl_data;
+
+    // read in control word, modify and write back out
+    ctrl_data = _read(HDSP253X_ADDR_CTRL_WORD);
+    if (enable)
+    {
+      ctrl_data |= HDSP253X_CTRL_FLASH_MASK;
+    }
+    else
+    {
+      ctrl_data &= ~HDSP253X_CTRL_FLASH_MASK;
+    }
+    _write(HDSP253X_ADDR_CTRL_WORD, ctrl_data);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_all_flash_states
+ |
+ |  Description:    Sets flashing states of all characters in flash RAM, using 
+ |                  supplied bit mask. Each bit corresponds to a character
+ |                  (bit 7 on left, bit 0 on right), and is set to flash and
+ |                  clear for steady operation. NOTE: The overall flashing 
+ |                  enable/disable state is set by the separate set flash 
+ |                  mode function.
+ |
+ |  Parameters:     flash_bits - bitmask containing flash states
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_all_flash_states(uint8_t flash_bits)
+{
+    int i;
+    uint8_t char_pos;
+
+    // loop round all character positions, extracting each bit in turn
+    for (i = 1; i <= HDSP253X_NUM_CHARS; i++)
+    {
+      // Get state of bottom bit from mask and use to adjust flash state
+      // Note that character address is reversed as we start from right
+      char_pos = HDSP253X_NUM_CHARS - i;
+      _write(HDSP253X_ADDR_FLASH_BASE + char_pos, flash_bits & 0x01);
+
+      // Shift the mask to the right, ready for the next go
+      flash_bits >>= 1;
+    }
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_set_char_flash_state
+ |
+ |  Description:    Sets flashing state of one character in flash RAM, using 
+ |                  supplied character position and enable state. NOTE: The 
+ |                  overall flashing enable/disable state is set by the 
+ |                  separate set flash mode function.
+ |
+ |  Parameters:     flash_state - TRUE to flash, FALSE for steady operation
+ |                  char_pos - position on the display (0 to 7)
+ |
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::set_char_flash_state(bool flash_state, uint8_t char_pos)
+{
+    // Write out the new flash state to the flash RAM
+    _write(HDSP253X_ADDR_FLASH_BASE + char_pos, flash_state);
+}
+
+/*---------------------------------------------------------------------------*\
+ |
+ |  Function:       HDSP253X_define_user_char
+ |
+ |  Description:    Full definition of UDC, firstly setting the UDC address
+ |                  to specified character, and then loading all 7 data rows.
+ |                  Note that for each row, only the bottom 5 bits are used.
+ |  
+ |  Parameters:     udc_char_num - number of UDC character, from 0 to 15
+ |                  row_data_1 - top row data
+ |                  row_data_2 - second row data
+ |                  row_data_3 - third row data
+ |                  row_data_4 - fourth row data
+ |                  row_data_5 - fifth row data
+ |                  row_data_6 - sixth row data
+ |                  row_data_7 - bottomp row data
+ |  
+ |  Returns:        Nothing
+ |
+\*---------------------------------------------------------------------------*/
+
+void HDSP253X_Display::define_user_char(uint8_t udc_char_num, uint8_t row_data_1, uint8_t row_data_2,
+                                        uint8_t row_data_3, uint8_t row_data_4, uint8_t row_data_5, 
+                                        uint8_t row_data_6, uint8_t row_data_7)
+{
+    // firstly set the UDC character address, by writing to the UDC addr reg
+    _write(HDSP253X_ADDR_UDC_ADDRESS, udc_char_num);
+
+    // now write out the 7 rows to the UDC RAM
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+0, row_data_1);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+1, row_data_2);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+2, row_data_3);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+3, row_data_4);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+4, row_data_5);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+5, row_data_6);
+    _write(HDSP253X_ADDR_UDC_ROW_BASE+6, row_data_7);
+}
+
+
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HDSP253X_Display.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,243 @@
+/* HDSP253X_Display - Intelligent 8 digit 5x7 LED matrix display
+ *
+ * Copyright (c) 2011 Wim Huiskamp
+ * Modified software based on sourcecode by RAC 06/08/2008
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _HDSP253X_DISPLAY_H
+#define _HDSP253X_DISPLAY_H
+/*---------------------------------------------------------------------------*\
+ |  Original text by RAC 06/08/2008 has been modified to fix those parts of
+ |  the description which explain hardware or software that has been removed or
+ |  adapted in the new version. 
+ |
+ |  Description: Display driver and demonstrator for HDSP253X series intelligent
+ |            8 character LED display modules. Options include adjusting 
+ |            brightness and message blinking.
+ |            This software drives a single display module using 8 bit databus,
+ |            5 bit addressbus and controlsignals. Note that this software
+ |            will drive all display devices in the series, including HDSP2530 Orange,
+ |            HDSP2531 Yellow, HDSP2532 red and HDSP2533 green devices. It will also
+ |            drive the smaller HDSP21XX series.
+ |
+ |            The peripheral is connected to the following pins:
+ |            HDSP253X
+ |                    - Reset (pin 1) to EnableBus.RESET
+ |                    - Flash (pin 2) to AddressBus.A5
+ |                    - Addr A0 (pin 3) to AddressBus.A0
+ |                    - Addr A1 (pin 4) to AddressBus.A1
+ |                    - Addr A2 (pin 5) to AddressBus.A2
+ |                    - Addr A3 (pin 6) to AddressBus.A3
+ |                    - Addr A4 (pin 10) to AddressBus.A4
+ |                    - Clock select (pin 11) to VCC (Pull Up)
+ |                    - Clock in/out (pin 12) to Not Connected
+ |                    - Write (pin 13) to ControlBus.WR
+ |                    - CE (Pin 14) to EnableBus.CSDISP
+ |                    - VDD 5V (Pin 15)
+ |                    - GND (supply) (Pin 16)
+ |                    - TST (Pin 16) NC
+ |                    - GND (logic) (Pin 18)   
+ |                    - Read (pin 19) to ControlBus.RD
+ |                    - Data D0 (pin 20) to Databus.D0
+ |                    - Data D1 (pin 21) to Databus.D1
+ |                    - Data D2 (pin 25) to Databus.D2
+ |                    - Data D3 (pin 26) to Databus.D3
+ |                    - Data D4 (pin 27) to Databus.D4
+ |                    - Data D5 (pin 28) to Databus.D5
+ |                    - Data D6 (pin 29) to Databus.D6
+ |                    - Data D7 (pin 30) to Databus.D7
+ |
+ |            The peripheral is connected to the following pins:
+ |            HDSP211X
+ |                    - Reset (pin 1) to EnableBus.RESET
+ |                    - Flash (pin 2) to AddressBus.A5
+ |                    - Addr A0 (pin 3) to AddressBus.A0
+ |                    - Addr A1 (pin 4) to AddressBus.A1
+ |                    - Addr A2 (pin 5) to AddressBus.A2
+ |                    - Addr A3 (pin 6) to AddressBus.A3
+ |                    - Addr A4 (pin 10) to AddressBus.A4
+ |                    - Clock select (pin 11) to VCC (Pull Up)
+ |                    - Clock in/out (pin 12) to Not Connected
+ |                    - Write (pin 13) to ControlBus.WR
+ |                    - VDD 5V (Pin 14)
+ |                    - GND (supply) (Pin 15)
+ |                    - GND (logic) (Pin 16)   
+ |                    - CE (Pin 17) to EnableBus.CSDISP
+ |                    - Read (pin 18) to ControlBus.RD
+ |                    - Data D0 (pin 19) to Databus.D0
+ |                    - Data D1 (pin 20) to Databus.D1
+ |                    - Data D2 (pin 23) to Databus.D2
+ |                    - Data D3 (pin 24) to Databus.D3
+ |                    - Data D4 (pin 25) to Databus.D4
+ |                    - Data D5 (pin 26) to Databus.D5
+ |                    - Data D6 (pin 27) to Databus.D6
+ |                    - Data D7 (pin 28) to Databus.D7
+ |
+ |  Details:  All signals to the HDSP253X are pulled up by 10K resistors.
+ |            The device must be reset by pulsing Reset low with Chip Enable
+ |            set high. Other signals are don't cares during a reset. This
+ |            firmware meets these conditions, as long as the pullups are 
+ |            correctly installed.
+ |
+ |            Connecting the clock select and in/out lines to the CPU is optional,
+ |            and may be used for experimentation.
+ |            If using one display, the clock select should normally be pulled
+ |            up high, which results in the clock signal being an output.
+ |            This driver software does not currently control these signals.
+ |
+ |            If using more than one display, the driver software will 
+ |            require modification and extension. Multiple displays should
+ |            have reset, data, address, flash and read/write lines paralleled.
+ |            Each display requires a unique Chip Enable input, and the 
+ |            driver software will need to select which display to access.
+ |            The first display should have clock select high, and its clock
+ |            output connected to the clock inputs on all the other displays;
+ |            these should have clock select low to input the clock signal.
+ |
+ |            Calls to wait_ms() are used to meet the display timing specs
+ |            may need to be modified at higher CPU speeds.
+ |
+ |
+ |  Legalese: This software is FREEWARE, and you can adapt it for any
+ |            purpose whatsoever. I cannot be held responsible for any
+ |            loss, injury, damage or death caused by the use of this 
+ |            software.
+ |
+\*---------------------------------------------------------------------------*/
+
+//Useful stuff to simplify porting of some third party software
+ #include <stdarg.h>
+ //#include "Utils.h"
+
+
+/*****************************************************************************/
+/*********************  DEFINITIONS FOR HDSP253X DISPLAY  ********************/
+/*****************************************************************************/
+
+// Specific delays for display operation, assuming internal clocking
+// This may need to be lengthened if a significantly slower external clock is used
+#define HDSP253X_1TCY_WAIT_MS       1
+#define HDSP253X_RST_CLR_DELAY_MS   2       // delay AFTER issuing reset or clear
+#define HDSP253X_SELFTEST_WAIT_MS   6000    // duration of self test operation
+
+// address values and masks for HDSP253X display access
+#define HDSP253X_ADDR_FLASH_BASE    0x00 
+#define HDSP253X_ADDR_UDC_ADDRESS   0x20 
+#define HDSP253X_ADDR_UDC_ROW_BASE  0x28 
+#define HDSP253X_ADDR_CTRL_WORD     0x30 
+#define HDSP253X_ADDR_CHAR_BASE     0x38 
+// minimises address line power consumption through pullups
+#define HDSP253X_ADDR_LOW_POWER     0x3F
+
+// control word masks for HDSP253X display
+#define HDSP253X_CTRL_BRIGHT_MASK   0x07 
+#define HDSP253X_CTRL_FLASH_MASK    0x08 
+#define HDSP253X_CTRL_BLINK_MASK    0x10 
+#define HDSP253X_CTRL_STRESULT_MASK 0x20 
+#define HDSP253X_CTRL_SELFTEST_MASK 0x40 
+#define HDSP253X_CTRL_CLEAR_MASK    0x80 
+
+// display brightness definitions, indicating percentage brightness
+#define HDSP253X_BRIGHT_100         0x00
+#define HDSP253X_BRIGHT_80          0x01
+#define HDSP253X_BRIGHT_53          0x02
+#define HDSP253X_BRIGHT_40          0x03
+#define HDSP253X_BRIGHT_27          0x04
+#define HDSP253X_BRIGHT_20          0x05
+#define HDSP253X_BRIGHT_13          0x06
+#define HDSP253X_BRIGHT_0           0x07
+
+// miscellaneous definitions for HDSP253X display
+#define HDSP253X_NUM_CHARS          8
+#define HDSP253X_CHAR_MASK          0x7F  
+#define HDSP253X_UDC_SEL            0x80
+#define HDSP253X_UDC_MASK           0x0F
+//#define HDSP253X_ASCII_UDC_CHARS    144
+//#define HDSP253X_POUND_CHAR         0x1E
+
+
+// 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
+
+
+/** Create an HDSP253X_Display object connected to the proper busses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_AddressBus address addressbus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+class HDSP253X_Display {
+public:
+    HDSP253X_Display(PCF8574_DataBus &databus, PCF8574_AddressBus &addressbus,
+                     PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus);
+    void cls();                              
+    void putc(char disp_char);
+//    char getc();    
+
+    void printf (char * format, ...);    
+    void locate(uint8_t column);
+    void define_user_char(uint8_t udc_char_num, uint8_t row_data_1, uint8_t row_data_2,
+                          uint8_t row_data_3, uint8_t row_data_4, uint8_t row_data_5, 
+                          uint8_t row_data_6, uint8_t row_data_7);    
+                          
+    void set_char_flash_state(bool flash_state, uint8_t char_pos);
+    void set_all_flash_states(uint8_t flash_bits);
+    void set_brightness(uint8_t brightness);  
+    void set_blink_mode(bool enable);  
+    void set_flash_mode(bool enable);        
+    void reset();
+//    void putudc(char byte);
+    void start_self_test();  
+    bool finish_self_test();  
+    
+protected:
+    PCF8574_DataBus &_databus;
+    PCF8574_AddressBus &_addressbus;
+    PCF8574_EnableBus &_enablebus;
+    MBED_ControlBus &_controlbus;
+
+//    int _row;
+    int _column;
+    void _write(uint8_t address, uint8_t data);
+    uint8_t _read(uint8_t address);
+    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);
+          
+};
+
+
+#endif
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Keyboard.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,147 @@
+/* Keyboard - Keyboard and Fire Switch control
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8574_DataBus.h"
+#include "PCF8574_EnableBus.h"
+#include "MBED_ControlBus.h"
+#include "Keyboard.h"
+
+
+/** Create a Keyboard object connected to the specified buses
+ *
+ * @param  PCF8574_DataBus databus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+Keyboard::Keyboard (PCF8574_DataBus &databus, PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus) : 
+                                     _databus(databus), _enablebus(enablebus), _controlbus(controlbus) {
+   _init();
+}    
+
+/** Init Keyboard
+ * @param
+ * @returns 
+ */
+void Keyboard::_init(void)
+{
+   _KeyReady = false;  
+   _KeyCode = KEY_NONE;        
+}
+
+
+/** Check Keypressed or Fire switch pressed
+ *
+ * @param none
+ * @returns bool keypressed 
+*/
+bool Keyboard::readable () {
+  uint8_t data = 0;
+
+  // Init to No keypressed
+  _KeyReady = false;
+  
+  if (_controlbus.CDINT() == HIGH) {
+    // CDA Key pressed  
+    _KeyReady = true;
+        
+    data = _read();    // Get the switchvalue and decode it    
+    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;                               
+    }
+  }
+
+  if (_controlbus.FIRE() == HIGH) {
+    // Manual Fire Key pressed  
+    _KeyReady = true;
+        
+    _KeyCode = KEY_FIRE;
+  }
+
+  return _KeyReady;
+}
+
+
+/** Read keycode
+ *
+ * @param none
+ * @returns keycode 
+*/
+Key_Code Keyboard::getkey() {
+  
+  if (_KeyReady) {
+    _KeyReady = false;  
+    return _KeyCode;  
+  }
+  else {
+    return KEY_NONE;
+  }
+}
+
+
+/** Read switch value
+ *
+ * @param none
+ * @returns switch register value 
+*/
+uint8_t Keyboard::_read() {
+    uint8_t data = 0;
+
+    // Switch databus to inputs
+    _databus.busdir(READ);        
+    // Switch databus buffer to inputs
+    _controlbus.busdir(READ);      
+    
+    
+    // Set CE low and wait
+    _enablebus.chipselect(CS_SWITCH, LOW);
+    wait_ms(1.0);
+
+    // Set RD low and wait
+    _controlbus.RD(LOW);
+    wait_ms(1.0);
+    
+    // Read the data byte from databus
+    data = _databus.read();
+
+    // set RD high and wait
+    _controlbus.RD(HIGH);
+    wait_ms(1.0);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_SWITCH, HIGH);
+    wait_ms(1.0);
+
+    // Switch databus buffer back to outputs
+    _controlbus.busdir(WRITE);        
+    // Switch databus to outputs
+    _databus.busdir(WRITE);   
+    
+    // Return read data to caller
+    return data;
+}
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Keyboard.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,63 @@
+/* Keyboard - Keyboard and Fire Switch control
+ *
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _KEYBOARD_H
+#define _KEYBOARD_H
+
+/*****************************************************************************/
+/*********************  DEFINITIONS FOR KEYBOARD   ***************************/
+/*****************************************************************************/
+
+// Definitions for Keyboard Latch
+// NOTE: NEED TO CHECK THESE !!!!
+#define D_KEYBOARD_NONE             0x00
+#define D_KEYBOARD_MODE             0x01
+#define D_KEYBOARD_EDIT_PATH        0x02
+#define D_KEYBOARD_BRIGHT           0x03
+#define D_KEYBOARD_NOTUSED_4        0x04
+#define D_KEYBOARD_GRAT_RT          0x05
+#define D_KEYBOARD_F_L_UP           0x06
+#define D_KEYBOARD_NOTUSED_7        0x07
+
+// Masks for keyboard codes, bit 7 not used
+#define D_KEYBOARD_MASK             0x7F 
+
+//Enums for Keyboard codes
+enum Key_Code { KEY_NONE, KEY_MODE, KEY_EDIT_PATH, KEY_BRIGHT, KEY_GRAT_RT, KEY_F_L_UP, KEY_FIRE };
+
+
+/** Create a Keyboard object connected to the proper busses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+class Keyboard {
+public:
+    Keyboard(PCF8574_DataBus &databus,
+               PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus);
+    bool readable ();
+    Key_Code getkey();
+            
+protected:
+    PCF8574_DataBus &_databus;
+    PCF8574_EnableBus &_enablebus;
+    MBED_ControlBus &_controlbus;   
+    bool _KeyReady;      
+    Key_Code _KeyCode;
+
+    uint8_t _read();   
+    void _init();          
+};
+
+
+#endif
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBED_ControlBus.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,395 @@
+/* MBED_ControlBus - Use MBED Port Pins for controlling the external Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "MBED_ControlBus.h"
+
+//Debounce and Edge detecting stuff
+#include "PinDetect.h"
+//#define __DIGITAL_IN
+//#define __INTERRUPT_IN
+#define __PINDETECT_IN
+
+
+
+
+/** Create an MBED_ControlBus object connected to the specified Pins
+ *
+ * @param PinName WR the Write pin 
+ * @param PinName RD the Read pin 
+ * @param PinName DTR the databuffer Transmit/Receive direction pin 
+ * @param PinName CDBUF the databuffer enable pin
+ * @param PinName CDINT the Keyboard interrupt pin  
+ * @param PinName FIRE the Manual Fire Unit pin   
+*/
+MBED_ControlBus::MBED_ControlBus(PinName WR, PinName RD, PinName DTR, PinName CDBUF, PinName CDINT, PinName FIRE) :
+   _WR(WR),        // WR pin
+   _RD(RD),        // RD pin
+   _DTR(DTR),      // DTR pin
+   _CDBUF(CDBUF),  // CDBUF pin   
+   _CDINT(CDINT),  // CDINT pin      
+   _FIRE(FIRE) {   // FIRE pin         
+   _init();
+}
+
+
+/** Set or Clear the WR pin on Control Bus
+ *
+ * @param Bit_Level wr_level
+*/
+void MBED_ControlBus::WR (Bit_Level wr_level) {
+
+    if (wr_level == LOW) {
+        // Make sure that databus buffer is enabled for Write
+        //busctrl(ENABLE, WRITE);        
+             
+        _RD = 1;                    // RD Pin High, make sure there is no collision    
+        _WR = 0;                    // WR Pin Low
+      }               
+    else {
+        _WR = 1;                    // WR Pin High
+    }      
+}
+ 
+
+/** Set or Clear the RD pin on Control Bus
+ *
+ * @param Bit_Level rd_level
+*/
+void MBED_ControlBus::RD (Bit_Level rd_level) {
+
+    if (rd_level == LOW) {
+        // Make sure that databus buffer is enabled for Read
+        //busctrl(ENABLE, READ);
+
+        _WR = 1;                    // WR Pin High, make sure there is no collision    
+        _RD = 0;                    // RD Pin Low
+      }               
+    else {
+        _RD = 1;                    // RD Pin High
+    }      
+}
+               
+
+/** Enable databus buffer for Write or Read
+ *
+ * @param Bus_Dir buf_dir
+*/
+void MBED_ControlBus::busdir (Bus_Dir buf_dir) {
+
+    if (buf_dir == READ) {
+        // Make sure that databus buffer is enabled for READ
+        _DTR   = 0;                 // DTR Pin Low, Read Direction            
+        _CDBUF = 0;                 // CDBUF Pin Low, Enable Buffer                
+      }                
+    else {
+        // Make sure that databus buffer is enabled for Write   
+        _DTR   = 1;                 // DTR Pin High, Write Direction            
+        _CDBUF = 0;                 // CDBUF Pin Low, Enable Buffer
+    }      
+}
+
+
+/** Enable/Disable databus buffer and control Write or Read Direction
+ *
+ * @param Bus_Ena buf_ena
+ * @param Bus_Dir buf_dir
+*/
+void MBED_ControlBus::busctrl (Bus_Ena buf_ena, Bus_Dir buf_dir) {
+
+    if (buf_ena == ENABLE) {
+        _CDBUF = 0;                 // CDBUF Pin Low, Enable Buffer
+      }                
+    else {
+        _CDBUF = 1;                 // CDBUF Pin High, Disable Buffer                
+    }      
+
+    if (buf_dir == READ) {
+        _DTR   = 0;                 // DTR Pin Low, Read Direction            
+      }                
+    else {
+        _DTR   = 1;                 // DTR Pin High, Write Direction            
+    }      
+}
+
+
+#ifdef __DIGITAL_IN
+/** Get the CDINT pin value from Control Bus
+ *
+ * @returns Bit_Level CDINT_level
+*/
+Bit_Level MBED_ControlBus::CDINT () {
+    
+    // CDINT Pin value, used as regular Pin rather than as interrupt
+    if (_CDINT == 0)
+      return LOW;
+    else 
+      return HIGH;      
+}
+
+/** Get the FIRE pin value from Control Bus
+ *
+ * @returns Bit_Level FIRE_level
+*/
+Bit_Level MBED_ControlBus::FIRE() {
+    
+    // FIRE Pin value, used as regular Pin rather than as interrupt
+    if (_FIRE == 0)
+      return LOW;
+    else 
+      return HIGH;      
+}
+
+/** Setup debouncing and edge detection on the CDINT pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_CDINT_init() {
+}
+
+/** Setup debouncing and edge detection on the FIRE pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_FIRE_init() {
+}
+#endif   //__DIGITAL_IN
+
+
+
+#ifdef __INTERRUPT_IN
+/** Get the CDINT pin value from Control Bus
+ *
+ * @returns Bit_Level CDINT_detected
+*/
+Bit_Level MBED_ControlBus::CDINT () {
+       
+    // CDINT pin has been Debounced and Edge detected
+    // Respond only once for every keypress
+    if (_CDINT_detected) {
+      _CDINT_detected = false;
+      return HIGH;
+    }
+    else {
+      return LOW;      
+    }
+}
+ 
+/** Get the FIRE pin value from Control Bus
+ *
+ * @returns Bit_Level FIRE_detected
+*/
+Bit_Level MBED_ControlBus::FIRE() {
+    
+    // FIRE pin has been Debounced and Edge detected
+    // Respond only once for every keypress
+    if (_FIRE_detected) {
+      _FIRE_detected = false;
+      return HIGH;
+    }
+    else {
+      return LOW;      
+    }
+}
+
+
+/** Called on detection of a rising edge at the CDINT pin 
+ *
+ * @returns
+*/
+ void MBED_ControlBus::_CDINT_activated(void) {
+    _CDINT_detected = true;
+}
+
+
+/** Called on detection of a rising edge at the FIRE pin 
+ *
+ * @returns
+*/
+ void MBED_ControlBus::_FIRE_activated(void) {
+    _FIRE_detected = true;
+}
+
+
+/** Setup simple edge detection on the CDINT pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_CDINT_init() {
+    // Setup the callback function
+   _CDINT.mode(PullDown);
+   _CDINT.rise(this, &MBED_ControlBus::_CDINT_activated);
+
+   // Init the edge detection boolean
+   _CDINT_detected = false;
+}
+
+/** Setup simple edge detection on the FIRE pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_FIRE_init() {
+    // Setup the callback function
+   _FIRE.mode(PullDown);
+   _FIRE.rise(this, &MBED_ControlBus::_FIRE_activated);
+
+   // Init the edge detection boolean
+   _FIRE_detected = false;
+}
+
+/** Setup debouncing and edge detection on the CDINT pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_CDINT_init() {
+}
+
+/** Setup debouncing and edge detection on the FIRE pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_FIRE_init() {
+}
+#endif //__INTERRUPT_IN
+
+
+
+#ifdef __PINDETECT_IN
+/** Get the CDINT pin value from Control Bus
+ *
+ * @returns Bit_Level CDINT_detected
+*/
+Bit_Level MBED_ControlBus::CDINT () {
+       
+    // CDINT pin has been Debounced and Edge detected
+    // Respond only once for every keypress
+    if (_CDINT_detected) {
+      _CDINT_detected = false;
+      return HIGH;
+    }
+    else {
+      return LOW;      
+    }
+}
+ 
+ /** Get the FIRE pin value from Control Bus
+ *
+ * @returns Bit_Level FIRE_detected
+*/
+Bit_Level MBED_ControlBus::FIRE() {
+    
+    // FIRE pin has been Debounced and Edge detected
+    // Respond only once for every keypress
+    if (_FIRE_detected) {
+      _FIRE_detected = false;
+      return HIGH;
+    }
+    else {
+      return LOW;      
+    }
+}
+
+/** Called on detection of a rising edge at the CDINT pin 
+ *
+ * @returns
+*/
+ void MBED_ControlBus::_CDINT_activated(void) {
+    _CDINT_detected = true;
+}
+
+/** Called on detection of a falling edge at the CDINT pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_CDINT_deactivated(void) {
+    _CDINT_detected = false;
+}
+
+/** Called on detection of a rising edge at the FIRE pin 
+ *
+ * @returns
+*/
+ void MBED_ControlBus::_FIRE_activated(void) {
+    _FIRE_detected = true;
+}
+
+/** Called on detection of a falling edge at the FIRE pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_FIRE_deactivated(void) {
+    _FIRE_detected = false;
+}
+
+/** Setup debouncing and edge detection on the CDINT pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_CDINT_init() {
+
+    // Setup the callback functions
+   _CDINT.mode(PullDown);
+   _CDINT.attach_asserted(this, &MBED_ControlBus::_CDINT_activated);
+   _CDINT.attach_deasserted(this, &MBED_ControlBus::_CDINT_deactivated);
+//   _CDINT.attach_asserted_held( &keyPressedHeld );
+//   _CDINT.attach_deasserted_held( &keyReleasedHeld );
+ 
+   // Init the edge detection boolean
+   _CDINT_detected = false;
+
+   // Sampling does not begin until you set a frequency.
+   // The default is 20ms. If you want a different frequency
+   // then pass the period in microseconds for example, for 10ms :-
+   //     _CDINT.setSampleFrequency(10000);
+   //
+   _CDINT.setSampleFrequency(); // Defaults to 20ms.
+}
+
+/** Setup debouncing and edge detection on the FIRE pin 
+ *
+ * @returns
+*/
+void MBED_ControlBus::_FIRE_init() {
+
+    // Setup the callback functions
+   _FIRE.mode(PullDown);
+   _FIRE.attach_asserted(this, &MBED_ControlBus::_FIRE_activated);
+   _FIRE.attach_deasserted(this, &MBED_ControlBus::_FIRE_deactivated);
+//   _FIRE.attach_asserted_held( &keyPressedHeld );
+//   _FIRE.attach_deasserted_held( &keyReleasedHeld );
+ 
+   // Init the edge detection boolean
+   _FIRE_detected = false;
+
+   // Sampling does not begin until you set a frequency.
+   // The default is 20ms. If you want a different frequency
+   // then pass the period in microseconds for example, for 10ms :-
+   //     _FIRE.setSampleFrequency(10000);
+   //
+   _FIRE.setSampleFrequency(); // Defaults to 20ms.
+}
+#endif // __PINDETECT_IN
+
+
+/** Init MBED_ControlBus
+ * @param
+ * @returns 
+ */
+void MBED_ControlBus::_init() {
+    // Make sure that all Control pins are disabled
+    _RD    = 1;                        // RD Pin High    
+    _WR    = 1;                        // WR Pin High        
+    
+    // Make sure that databus buffer is enabled for Write
+    busctrl(ENABLE, WRITE);
+    
+    // Setup debouncing and edge detection for CDINT    
+    _CDINT_init();    
+    
+    // Setup debouncing and edge detection for FIRE    
+    _FIRE_init();        
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBED_ControlBus.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,67 @@
+/* MBED_ControlBus - Use the MBED Port pins for controlling the Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _MBED_CONTROLBUS_H
+#define _MBED_CONTROLBUS_H
+
+//Enums for Control Bus
+#include "BusEnums.h"
+
+//Debounce and Edge detecting stuff
+#include "PinDetect.h"
+
+/** Create an MBED_ControlBus object connected to the specified Pins
+ *
+ * @param PinName WR the Write pin 
+ * @param PinName RD the Read pin 
+ * @param PinName DTR the databuffer Transmit/Receive direction pin 
+ * @param PinName CDBUF the databuffer enable pin
+ * @param PinName CDINT the Keyboard interrupt pin 
+ * @param PinName FIRE the Manual Fire Unit pin    
+*/
+class MBED_ControlBus {
+public:
+    MBED_ControlBus(PinName WR, PinName RD, PinName DTR, PinName CDBUF, PinName CDINT, PinName FIRE);
+    void WR (Bit_Level wr_level);
+    void RD (Bit_Level rd_level);
+    void busdir (Bus_Dir buf_dir);    
+    void busctrl (Bus_Ena buf_ena, Bus_Dir buf_dir);   
+    Bit_Level CDINT ();
+    Bit_Level FIRE ();    
+protected:
+    DigitalOut _WR;    // Write pin 
+    DigitalOut _RD;    // Read pin 
+    DigitalOut _DTR;   // Databuffer Transmit/Receive direction pin 
+    DigitalOut _CDBUF; // Databuffer enable pin
+    
+//Plain digital input pin
+//    DigitalIn  _CDINT; // Keyboard interrupt pin
+//    DigitalIn  _FIRE;  // Fire interrupt pin
+    
+//Plain digital interrupt pin
+//    InterruptIn  _CDINT; // Keyboard interrupt pin
+//    InterruptIn  _FIRE;  // Fire interrupt pin
+
+//Debounced and Edge detected input pin (Andy Kirkmans's Lib
+    PinDetect  _CDINT; // Keyboard interrupt pin    
+    PinDetect  _FIRE;  // Fire interrupt pin
+        
+    bool _CDINT_detected;
+    bool _FIRE_detected;
+
+    void _CDINT_activated();
+    void _CDINT_deactivated();
+    void _CDINT_init();        
+
+    void _FIRE_activated();
+    void _FIRE_deactivated();
+    void _FIRE_init();        
+
+    void _init(); 
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_AddressBus.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,40 @@
+/* PCF8574_AddressBus - Use the PCF8574 I2C Port Extender for controlling the Address Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8574_AddressBus.h"
+
+/** Create an PCF8574_AddressBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+PCF8574_AddressBus::PCF8574_AddressBus(I2C &i2c, char deviceAddress) : _i2c(i2c) {
+   _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
+   _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read
+   _init();
+}
+
+/** Optimised AddressBus write operation.
+ * @param address the addressvalue to output on the bus
+*/
+void PCF8574_AddressBus::write(char address) {
+    char data[1];
+    
+    data[0] = address;
+    _i2c.write(_writeOpcode, data, 1);    // Write addressvalue to bus   
+}
+
+
+/** Init PCF8574_AddressBus
+ * @param
+ * @returns 
+ */
+void PCF8574_AddressBus::_init() {
+ 
+    write(0x00);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_AddressBus.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,41 @@
+/* PCF8574_AddressBus - Use the PCF8574 I2C Port Extender for controlling the Address Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _PCF8574_ADDRESSBUS_H
+#define _PCF8574_ADDRESSBUS_H
+
+
+//Pin Defines for PCF8574 Address Bus
+#define D_A0                   0x01
+#define D_A1                   0x02
+#define D_A2                   0x04
+#define D_A3                   0x08
+#define D_A4                   0x10
+#define D_A5                   0x20
+#define D_A6                   0x40
+#define D_A7                   0x80
+
+#define D_ADDR_MSK             0x3F
+
+
+/** Create an PCF8574_AddressBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+class PCF8574_AddressBus {
+public:
+    PCF8574_AddressBus(I2C &i2c, char deviceAddress);
+    void write(char address);
+protected:
+    I2C &_i2c;
+    char _readOpcode;
+    char _writeOpcode; 
+    void _init(); 
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_DataBus.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,75 @@
+/* PCF8574_DataBus - Use the PCF8574 I2C Port Extender for controlling the Data Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8574_DataBus.h"
+
+/** Create an PCF8574_DataBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+PCF8574_DataBus::PCF8574_DataBus(I2C &i2c, char deviceAddress) : _i2c(i2c) {
+   _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
+   _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read
+   _init();
+}
+
+/** Optimised DataBus write operation.
+ * @param byte the datavalue to output on the bus
+*/
+void PCF8574_DataBus::write(char byte) {
+    char data[1];
+    
+    data[0] = byte;
+    _i2c.write(_writeOpcode, data, 1);    // Write datavalue to bus   
+}
+
+/** Optimised DataBus read operation.
+ *
+ * @returns current data from Databus 
+*/
+char PCF8574_DataBus::read() {
+    char data[1];
+
+//Make sure that databus is enabled for Read
+//    data[0] = 0xFF;                       // Init Port for datainput by Writing 0xFF 
+//   _i2c.write(_writeOpcode, data, 1);    // Write to bus   
+    
+    _i2c.read(_readOpcode, data, 1);      // Read data from bus
+     
+   return data[0];
+}
+
+
+/** Enable databus for Write or Read
+ *
+ * @param Bus_Dir bus_dir
+*/
+void PCF8574_DataBus::busdir (Bus_Dir bus_dir) {
+
+    if (bus_dir == READ) {
+      // Make sure that databus is enabled for READ
+      write(0xFF);                          // Init Port as input by Writing 0xFF 
+            
+    }                
+    else {
+      // Make sure that databus is enabled for WRITE   
+      write(0xFF);                          // Not really needed, just Init Port to safe settings
+    }      
+}
+
+
+
+/** Init PCF8574_DataBus
+ * @param
+ * @returns 
+ */
+void PCF8574_DataBus::_init() {
+ 
+    busdir(WRITE);                          // Init Port as output 
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_DataBus.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,45 @@
+/* PCF8574_DataBus - Use the PCF8574 I2C Port Extender for controlling the Data Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _PCF8574_DATABUS_H
+#define _PCF8574_DATABUS_H
+
+//Pin Defines for PCF8574 Data Bus
+#define D_D0                   0x01
+#define D_D1                   0x02
+#define D_D2                   0x04
+#define D_D3                   0x08
+#define D_D4                   0x10
+#define D_D5                   0x20
+#define D_D6                   0x40
+#define D_D7                   0x80
+
+#define D_DATA_MSK             0xFF
+
+//Enums for Data Bus
+#include "BusEnums.h"
+
+
+/** Create an PCF8574_DataBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+class PCF8574_DataBus {
+public:
+    PCF8574_DataBus(I2C &i2c, char deviceAddress);
+    char read();
+    void write(char byte);
+    void busdir (Bus_Dir bus_dir);    
+protected:
+    I2C &_i2c;
+    char _readOpcode;
+    char _writeOpcode; 
+    void _init(); 
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_EnableBus.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,130 @@
+/* PCF8574_EnableBus - Use the PCF8574 I2C Port Extender for controlling the Chip Enable Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8574_EnableBus.h"
+
+
+/** Create an PCF8574_EnableBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+PCF8574_EnableBus::PCF8574_EnableBus(I2C &i2c, char deviceAddress) : _i2c(i2c) {
+   _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
+   _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read
+   _init();
+}
+
+
+/** Set or Reset Chip Select pins on Enable Bus
+ *
+ * @param CS_Pin cs_pin 
+ * @param Bit_Level cs_level
+*/
+void PCF8574_EnableBus::chipselect (CS_Pin cs_pin, Bit_Level cs_level) {
+    int result = 1;
+      
+    switch (cs_pin) {
+     case CS_SWITCH : if (cs_level == LOW)
+                         _enable_bus = ~D_CS_SWITCH; // CS Pin Low, make sure that only one CS is active
+                      else
+                         _enable_bus |= D_CS_SWITCH; // CS Pin High
+                      break;
+     case LATCHEN_1 : if (cs_level == LOW)
+                         _enable_bus = ~D_LATCHEN_1; // CS Pin Low, make sure that only one CS is active
+                      else
+                         _enable_bus |= D_LATCHEN_1; // CS Pin High
+                      break;
+     case LATCHEN_2 : if (cs_level == LOW)
+                         _enable_bus = ~D_LATCHEN_2; // CS Pin Low, make sure that only one CS is active
+                      else
+                         _enable_bus |= D_LATCHEN_2; // CS Pin High
+                      break;
+     case CS_BRIGHT : if (cs_level == LOW)
+                         _enable_bus = ~D_CS_BRIGHT; // CS Pin Low, make sure that only one CS is active
+                      else
+                         _enable_bus |= D_CS_BRIGHT; // CS Pin High
+                      break;
+     case CS_DISP : if (cs_level == LOW)
+                         _enable_bus = ~D_CS_DISP;   // CS Pin Low, make sure that only one CS is active
+                      else
+                         _enable_bus |= D_CS_DISP;   // CS Pin High
+                      break;
+     
+     default:          // Oops, we should never end up here....
+                      result = -1;
+    }
+
+    _write();                              // Write chip enable bits to bus
+}
+
+/** Set or Clear the Reset pin on Enable Bus
+ *
+ * @param Bit_Level rst_level
+*/
+void PCF8574_EnableBus::reset (Bit_Level rst_level) {
+
+    if (rst_level == LOW) {
+        _reset_pin = 0x00;                 // Reset Pin Low
+      }               
+    else {
+        _reset_pin = D_RESET;              // Reset Pin High
+    }     
+    
+    _write();                              // Write RST bit to bus
+}
+ 
+               
+/** Set or Clear the NoGo pin on Enable Bus
+ *
+ * @param Bit_Level nogo_level
+*/
+void PCF8574_EnableBus::nogo (Bit_Level nogo_level) {
+
+    if (nogo_level == LOW) {
+        _nogo_pin = 0x00;                  // NOGO Pin Low
+      }               
+    else {
+        _nogo_pin = D_NOGO;                // NOGO Pin High
+    }     
+    
+    _write();                              // Write NoGo bit to bus
+}
+ 
+
+/** Optimised EnableBus write operation.
+ * @param byte the value to output on the bus
+*/
+void PCF8574_EnableBus::_write(char byte) {
+    char data[1];
+    
+    data[0] = byte;
+    _i2c.write(_writeOpcode, data, 1);    // Write value to bus   
+}
+
+/** Optimised EnableBus write operation.
+ * @param 
+*/
+void PCF8574_EnableBus::_write() {
+    char data[1];
+    
+    data[0] = (_enable_bus & D_ENABLE_MSK) | _reset_pin | _nogo_pin;      // Combine enable bits and control bits
+    _i2c.write(_writeOpcode, data, 1);    // Write value to bus   
+}
+
+
+/** Init PCF8574_EnableBus
+ * @param
+ * @returns 
+ */
+void PCF8574_EnableBus::_init() {
+    _enable_bus = 0xFF;                    // Make sure that all CS pins are disabled
+    _reset_pin  = D_RESET;                 // Make sure that Reset pin is disabled
+    _nogo_pin   = D_NOGO;                  // Make sure that NoGo pin is disabled    
+    _write();                              // Write value to bus    
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCF8574_EnableBus.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,53 @@
+/* PCF8574_EnableBus - Use the PCF8574 I2C Port Extender for controlling the Chip Enable Bus
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _PCF8574_ENABLEBUS_H
+#define _PCF8574_ENABLEBUS_H
+
+//Pin Defines for PCF8574 Enable Bus
+//Note: 'Reset' causes all devices on the 'Control & Display Unit' to be reset!
+#define D_CS_SWITCH            0x01
+#define D_LATCHEN_1            0x02
+#define D_LATCHEN_2            0x04
+#define D_CS_BRIGHT            0x08
+#define D_CS_DISP              0x10
+#define D_CS_SPARE             0x20
+#define D_RESET                0x40
+#define D_NOGO                 0x80
+
+#define D_ENABLE_MSK           0x3F
+
+//Enums for Enable Bus
+#include "BusEnums.h"
+enum CS_Pin { CS_SWITCH, LATCHEN_1, LATCHEN_2, CS_BRIGHT, CS_DISP, CS_SPARE };
+
+
+/** Create an PCF8574_EnableBus object connected to the specified I2C object and using the specified deviceAddress
+ *
+ * @param I2C &i2c the I2C port to connect to 
+ * @param char deviceAddress the address of the PCF8574
+*/
+class PCF8574_EnableBus {
+public:
+    PCF8574_EnableBus(I2C &i2c, char deviceAddress);
+    void chipselect (CS_Pin cs_pin, Bit_Level cs_level);
+    void reset (Bit_Level rst_level);
+    void nogo (Bit_Level nogo_level);
+protected:
+    I2C &_i2c;
+    char _readOpcode;
+    char _writeOpcode; 
+    char _enable_bus;   
+    char _reset_pin;   
+    char _nogo_pin;   
+//    char _read();
+    void _write();  
+    void _write(char byte);      
+    void _init(); 
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PinDetect.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,501 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#ifndef AJK_PIN_DETECT_H
+#define AJK_PIN_DETECT_H
+
+#ifndef MBED_H
+#include "mbed.h"
+#endif
+
+#ifndef PINDETECT_PIN_ASSTERED
+#define PINDETECT_PIN_ASSTERED   1
+#endif
+
+#ifndef PINDETECT_SAMPLE_PERIOD
+#define PINDETECT_SAMPLE_PERIOD 20000
+#endif
+
+#ifndef PINDETECT_ASSERT_COUNT  
+#define PINDETECT_ASSERT_COUNT  1
+#endif
+
+#ifndef PINDETECT_HOLD_COUNT
+#define PINDETECT_HOLD_COUNT    50
+#endif
+
+namespace AjK {
+
+/** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks.
+ *
+ * This is done by sampling the specified pin at regular intervals and detecting any
+ * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached
+ * callback handler is called. Additionally, if the pin stays in the same state after
+ * a state change for a defined period of time, an extra callback is made allowing a
+ * program to detect when a "key is pressed and held down" rather than a momentary
+ * key/switch press.
+ *
+ * All parameters are customisable which include:-
+ *  <ul>
+ *  <li> The sampling frequency. </li>
+ *  <li> The number of continuous samples until a state change is detected. </li> 
+ *  <li> The number of continuous samples until a key is assumed held after a state change. </li>
+ *  <li> The logic level which is assumed to be asserted (0volts or +volts). </li>
+ *  </ul>
+ *
+ * Only callbacks that have been attached will be called by the library.
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "PinDetect.h"
+ *
+ * PinDetect  pin( p30 );
+ * DigitialOut led1( LED1 );
+ * DigitialOut led2( LED2 );
+ * DigitialOut led3( LED3 );
+ * DigitialOut led4( LED4 );
+ *
+ * void keyPressed( void ) {
+ *     led2 = 1;
+ *     led3 = 0;
+ *     led4 = 0;
+ * }
+ *
+ * void keyReleased( void ) {
+ *     led2 = 0;
+ *     led3 = 0;
+ *     led4 = 0;
+ * }
+ *
+ * void keyPressedHeld( void ) {
+ *     led3 = 1;
+ * }
+ *
+ * void keyReleasedHeld( void ) {
+ *     led4 = 1;
+ * }
+ *
+ * int main() {
+ *
+ *     pin.mode( PullDown );
+ *     pin.attach_asserted( &keyPressed );
+ *     pin.attach_deasserted( &keyReleased );
+ *     pin.attach_asserted_held( &keyPressedHeld );
+ *     pin.attach_deasserted_held( &keyReleasedHeld );
+ *
+ *     // Sampling does not begin until you set a frequency.
+ *     // The default is 20ms. If you want a different frequency
+ *     // then pass the period in microseconds for example, for 10ms :-
+ *     //     pin.setSampleFrequency( 10000 );
+ *     //
+ *     pin.setSampleFrequency(); // Defaults to 20ms.
+ *
+ *     while( 1 ) {
+ *         led1 = !led1;
+ *         wait( 0.2 );
+ *     }
+ * }
+ * @endcode
+ *
+ * This example will flash led1 in a similar to a standard starting program.
+ *
+ * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0"
+ * (switch off) led2 goes out. Holding the "switch" at one for one second will switch
+ * on led3. An unasserted P30 (switched off) will, after one second illuminate led4
+ * when the deasserted calledback is called.
+ *
+ * The above is a very basic introduction. For more details:-
+ * @see example.h
+ */
+class PinDetect {
+
+protected:
+    DigitalIn   *_in;
+    Ticker      *_ticker;
+    int         _prevState;
+    int         _currentStateCounter;
+    int         _sampleTime;
+    int         _assertValue;
+    int         _samplesTillAssertReload;
+    int         _samplesTillAssert;
+    int         _samplesTillHeldReload;
+    int         _samplesTillHeld;
+    FunctionPointer _callbackAsserted;
+    FunctionPointer _callbackDeasserted;
+    FunctionPointer _callbackAssertedHeld;
+    FunctionPointer _callbackDeassertedHeld;
+    
+    /** initialise class
+     *
+     * @param PinName p is a valid pin that supports DigitalIn
+     * @param PinMode m The mode the DigitalIn should use.
+     */
+    void init(PinName p, PinMode m) {
+        _sampleTime              = PINDETECT_SAMPLE_PERIOD;
+        _samplesTillAssert       = PINDETECT_ASSERT_COUNT;
+        _samplesTillHeld         = 0;
+        _samplesTillAssertReload = PINDETECT_ASSERT_COUNT;
+        _samplesTillHeldReload   = PINDETECT_HOLD_COUNT;
+        _assertValue             = PINDETECT_PIN_ASSTERED;
+        
+        _in = new DigitalIn( p );
+        _in->mode( m );        
+        _prevState = _in->read();        
+        _ticker = new Ticker;
+    }
+    
+public:
+
+    friend class Ticker;
+    
+    PinDetect() { error("You must supply a PinName"); }
+
+    /** PinDetect constructor
+     *
+     * By default the PinMode is set to PullDown.
+     *
+     * @see http://mbed.org/handbook/DigitalIn
+     * @param p PinName is a valid pin that supports DigitalIn
+     */    
+    PinDetect(PinName p) {
+        init( p, PullDown );
+    }
+
+    /** PinDetect constructor
+     *
+     * @see http://mbed.org/handbook/DigitalIn
+     * @param PinName p is a valid pin that supports DigitalIn
+     * @param PinMode m The mode the DigitalIn should use.
+     */    
+    PinDetect(PinName p, PinMode m) {
+        init( p, m );
+    }
+    
+    /** PinDetect destructor
+     */    
+    ~PinDetect() {
+        if ( _ticker )  delete( _ticker );
+        if ( _in )      delete( _in );
+    }
+    
+    /** Set the sampling time in microseconds.
+     *
+     * @param int The time between pin samples in microseconds.
+     */
+    void setSampleFrequency(int i = PINDETECT_SAMPLE_PERIOD) { 
+        _sampleTime = i; 
+        _prevState  = _in->read();        
+        _ticker->attach_us( this, &PinDetect::isr, _sampleTime );
+    }
+    
+    /** Set the value used as assert.
+     *
+     * Defaults to 1 (ie if pin == 1 then pin asserted).
+     *
+     * @param int New assert value (1 or 0)
+     */
+    void setAssertValue (int i = PINDETECT_PIN_ASSTERED) { _assertValue = i & 1; }
+    
+    /** Set the number of continuous samples until assert assumed.
+     *
+     * Defaults to 1 (1 * sample frequency).
+     *
+     * @param int The number of continuous samples until assert assumed.
+     */    
+    void setSamplesTillAssert(int i) { _samplesTillAssertReload = i; }
+    
+    /** Set the number of continuous samples until held assumed.
+     *
+     * Defaults to 50 * sample frequency.
+     *
+     * @param int The number of continuous samples until held assumed.
+     */    
+    void setSamplesTillHeld(int i) { _samplesTillHeldReload = i; }
+    
+    /** Set the pin mode.
+     *
+     * @see http://mbed.org/projects/libraries/api/mbed/trunk/DigitalInOut#DigitalInOut.mode
+     * @param PinMode m The mode to pass on to the DigitalIn
+     */
+    void mode(PinMode m) { _in->mode( m ); }
+    
+    /** Attach a callback function 
+     *
+     * @code
+     *
+     * DigitalOut led1( LED1 );
+     * PinDetect pin( p30 );
+     *
+     * void myCallback( void ) {
+     *   led1 = 1;
+     * };
+     * 
+     * main() {
+     *     pin.attach_asserted( &myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is asserted.
+     * @param function A C function pointer
+     */
+    void attach_asserted(void (*function)(void)) {
+        _callbackAsserted.attach( function );
+    }
+    
+    /** Attach a callback object/method 
+     *
+     * @code
+     *
+     * class Bar {
+     *   public:
+     *     void myCallback( void ) { led1 = 1; }
+     * };
+     *
+     * DigitalOut led1( LED1 );
+     * PinDetect pin( p30 );
+     * Bar bar;
+     *
+     * main() {
+     *     pin.attach_asserted( &bar, &Bar::myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is asserted.
+     * @param object An object that conatins the callback method.
+     * @param method The method within the object to call.
+     */
+    template<typename T>
+    void attach_asserted(T *object, void (T::*member)(void)) {
+        _callbackAsserted.attach( object, member );        
+    }
+    
+    /** Attach a callback function 
+     *
+     * @code
+     *
+     * DigitalOut led1( LED1 );
+     * PinDetect pin( p30 );
+     *
+     * void myCallback( void ) {
+     *   led1 = 0;
+     * };
+     *
+     * main() {
+     *     pin.attach_deasserted( &myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is deasserted.
+     * @param function A C function pointer
+     */
+    void attach_deasserted(void (*function)(void)) {
+        _callbackDeasserted.attach( function );
+    }
+    
+    /** Attach a callback object/method
+     *
+     * @code
+     *
+     * class Bar {
+     *   public:
+     *     void myCallback( void ) { led1 = 0; }
+     * };
+     *
+     * DigitalOut led1( LED1 );
+     * PinDetect pin( p30 );
+     * Bar bar;
+     * 
+     * main() {
+     *     pin.attach_deasserted( &bar, &Bar::myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is deasserted.
+     * @param object An object that conatins the callback method.
+     * @param method The method within the object to call.
+     */
+    template<typename T>
+    void attach_deasserted(T *object, void (T::*member)(void)) {
+        _callbackDeasserted.attach( object, member );        
+    }
+    
+    /** Attach a callback function 
+     *
+     * @code
+     *
+     * DigitalOut led2( LED2 );
+     * PinDetect pin( p30 );
+     *
+     * void myCallback( void ) {
+     *   led2 = 1;
+     * };
+     *
+     * main() {
+     *     pin.attach_asserted_held( &myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is asserted and held.
+     * @param function A C function pointer
+     */
+    void attach_asserted_held(void (*function)(void)) {
+        _callbackAssertedHeld.attach( function );
+    }
+    
+    /** Attach a callback object/method
+     *
+     * @code
+     *
+     * class Bar {
+     *   public:
+     *     void myCallback( void ) { led2 = 0; }
+     * };
+     *
+     * DigitalOut led2( LED2 );
+     * PinDetect pin( p30 );
+     * Bar bar;
+     * 
+     * main() {
+     *     pin.attach_asserted_held( &bar, &Bar::myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is asserted and held.
+     * @param object An object that conatins the callback method.
+     * @param method The method within the object to call.
+     */
+    template<typename T>
+    void attach_asserted_held(T *object, void (T::*member)(void)) {
+        _callbackAssertedHeld.attach( object, member );        
+    }
+    
+    /** Attach a callback function 
+     *
+     * @code
+     *
+     * DigitalOut led3( LED3 );
+     * PinDetect pin( p30 );
+     *
+     * void myCallback( void ) {
+     *   led3 = 1;
+     * };
+     *
+     * main() {
+     *     pin.attach_deasserted_held( &myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is deasserted and held.
+     * @param function A C function pointer
+     */
+    void attach_deasserted_held(void (*function)(void)) {
+        _callbackDeassertedHeld.attach( function );
+    }
+    
+    /** Attach a callback object/method
+     *
+     * @code
+     *
+     * class Bar {
+     *   public:
+     *     void myCallback( void ) { led3 = 0; }
+     * };
+     *
+     * DigitalOut led3( LED3 );
+     * PinDetect pin( p30 );
+     * Bar bar;
+     * 
+     * main() {
+     *     pin.attach_deasserted_held( &bar, &Bar::myCallback );
+     * }
+     *
+     * @endcode
+     *
+     * Call this function when a pin is deasserted and held.
+     * @param object An object that conatins the callback method.
+     * @param method The method within the object to call.
+     */
+    template<typename T>
+    void attach_deasserted_held(T *object, void (T::*member)(void)) {
+        _callbackDeassertedHeld.attach( object, member );        
+    }
+    
+    /** operator int()
+     *
+     * Read the value of the pin being sampled.
+     */
+    operator int() { return _in->read(); }
+
+protected:    
+    /** The Ticker periodic callback function
+     */
+    void isr(void) {
+        int currentState = _in->read();
+    
+        if ( currentState != _prevState ) {
+            if ( _samplesTillAssert == 0 ) {
+                _prevState = currentState;
+                _samplesTillHeld = _samplesTillHeldReload;
+                if ( currentState == _assertValue ) 
+                    _callbackAsserted.call();
+                else                              
+                    _callbackDeasserted.call();
+            }
+            else {
+                _samplesTillAssert--;
+            }
+        }
+        else {
+            _samplesTillAssert = _samplesTillAssertReload;
+        }
+        
+        if ( _samplesTillHeld ) {
+            if ( _prevState == currentState ) {
+                _samplesTillHeld--;
+                if ( _samplesTillHeld == 0 ) {
+                    if ( currentState == _assertValue ) 
+                        _callbackAssertedHeld.call();
+                    else                              
+                        _callbackDeassertedHeld.call();
+                }
+            }
+            else {
+                _samplesTillHeld = 0;
+            }
+        }
+    }
+    
+};
+
+}; // namespace AjK ends.
+
+using namespace AjK;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/STANAG_Codes.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,249 @@
+/* STANAG Codes - LTD STANAG Codes
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "STANAG_Codes.h"
+
+
+/** Create a STANAG Codes object
+ *
+ * @param  none
+ * @brief
+*/
+STANAG_Codes::STANAG_Codes() {
+
+  _init(); 
+}
+
+/** Init STANAG_Codes()
+ * @param
+ * @returns 
+ */
+void STANAG_Codes::_init(void) {
+
+  for (_codeIdx=0; _codeIdx < D_STANAG_CODES; _codeIdx++) {
+ 
+    for (_digitIdx=0; _digitIdx < D_STANAG_DIGITS; _digitIdx++) {
+      _codes[_codeIdx][_digitIdx] = STANAG_DEFAULTS[_codeIdx][_digitIdx];
+    }
+  }
+
+#if(0)
+  for (_codeIdx=0; _codeIdx < D_STANAG_CODES; _codeIdx++) {
+     _codes[_codeIdx] = STANAG_DEFAULTS[_codeIdx];
+  }
+#endif
+
+  _codeIdx = 0;
+  _digitIdx = 0;
+}
+
+
+/** Set the code Index of the selected STANAG Code
+ * @param uint8_t codeIdx
+ * @returns value of STANAG code Index
+ */
+uint8_t STANAG_Codes::setCodeIdx(uint8_t codeIdx) {
+  
+  //Check upper boundary
+  if (codeIdx > D_STANAG_CODES-1) {
+    _codeIdx = D_STANAG_CODES-1;  
+  }
+  else {
+    _codeIdx = codeIdx;
+  };
+ 
+  return _codeIdx;
+}
+    
+    
+/** Get code Index of the selected STANAG Code
+ * @param 
+ * @returns value of STANAG code Index
+ */
+uint8_t STANAG_Codes::getCodeIdx() {
+ 
+  return _codeIdx;
+}
+    
+
+/** Increment code Index of the selected STANAG Code
+ * @param 
+ * @returns value of STANAG code Index
+ */
+uint8_t STANAG_Codes::incCodeIdx() {
+
+  _codeIdx++;
+  
+  //Check upper boundary and wrap around
+  if (_codeIdx > D_STANAG_CODES-1) {
+      _codeIdx = 0;  
+  };
+ 
+  return _codeIdx;
+}
+
+
+/** Set the digit index of the selected STANAG Code
+ * @param uint8_t digitIdx
+ * @returns value of the digit index
+ */
+uint8_t STANAG_Codes::setDigitIdx(uint8_t digitIdx) {
+  
+  //Check upper boundary
+  if (digitIdx > D_STANAG_DIGITS-1) {
+    _digitIdx = D_STANAG_DIGITS-1;  
+  }
+  else {
+    _digitIdx = digitIdx;
+  };
+ 
+  return _digitIdx;
+}
+    
+    
+/** Get digit Index of the selected STANAG Code
+ * @param 
+ * @returns value of digit Index
+ */
+uint8_t STANAG_Codes::getDigitIdx() {
+ 
+  return _digitIdx;
+}
+    
+
+/** Increment digit Index of the selected STANAG Code
+ * @param 
+ * @returns value of digit Index
+ */
+uint8_t STANAG_Codes::incDigitIdx() {
+
+  _digitIdx++;
+  
+  //Check upper boundary and wrap around
+  if (_digitIdx > D_STANAG_DIGITS-1) {
+      _digitIdx = 0;  
+  };
+ 
+  return _digitIdx;
+}
+
+
+/** Increment Digit of the selected STANAG Code
+ * @param 
+ * @returns value of Digit
+ */
+uint8_t STANAG_Codes::incDigit() {
+  uint8_t digit;
+  
+  //Get digit value and increment
+  digit = _codes[_codeIdx][_digitIdx];
+  digit++;
+  
+//NOTE: maybe additional checks required. Valid codes seem to start with a "1" ???
+ 
+  //Check upper boundary and wrap around
+  if (digit > 9) {
+    digit=0;   
+  };
+ 
+  // Save updated digit
+  _codes[_codeIdx][_digitIdx]=digit;
+  
+  return digit;
+}
+
+   
+
+/** Compute the integer value of the selected STANAG Code
+ * @param uint8_t codeIdx
+ * @returns integer value of STANAG code
+ */
+int STANAG_Codes::getCode(uint8_t codeIdx) {
+  uint8_t digitIdx;
+  int code;
+  
+  code=0;
+  for (digitIdx=0; digitIdx < D_STANAG_DIGITS; digitIdx++) {
+
+    // ..., thousands, hundreds, tens, units    
+    code = code + _codes[codeIdx][digitIdx] * DECIMALS[D_STANAG_DIGITS - 1 - digitIdx];    
+  };  
+    
+  return code;
+}     
+
+
+/** Compute the integer value of the currently selected STANAG Code
+ * @param 
+ * @returns integer value of STANAG code
+ */
+int STANAG_Codes::getCode() {
+    
+  return getCode(_codeIdx);
+}     
+
+
+/** Compute and Set the digits of the selected STANAG Code
+ * @param uint8_t codeIdx
+ * @param int code 
+ * @returns valid integer value of STANAG code
+ */
+int STANAG_Codes::setCode(uint8_t codeIdx, int code) {
+  uint8_t digitIdx;
+  int temp;
+
+  //Check lower boundary
+  if (code<0) {
+    code=0;
+  }
+  else {
+    //Check upper boundary
+    if (code > DECIMALS[D_STANAG_DIGITS]) {
+      code = DECIMALS[D_STANAG_DIGITS] - 1;
+    }
+  };
+
+  // Extract decimal digits
+  temp=code;
+  for (digitIdx=0; digitIdx < D_STANAG_DIGITS; digitIdx++) {
+    
+    // ..., thousands, hundreds, tens, units
+    _codes[codeIdx][digitIdx] = temp / DECIMALS[D_STANAG_DIGITS - 1 - digitIdx];  // Extract most significant decimal digit
+    temp = temp % DECIMALS[D_STANAG_DIGITS - 1 - digitIdx];                       // Remainder for next digit  
+  };  
+    
+  return code;
+}     
+
+
+/** Compute and Set the digits of the currently selected STANAG Code
+ * @param int code 
+ * @returns valid integer value of STANAG code
+ */
+int STANAG_Codes::setCode(int code) {
+    
+  return setCode(_codeIdx, code);
+}     
+
+
+
+#if(0)
+int STANAG_Codes::setCodeDigits(uint8_t codeIdx, STANAG_Code_t STANAG_code) {
+}    
+
+STANAG_Code_t STANAG_Codes::getCodeDigits(uint8_t codeIdx) {
+} 
+#endif
+ 
+
+
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/STANAG_Codes.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,72 @@
+/* STANAG Codes - LTD STANAG Codes
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _STANAG_H
+#define _STANAG_H
+
+/*****************************************************************************/
+/*********************  DEFINITIONS FOR STANAG   *****************************/
+/*****************************************************************************/
+
+// Definitions
+#define D_STANAG_CODES              20
+#define D_STANAG_DIGITS              4
+
+// Typedefs
+typedef uint8_t STANAG_Code_t[D_STANAG_DIGITS];
+
+const int DECIMALS[D_STANAG_DIGITS+1] = {1, 10, 100, 1000, 10000};
+
+const STANAG_Code_t STANAG_DEFAULTS[D_STANAG_CODES] = {{1,0,0,0},{1,0,0,1},{1,0,0,2},{1,0,0,3},{1,0,0,4},
+                                                       {1,0,1,0},{1,0,1,1},{1,0,1,2},{1,0,1,3},{1,0,1,4},
+                                                       {1,0,2,0},{1,0,2,1},{1,0,2,2},{1,0,2,3},{1,0,2,4},
+                                                       {1,0,3,0},{1,0,3,1},{1,0,3,2},{1,0,3,3},{1,0,3,4}};
+
+// Masks
+
+// Enums
+
+/** Create a STANAG Codes object
+ *
+ * @param  none
+ * @brief
+*/
+class STANAG_Codes {
+public:
+    STANAG_Codes();
+    uint8_t setCodeIdx(uint8_t codeIdx);
+    uint8_t getCodeIdx();
+    uint8_t incCodeIdx();
+            
+    uint8_t setDigitIdx(uint8_t digitIdx);    
+    uint8_t getDigitIdx();                    
+    uint8_t incDigitIdx();                        
+    uint8_t incDigit();                            
+    
+    int setCode(uint8_t codeIdx, int code);    
+    int getCode(uint8_t codeIdx);        
+    int setCode(int code);    
+    int getCode();        
+    
+//  int setCodeDigits(uint8_t codeIdx, STANAG_Code_t STANAG_code);    
+//  STANAG_Code_t getCodeDigits(uint8_t codeIdx); 
+   
+protected:
+    uint8_t _codeIdx;
+    uint8_t _digitIdx;
+//    int     _codes[D_STANAG_CODES][D_STANAG_DIGITS];
+    STANAG_Code_t _codes[D_STANAG_CODES];
+    
+    void _init();          
+};
+
+
+#endif
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Status_Display.cpp	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,355 @@
+/* Status_Display - LED Status Display control
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#include "mbed.h"
+#include "PCF8574_DataBus.h"
+#include "PCF8574_EnableBus.h"
+#include "MBED_ControlBus.h"
+#include "Status_Display.h"
+
+
+/** Create a Status_Display object connected to the specified buses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+Status_Display::Status_Display (PCF8574_DataBus &databus, PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus) : 
+                                     _databus(databus), _enablebus(enablebus), _controlbus(controlbus) {
+   _init();
+}    
+
+/** Init Status_Display
+ * @param
+ * @returns 
+ *
+ * @brief
+ */
+void Status_Display::_init(void)
+{
+    // Apply reset
+//    reset();  // Note that this would also reset the Alphanumeric display. 
+
+    _latch1     = 0x00;                    // Make sure that all LEDs are disabled
+    _latch2     = 0x00;                    // Make sure that all LEDs are disabled 
+    _brightness = D_STATUS_LED_BRIGHT_DEF; // Default Brightness  
+
+    _write_latch1();                       // Write Status LED 
+    _write_latch2();                       // Write Status LED 
+    _write_latchbrightness();              // Write Brightness 
+
+    NoGo (LED_OFF);                        // NoGo Off (separate control)          
+}
+
+
+/** Set or Reset LED lamptest, note that current LED state is lost
+ *
+ * @param LED_State led_state
+ *
+ * @brief 
+*/
+void Status_Display::lamptest (LED_State led_state) {
+    int result = 1;
+    
+    if (led_state == LED_ON) {
+      // Status LEDs controlled by Latch1     
+      _latch1 = D_STATUS_LED_MULT | D_STATUS_LED_LASER | D_STATUS_LED_BATT | D_STATUS_LED_TEMP | D_STATUS_LED_ENRGY;
+      // Backlight On      
+      _latch1 |= D_STATUS_BACKLIGHT;
+
+      // Status LEDs controlled by Latch2 
+      _latch2 = D_STATUS_LED_CODE | D_STATUS_LED_RANGE | D_STATUS_LED_DESIG | D_STATUS_LED_ADDR | D_STATUS_LED_FREQ | D_STATUS_LED_PATH;
+
+      // NoGo On (separate control)     
+      NoGo (LED_ON);
+    }
+    else {
+      _latch1     = 0x00;                    // Make sure that all LEDs are disabled
+      _latch2     = 0x00;                    // Make sure that all LEDs are disabled 
+      
+      // NoGo Off (separate control)          
+      NoGo (LED_OFF);    
+    }  
+
+    // Write LED status
+    _write_latch1();
+    _write_latch2();           
+}
+
+
+
+/** Set or Reset Status LEDs
+ *
+ * @param LED_Pin led_pin 
+ * @param LED_State led_state
+ *
+ * @brief 
+*/
+void Status_Display::LED (LED_Pin led_pin, LED_State led_state) {
+    int result = 1;
+      
+    switch (led_pin) {
+// Status LEDs controlled by Latch1 
+     case LED_MULT : if (led_state == LED_ON)
+                         _latch1 |= D_STATUS_LED_MULT;      // LED Pin High
+                      else
+                         _latch1 &= ~D_STATUS_LED_MULT;     // LED Pin Low
+                      break;
+     case LED_LASER : if (led_state == LED_ON)
+                         _latch1 |= D_STATUS_LED_LASER;     // LED Pin High
+                      else
+                         _latch1 &= ~D_STATUS_LED_LASER;    // LED Pin Low
+                      break;
+     case LED_BATT : if (led_state == LED_ON)
+                         _latch1 |= D_STATUS_LED_BATT;      // LED Pin High
+                      else
+                         _latch1 &= ~D_STATUS_LED_BATT;     // LED Pin Low
+                      break;
+     case LED_TEMP : if (led_state == LED_ON)
+                         _latch1 |= D_STATUS_LED_TEMP;      // LED Pin High
+                      else
+                         _latch1 &= ~D_STATUS_LED_TEMP;     // LED Pin Low
+                      break;
+     case LED_ENRGY : if (led_state == LED_ON)
+                         _latch1 |= D_STATUS_LED_ENRGY;     // LED Pin High
+                      else
+                         _latch1 &= ~D_STATUS_LED_ENRGY;    // LED Pin Low
+                      break;
+
+// Status LEDs controlled by Latch2 
+     case LED_CODE : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_CODE;      // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_CODE;     // LED Pin Low
+                      break;
+     case LED_RANGE : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_RANGE;     // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_RANGE;    // LED Pin Low
+                      break;
+     case LED_DESIG : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_DESIG;     // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_DESIG;    // LED Pin Low
+                      break;
+     case LED_ADDR : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_ADDR;      // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_ADDR;     // LED Pin Low
+                      break;
+     case LED_FREQ : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_FREQ;      // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_FREQ;     // LED Pin Low
+                      break;
+     case LED_PATH : if (led_state == LED_ON)
+                         _latch2 |= D_STATUS_LED_PATH;      // LED Pin High
+                      else
+                         _latch2 &= ~D_STATUS_LED_PATH;     // LED Pin Low
+                      break;
+     
+     default:          // Oops, we should never end up here....
+                      result = -1;
+    }
+
+    _write_latch1();                                 // Write LED status
+    _write_latch2();           
+}
+
+
+/** Set or Clear the NoGo LED
+ *
+ * @param LED_State nogo_state
+ *
+ * @brief 
+*/
+void Status_Display::NoGo(LED_State NoGo_state) {
+  // Note that the NoGo LED has a separate pin and is directly connected to the Enable bus
+  // 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
+  }              
+  else {
+    _enablebus.nogo(LOW);      // NoGo LED Off
+  }     
+  
+}
+               
+/** Set or Clear the Backlight
+ *
+ * @param LED_State led_state
+ *
+ * @brief 
+*/
+void Status_Display::backlight (LED_State backlight_state) {
+
+    if (backlight_state == LED_ON) {
+        _latch1 |= D_STATUS_BACKLIGHT;     // Backlight On
+      }               
+    else {
+        _latch1 &= ~D_STATUS_BACKLIGHT;    // Backlight Off
+    }     
+    
+    _write_latch1();                       // Write Backlight state
+}
+ 
+
+/** Set Backlight and Status LEDs Brightness
+ *
+ * @param uint8_t brightness
+ *
+ * @brief 
+*/
+void Status_Display::set_brightness (uint8_t brightness) {
+
+    _brightness = brightness & STATUS_LED_BRIGHT_MASK;   
+
+    _write_latchbrightness();               // Write Brightness value
+}
+ 
+
+/** Set Backlight and Status LEDs Brightness
+ *
+ * @param Brightness brightness
+ *
+ * @brief 
+*/
+void Status_Display::set_brightness (Brightness brightness) {
+
+    switch (brightness) {
+     case BRT_OFF : set_brightness(D_STATUS_LED_BRIGHT_OFF);
+                    break;
+     case BRT_LOW : set_brightness(D_STATUS_LED_BRIGHT_LOW);
+                    break;
+     case BRT_MED : set_brightness(D_STATUS_LED_BRIGHT_MED);
+                    break;
+     case BRT_HIGH : set_brightness(D_STATUS_LED_BRIGHT_HGH);
+                    break;
+     default:       // Oops, we should never end up here....
+                    set_brightness(D_STATUS_LED_BRIGHT_DEF);
+    }
+                      
+}
+ 
+
+/** Write Latch1 value
+ *
+ * @param  none
+ *
+ * @brief 
+*/
+void Status_Display::_write_latch1()
+{
+//    // Switch databus buffer to outputs
+//    _controlbus.busdir(WRITE);        
+//    // Switch databus to outputs
+//    _databus.busdir(WRITE);        
+    
+    // Set CE low and wait
+    _enablebus.chipselect(LATCHEN_1, LOW);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    // Write data to the databus
+    _databus.write(_latch1);        
+ 
+    // Set WR low, wait, then set high and wait
+    _controlbus.WR(LOW);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+    _controlbus.WR(HIGH);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+
+    // Set CE high and wait
+    _enablebus.chipselect(LATCHEN_1, HIGH);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    
+//    // Switch databus back to inputs
+//    _databus.busdir(READ);        
+//    // Switch databus buffer back to inputs
+//    _controlbus.busdir(READ);        
+
+}
+
+
+/** Write Latch2 value
+ *
+ * @param none
+ *
+ * @brief 
+*/
+void Status_Display::_write_latch2()
+{
+//    // Switch databus buffer to outputs
+//    _controlbus.busdir(WRITE);        
+//    // Switch databus to outputs
+//    _databus.busdir(WRITE);        
+    
+    // Set CE low and wait
+    _enablebus.chipselect(LATCHEN_2, LOW);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    // Write data to the databus
+    _databus.write(_latch2);        
+ 
+    // Set WR low, wait, then set high and wait
+    _controlbus.WR(LOW);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+    _controlbus.WR(HIGH);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(LATCHEN_2, HIGH);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    
+//    // Switch databus back to inputs
+//    _databus.busdir(READ);        
+//    // Switch databus buffer back to inputs
+//    _controlbus.busdir(READ);        
+
+}
+
+/** Write Brightness value
+ *
+ * @param none
+ *
+ * @brief 
+*/
+void Status_Display::_write_latchbrightness()
+{
+//    // Switch databus buffer to outputs
+//    _controlbus.busdir(WRITE);        
+//    // Switch databus to outputs
+//    _databus.busdir(WRITE);        
+    
+    // Set CE low and wait
+    _enablebus.chipselect(CS_BRIGHT, LOW);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    // Write data to the databus
+    _databus.write(_brightness);        
+ 
+    // Set WR low, wait, then set high and wait
+    _controlbus.WR(LOW);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+    _controlbus.WR(HIGH);
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    // Set CE high and wait
+    _enablebus.chipselect(CS_BRIGHT, HIGH);  
+    wait_ms(STATUS_1TCY_WAIT_MS);
+
+    
+//    // Switch databus back to inputs
+//    _databus.busdir(READ);        
+//    // Switch databus buffer back to inputs
+//    _controlbus.busdir(READ);        
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Status_Display.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,111 @@
+/* Status_Display - LED status indicators
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _STATUS_DISPLAY_H
+#define _STATUS_DISPLAY_H
+
+//Useful stuff to simplify porting of some third party software
+#include "Utils.h"
+
+/*****************************************************************************/
+/*********************  DEFINITIONS FOR STATUS DISPLAY ** ********************/
+/*****************************************************************************/
+
+// Specific delays for display operation
+#define STATUS_1TCY_WAIT_MS         1
+
+// Definitions for Latch1 of Status LEDs
+#define D_STATUS_LED_MULT           0x01
+#define D_STATUS_LED_LASER          0x02
+#define D_STATUS_LED_BATT           0x04
+#define D_STATUS_LED_TEMP           0x08
+#define D_STATUS_LED_ENRGY          0x10
+#define D_STATUS_LED_NOTUSED_15     0x20
+#define D_STATUS_LED_NOTUSED_16     0x40
+#define D_STATUS_BACKLIGHT          0x80
+
+// Definitions for Latch2 of Status LEDs
+#define D_STATUS_LED_NOTUSED_20     0x01
+#define D_STATUS_LED_CODE           0x02
+#define D_STATUS_LED_RANGE          0x04
+#define D_STATUS_LED_DESIG          0x08
+#define D_STATUS_LED_ADDR           0x10
+#define D_STATUS_LED_FREQ           0x20
+#define D_STATUS_LED_PATH           0x40
+#define D_STATUS_LED_NOTUSED_27     0x80
+
+
+// Definitions for LatchBrightness of Status LEDs
+// Value indicates cd/m2
+#define D_STATUS_LED_BRIGHT_000     0x00
+#define D_STATUS_LED_BRIGHT_022     0x01
+#define D_STATUS_LED_BRIGHT_053     0x02
+#define D_STATUS_LED_BRIGHT_112     0x03
+#define D_STATUS_LED_BRIGHT_253     0x04
+#define D_STATUS_LED_BRIGHT_570     0x05
+#define D_STATUS_LED_BRIGHT_129     0x06
+#define D_STATUS_LED_BRIGHT_360     0x07
+
+// control word masks for Status LEDs
+#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_MED     D_STATUS_LED_BRIGHT_570
+#define D_STATUS_LED_BRIGHT_HGH     D_STATUS_LED_BRIGHT_360
+
+// default display brightness
+#define D_STATUS_LED_BRIGHT_DEF     D_STATUS_LED_BRIGHT_LOW
+
+//Enums for Status LEDs
+enum LED_Pin { LED_MULT, LED_LASER, LED_BATT, LED_TEMP, LED_ENRGY, LED_CODE, LED_RANGE, LED_DESIG, LED_ADDR, LED_FREQ, LED_PATH };
+enum LED_State { LED_ON, LED_OFF};
+
+//Enums for Brightness
+enum Brightness { BRT_OFF, BRT_LOW, BRT_MED, BRT_HIGH };
+
+/** Create a Status_Display object connected to the proper busses
+ *
+ * @param  PCF8574_DataBus data databus to connect to 
+ * @param  PCF8574_EnableBus enable enablebus to connect to 
+ * @param  MBED_ControlBus control controlbus to connect to 
+*/
+class Status_Display {
+public:
+    Status_Display(PCF8574_DataBus &databus,
+                   PCF8574_EnableBus &enablebus, MBED_ControlBus &controlbus);
+    void lamptest (LED_State led_state);
+    void LED (LED_Pin led_pin, LED_State led_state);
+    void NoGo(LED_State NoGo_state);
+    void backlight (LED_State backlight_state);
+    void set_brightness(uint8_t brightness);  
+    void set_brightness(Brightness brightness);  
+            
+protected:
+    PCF8574_DataBus &_databus;
+    PCF8574_EnableBus &_enablebus;
+    MBED_ControlBus &_controlbus;
+
+    uint8_t _latch1;
+    uint8_t _latch2;
+    uint8_t _brightness;
+//    void _write_latch1(char data);
+//    void _write_latch2(char data);
+    void _write_latch1();
+    void _write_latch2();
+    void _write_latchbrightness();                
+    void _init(); 
+          
+};
+
+
+#endif
+/*****************************************************************************/
+/******************************  END OF FILE  ********************************/
+/*****************************************************************************/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Testloop.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,342 @@
+//------------------------------------------------------------//
+// Testing Stuff                                              //   
+//------------------------------------------------------------//
+void show_LEDS () {
+  static int state = 0;
+ 
+  switch (state) {
+   case 0: 
+        myled1 = 1;
+        myled2 = 0;
+        myled3 = 0;
+        state = 1;
+        break;
+   case 1: 
+        myled1 = 0;
+        myled2 = 1;
+        myled3 = 0;
+        state = 2;
+        break;
+   case 2:     
+        myled1 = 0;
+        myled2 = 0;
+        myled3 = 1;
+        state = 0;
+        break;
+   }
+}
+
+
+void show_menu() {
+    pc.printf("0: Exit\r");
+    pc.printf("1: Show Menu\r");    
+    pc.printf("2: Send Message\r"); 
+    pc.printf("3: Toggle Heartbeat\r");    
+    pc.printf("4: Show STANAGs\r");        
+    pc.printf("5: Set all STANAGs\r");
+    pc.printf("6: Inc STANAG Code Idx\r"); 
+    pc.printf("7: Inc STANAG Digit Idx\r");                                
+    pc.printf("8: Inc STANAG Digit\r");                                    
+    pc.printf("9: Test I2C Databus\r");                                        
+    pc.printf("A: Test I2C Addressbus\r");                                        
+    pc.printf("B: Test I2C Enablebus\r");        
+    pc.printf("C: Test Status LEDs\r");            
+    pc.printf("D: Test Brightness LEDs\r");                
+    pc.printf("\r");                
+}
+
+
+void testloop() {
+  bool running=true;
+  char command;
+  int count;
+  
+    pc.printf("Start Test!\r");
+    show_LEDS();
+    show_menu();
+    myled4=1;
+    while(running) {
+    
+       if(pc.readable()) {
+         command = pc.getc();       
+         pc.printf("\r");         
+         show_LEDS();         
+
+         switch (command) {
+          case '0' :
+                     pc.printf("Done\r");                    
+                     running = false;  
+                     break;
+          
+          case '1' :
+                     show_menu();
+                     break;
+                    
+          case '2' :
+                     pc.printf("Hello World!\r");          
+                     break;
+          
+          case '3' :
+                     if (heartbeatflag){
+                       heartbeat_stop();
+                     }
+                     else {
+                       heartbeat.start();
+                     };            
+                     break;
+
+          case '4' :
+                     pc.printf("Show STANAGs\r");  
+                     for (int codeIdx=0; codeIdx < D_STANAG_CODES; codeIdx++) {
+                       pc.printf("Code[%d] = %d\r", codeIdx, STANAG_codes.getCode(codeIdx) );
+                     }  
+                     break;
+
+          case '5' :
+                     pc.printf("Set STANAGs\r");
+                     for (int codeIdx=0; codeIdx < D_STANAG_CODES; codeIdx++) {
+                       STANAG_codes.setCode(codeIdx, 2000 + codeIdx );
+                     }  
+        
+                     break;
+ 
+          case '6' :
+                      pc.printf("Inc STANAG Code Idx\r"); 
+                      pc.printf("New Idx = %d\r", STANAG_codes.incCodeIdx() );
+                        
+                      break;
+          case '7' :
+                      pc.printf("Inc STANAG Digit Idx\r"); 
+                      pc.printf("New Idx = %d\r", STANAG_codes.incDigitIdx() );
+                        
+                      break;
+ 
+          case '8' :
+                      pc.printf("Inc STANAG Digit\r"); 
+                      pc.printf("New Digit = %d\r", STANAG_codes.incDigit() );
+                        
+                      pc.printf("New Code = %4d\r", STANAG_codes.getCode() );                      
+                      break;
+          case '9' :
+                      pc.printf("Test I2C Databus\r"); 
+                      pc.printf("Press any key to quit...");
+                      count=0;                       
+                      while(! pc.readable()) {
+                        myled2 = 1;      
+                        wait(0.1);
+                        myled2 = 0;
+                        wait(0.1);
+
+                        databus.write(count); 
+                        //addressbus.write(count);
+                        //enablebus.chipselect(CS_DISP, HIGH);
+                        count = (count + 1) & 0xFF;
+                      }                      
+                      
+                      command = pc.getc(); 
+                      pc.printf("..Done\r");                      
+                      
+                      break;
+          case 'A' :
+                      pc.printf("Test I2C Addressbus\r"); 
+                      pc.printf("Press any key to quit...");
+                      count=0;                       
+                      while(! pc.readable()) {
+                        myled2 = 1;      
+                        wait(0.1);
+                        myled2 = 0;
+                        wait(0.1);
+
+                        //databus.write(count); 
+                        addressbus.write(count);
+                        //enablebus.chipselect(CS_DISP, HIGH);
+                        count = (count + 1) & 0xFF;
+                      }                      
+                      
+                      command = pc.getc(); 
+                      pc.printf("..Done\r");                      
+                      
+                      break;
+ 
+          case 'B' :
+                      pc.printf("Test I2C Enablebus\r"); 
+                      pc.printf("Press any key to quit...");
+                      count=0;                       
+                      while(! pc.readable()) {
+
+                        myled2 = 1;      
+                        enablebus.chipselect(CS_SWITCH, LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+//                        enablebus.chipselect(CS_SWITCH, HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.chipselect(LATCHEN_1, LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+//                        enablebus.chipselect(LATCHEN_1, HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.chipselect(LATCHEN_2, LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+//                        enablebus.chipselect(LATCHEN_2, HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.chipselect(CS_BRIGHT, LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+//                        enablebus.chipselect(CS_BRIGHT, HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.chipselect(CS_DISP, LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+                        enablebus.chipselect(CS_DISP, HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.reset(LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+                        enablebus.reset(HIGH);                        
+                        wait(0.1);
+
+                        myled2 = 1;      
+                        enablebus.nogo(LOW);                        
+                        wait(0.1);
+                        myled2 = 0;
+                        enablebus.nogo(HIGH);                        
+                        wait(0.1);
+
+                        //databus.write(count); 
+                        //addressbus.write(count);
+                        //count = (count + 1) & 0xFF;
+                      }                      
+                      
+                      command = pc.getc(); 
+                      pc.printf("..Done\r");                      
+                      
+                      break;
+                      
+          case 'C' :
+                      pc.printf("Test Status LEDs\r"); 
+                      pc.printf("Press any key to quit...");
+                      count=0;                       
+                      while(! pc.readable()) {
+                      // LEDs On
+                        LF28A_status.NoGo(LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_LASER, LED_ON);
+                        wait(0.1);                                                
+                        LF28A_status.LED(LED_TEMP, LED_ON);
+                        wait(0.1);
+                                                
+                        LF28A_status.LED(LED_MULT, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_ENRGY, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_BATT, LED_ON);
+                        wait(0.1);                        
+                        
+                        LF28A_status.LED(LED_DESIG, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_RANGE, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_CODE, LED_ON);
+                        wait(0.1);                        
+                        
+                        LF28A_status.LED(LED_ADDR, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_FREQ, LED_ON);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_PATH, LED_ON);
+                        wait(0.1);                        
+                                                                                                                        
+                        LF28A_status.backlight(LED_ON);
+                        wait(0.1);                        
+
+                      // LEDs Off
+                        LF28A_status.NoGo(LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_LASER, LED_OFF);
+                        wait(0.1);                                                
+                        LF28A_status.LED(LED_TEMP, LED_OFF);
+                        wait(0.1);
+                                                
+                        LF28A_status.LED(LED_MULT, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_ENRGY, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_BATT, LED_OFF);
+                        wait(0.1);                        
+                        
+                        LF28A_status.LED(LED_DESIG, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_RANGE, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_CODE, LED_OFF);
+                        wait(0.1);                        
+                        
+                        LF28A_status.LED(LED_ADDR, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_FREQ, LED_OFF);
+                        wait(0.1);                        
+                        LF28A_status.LED(LED_PATH, LED_OFF);
+                        wait(0.1);                        
+                                                                                                                        
+                        LF28A_status.backlight(LED_OFF);
+                        wait(0.1);                        
+                      }                      
+                      
+                      command = pc.getc(); 
+                      pc.printf("..Done\r");                      
+                      
+                      break;                      
+
+          case 'D' :
+                      pc.printf("Test Brightness LEDs\r"); 
+                      pc.printf("Press any key to quit...");
+
+                      // LEDs On
+                      LF28A_status.NoGo(LED_ON);
+                      LF28A_status.LED(LED_LASER, LED_ON);
+                      LF28A_status.LED(LED_TEMP, LED_ON);
+
+                      while(! pc.readable()) {
+                        LF28A_status.set_brightness(BRT_LOW); 
+                        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_OFF);                                                 
+                        wait(0.5);                        
+                      }                      
+                      // LEDs Off
+                      LF28A_status.NoGo(LED_OFF);
+                      LF28A_status.LED(LED_LASER, LED_OFF);
+                      LF28A_status.LED(LED_TEMP, LED_OFF);
+
+                      LF28A_status.set_brightness(BRT_LOW); 
+                                                
+                      command = pc.getc(); 
+                      pc.printf("..Done\r");                      
+                      
+                      break;   
+                              
+        } //switch
+      }//if
+    }//while
+
+    pc.printf("End Test!\r\r");
+}
+
+//------------------------------------------------------------//
+// End Testing Stuff                                          //   
+//------------------------------------------------------------//
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils.h	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,18 @@
+/* Utils - Useful stuff to simplify porting of some third party software
+ * Copyright (c) 2011 Wim Huiskamp
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * version 0.2 Initial Release
+*/
+#ifndef _UTILS_H
+#define _UTILS_H
+
+//Typedefs
+
+#ifndef min
+#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+
+#endif
\ No newline at end of file
--- /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");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.lib	Sat Aug 20 12:49:44 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/projects/libraries/svn/mbed/trunk@28
\ No newline at end of file