Example project for the Rioux Chem control box

Dependencies:   mbed MODSERIAL

Dependents:   screentest

Rioux Chem Control Box

/media/uploads/emh203/ccb.jpg

This is the example project for the Rioux Chem Control Box. I have posted some youtube videos to guide you through the hardware and software:

Rioux Chem Control Box - Hardware

http://www.youtube.com/watch?v=MoZ92GRYa4s

Rioux Chem Control Box - Software - Part I

http://www.youtube.com/watch?v=_MwaTLL4dyA==

Rioux Chem Control Box - Software - Part II

http://www.youtube.com/watch?v=j_P89izfgoQ

Files at this revision

API Documentation at this revision

Comitter:
emh203
Date:
Sat Jan 25 19:10:17 2014 +0000
Child:
1:d64ac853223c
Commit message:
1st version to Demo! All interfaces tested and working

Changed in this revision

DRIVERS/CHEM_BOX_COMMON.cpp Show annotated file Show diff for this revision Revisions of this file
DRIVERS/CHEM_BOX_INTERFACE.h Show annotated file Show diff for this revision Revisions of this file
MODSERIAL.lib 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.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRIVERS/CHEM_BOX_COMMON.cpp	Sat Jan 25 19:10:17 2014 +0000
@@ -0,0 +1,1828 @@
+#include "mbed.h"
+#include "CHEM_BOX_INTERFACE.h"
+#include "MODSERIAL.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+//Mbed Objects
+
+DigitalOut AIO_ADC1_CS(p30);     
+
+DigitalOut AIO_ADC2_CS(p29);  
+
+PwmOut BUZZER_CONTROL(p26);
+
+DigitalOut MCU_SR_CLEAR(p25);    
+
+DigitalOut AIO_DAC1_CS(p24);    
+
+DigitalOut AIO_DAC2_CS(p23);     
+
+DigitalOut MFC_POWER_CONTROL(p22); 
+
+PwmOut FAN_CONTROL(p21);       
+
+SPI SPI1(p5,p6,p7);
+
+DigitalOut MCU_SR_LOAD(p8); 
+
+SPI SPI0(p11,p12,p13); 
+
+DigitalOut SmartSwitch_SS(p14); 
+
+BusOut TEMP_SENSE_ADDRESS(p15,p16,p17,p18);
+
+DigitalOut TEMP_SENSE_CS(p19); 
+
+DigitalIn LCD_SWITCH(p20); 
+
+MODSERIAL RS232_0(p9, p10, 1024, 1024); 
+
+MODSERIAL RS232_1(p28, p27, 1024, 1024); 
+
+// Make TX buffer 1024bytes and RX buffer use 512bytes.
+MODSERIAL PC(USBTX, USBRX, 1024, 1024); // tx, rx
+
+//Local Variables
+
+
+static uint8_t HeaterBits = 0;
+
+static uint16_t SolenoidBits = 0;
+
+static uint8_t DigitalOutputBits = 0;
+
+Timeout BuzzTimeout;
+     
+static uint16_t Thermocouple_FAULT = 0;     
+
+static uint16_t Thermocouple_SCV = 0;     
+
+static uint16_t Thermocouple_SCG = 0;     
+
+static uint16_t Thermocouple_OC= 0;     
+
+static float Temperature[12];
+
+static float InternalTemperature[12];
+
+static uint16_t ReadRawADC(uint8_t Channel);
+
+
+//Local Functions
+
+void InitTerminal();
+
+void WriteRAW_DAC_Value(uint8_t Channel,uint16_t Data);
+
+
+
+void InitChemBox()
+{
+
+    AIO_ADC1_CS = 1;     
+    
+    AIO_ADC2_CS = 1;   
+    
+    BUZZER_CONTROL.period_ms(1.0);
+    
+    MCU_SR_CLEAR = 1;   
+    
+    AIO_ADC1_CS = 1;    
+    
+    AIO_ADC2_CS = 1;    
+    
+    MFC_POWER_CONTROL = 0;
+    
+    FAN_CONTROL.period_us(1000);    
+    
+    FAN_CONTROL.write(0);
+        
+    SPI1.format(8,0);
+    
+    SPI1.frequency(4000000);
+    
+    MCU_SR_LOAD = 0;
+    
+    SPI0.format(8,0);
+    
+    SPI0.frequency(4000000);
+    
+    SmartSwitch_SS = 1; 
+    
+    TEMP_SENSE_ADDRESS = 0;
+    
+    TEMP_SENSE_CS = 1;
+
+    HeaterBits = 0;
+
+    SolenoidBits = 0;
+
+    DigitalOutputBits = 0;
+
+    Thermocouple_FAULT = 0;     
+
+    Thermocouple_SCV = 0;     
+    
+    Thermocouple_SCG = 0;     
+    
+    Thermocouple_OC= 0;     
+
+    InitTerminal();
+    
+    GFX_Init();
+}
+
+
+void SetFanSpeed(uint8_t S)
+{
+  if(S>100)
+    S = 100;
+    
+    FAN_CONTROL = (float)(S)/100.0;
+   
+}
+
+void EnableFan()
+{
+    SetFanSpeed(100);
+}
+
+void DisableFan()
+{
+    SetFanSpeed(0);
+}    
+
+void BuzzOff()
+{
+    BUZZER_CONTROL = 0;
+}
+
+void Buzz(float Time)
+{
+   BUZZER_CONTROL = 0.5;
+   BuzzTimeout.attach(&BuzzOff, Time);
+  
+}
+
+
+void EnableHeater(uint8_t RelayIndex)
+{
+    HeaterBits |= (1<<RelayIndex);
+}
+
+void DisableHeater(uint8_t RelayIndex)
+{
+    HeaterBits &= ~(1<<RelayIndex);
+}
+
+void EnableSolenoidValve(uint8_t SolenoidIndex)
+{
+    SolenoidBits |= (1<<SolenoidIndex);
+}
+
+void DisableSolenoidValue(uint8_t SolenoidIndex)
+{
+    SolenoidBits &= ~(1<<SolenoidIndex);
+}
+
+void DisableAllHeatersAndSolenoids()
+{
+    
+    SolenoidBits = 0;
+    HeaterBits = 0;
+
+    MCU_SR_CLEAR = 1;
+    
+    MCU_SR_CLEAR = 0;
+
+    MCU_SR_CLEAR = 1;
+    
+    MCU_SR_LOAD = 1;
+   
+    MCU_SR_LOAD = 0;
+}
+
+void EnableMiscDigitalOutput(uint8_t DigitalOutIndex)
+{
+    DigitalOutputBits |= (1<<DigitalOutIndex);
+}
+
+void DisableMiscDigitalOutput(uint8_t DigitalOutIndex)
+{
+    DigitalOutputBits &= ~(1<<DigitalOutIndex);
+}
+
+void FlushDigitalIO()
+{
+    SPI1.format(8,0);
+    
+    SPI1.write((SolenoidBits >> 8) & 0xFF);
+    SPI1.write(SolenoidBits & 0xFF);
+    SPI1.write(HeaterBits & 0xFF);
+    SPI1.write(DigitalOutputBits & 0xFF);
+    
+    MCU_SR_LOAD = 1;
+    MCU_SR_LOAD = 0;
+}
+
+//Make sure to call  ReadThermocouple befor eyou call this so internal variables are updated
+uint16_t ReadThermocouple_OC() 
+{
+    return Thermocouple_OC;
+}
+//Make sure to call  ReadThermocouple befor eyou call this so internal variables are updated
+uint16_t ReadThermocouple_SCG()
+{
+    return Thermocouple_SCG;
+}
+//Make sure to call  ReadThermocouple befor eyou call this so internal variables are updated
+uint16_t ReadThermocouple_SCV()
+{
+    return  Thermocouple_SCV;
+}
+//Make sure to call  ReadThermocouple befor eyou call this so internal variables are updated
+uint16_t ReadThermocouple_FAULT()
+{
+    return  Thermocouple_FAULT;
+}
+
+
+float ReadInternalTemperature(uint8_t ThermocoupleIndex)
+{
+    ReadThermocouple(ThermocoupleIndex); //this will yank out the Data
+    return InternalTemperature[ThermocoupleIndex];
+}
+
+
+   
+float ReadThermocouple(uint8_t ThermocoupleIndex)
+{
+    uint8_t i=0;
+    uint32_t    ThermocoupleData = 0;
+    uint8_t TempData[4];
+    
+    int16_t InternalTemp = 0;
+    int16_t ThermocoupleTemp = 0;
+    
+    //reset SPi format
+    SPI1.format(8,0);
+    
+    TEMP_SENSE_ADDRESS = ThermocoupleIndex & 0x1f;
+    
+    TEMP_SENSE_CS = 0;
+    
+    for(i=0;i<4;i++)
+        TempData[i] = SPI1.write(0);
+    
+    TEMP_SENSE_CS = 1;
+
+
+    ThermocoupleData =   (uint32_t)(TempData[3])         | 
+                        (((uint32_t)(TempData[2]))<<8)   |
+                        (((uint32_t)(TempData[1]))<<16)  |
+                        (((uint32_t)(TempData[0]))<<24);
+                        
+    
+    if(ThermocoupleData & 0x01)
+         Thermocouple_OC |= (1<<ThermocoupleIndex);
+    else
+         Thermocouple_OC &= ~(1<<ThermocoupleIndex);       
+
+    if(ThermocoupleData & 0x02)
+        Thermocouple_SCG |= (1<<ThermocoupleIndex);
+    else
+        Thermocouple_SCG &= ~(1<<ThermocoupleIndex);
+
+    if(ThermocoupleData & 0x04)
+        Thermocouple_SCV |= (1<<ThermocoupleIndex);
+    else
+        Thermocouple_SCV &= ~(1<<ThermocoupleIndex);
+
+    if(ThermocoupleData & (1<<16))
+        Thermocouple_FAULT |= (1<<ThermocoupleIndex);
+    else
+        Thermocouple_FAULT &= ~(1<<ThermocoupleIndex);
+
+    if(ThermocoupleData & (1<<15))
+        InternalTemp = (int16_t) ( ( (ThermocoupleData>>4) & 0xFFF) | 0xF000);  //Sign extend in this case.... we need to map a 12 bit signed number to 16-bits
+    else
+        InternalTemp = (int16_t)( ( (ThermocoupleData>>4) & 0xFFF));
+
+
+     if(ThermocoupleData & (0x10000000))
+        ThermocoupleTemp = (int16_t)(((ThermocoupleData>>18) & 0x2FFF) | 0xC000);  //Sign extend in this case.... we need to map a 14 bit signed number to 16-bits
+    else
+        ThermocoupleTemp = (int16_t)(((ThermocoupleData>>18) & 0x2FFF));
+
+     Temperature[ThermocoupleIndex] = (float)ThermocoupleTemp/4.0;
+
+     InternalTemperature[ThermocoupleIndex] = (float)InternalTemp/16.0;;
+
+    return  Temperature[ThermocoupleIndex];
+}
+
+float ReadMFC_AnalogInput(uint8_t Channel)
+{
+    if(Channel > 7)
+        Channel = 7;
+
+    return ((float)(ReadRawADC(Channel)) /4095.0) * 5.0;
+
+}
+
+void EnableMFC_Power()
+{
+    MFC_POWER_CONTROL = 1;
+}
+
+void DisableMFC_Power()
+{
+    MFC_POWER_CONTROL = 0;
+}
+
+
+float ReadMISC_AnalogInput(uint8_t Channel)
+{
+
+    if(Channel > 3)
+        Channel = 3;
+
+    return ((float)(ReadRawADC(Channel + 9)) /4095.0) * 5.0;
+
+}
+
+float Read4to20(uint8_t Channel)
+{
+
+    if(Channel > 1)
+        Channel = 1;
+
+    return (((float)(ReadRawADC(Channel + 7)) /4095.0) * 5.0) / 240;
+    
+}
+
+
+static uint16_t ReadRawADC(uint8_t Channel)
+{
+    uint8_t ControlByte[3];
+    uint8_t ADC_Data[3];
+    uint16_t V;
+    
+    SPI0.format(8,0);   //The ADC requires mode 0,0
+    
+    /*See Microchip manual DS21298E-page 21*/
+    
+    ControlByte[0] = (((Channel&0x07)>>2) & 0x01) | (3<<1);
+    ControlByte[1] = Channel<<6;
+    ControlByte[2] = 0;
+    
+    
+    if(Channel<8)
+        AIO_ADC1_CS = 0;
+    else
+        AIO_ADC2_CS = 0;
+            
+        //unroll the loop    
+        ADC_Data[0] = SPI0.write(ControlByte[0]);
+        ADC_Data[1] = SPI0.write(ControlByte[1]);
+        ADC_Data[2] = SPI0.write(ControlByte[2]);
+   
+        AIO_ADC1_CS = 1;
+        AIO_ADC2_CS = 1;
+        
+        
+        V = ((uint16_t)(ADC_Data[1])<<8 | (uint16_t)(ADC_Data[2])) & 0xFFF;
+   
+        return (V);
+        
+}
+
+
+void WriteMFC_AnalogOut(uint8_t Channel,float Value)
+{
+
+    if(Channel>7)
+        Channel = 7;
+        
+    if(Value >5.0)
+        Value = 5.0;
+     
+    if(Value<0.0)
+        Value = 0.0;
+  
+    WriteRAW_DAC_Value(Channel,(uint16_t)((Value/5.0) * 4095));
+ 
+}
+
+void WriteMISC_AnalogOut(uint8_t Channel,float Value)
+{
+    if(Channel>3)
+        Channel = 3;
+        
+    if(Value >5.0)
+        Value = 5.0;
+     
+    if(Value<0.0)
+        Value = 0.0;
+
+        WriteRAW_DAC_Value(8+Channel,(uint16_t)((Value/5.0)*4095));
+}
+
+
+void WriteRAW_DAC_Value(uint8_t Channel,uint16_t Data)
+{
+
+    uint16_t DataOut;
+    
+    if(Channel<8)
+        AIO_DAC1_CS = 0;
+    else
+        AIO_DAC2_CS = 0;
+
+    SPI0.format(8,1);   //The DAC requires mode 0,1
+   
+    DataOut = ((uint16_t)(Channel) & 0x7)<<12  | (Data & 0xFFF);
+    
+    SPI0.write((DataOut>>8)&0xFF);
+    SPI0.write(DataOut&0xFF);
+
+    AIO_DAC1_CS = 1;
+    AIO_DAC2_CS = 1;
+
+}
+
+
+
+
+#define MAX_TERMINAL_LINE_CHARS 128
+#define MAX_TERMINAL_CMD_CHARS  64
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef void (*TerminalCallback)(char *);
+
+
+typedef struct 
+{
+    const char *CommandString;
+    TerminalCallback Callback;
+    const char *HelpString;
+        
+} TerminalCallbackRecord;
+
+//Callback function prototypes
+void TerminalCmd_Help(char *arg);
+void TerminalCmd_Stub(char *arg);
+void TerminalCmd_EnableHeater(char *arg);
+void TerminalCmd_DisableHeater(char *arg);
+void TerminalCmd_EnableSolenoidValve(char *arg);
+void TerminalCmd_DisableSolenoidValue(char *arg);
+void TerminalCmd_DisableAllHeatersAndSolenoids(char *arg);
+void TerminalCmd_EnableMiscDigitalOutput(char *arg);
+void TerminalCmd_DisableMiscDigitalOutput(char *arg);
+void TerminalCmd_FlushDigitalIO(char *arg);
+void TerminalCmd_FanOn(char *arg);
+void TerminalCmd_FanOff(char *arg);
+void TerminalCmd_Buzz(char *arg);
+void TerminalCmd_T(char *arg);
+void TerminalCmd_MFCI(char *arg);
+void TerminalCmd_MFCO(char *arg);
+void TerminalCmd_4TO20(char *arg);
+void TerminalCmd_AIN(char *arg);
+void TerminalCmd_MFCON(char *arg);
+void TerminalCmd_MFCOFF(char *arg);
+void TerminalCmd_AOUT(char *arg);
+void TerminalCmd_Reset(char *arg);
+
+//Populate this array with the callback functions and their terminal command string
+TerminalCallbackRecord MyTerminalCallbackRecords[] ={   {"reset",TerminalCmd_Reset,"Resets the CHEM box"},
+
+                                                        {"help",TerminalCmd_Help,"Lists available commands"},
+                                                        
+                                                        {"EH",TerminalCmd_EnableHeater,"Enables a heater channel.  Argument should be between 0 and 7.   Outputs will update when a FDIO command is issued"},
+                                                        
+                                                        {"DH",TerminalCmd_DisableHeater,"Disables a heater channel.  Argument should be between 0 and 7. Outputs will update when a FDIO command is issued"},
+                                                        
+                                                        {"ESV",TerminalCmd_EnableSolenoidValve,"Enables a solenoid channel. Argument should be between 0 and 11.  Outputs will update when a FDIO command is issued"},
+                                                        
+                                                        {"DSV",TerminalCmd_DisableSolenoidValue,"Disables a solenoid channel. Argument should be between 0 and 11.  Outputs will update when a FFDIO command is issued"},
+                                                        
+                                                        {"DAHAS",TerminalCmd_DisableAllHeatersAndSolenoids,"Disables all heaters and solenoids.  Command is immediately executed."},
+                                                        
+                                                        {"EMDO",TerminalCmd_EnableMiscDigitalOutput,"Enables a misc. digital output.  Argument should be between 0 and 3.  Output will update when a FDIO command is issued"},
+                                                        
+                                                        {"DMDO",TerminalCmd_DisableMiscDigitalOutput,"Enables a misc. digital output.  Argument should be between 0 and 3.  Output will update when a FDIO command is issued"},
+                                                        
+                                                        {"FDIO",TerminalCmd_FlushDigitalIO,"Updates the all of the digital IO channels"},
+                                                        
+                                                        {"FON",TerminalCmd_FanOn,"Turns on the fans"},
+                                                        
+                                                        {"FOFF",TerminalCmd_FanOff,"Turns off the fans"},
+                                                        
+                                                        {"BUZZ",TerminalCmd_Buzz,"Buzz for a little bit.  Argument should be a floating point number representing the number of seconds to buzz"},
+                                                        
+                                                        {"T",TerminalCmd_T,"Read thermocouple channel"},
+                                                        
+                                                        {"MFCI",TerminalCmd_MFCI,"Reads in voltage from MFC channel"},
+                                                        
+                                                        {"MFCO",TerminalCmd_MFCO,"Sets voltage at MFC output channel.  First argument should be the channel.  Second argument should be the voltage.  I.E.  MFCO 1.45"},
+                                                        
+                                                        {"AOUT",TerminalCmd_AOUT,"Sets voltage at misc. output channel. First argument should be the channel.  Second argument should be the voltage.  I.E.  AOUT 3.211"},
+                                                        
+                                                        {"4TO20",TerminalCmd_4TO20,"Reads a 4 to 20 mA channel"},
+                                                        
+                                                        {"AIN",TerminalCmd_AIN,"Reads a general purpose analog in channel"},
+                                                        
+                                                        {"MFCON",TerminalCmd_MFCON,"Turns on the MFC power"},
+                                                        
+                                                        {"MFCOFF",TerminalCmd_MFCOFF,"Turns off the MFC power"}
+                                                    };
+
+
+extern "C" void mbed_reset();
+
+void TerminalCmd_Reset(char *arg)
+{
+    mbed_reset();
+}
+
+void TerminalCmd_Stub(char *arg)
+{
+    PC.printf("stub \r\n");
+}
+
+void TerminalCmd_MFCI(char *arg)
+{
+    int Channel = -1;
+    float Data;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=6)
+        {
+            Data =  ReadMFC_AnalogInput(Channel);
+            PC.printf("MFCI:%d:%.3f",Channel,Data);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 6",Channel);
+        }
+    }
+    else
+    {
+        for(Channel = 0; Channel<=6; Channel++)
+        {
+            Data =  ReadMFC_AnalogInput(Channel);
+            PC.printf("MFCI:%d:%.3f\r\n",Channel,Data);
+        }    
+    }
+}
+
+void TerminalCmd_MFCON(char *arg)
+{
+    EnableMFC_Power();
+}
+
+
+void TerminalCmd_MFCOFF(char *arg)
+{
+    DisableMFC_Power();
+}
+
+
+void TerminalCmd_MFCO(char *arg)
+{
+    int Channel = -1;
+    float Data = 0.0;
+    
+    if(sscanf(arg,"%d %f",&Channel,&Data) == 2)
+    {
+        if(Channel>=0 && Channel <=7)
+        {
+            WriteMFC_AnalogOut(Channel,Data);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 1",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Channel should be an integer between 0 and 7 and value should be a float between 0.0 and 5.0. i.e. MFCO 2 4.45",arg);
+    }
+}
+
+void TerminalCmd_AOUT(char *arg)
+{
+    int Channel = -1;
+    float Data = 0.0;
+    
+    if(sscanf(arg,"%d %f",&Channel,&Data) == 2)
+    {
+        if(Channel>=0 && Channel <=3)
+        {
+            WriteMISC_AnalogOut(Channel,Data);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 3",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Channel should be an integer between 0 and 7 and value should be a float between 0.0 and 5.0.   i.e. AOUT 1 1.25",arg);
+    }
+}
+
+void TerminalCmd_4TO20(char *arg)
+{
+    int Channel = -1;
+    float Data;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=1)
+        {
+            Data =  Read4to20(Channel);
+            PC.printf("4TO20:%d:%.3f",Channel,Data);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 1",Channel);
+        }
+    }
+    else
+    {
+      
+        for(Channel = 0;Channel<=1;Channel++)
+        {
+            Data =  Read4to20(Channel);
+            PC.printf("4TO20:%d:%.3f\r\n",Channel,Data);
+        }
+      
+    }
+
+
+}
+
+void TerminalCmd_AIN(char *arg)
+{
+    int Channel = -1;
+    float Data;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=3)
+        {
+            Data =  ReadMISC_AnalogInput(Channel);
+            PC.printf("AIN:%d:%.3f",Channel,Data);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 3",Channel);
+        }
+    }
+    else
+    {
+        for(Channel = 0;Channel<=3;Channel++)
+        {
+            Data =  ReadMISC_AnalogInput(Channel);
+            PC.printf("AIN:%d:%.3f\r\n",Channel,Data);
+        }
+    }
+}
+
+
+
+void TerminalCmd_EnableHeater(char *arg)
+{
+    int Channel = -1;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=7)
+        {
+            EnableHeater(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 7",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 7",arg);
+    }
+}
+
+void TerminalCmd_DisableHeater(char *arg)
+{
+int Channel = -1;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=7)
+        {
+            DisableHeater(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 7",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 7",arg);
+    }
+
+}
+
+void TerminalCmd_EnableSolenoidValve(char *arg)
+{
+
+int Channel = -1;
+    
+    if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=11)
+        {
+            EnableSolenoidValve(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 11",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 11",arg);
+    }
+}
+
+void TerminalCmd_DisableSolenoidValue(char *arg)
+{
+int Channel = -1;
+
+   if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if( Channel >= 0 && Channel <= 11)
+        {
+            DisableSolenoidValue(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 11",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 11",arg);
+    }
+
+}
+void TerminalCmd_DisableAllHeatersAndSolenoids(char *arg)
+{
+    
+    DisableAllHeatersAndSolenoids();
+
+}
+
+void TerminalCmd_EnableMiscDigitalOutput(char *arg)
+{
+int Channel = -1;
+
+  if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=3)
+        {
+            EnableMiscDigitalOutput(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 3",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 3",arg);
+    }
+
+}
+
+void TerminalCmd_DisableMiscDigitalOutput(char *arg)
+{
+int Channel = -1;
+
+  if(sscanf(arg,"%d",&Channel) == 1)
+    {
+        if(Channel>=0 && Channel <=3)
+        {
+           DisableMiscDigitalOutput(Channel);
+        }
+        else
+        {
+            PC.printf("%d is an invalid channel.   Channel should be integer between 0 and 3",Channel);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 3",arg);
+    }
+
+}
+
+void TerminalCmd_FlushDigitalIO(char *arg)
+{
+    FlushDigitalIO();
+}
+
+void TerminalCmd_FanOn(char *arg)
+{
+     SetFanSpeed(100);   //PWMing the FANs doesn't work with the ME40100V1 models!   WE will just on or off
+}
+
+void TerminalCmd_FanOff(char *arg)
+{
+     SetFanSpeed(0);   //PWMing the FANs doesn't work with the ME40100V1 models!   WE will just on or off
+}
+
+void TerminalCmd_Fan(char *arg)
+{
+int Speed = -1;
+
+ if(sscanf(arg,"%d",&Speed) == 1)
+    {
+        if(Speed>=0 && Speed<=100)
+        {
+           SetFanSpeed(Speed);
+        }
+        else
+        {
+            PC.printf("%d is an invalid speed.   Speed should be between 0 and 100",Speed);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be integer between 0 and 100",arg);
+    }
+
+}
+
+
+void TerminalCmd_T(char *arg)
+{
+    float Temp = 0;
+    int Channel = -1;
+    
+     if(sscanf(arg,"%d",&Channel) == 1)
+        {
+                Temp = ReadThermocouple(Channel);
+                 PC.printf("TEMP:%d:%.2f\r\n",Channel,Temp);
+        }
+        else
+        {
+            for(Channel = 0; Channel<12;Channel++)
+            {
+                 Temp = ReadThermocouple(Channel);
+                 PC.printf("TEMP:%d:%.2f\r\n",Channel,Temp);
+            }
+        }
+}
+
+void TerminalCmd_Buzz(char *arg)
+{
+ 
+ float T = -1.0;
+
+ if(sscanf(arg,"%f",&T) == 1)
+    {
+        if(T>=0.0 && T<=5.0)
+        {
+           Buzz(T);
+        }
+        else
+        {
+            PC.printf("%f is an invalid time period for buzz.   Time should be between 0.0 and 5.0 seconds",T);
+        }
+    }
+    else
+    {
+        PC.printf("Bad argument... %s.  Should be float between 0.0 and 5.0",arg);
+    }
+
+}
+
+
+
+
+//*****************************************************************
+//Plumbing.....
+//*****************************************************************
+
+#define NUM_TERMINAL_COMMANDS  (sizeof(MyTerminalCallbackRecords)/sizeof(TerminalCallbackRecord))
+
+char TerminalLineBuf[MAX_TERMINAL_LINE_CHARS];
+uint8_t TerminalPos;
+char TerminalCmdBuf[MAX_TERMINAL_CMD_CHARS+1];
+char TerminalArgs[MAX_TERMINAL_LINE_CHARS-MAX_TERMINAL_CMD_CHARS];
+uint8_t NextCharIn;
+uint8_t CmdFound;
+ 
+void TerminalBootMsg()
+{
+
+PC.printf("\r\n\r\n"); 
+PC.printf("***********************************\r\n"); 
+PC.printf("CHEM Control Box                   \r\n");
+PC.printf("API Version %s \r\n",API_VERSION);
+PC.printf("Copyright (C) <2013>  Eli Hughes\r\n");
+PC.printf("Wavenumber LLC\r\n"); 
+PC.printf("***********************************\r\n\r\n>"); 
+
+}
+
+void InitTerminal()
+{
+
+    PC.baud(115200);
+    TerminalPos = 0;
+    CmdFound = 0;
+    TerminalBootMsg();
+}
+
+void TerminalCmd_Help(char *arg)
+{
+    uint8_t i;
+
+    PC.printf("\r\n\r\nCommand List:\r\n");
+    PC.printf("----------------------\r\n");
+
+    for(i=0;i<NUM_TERMINAL_COMMANDS;i++)
+    {
+         PC.printf("%s  ---->  %s\r\n\r\n",MyTerminalCallbackRecords[i].CommandString,MyTerminalCallbackRecords[i].HelpString);    
+    }
+
+    PC.printf("\r\n\r\n");
+}
+
+void TerminalCmd_Reboot(char *arg)
+{
+      TerminalBootMsg();
+}
+
+void ProcessTerminal()
+{
+     uint8_t i,j;
+     uint8_t ArgsFound;
+        
+    if(PC.readable())
+    {
+       NextCharIn = PC.getc();
+       
+        switch(NextCharIn)
+        {
+            case '\r':
+             
+             TerminalLineBuf[TerminalPos++] = 0x0;
+             PC.putc(NextCharIn);
+           
+             if(TerminalPos > 1)
+             {
+                 //find the command
+                 i=0;
+                 while(TerminalLineBuf[i]>0x20 &&  TerminalLineBuf[i]<0x7f)
+                 {
+                      TerminalCmdBuf[i] = TerminalLineBuf[i];
+                      i++;
+    
+                    if(i==MAX_TERMINAL_CMD_CHARS)
+                        {
+                         break;
+                        }
+                 }
+                    
+                TerminalCmdBuf[i] = 0;
+                TerminalCmdBuf[i+1] = 0;
+                
+                
+                ArgsFound = TRUE;
+                memset(TerminalArgs,0x00,sizeof(TerminalArgs));
+                //scan for num terminator or next non whitespace
+                while(TerminalLineBuf[i]<=0x20 && (i<MAX_TERMINAL_LINE_CHARS))
+                {
+                    if(TerminalLineBuf[i] == 0x00)
+                    {
+                    
+                        //if we find a NULL terminator before a non whitespace character they flag for no arguments
+                        ArgsFound = FALSE;
+                        break;
+                    }   
+                    i++; 
+                }
+                
+                if(ArgsFound == TRUE)
+                {
+                    strcpy(TerminalArgs,&TerminalLineBuf[i]);
+                    
+                    //trim trailing whitespace
+                    i = sizeof(TerminalArgs)-1;
+                    
+                    while((TerminalArgs[i]<0x21) && (i>0))
+                    {
+                        TerminalArgs[i]= 0x00;
+                        i--;
+                    }       
+                }
+                
+                CmdFound = FALSE;
+                for(j=0;j<NUM_TERMINAL_COMMANDS;j++)
+                {           
+                    if(strcmp(TerminalCmdBuf,MyTerminalCallbackRecords[j].CommandString) == 0)
+                    {
+                        PC.printf("\r\n");
+                        if(MyTerminalCallbackRecords[j].Callback != NULL)
+                            MyTerminalCallbackRecords[j].Callback(TerminalArgs);
+                    
+                        CmdFound = TRUE;
+                        break;
+                    }             
+                }        
+                if(CmdFound == FALSE)
+                {
+                  PC.printf("\r\n%s command not recognized.\r\n\r\n",TerminalCmdBuf);
+                  TerminalCmd_Help("no arg");
+                  
+                }
+              }    
+             PC.printf("\r\n>");
+             TerminalPos = 0;
+            
+            break;
+            
+            case '\b':
+                if(TerminalPos > 0)
+                {
+                    TerminalPos--;    
+                    PC.putc(NextCharIn);
+                }
+            break;
+            
+            default:
+                
+                if(TerminalPos == 0 && NextCharIn == 0x020)
+                {
+                     //Do nothing if space bar is pressed at beginning of line    
+                }
+                   else if(NextCharIn >= 0x20 && NextCharIn<0x7F)
+                {
+                    
+                    if(TerminalPos < MAX_TERMINAL_LINE_CHARS-1)
+                    {
+                         TerminalLineBuf[TerminalPos++] = NextCharIn;
+                         PC.putc(NextCharIn);
+                    }
+                }
+            
+            break;
+        
+        }
+    }
+ 
+}
+
+
+
+
+
+//    _      _____ _____     _______ _____            _____  _    _ _____ _____  _____ 
+//   | |    / ____|  __ \   / / ____|  __ \     /\   |  __ \| |  | |_   _/ ____|/ ____|
+//   | |   | |    | |  | | / / |  __| |__) |   /  \  | |__) | |__| | | || |    | (___  
+//   | |   | |    | |  | |/ /| | |_ |  _  /   / /\ \ |  ___/|  __  | | || |     \___ \ 
+//   | |___| |____| |__| / / | |__| | | \ \  / ____ \| |    | |  | |_| || |____ ____) |
+//   |______\_____|_____/_/   \_____|_|  \_\/_/    \_\_|    |_|  |_|_____\_____|_____/ 
+//                                                                                     
+//                                                                                     
+ 
+void SmartSwitch_Reset();
+void SmartSwitch_SetBrightness(uint8_t Brightness);
+void InitSmartSwitch();
+void PowerUpSmartSwitch();
+void PowerDownSmartSwitch();
+void SmartSwitchWriteByte(uint8_t DataOut);
+void SmartSwitch_SetBackLightColor2(uint8_t RGB);
+void SmartSwitch_ImageDump(uint8_t *Img);
+void SmartSwitchClear();
+
+ 
+ 
+ 
+#define BACK_BUFFER_SIZE_X    (64)
+#define BACK_BUFFER_SIZE_Y    (32)
+
+#define PHYSICAL_DISPLAY_XRES               (uint8_t)(64)
+#define PHYSICAL_DISPLAY_YRES               (uint8_t)(32)
+#define DISPLAY_X_WIDTH_BYTE                (PHYSICAL_DISPLAY_XRES>>3)
+#define DISPLAY_BUFFER_TOTAL_SIZE           (DISPLAY_X_WIDTH_BYTE*PHYSICAL_DISPLAY_YRES*2)
+#define GREEN_DATA_BUFFER_OFFSET            (DISPLAY_X_WIDTH_BYTE * PHYSICAL_DISPLAY_YRES)
+#define PHYSICAL_DISPLAY_X_WIDTH_IN_BYTES   (PHYSICAL_DISPLAY_XRES>>3)
+#define PHYSICAL_DISPLAY_PLANE_BUFFER_SIZE  (PHYSICAL_DISPLAY_X_WIDTH_IN_BYTES * PHYSICAL_DISPLAY_YRES)
+#define PHYSICAL_DISPLAY_BUFFER_TOTAL_SIZE  (PHYSICAL_DISPLAY_X_WIDTH_IN_BYTES * PHYSICAL_DISPLAY_YRES*2) 
+ 
+#define SMART_SWITCH_CMD_DISPLAY_DATA           0x55
+#define SMART_SWITCH_CMD_SET_BACKLIGHT_COLOR    0x40
+#define SMART_SWITCH_CMD_SET_BRIGHTNESS         0x41
+#define SMART_SWITCH_CMD_RESET                  0x5E
+#define SMART_SWITCH_CMD_RESET_PARAMETER        0x03
+
+#define SMART_SWITCH_BACKLIGHT_RED              (0x03<<4)
+#define SMART_SWITCH_BACKLIGHT_YELLOW           (0x03<<4)|(0x03<<2)
+#define SMART_SWITCH_BACKLIGHT_GREEN            (0x03<<2)
+ 
+ #define GFX_MAX_STRING_LEN 32
+ 
+void SmartSwitch_ImageDump(uint8_t *Img)
+{
+   int i;
+   
+   SPI1.format(8,2);
+    
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_DISPLAY_DATA);
+   
+   for(i=0;i<256;i++)
+   {
+    SmartSwitchWriteByte(Img[i]);
+   }
+   
+   SmartSwitch_SS = 1;
+}
+
+void SmartSwitchClear()
+{
+   int i;
+   
+   
+   SPI1.format(8,2);
+   
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_DISPLAY_DATA);
+   
+   for(i=0;i<256;i++)
+   {
+     SmartSwitchWriteByte(0x00);
+   }
+   
+   SmartSwitch_SS = 1;
+}
+
+void SmartSwitch_Reset()
+{
+   
+   SPI1.format(8,2);
+   
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_RESET);
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_RESET_PARAMETER);
+   SmartSwitch_SS = 1;
+}
+
+void SmartSwitch_SetBackLightColor(uint8_t Red,uint8_t Green,uint8_t Blue)
+{
+  
+   SPI1.format(8,2);
+  
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_SET_BACKLIGHT_COLOR);
+   SmartSwitchWriteByte(Red<<6 | Green<<4 | Blue <<2 | 0x3);
+   SmartSwitch_SS = 1;
+}
+
+void SmartSwitch_SetBackLightColor2(uint8_t RGB)
+{
+   SPI1.format(8,2);
+   
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_SET_BACKLIGHT_COLOR);
+   SmartSwitchWriteByte(RGB<<2 | 0x3);
+   SmartSwitch_SS = 1;
+}
+
+void SmartSwitch_SetBrightness(uint8_t Brightness)
+{
+   SPI1.format(8,2);
+   
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_SET_BRIGHTNESS);
+   SmartSwitchWriteByte(Brightness<<5 | 0x1F);
+   SmartSwitch_SS = 1;
+}
+
+void InitSmartSwitch()
+{
+   SmartSwitch_SS = 1;
+   SmartSwitch_Reset();
+}
+
+void SmartSwitchWriteByte(uint8_t DataOut)
+{
+
+   SPI1.write(DataOut);
+
+}
+
+
+//Linking Functions to Physical Screen
+//***********************************************************************************
+
+void GFX_InitPhysicalScreen()
+{
+     InitSmartSwitch();
+}
+
+
+const uint8_t BitReverseTable[256] =
+{
+0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+void GFX_DumpRenderContextToPhysicalScreen(RenderContext *Image)
+{
+   int x,y;
+   uint8_t  NextByteOut; 
+   
+   SPI1.format(8,2);
+   
+   SmartSwitch_SS = 0;
+   SmartSwitchWriteByte(SMART_SWITCH_CMD_DISPLAY_DATA);
+   
+   for(y=0;y<PHYSICAL_DISPLAY_YRES;y++)
+   {
+       for(x=0;x<PHYSICAL_DISPLAY_X_WIDTH_IN_BYTES;x++)
+       {
+          //Need to rotate the display 180 degrees
+          NextByteOut = Image->RenderPlane.BitPlaneSpace[(((PHYSICAL_DISPLAY_YRES - y - 1) * PHYSICAL_DISPLAY_X_WIDTH_IN_BYTES)) + x];
+          SmartSwitchWriteByte(BitReverseTable[NextByteOut]);
+       }
+   }
+   SmartSwitch_SS = 1;
+}
+
+
+//Device Independent Functions
+//***********************************************************************************
+
+//Reserve Space for the backbuffer
+
+RenderContext BackBuffer;
+uint8_t BackBufferRenderPlaneSpace[PHYSICAL_DISPLAY_PLANE_BUFFER_SIZE];
+
+int16_t GFX_Drawcharacter(RenderContext *Image, uint8_t character, int16_t StartX, int16_t StartY, GFXFont *MyFont);
+int16_t GFX_GetStringWidth(char * String,GFXFont * MyFont);
+
+//FontData
+
+#define FONT5x7_FONT_WIDTH 5
+#define FONT5x7_FONT_HEIGHT 8
+#define FONT5x7_FONT_ELEMENTS 128
+#define FONT5x7_FONT_COLUMN_SIZE_IN_BYTE  1
+
+uint8_t FontTable_Font5x7 [640] = {
+0x00 ,0x08 ,0x0C ,0xFA ,0x81 ,0xFA ,0x0C ,0x08 ,0x00 ,0x00 ,0x00 ,0x10 ,0x30 ,0x5F ,0x81 ,0x5F ,
+0x30 ,0x10 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xBE ,0x00 ,0x00 ,0x00 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x00 ,0x28 ,
+0xFE ,0x28 ,0xFE ,0x28 ,0x48 ,0xFE ,0x54 ,0xFE ,0x24 ,0x06 ,0xE6 ,0x10 ,0xCE ,0xC0 ,0x60 ,0x92 ,
+0x94 ,0x78 ,0x10 ,0x06 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7C ,0x82 ,0x00 ,0x00 ,0x00 ,0x82 ,0x7C ,0x00 ,
+0x00 ,0x00 ,0x54 ,0x38 ,0xFE ,0x38 ,0x54 ,0x10 ,0x10 ,0x7C ,0x10 ,0x10 ,0x80 ,0x60 ,0x00 ,0x00 ,
+0x00 ,0x10 ,0x10 ,0x10 ,0x10 ,0x10 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0xC0 ,0x30 ,0x0C ,0x02 ,0x00 ,
+0x7C ,0xA2 ,0x92 ,0x8A ,0x7C ,0x88 ,0x84 ,0xFE ,0x80 ,0x80 ,0x84 ,0xC2 ,0xA2 ,0x92 ,0x8C ,0x44 ,
+0x92 ,0x92 ,0x92 ,0x6C ,0x10 ,0x18 ,0x14 ,0xFE ,0x10 ,0x4E ,0x8A ,0x8A ,0x8A ,0x72 ,0x7C ,0x92 ,
+0x92 ,0x92 ,0x64 ,0x02 ,0xC2 ,0x22 ,0x12 ,0x0E ,0x6C ,0x92 ,0x92 ,0x92 ,0x6C ,0x0C ,0x92 ,0x92 ,
+0x92 ,0x7C ,0x48 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80 ,0x68 ,0x00 ,0x00 ,0x00 ,0x10 ,0x28 ,0x44 ,0x82 ,
+0x00 ,0x28 ,0x28 ,0x28 ,0x28 ,0x00 ,0x82 ,0x44 ,0x28 ,0x10 ,0x00 ,0x04 ,0x02 ,0xA2 ,0x12 ,0x0C ,
+0x3C ,0x42 ,0x9A ,0xA2 ,0x1C ,0xF8 ,0x14 ,0x12 ,0x14 ,0xF8 ,0xFE ,0x92 ,0x92 ,0x92 ,0x6C ,0x7C ,
+0x82 ,0x82 ,0x82 ,0x44 ,0xFE ,0x82 ,0x82 ,0x44 ,0x38 ,0xFE ,0x92 ,0x92 ,0x82 ,0x82 ,0xFE ,0x12 ,
+0x12 ,0x02 ,0x02 ,0x7C ,0x92 ,0x92 ,0x92 ,0x74 ,0xFE ,0x10 ,0x10 ,0x10 ,0xFE ,0x82 ,0x82 ,0xFE ,
+0x82 ,0x82 ,0x40 ,0x80 ,0x80 ,0x80 ,0x7E ,0xFE ,0x10 ,0x28 ,0x44 ,0x82 ,0xFE ,0x80 ,0x80 ,0x80 ,
+0x00 ,0xFE ,0x04 ,0x08 ,0x04 ,0xFE ,0xFE ,0x04 ,0x18 ,0x20 ,0xFE ,0x7C ,0x82 ,0x82 ,0x82 ,0x7C ,
+0xFE ,0x12 ,0x12 ,0x12 ,0x0C ,0x7C ,0x82 ,0xA2 ,0xC2 ,0xFC ,0xFE ,0x12 ,0x32 ,0x52 ,0x8C ,0x4C ,
+0x92 ,0x92 ,0x92 ,0x64 ,0x02 ,0x02 ,0xFE ,0x02 ,0x02 ,0x7E ,0x80 ,0x80 ,0x80 ,0x7E ,0x3E ,0x40 ,
+0x80 ,0x40 ,0x3E ,0xFE ,0x40 ,0x20 ,0x40 ,0xFE ,0xC6 ,0x28 ,0x10 ,0x28 ,0xC6 ,0x02 ,0x04 ,0xF8 ,
+0x04 ,0x02 ,0xC2 ,0xA2 ,0x92 ,0x8A ,0x86 ,0xFE ,0x82 ,0x82 ,0x00 ,0x00 ,0x02 ,0x0C ,0x30 ,0xC0 ,
+0x00 ,0x82 ,0x82 ,0xFE ,0x00 ,0x00 ,0x04 ,0x02 ,0x04 ,0x00 ,0x00 ,0x80 ,0x80 ,0x80 ,0x80 ,0x80 ,
+0x06 ,0x08 ,0x00 ,0x00 ,0x00 ,0x70 ,0x88 ,0x88 ,0x70 ,0x80 ,0xFC ,0x90 ,0x90 ,0x60 ,0x00 ,0x70 ,
+0x88 ,0x88 ,0x88 ,0x00 ,0x60 ,0x90 ,0x90 ,0x7C ,0x80 ,0x70 ,0xA8 ,0xA8 ,0x90 ,0x00 ,0x10 ,0xF8 ,
+0x14 ,0x04 ,0x00 ,0x98 ,0xA4 ,0xA4 ,0x78 ,0x00 ,0xFC ,0x20 ,0x10 ,0xE0 ,0x00 ,0xE8 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x40 ,0x80 ,0x80 ,0x74 ,0x00 ,0xFC ,0x20 ,0x50 ,0x88 ,0x00 ,0xFC ,0x00 ,0x00 ,0x00 ,
+0x00 ,0xF0 ,0x08 ,0x30 ,0x08 ,0xF0 ,0xF8 ,0x08 ,0x08 ,0xF0 ,0x00 ,0x70 ,0x88 ,0x88 ,0x70 ,0x00 ,
+0xF8 ,0x24 ,0x24 ,0x18 ,0x00 ,0x18 ,0x24 ,0x24 ,0xF8 ,0x00 ,0xF0 ,0x08 ,0x08 ,0x10 ,0x00 ,0x90 ,
+0xA8 ,0xA8 ,0x48 ,0x00 ,0x08 ,0x7C ,0x88 ,0x00 ,0x00 ,0x78 ,0x80 ,0x80 ,0x78 ,0x00 ,0x38 ,0x40 ,
+0x80 ,0x40 ,0x38 ,0x78 ,0x80 ,0x40 ,0x80 ,0x78 ,0x88 ,0x50 ,0x20 ,0x50 ,0x88 ,0x08 ,0x10 ,0xE0 ,
+0x10 ,0x08 ,0xC8 ,0xA8 ,0x98 ,0x00 ,0x00 ,0x10 ,0x6C ,0x82 ,0x00 ,0x00 ,0xFE ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x82 ,0x6C ,0x10 ,0x00 ,0x00 ,0x08 ,0x04 ,0x08 ,0x10 ,0x08 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00  };
+
+uint8_t CharacterWidthTable_Font5x7   [128] = {
+0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,
+0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,
+0x05 ,0x01 ,0x03 ,0x05 ,0x05 ,0x05 ,0x05 ,0x01 ,0x02 ,0x02 ,0x05 ,0x05 ,0x02 ,0x05 ,0x01 ,0x04 ,
+0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x01 ,0x01 ,0x04 ,0x04 ,0x04 ,0x05 ,
+0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x04 ,0x05 ,0x05 ,0x05 ,
+0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x05 ,0x03 ,0x04 ,0x05 ,0x03 ,0x05 ,
+0x02 ,0x05 ,0x04 ,0x04 ,0x05 ,0x04 ,0x04 ,0x04 ,0x04 ,0x01 ,0x04 ,0x04 ,0x01 ,0x05 ,0x04 ,0x05 ,
+0x05 ,0x05 ,0x04 ,0x04 ,0x03 ,0x04 ,0x05 ,0x05 ,0x05 ,0x05 ,0x03 ,0x03 ,0x01 ,0x05 ,0x05 ,0x05  };
+
+#define FONT3x5_FONT_WIDTH 3
+#define FONT3x5_FONT_HEIGHT 5
+#define FONT3x5_ELEMENTS 128
+#define FONT3x5_FONT_COLUMN_SIZE_IN_BYTE  1
+
+
+uint8_t FontTable_Font3x5 [384] = {
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x17 ,0x00 ,0x00 ,0x03 ,0x00 ,0x03 ,0x0E ,0x1F ,0x0E ,0x14 ,0x1F ,0x0A ,0x00 ,
+0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x00 ,0x00 ,0x0E ,0x11 ,0x00 ,0x11 ,0x0E ,0x00 ,0x15 ,0x0E ,
+0x15 ,0x04 ,0x0E ,0x04 ,0x10 ,0x08 ,0x00 ,0x04 ,0x04 ,0x04 ,0x10 ,0x00 ,0x00 ,0x18 ,0x04 ,0x03 ,
+0x0E ,0x11 ,0x0E ,0x12 ,0x1F ,0x10 ,0x19 ,0x15 ,0x16 ,0x11 ,0x15 ,0x0A ,0x07 ,0x04 ,0x1F ,0x17 ,
+0x15 ,0x09 ,0x1E ,0x15 ,0x18 ,0x01 ,0x1D ,0x03 ,0x1B ,0x15 ,0x1B ,0x06 ,0x15 ,0x0E ,0x0A ,0x00 ,
+0x00 ,0x10 ,0x0A ,0x00 ,0x04 ,0x0A ,0x11 ,0x00 ,0x00 ,0x00 ,0x11 ,0x0A ,0x04 ,0x01 ,0x15 ,0x02 ,
+0x09 ,0x15 ,0x0E ,0x1E ,0x05 ,0x1E ,0x1F ,0x15 ,0x0A ,0x0E ,0x11 ,0x0A ,0x1F ,0x11 ,0x0E ,0x1F ,
+0x15 ,0x11 ,0x1F ,0x05 ,0x05 ,0x1E ,0x15 ,0x1D ,0x1F ,0x04 ,0x1F ,0x11 ,0x1F ,0x11 ,0x08 ,0x10 ,
+0x0F ,0x1F ,0x06 ,0x19 ,0x1F ,0x10 ,0x10 ,0x1F ,0x02 ,0x1F ,0x1F ,0x06 ,0x1F ,0x1F ,0x11 ,0x1F ,
+0x1F ,0x05 ,0x07 ,0x1F ,0x19 ,0x1F ,0x1F ,0x0D ,0x16 ,0x16 ,0x15 ,0x1D ,0x01 ,0x1F ,0x01 ,0x1F ,
+0x10 ,0x1F ,0x0F ,0x10 ,0x0F ,0x1F ,0x08 ,0x1F ,0x1B ,0x04 ,0x1B ,0x01 ,0x1E ,0x01 ,0x19 ,0x15 ,
+0x13 ,0x1F ,0x11 ,0x00 ,0x03 ,0x0C ,0x10 ,0x11 ,0x1F ,0x00 ,0x02 ,0x01 ,0x02 ,0x10 ,0x10 ,0x10 ,
+0x01 ,0x02 ,0x00 ,0x08 ,0x14 ,0x1C ,0x1F ,0x14 ,0x08 ,0x0C ,0x12 ,0x12 ,0x08 ,0x14 ,0x1F ,0x0C ,
+0x16 ,0x16 ,0x14 ,0x0E ,0x05 ,0x06 ,0x15 ,0x0F ,0x1F ,0x04 ,0x18 ,0x1D ,0x00 ,0x00 ,0x10 ,0x0D ,
+0x00 ,0x1F ,0x0C ,0x12 ,0x1F ,0x00 ,0x00 ,0x1C ,0x08 ,0x1C ,0x1C ,0x02 ,0x1C ,0x0C ,0x12 ,0x0C ,
+0x1E ,0x05 ,0x02 ,0x02 ,0x05 ,0x1E ,0x1C ,0x02 ,0x04 ,0x14 ,0x1A ,0x00 ,0x04 ,0x1E ,0x04 ,0x1E ,
+0x10 ,0x1E ,0x0E ,0x10 ,0x0E ,0x1C ,0x08 ,0x1C ,0x12 ,0x0C ,0x12 ,0x12 ,0x0C ,0x02 ,0x12 ,0x1A ,
+0x16 ,0x04 ,0x0E ,0x11 ,0x1F ,0x00 ,0x00 ,0x11 ,0x0E ,0x04 ,0x02 ,0x02 ,0x04 ,0x00 ,0x00 ,0x00  };
+
+
+uint8_t CharacterWidthTable_Font3x5 [128] = {
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,
+0x03 ,0x01 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x01 ,0x02 ,0x03 ,0x03 ,0x03 ,0x02 ,0x03 ,0x01 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x01 ,0x02 ,0x03 ,0x03 ,0x03 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x02 ,0x03 ,0x02 ,0x03 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x01 ,0x03 ,0x03 ,0x01 ,0x03 ,0x03 ,0x03 ,
+0x03 ,0x03 ,0x03 ,0x02 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x03 ,0x01 ,0x03 ,0x03 ,0x03  };
+
+GFXFont Font5x7;
+GFXFont Font3x5;
+
+void GFX_Init()
+{
+    
+    //Staticially Allocate and setup the backbuffer space;
+    
+    BackBuffer.RenderPlane.BitPlaneSpace = &BackBufferRenderPlaneSpace[0];
+   
+    BackBuffer.SizeX = BACK_BUFFER_SIZE_X;
+    BackBuffer.SizeY = BACK_BUFFER_SIZE_Y;
+
+    BackBuffer.RenderPlane.SizeX = BACK_BUFFER_SIZE_X;
+    BackBuffer.RenderPlane.SizeY = BACK_BUFFER_SIZE_Y;
+
+    
+    GFX_FullDisplayBufferClear(&BackBuffer);
+
+    //Initialize the stock fonts
+
+    Font5x7.CharacterWidthTable = (uint8_t *)CharacterWidthTable_Font5x7;
+    Font5x7.FontBuffer = (uint8_t *)FontTable_Font5x7;
+    Font5x7.FontHeight = FONT5x7_FONT_HEIGHT;
+    Font5x7.FontWidth = FONT5x7_FONT_WIDTH;
+    Font5x7.BytesPerColumn = FONT5x7_FONT_COLUMN_SIZE_IN_BYTE;
+
+    Font3x5.CharacterWidthTable = (uint8_t *)CharacterWidthTable_Font3x5;
+    Font3x5.FontBuffer = (uint8_t *)FontTable_Font3x5;
+    Font3x5.FontHeight = FONT3x5_FONT_HEIGHT;
+    Font3x5.FontWidth = FONT3x5_FONT_WIDTH;
+    Font3x5.BytesPerColumn = FONT3x5_FONT_COLUMN_SIZE_IN_BYTE;
+    
+    GFX_InitPhysicalScreen();
+    
+}
+
+
+
+void GFX_FullDisplayBufferClear(RenderContext *Image)
+{
+    BitPlane_Clear(&Image->RenderPlane);
+}
+
+
+void GFX_PutPixel(RenderContext *Image, int16_t x, int16_t y)
+{
+    if((x<Image->SizeX) && (y<Image->SizeY) && (x>=0) && (y>=0))
+    {
+         BitPlane_Put(&Image->RenderPlane,Image->SizeX-x-1,Image->SizeY-y-1,TRUE);
+    }
+}
+
+
+
+#ifndef _INLINE_GFX_GET_PIXEL
+uint8_t GFX_GetPixel(RenderContext *Image, int16_t x, int16_t y)
+{
+    uint8_t PixelColor = 0;
+    
+    if((x<Image->SizeX) && (y<Image->SizeY) && (x>=0) && (y>=0))
+    {
+        
+        PixelColor = BitPlane_Get(&Image->RenderPlane,x,y);
+    }
+    
+    return PixelColor;
+}
+#endif
+
+
+void GFX_DrawHline(RenderContext *Image, int16_t XStart, int16_t XStop, int16_t Y)
+{
+    int16_t LineStart;
+    int16_t LineStop;
+    uint16_t i;
+    
+    if((Y<Image->SizeY)  && (Y>=0))
+    {
+        if(XStart>XStop)
+        {
+            LineStart = XStop;    
+            LineStop = XStart;
+        }    
+        else
+        {
+            LineStart = XStart;    
+            LineStop = XStop;
+        }
+        
+        if(LineStart<0)
+        {
+            LineStart = 0;
+        }
+    
+        if(LineStop>Image->SizeX)
+        {
+            LineStop =     Image->SizeX-1;
+        }
+    
+        if(LineStart == LineStop)
+        {
+            GFX_PutPixel(Image,LineStart,Y);    
+        }
+        else
+        {
+            for(i=LineStart; i<=LineStop ; i++)
+            {
+                GFX_PutPixel(Image,i,Y);    
+            }
+        }    
+    }    
+    
+}
+
+
+
+ void GFX_DrawVline(RenderContext *Image, int16_t YStart, int16_t YStop, int16_t X)
+{
+    int16_t LineStart;
+    int16_t LineStop;
+    int16_t i;
+
+    if((X<Image->SizeX) && (X>=0))
+    {
+    
+        if(YStart>YStop)
+        {
+            LineStart = YStop;    
+            LineStop = YStart;
+        }    
+        else
+        {
+            LineStart = YStart;    
+            LineStop = YStop;
+        }
+        
+        if(LineStart<0)
+        {
+            LineStart = 0;
+        }
+    
+
+        if(LineStop>Image->SizeY)
+        {
+            LineStop =     Image->SizeY-1;
+        }
+    
+        for(i=LineStart; i<=LineStop ; i++)
+        {
+            GFX_PutPixel(Image,X,i);    
+        }    
+    }    
+}
+
+
+void GFX_DrawLine(RenderContext * Image, int16_t X1,int16_t Y1, int16_t X2,int16_t Y2)
+{
+    //A simple Implementation of Bresenham's line Algorithm
+    int16_t StartX,StopX,StartY,StopY;
+    int16_t dX,dY;
+    int16_t Y_Numerator;
+    int16_t X_Numerator;
+    int16_t Y;
+    int16_t X;
+    int16_t i;
+    uint8_t YDir = 0;
+    //First Make sure that it is left to right
+    //If not them flop them
+    if(X2>X1)
+    {
+        StartX = X1;
+        StopX = X2;    
+        StartY = Y1;
+        StopY = Y2;    
+    }    
+    else
+    {
+        StartX = X2;
+        StopX = X1;    
+        StartY = Y2;
+        StopY = Y1;    
+    }
+    GFX_PutPixel(Image, StopX,StopY);
+    if(StopY>=StartY)
+    {
+        dY = StopY - StartY;
+        YDir = 0;
+    }
+    else
+    {
+        dY = StartY - StopY;
+        YDir = 1;
+    }
+    dX = StopX - StartX;
+    //Now, if the slope is less greater than one,  we need to swap all X/Y operations
+    if(dY<=dX)
+    {
+        //Slope is less than one, proceed at normal and step along the x axis
+        Y=StartY;   //start the whole part of the Y value at the starting pixeel.
+        X=StartX;
+        //We need to start the numerator of the fraction half way through the fraction so evertyhing rounds at
+        //fraction midpoint
+        Y_Numerator = dX>>1;   //The fraction demonimator is assumeed to be dX
+                                // out fixed point Y value is  Y + (Y_Numerator / dX)
+                                //Every time we step the X coordinate by one, we need to step
+                                //out Y coordinate by dY/dX.  We do this by just adding dY to our
+                                //numerator.  When the numerator gets bigger than the
+                                //denomiator, the increment the whole part by one and decrement the numerator
+                                //by the denominator
+        for(i=0;i<dX;i++)
+        {
+            GFX_PutPixel(Image,X,Y);
+            X++;
+            //Now do all the fractional stuff
+            Y_Numerator += dY;
+            if(Y_Numerator >= dX)
+            {    
+                Y_Numerator-=dX;
+                if(StopY > StartY)
+                {
+                    Y++;
+                }
+                else
+                {
+                    Y--;    
+                }
+            }
+        }
+    }
+    else
+    {
+        //Same as before by step along the y axis.    
+        Y=StartY;   
+        X=StartX;
+        X_Numerator = dY>>1;   
+        for(i=0;i<dY;i++)
+        {
+            GFX_PutPixel(Image,X,Y);
+            //Now do all the fractional stuff
+            if(YDir)
+            {
+                Y--;
+            }
+            else
+            {
+                Y++;
+            }
+            X_Numerator += dX;
+            if(X_Numerator >= dY)
+            {    
+                X_Numerator-=dY;
+                if(StopX > StartX)
+                {
+                    X++;
+                }
+                else
+                {
+                    X--;    
+                }
+            }
+        }
+    }
+}
+
+void GFX_DrawBox(RenderContext *Image, GFXDisplayBox *Box)
+{
+    GFX_DrawHline(Image,Box->P1.X,Box->P2.X,Box->P1.Y);
+    GFX_DrawHline(Image,Box->P1.X,Box->P2.X,Box->P2.Y);
+    GFX_DrawVline(Image,Box->P1.Y,Box->P2.Y,Box->P1.X);
+    GFX_DrawVline(Image,Box->P1.Y,Box->P2.Y,Box->P2.X);
+}
+
+int16_t GFX_DrawCharacter(RenderContext * Image,uint8_t Character,int16_t StartX, int16_t StartY, GFXFont * MyFont)
+{
+    uint8_t i,j,Mask;
+    uint16_t CharStartIndex,ColumnStartIndex,ByteOffset;
+
+    CharStartIndex = (Character * (MyFont->BytesPerColumn) * (MyFont->FontWidth));
+
+    for(j=0;j<MyFont->CharacterWidthTable[Character];j++)
+        {
+            //Draw the current slice
+            ColumnStartIndex = j* (MyFont->BytesPerColumn);
+
+            for(i=0;i<MyFont->FontHeight;i++)
+            {
+                ByteOffset = i>>3;
+                Mask = 0x01 << (i&0x07);
+            
+                if( (MyFont->FontBuffer[CharStartIndex + ColumnStartIndex + ByteOffset]) & Mask)
+                {
+                    GFX_PutPixel(Image, StartX, StartY + i);
+                }        
+            }
+          StartX++;
+        }
+    return StartX;
+}
+
+
+int16_t GFX_GetStringWidth(char * String,GFXFont * MyFont)
+{
+    uint8_t Ptr = 0;
+    uint8_t NextChar;
+    int16_t StringSize = 0;
+    
+    NextChar = String[Ptr];
+    Ptr++;
+    
+    while((NextChar!=0) && (Ptr <GFX_MAX_STRING_LEN))
+    {
+        StringSize += MyFont->CharacterWidthTable[NextChar] + 1;
+        NextChar = String[Ptr];
+        Ptr++;
+    }
+    
+    return StringSize;
+}
+
+void GFX_DrawCenteredString(RenderContext * Image,char * String,int16_t StartX, int16_t StartY, GFXFont * MyFont)
+{
+    StartX -= (GFX_GetStringWidth(String,MyFont)>>1);
+    GFX_DrawString(Image,String,StartX,StartY,MyFont);
+}
+
+void GFX_DrawString(RenderContext * Image,char * String,int16_t StartX, int16_t StartY, GFXFont * MyFont)
+{
+
+uint8_t Ptr = 0;
+uint8_t NextChar;
+
+NextChar = String[Ptr];
+
+    while((NextChar!=0) && (Ptr <GFX_MAX_STRING_LEN))
+    {
+        StartX = GFX_DrawCharacter(Image,NextChar,StartX,StartY,MyFont);
+        Ptr++;
+        NextChar = String[Ptr];
+        StartX++;
+    }
+
+}
+
+char GFXStringBuf[64];
+
+void  GFX_printf(RenderContext * Image,int16_t StartX, int16_t StartY, GFXFont * MyFont, const char *FormatString,...)
+{
+     va_list argptr; 
+     va_start(argptr,FormatString); 
+     vsprintf((char *)GFXStringBuf,FormatString,argptr);
+     va_end(argptr);   
+     
+     GFX_DrawString(Image,GFXStringBuf,StartX,StartY,MyFont);
+}
+
+#ifndef INLINE_BITPLANE_PUT
+void BitPlane_Put(BitPlane  * BP, uint16_t X,uint16_t Y, uint8_t Value)
+{
+    uint16_t Offset;
+    uint8_t Mask;
+    
+    Offset = (Y * ((BP->SizeX)>>3)) + (X>>3);
+    Mask = 0x01 << (X & 0x07);
+
+    if(Value)
+    {
+        BP->BitPlaneSpace[Offset] |= Mask;
+    }
+    else
+    {
+        BP->BitPlaneSpace[Offset] &= ~Mask;
+    }
+}
+#endif
+
+#ifndef INLINE_BITPLANE_GET
+uint8_t BitPlane_Get(BitPlane  * BP, uint16_t X,uint16_t Y)
+{
+    uint16_t Offset;
+    uint8_t Mask;
+ 
+    Offset = (Y * ((BP->SizeX)>>3)) + (X>>3);
+    Mask = 0x01 << (X & 0x07);
+
+    if((BP->BitPlaneSpace[Offset])&Mask)
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+#endif
+
+void BitPlane_Clear(BitPlane  * BP) 
+{
+    uint16_t PlaneSpaceSize;
+    uint16_t i;
+
+    PlaneSpaceSize = ((BP->SizeX)>>3) * BP->SizeY;
+
+    for (i=0;i<PlaneSpaceSize;i++) {
+        BP->BitPlaneSpace[i] = 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRIVERS/CHEM_BOX_INTERFACE.h	Sat Jan 25 19:10:17 2014 +0000
@@ -0,0 +1,318 @@
+#include "MODSERIAL.h"
+
+#ifndef CHEM_BOX_INTERFACE
+#define CHEM_BOX_INTERFACE
+
+#define API_VERSION "1.0"
+
+//     _____ _    _ ______ __  __   ____   ______   __           _____ _____ 
+//    / ____| |  | |  ____|  \/  | |  _ \ / __ \ \ / /     /\   |  __ \_   _|
+//   | |    | |__| | |__  | \  / | | |_) | |  | \ V /     /  \  | |__) || |  
+//   | |    |  __  |  __| | |\/| | |  _ <| |  | |> <     / /\ \ |  ___/ | |  
+//   | |____| |  | | |____| |  | | | |_) | |__| / . \   / ____ \| |    _| |_ 
+//    \_____|_|  |_|______|_|  |_| |____/ \____/_/ \_\ /_/    \_\_|   |_____|
+//                                                                           
+//                                                                           
+
+//Initializes the hardware for the Chem box.   Must be called before any other CHEM box functions are called.
+void InitChemBox();
+
+//Special Note....   All of the Digital IO functions are queued.  This means that they do not take effect
+//until the function FlushDigitalIO() is called.
+
+
+//Enables one of the 8 heater channels.   Just pass a number between 0 and 7
+void EnableHeater(uint8_t RelayIndex);
+
+
+//Disables one of the 8 heater channels.   Just pass a number between 0 and 7
+void DisableHeater(uint8_t RelayIndex);
+
+//Enables one of the 12 Solenoid valve channels.   Just pass a number between 0 and 12
+void EnableSolenoidValve(uint8_t SolenoidIndex);
+
+//Disables one of the 12 Solenoid valve channels.   Just pass a number between 0 and 12
+void DisableSolenoidValue(uint8_t SolenoidIndex);
+
+//Enables one of the 4 digital I/O channels.   Just pass a number between 0 and 3
+void EnableMiscDigitalOutput(uint8_t DigitalOutIndex);
+
+//Disables one of the 4 digital I/O channels.   Just pass a number between 0 and 3
+void DisableMiscDigitalOutput(uint8_t DigitalOutIndex);
+
+//Updates all of the Digital I/O, heater and solenoid channels.  Call this function to enable all the queued up I/O commands
+void FlushDigitalIO();
+
+//Immediatelly disables all heaters and Solenoids.   FlushDigitalIO() does not need to be called for this to have an effect  
+void DisableAllHeatersAndSolenoids();
+
+//Enables the +/-15v power to the MFC Channels
+void EnableMFC_Power();
+
+//Disbales the +/-15v power to the MFC Channels
+void DisableMFC_Power();
+
+//Writes to one of the MFC Analog output channels.    The Value given to the function is in volts
+void WriteMFC_AnalogOut(uint8_t Channel,float Value);
+
+//Reads on the MFC Analog input channels.    The value returned is in volts
+float ReadMFC_AnalogInput(uint8_t Channel);
+
+//Reads a 4 to 20mA channel.   value returned is in amps (.004 to .020)
+float Read4to20(uint8_t Channel);
+
+//Turns the Fan on
+void EnableFan();
+
+//Turns the Fan off();
+void DisableFan();
+
+// Makes the buzzer ring for a time period (in seconds)
+//Note that this function immediately exits and the beeping is done in the background
+//If you want to beep a couple times,  you will need to delay for a certain time period after you call this function
+//before you can call it again
+void Buzz(float Time);
+
+//reads a thermocouple.  Returns temperature in degrees C
+float ReadThermocouple(uint8_t ThermocoupleIndex);
+
+//Determines if a thermocouple is disconnected.  Each BIT in the return will be set if the Thermocouple is open.
+//so,  to see if a particular thermocouple is no connected, you need to bitmask the result.
+/*
+    OC_State = ReadThermocouple_OC();
+
+    if(OC_State & (1<<5))
+        {
+            //we are here if thermocouple 5 is not connected.   The if statement does a bitwise AND to check the bit    
+        }
+
+*/
+uint16_t ReadThermocouple_OC();
+
+
+
+//Determines if a thermocouple is shorted to ground.  Each BIT in the return will be set if the Thermocouple is sorted to ground.
+//so,  to see if a particular thermocouple is shorted to ground, you need to bitmask the result.
+/*
+    SCG_State = ReadThermocouple_SCG();
+
+    if(SCG_State & (1<<7))
+        {
+            //we are here if thermocouple 7 is shorted to ground.   The if statement does a bitwise AND to check the bit    
+        }
+
+*/
+uint16_t ReadThermocouple_SCG();
+
+//Determines if a thermocouple is shorted to VCC.  Each BIT in the return will be set if the Thermocouple is shorted to VCC.
+//so,  to see if a particular thermocouple is shorted to VCC, you need to bitmask the result.
+/*
+    SCV_State = ReadThermocouple_SCG();
+
+    if(SCv_State & (1<<4))
+        {
+            //we are here if thermocouple 5 is shorted to VCC.   The if statement does a bitwise AND to check the bit    
+        }
+
+*/
+uint16_t ReadThermocouple_SCV();
+
+
+
+//Determines if a thermocouple is faulted (see MAX31855 Datasheet).  Each BIT in the return will be set if the Thermocouple is faulted
+//so,  to see if a particular thermocouple is faulted, you need to bitmask the result.
+/*
+    Faulted_State = ReadThermocouple_FAULT();
+
+    if(Faulted_State  & (1<<10))
+        {
+            //we are here if thermocouple 10 is faulted   The if statement does a bitwise AND to check the bit    
+        }
+
+*/
+
+
+uint16_t ReadThermocouple_FAULT();
+
+//Writes to one of the Misc Analog Output channels.  The Value shoul dbe in Volts (from 0 to 5v)
+void WriteMISC_AnalogOut(uint8_t Channel,float Value);
+
+//Reads one of the MISC Analog Input channels.   The value returned will be in volts (from 0 to 5v)
+float ReadMISC_AnalogInput(uint8_t Channel);
+
+//This function must be called in your main loop if you want the USB terminal interface to work!
+void ProcessTerminal();
+
+
+//This is the Serial object (see MODSERIAL Documentation on the MBED site for details) for RS-232 channel 0
+extern MODSERIAL RS232_0;
+
+//This is the Serial object (see MODSERIAL Documentation on the MBED site for details) for RS-232 channel 0
+extern MODSERIAL RS232_1;
+
+//This is the serial object for the USB connection.  Used by the Serial terminal
+extern MODSERIAL PC;
+
+
+//     _____                 _     _                     _____ _____  
+//    / ____|               | |   (_)              /\   |  __ \_   _| 
+//   | |  __ _ __ __ _ _ __ | |__  _  ___ ___     /  \  | |__) || |   
+//   | | |_ | '__/ _` | '_ \| '_ \| |/ __/ __|   / /\ \ |  ___/ | |   
+//   | |__| | | | (_| | |_) | | | | | (__\__ \  / ____ \| |    _| |_  
+//    \_____|_|  \__,_| .__/|_| |_|_|\___|___/ /_/    \_\_|   |_____| 
+//                    | |                                             
+//                    |_|                                             
+
+#define PHYSICAL_DISPLAY_XRES               (uint8_t)(64)
+#define PHYSICAL_DISPLAY_YRES               (uint8_t)(32)
+
+#define _INLINE_GFX_GET_PIXEL
+#define _INLINE_GFX_PUT_PIXEL
+
+typedef struct 
+{
+        uint8_t *BitPlaneSpace;
+        uint16_t SizeX; // must be a uint8_t aligned
+        uint16_t SizeY;
+        
+} BitPlane;
+
+
+typedef struct 
+{
+    int16_t X;
+    int16_t Y;    
+} GFXDisplayPoint;
+
+
+typedef struct 
+{
+    BitPlane RenderPlane;
+    uint16_t SizeX;
+    uint16_t SizeY;
+    
+} RenderContext;
+
+
+typedef struct 
+{
+    GFXDisplayPoint P1;
+    GFXDisplayPoint P2;    
+} GFXDisplayBox;
+
+
+typedef struct 
+{
+    uint8_t FontWidth;
+    uint8_t FontHeight;
+    uint8_t BytesPerColumn;
+    uint8_t *FontBuffer;    
+    uint8_t *CharacterWidthTable;
+
+} GFXFont;
+
+
+//System/Hardware specific stuff
+void GFX_InitPhysicalScreen();
+void GFX_DumpRenderContextToPhysicalScreen(RenderContext *Image);
+void GFX_Init();
+void GFX_PowerUpScreen();
+void GFX_PowerDownScreen();
+
+//Useful User Graphics Functions
+void GFX_FullDisplayBufferClear(RenderContext *Image);
+//Draws a single pixel
+void GFX_PutPixel(RenderContext *Image, int16_t x, int16_t y);
+//draws a horizontal line
+void GFX_DrawHline(RenderContext *Image, int16_t XStart, int16_t XStop, int16_t Y);
+//Draws a veritcal line
+void GFX_DrawVline(RenderContext *Image, int16_t YStart, int16_t YStop, int16_t X);
+//Draws a line between 2 points
+void GFX_DrawLine(RenderContext *Image, int16_t X1,int16_t Y1, int16_t X2,int16_t Y2);
+//Draws a box
+void GFX_DrawBox(RenderContext *Image, GFXDisplayBox *Box);
+//Draws a string
+void GFX_DrawString(RenderContext * Image,char * String,int16_t StartX, int16_t StartY, GFXFont * MyFont);
+//Draws a string using standard printf escape sequences
+void GFX_printf(RenderContext * Image,int16_t StartX, int16_t StartY, GFXFont * MyFont, const char *FormatString,...);
+//Draws a string that is horizontally centered
+void GFX_DrawCenteredString(RenderContext * Image,char * String,int16_t StartX, int16_t StartY, GFXFont * MyFont);
+
+
+
+#ifdef INLINE_BITPLANE_PUT
+    inline void BitPlane_Put(BitPlane  * BP, uint16_t X,uint16_t Y, uint8_t Value)
+    {
+        uint16_t Offset;
+        uint8_t Mask;
+        
+        Offset = (Y * ((BP->SizeX)>>3)) + (X>>3);
+        Mask = 0x01 << (X & 0x07);
+    
+        if(Value)
+        {
+            BP->BitPlaneSpace[Offset] |= Mask;
+        }
+        else
+        {
+            BP->BitPlaneSpace[Offset] &= ~Mask;
+        }
+    }
+#else
+    void BitPlane_Put(BitPlane  * BP, uint16_t X,uint16_t Y, uint8_t Value);
+#endif
+
+#ifdef INLINE_BITPLANE_GET
+    inline uint8_t BitPlane_Get(BitPlane  * BP, uint16_t X,uint16_t Y)
+    {
+        uint16_t Offset;
+        uint8_t Mask;
+     
+        Offset = (Y * ((BP->SizeX)>>3)) + (X>>3);
+        Mask = 0x01 << (X & 0x07);
+    
+        if((BP->BitPlaneSpace[Offset])&Mask)
+        {
+            return TRUE;
+        }
+        else
+        {
+            return FALSE;
+        }
+    }
+#else
+    uint8_t BitPlane_Get(BitPlane  * BP, uint16_t X,uint16_t Y);
+#endif
+
+
+void BitPlane_Clear(BitPlane  * BP);
+
+#ifdef _INLINE_GFX_GET_PIXEL
+inline uint8_t GFX_GetPixel(RenderContext *Image, int16_t x, int16_t y)
+{
+    uint8_t PixelColor = 0;
+    
+    if((x<Image->SizeX) && (y<Image->SizeY) && (x>=0) && (y>=0))
+    {
+        
+        if(BitPlane_Get(&Image->RenderPlane,x,y))
+            PixelColor = 1;
+
+    }
+    
+    return PixelColor;
+}
+#else
+    uint8_t GFX_GetPixel(RenderContext *Image, int16_t x, int16_t y);
+#endif
+
+extern RenderContext BackBuffer;
+
+//Two useful fonts!
+extern GFXFont Font5x7;
+extern GFXFont Font3x5;
+
+//values for Red, Green and Blue can be 0-3 (4 levels for each color)
+void SmartSwitch_SetBackLightColor(uint8_t Red,uint8_t Green,uint8_t Blue);
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Sat Jan 25 19:10:17 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Sissors/code/MODSERIAL/#b04ce87dc424
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Jan 25 19:10:17 2014 +0000
@@ -0,0 +1,93 @@
+#include "mbed.h"
+#include "CHEM_BOX_INTERFACE.h"
+
+Timer ControlLoopTimer;
+float CurrentTemperature;
+
+
+int main() 
+{
+    int i;
+
+    //This function always needs called before you do anythign wit the CHEM BOX.
+    InitChemBox();
+
+    //Beep 6 times
+    for(i=0;i<6;i++)
+      {
+        Buzz(.05);  //Since the Buzz function immediately returns we should wait a bit before calling it again in the loop
+        wait(.1);   //I want a 50% duty cycle so I will wait twice as long as my previous Buzz() call
+     }
+     
+     
+      //Here is an example of how to draw on the screen!
+      
+      //This makes the backlight white.   Each color can be between 0 and 3 (integers... 0,1,2,3)
+      SmartSwitch_SetBackLightColor(3, 3, 3);
+      
+      //The display routines are fully buffered.   When you call the draw routines,  the write to the backbuffer, not the screen.
+      //The flow is to clear the backbuffer,   call all the drawing routines,  then dump the backbuffer to the screen.   
+      
+      //This clears the back buffer
+      GFX_FullDisplayBufferClear(&BackBuffer);
+      
+      //Draw a box around the edge of the screen
+      
+      GFX_DrawLine(&BackBuffer, 0,0, PHYSICAL_DISPLAY_XRES - 1,0);
+      GFX_DrawLine(&BackBuffer, PHYSICAL_DISPLAY_XRES - 1,0,PHYSICAL_DISPLAY_XRES - 1 ,PHYSICAL_DISPLAY_YRES - 1);
+      GFX_DrawLine(&BackBuffer, PHYSICAL_DISPLAY_XRES - 1 ,PHYSICAL_DISPLAY_YRES - 1,0,PHYSICAL_DISPLAY_YRES - 1);
+      GFX_DrawLine(&BackBuffer,0, PHYSICAL_DISPLAY_YRES - 1,0,0);
+      
+      //Draw a plain string using the 5x7 font.   
+      GFX_DrawString(&BackBuffer,"Rioux Box",6,2, &Font5x7);
+      
+      GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES - 1 ,12);
+      
+      //This shows how to do a printf.   Using this allows you to put internal variables, etc on the screen.   
+      //Just lookup documentation on printf on the web to see examples of escape sequences in the control strings   
+      //In this example API_VERSION is a string so we use %s to display it  
+      GFX_printf(&BackBuffer,15,20, &Font3x5,"Ver: %s",API_VERSION);
+      
+      //Move the backbuffer to the actual display
+      GFX_DumpRenderContextToPhysicalScreen(&BackBuffer);
+      
+     
+    //Here is the main super loop
+    
+    //reset and start our control loop Timer
+    ControlLoopTimer.reset();
+    ControlLoopTimer.start();
+    
+    while(1)
+     {
+          //Call this often if you want the USB interface/Terminal
+          ProcessTerminal();
+      
+            /*
+            
+            //control loop example
+            //We will do something ever 250mS.
+            //Use a timer and an if statement we won't hold the microprocessor from do other things in the main super loop!
+            if(ControlLoopTimer.read_ms >= 250)
+            {
+                ControlLoopTimer.reset();    
+                
+                //if 250mSec has elapsed then do our control loop
+                
+                CurrentTemperature = ReadThermocouple(0);
+                
+                if(CurrentTemperature < 15.5)
+                {
+                    EnableHeater(0);
+                }
+                else
+                {
+                   DisableHeater(0);
+                }
+                
+                FlushDigitalIO(); //Remeber, the digital outs are queued up until this is called!
+            }
+            */
+     }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Jan 25 19:10:17 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/a9913a65894f
\ No newline at end of file