For Terrance

Dependencies:   mbed

Code/System.c

Committer:
emh203
Date:
2012-06-13
Revision:
0:085749c8446f

File content as of revision 0:085749c8446f:

#include "System.h"

DigitalOut EXT_LED0(LED2);
DigitalOut ETH_LED_GREEN(p29);
DigitalOut ETH_LED_YELLOW(p30);
DigitalIn  ActionButton(p28);
DigitalIn  SDCardDetect(p9);
Ticker  SystemTick;

WORD UpdateHostTerminalTick;
WORD DisplayUpdateTick;
WORD ButtonCheckTick;
WORD DisplayShutOffTick;

BYTE SystemState;
CHAR DTBuf[32];
CHAR DataLineBuf[256];

//*****************************************************************
//smart Display related stuff
//*****************************************************************

#define DISPLAY_MEASUREMENTS       0x00
#define DISPLAY_BATTERY            0x01
#define DISPLAY_DATE_TIME          0x02
#define DISPLAY_CARD_STATUS        0x03
#define DISPLAY_BUFFER_STATS       0x04
#define DISPLAY_FIRMWARE_VERSION   0x05
#define DISPLAY_ID                 0x06
#define DISPLAY_OFF                0xFF

#define NUM_DISPLAYS               7
#define DISPLAY_SHUTOFF_TIME    10000

BYTE DisplayMode;
BYTE LastBackLightColor = 0;

//*****************************************************************
//Action Button Related stuff
//*****************************************************************
#define WAITING_FOR_PRESS   0x00
#define WAITING_FOR_RELEASE 0x01

BYTE PreviousButtonState;   
BYTE CurrentButtonState;   
WORD ButtonHoldTime;
BYTE ButtonCheckState;
void ActionButtonHandler(WORD ButtonPressTime);

//*****************************************************************
//Terminal Related stuff
//*****************************************************************

//#define MAX_TERMINAL_LINE_CHARS 128
//CHAR TerminalLineBuf[MAX_TERMINAL_LINE_CHARS];
//BYTE TerminalPos;
time_t CurrentTime_InSec;
tm *CurrentTime;
BOOL ProcessTerminalLine(CHAR * LineIn);
BOOL CheckForTime(CHAR *LineIn);
BOOL CheckForDate(CHAR *LineIn);
BOOL CheckForTimeInit(CHAR * LineIn);
BOOL CheckforConfig(CHAR *LineIn);

//*****************************************************************
//Logging Related Stuff
//*****************************************************************
CHAR CurrentLogFileName[256];
BOOL InitDataLog();
BOOL DataLogError;
CHAR *ErrorMsg;

void CreateLogFileName();

FATFS MyFileSystem;
FIL  CurrentLogFileHandle;

//DataBlock MyDataBlock[2];
DataBlock MyDataBlock;

BYTE ActiveDataBlock;
DWORD   DataBlocksWritten;
DWORD   DataPointIndex;
SIGNED_DWORD ReadWriteDifferential;

DWORD   WritesSinceLastFlush;

#define BINARY_WRITE_CACHE_THRESHOLD   512
BYTE    BinaryDataCache[BINARY_WRITE_CACHE_THRESHOLD + 64];
DWORD   BinaryDataCachePtr;

#define NUM_WRITES_BEFORE_FLUSH (10)

//*****************************************************************
//Misc System Related Stuff
//*****************************************************************
void SystemTickIrq();
void AdjustIOffset();

void InitRobotPowerMeasurementSystem()
{
    InitDataBlocks(&MyDataBlock);
     
    ActiveDataBlock = 0;
    DataBlocksWritten = 0;
    DataPointIndex = 0;
    
    SystemTick.attach_us(&SystemTickIrq,10000);
    CurrentTime_InSec = time(NULL);
  
    DataLogError = FALSE;
}


void InitDataBlocks(DataBlock * DB)
{
    int i;
  
    for(i=0;i<DATA_BLOCK_SIZE;i++)
    {
        DB->Voltage[i] = 0;
        DB->Current[i] = 0;
    }
    
     DB->WriteOutPtr = 0;
     DB->ReadInPtr = 0;
}


void EnterSystemState(BYTE NextState)
{
    switch(NextState)
    {
        default:
        case SYSTEM_STATE_INIT:
            DisplayMode = DISPLAY_MEASUREMENTS;
            SystemState = NextState;
        break;
        
        case SYSTEM_STATE_LOGGING:
              DisplayMode = DISPLAY_CARD_STATUS;
              
              if(InitDataLog() == FALSE)
              {
                SystemState = NextState;
              
              }
              else
              {
                SystemState = SYSTEM_STATE_IDLE;
              }
              
        break;
        
        case SYSTEM_STATE_IDLE:
            DisplayMode = DISPLAY_CARD_STATUS;
            if(SystemState == SYSTEM_STATE_LOGGING)
            {
                f_close(&CurrentLogFileHandle);
                f_mount(0,NULL);
                PrintfEnqueue(&PCBackDoorTx,"Logging terminated on file %s\r\n>",CurrentLogFileName);
            }
            
            SystemState = NextState;
        break;
    }
}

BOOL InitDataLog()
{
    UINT BytesWritten;
    
    PrintfEnqueue(&PCBackDoorTx,"\r\n\r\bInitializing Data log....\r\n");
    CreateLogFileName();
    PrintfEnqueue(&PCBackDoorTx,"Filename: %s\r\n",CurrentLogFileName);
    PrintfEnqueue(&PCBackDoorTx,"Attempting File Open....\r\n");
   
    BinaryDataCachePtr = 0;
    WritesSinceLastFlush = 0;
    
    f_mount(0,&MyFileSystem);
    if(f_open(&CurrentLogFileHandle,&CurrentLogFileName[0],FA_WRITE | FA_OPEN_ALWAYS) != FR_OK)
      {
                DataLogError = TRUE;
                PrintfEnqueue(&PCBackDoorTx,"Could not open file!\r\n>");
                ErrorMsg = "Write Error!";
                return TRUE;
      }
    
     DataBlocksWritten = 0;
     DataPointIndex = 0;
     
     DataLogError = FALSE;
     PrintfEnqueue(&PCBackDoorTx,"Writing Headers....\r\n");
     time(&CurrentTime_InSec);
     strftime(DTBuf,128, "%Y.%m.%d", localtime(&CurrentTime_InSec));
     f_printf(&CurrentLogFileHandle, "Date      %s\r\n",DTBuf);
     strftime(DTBuf,128, "%H:%M:%S", localtime(&CurrentTime_InSec));
     f_printf(&CurrentLogFileHandle, "Time      %s\r\n\n",DTBuf);
     sprintf(DTBuf, "Sample Rate   %.1f Hz\r\n\r\n",SAMPLE_RATE);
     f_write(&CurrentLogFileHandle,DTBuf,strlen(DTBuf),&BytesWritten);
     PrintfEnqueue(&PCBackDoorTx,"Headers Written.... Starting log\r\n");
    
    
    PrintfEnqueue(&PCBackDoorTx,"\r\n>"); 

    return FALSE;
}


void CreateLogFileName()
{
     time(&CurrentTime_InSec);
     strftime(CurrentLogFileName,256, "F%Y.%m.%d.%H.%M.%S.csv", localtime(&CurrentTime_InSec));
}     



void SystemTickIrq()
{
    if(UpdateHostTerminalTick<0xFFFF)
        UpdateHostTerminalTick++;
        
    if(DisplayUpdateTick<0xFFFF)
        DisplayUpdateTick++;
        
    if(ButtonCheckTick<0xFFFF)
         ButtonCheckTick++;
         
     if(DisplayShutOffTick<0xFFFF)
        DisplayShutOffTick++;
}

void InitButton()
{
    ButtonCheckState = WAITING_FOR_PRESS;
    ButtonCheckTick = 0;
    PreviousButtonState = FALSE;
    CurrentButtonState = FALSE;

}
void CheckButton()
{
    if(ButtonCheckTick>0)
    {
        ButtonCheckTick = 0;
        
        PreviousButtonState = CurrentButtonState;
        CurrentButtonState = ActionButton.read();    
    
        switch(ButtonCheckState)
        {
            default:
            case WAITING_FOR_PRESS:
            
            if(CurrentButtonState == TRUE && PreviousButtonState == FALSE)
            {
                ButtonCheckState = WAITING_FOR_RELEASE; 
            }
            
            ButtonHoldTime = 0;
            
            break;
                        
            case WAITING_FOR_RELEASE:
            
            if(CurrentButtonState == TRUE && PreviousButtonState == TRUE)
            {
                ButtonHoldTime++;
            }
            else if(CurrentButtonState == FALSE && PreviousButtonState == TRUE)
            {
                ActionButtonHandler(ButtonHoldTime);
                ButtonCheckState = WAITING_FOR_PRESS;    
            }
            else
            {
               ButtonCheckState = WAITING_FOR_PRESS;    
            }
            break;
        }
    }
}


void ActionButtonHandler(WORD ButtonPressTime)
{
    DisplayShutOffTick = 0;

    if(ButtonPressTime<50)
    {
       if(DisplayMode == DISPLAY_OFF)
       {
         PowerUpSmartSwitch();
         SmartSwitch_Reset();
         SmartSwitchClear();
         DisplayMode = DISPLAY_MEASUREMENTS;
       }
       else
       {
       
            if(DataLogError == TRUE)
            {
                DataLogError = FALSE;
            }
            else
            {
                DisplayMode++;
               
                if(DisplayMode >= NUM_DISPLAYS)
                {
                    DisplayMode = 0;
                }
            }
        }
    }
    
    else if(ButtonPressTime>100 && ButtonPressTime<500)
    {
        switch(SystemState)
        {
            default:
            case SYSTEM_STATE_IDLE:
               switch(DisplayMode)
               {
                   default:
                 
                    break;
               
                    case DISPLAY_MEASUREMENTS:
                        AdjustIOffset();
                    break;
                    
                    
                    case DISPLAY_FIRMWARE_VERSION:
                        LoadConfiguration();
                    break;
                    
                    
                    case DISPLAY_CARD_STATUS:
                         if(SDCardDetect == 1)
                            {
                                EnterSystemState(SYSTEM_STATE_LOGGING);
                            }
                    break;
               }
            break;
            
         
            case SYSTEM_STATE_LOGGING:
              EnterSystemState(SYSTEM_STATE_IDLE);
             // unmount the file system
              f_mount(0,NULL);
            break;
        }
    }
}

void AdjustIOffset()
{
    DWORD SamplesToTake;
    DWORD i;
    float RunningSum = 0;
    
    PrintfEnqueue(&PCBackDoorTx,"Zeroing ACS576.....\r\n");
    
    ADCDataRdy=0;
    
    SamplesToTake = (DWORD)(SAMPLE_RATE)*2;
    
    for(i=0;i<SamplesToTake;i++)
    {
        SmartSwitch_SetBackLightColor2((BYTE)((float)i/(float)SamplesToTake * 64));
        
        while(ADCDataRdy == FALSE)
        {
        
        }
        ADCDataRdy = FALSE;
        RunningSum += RobotBusCurrentHR;
    }
    
    ACS576_IOFFSET_TRIM += RunningSum / SamplesToTake;

    SmartSwitch_SetBackLightColor(3,3,3);
    
    PrintfEnqueue(&PCBackDoorTx,"Exporting new configuration file.....\r\n>");
    
    ExportConfigurationSettings();
}


/*void UpdateHostTerminal()
{
 BYTE NextCharIn;
 
    if(BytesInQueue(&PCBackDoorRx)>0)
    {
        ByteDequeue(&PCBackDoorRx,&NextCharIn);
        
        switch(NextCharIn)
        {
            case '\r':
             
             TerminalLineBuf[TerminalPos++] = 0x0;
             ByteEnqueue(&PCBackDoorTx,NextCharIn);
             ProcessTerminalLine(TerminalLineBuf);
             ByteEnqueue(&PCBackDoorTx,'\n');
             ByteEnqueue(&PCBackDoorTx,'>');
             TerminalPos = 0;
              
            break;
            
            case '\b':
                if(TerminalPos > 0)
                {
                    TerminalPos--;    
                    ByteEnqueue(&PCBackDoorTx,NextCharIn);
                }
            break;
            
            default:
                
                if(NextCharIn > 32)
                {
                    if(TerminalPos < MAX_TERMINAL_LINE_CHARS-1)
                    {
                         TerminalLineBuf[TerminalPos++] = NextCharIn;
                           ByteEnqueue(&PCBackDoorTx,NextCharIn);
                    }
                }
            
            break;
        
        }
    }
 
}
*/

BOOL ProcessTerminalLine(CHAR * LineIn)
{
    CheckForTime(LineIn);
    CheckForDate(LineIn);
    CheckForTimeInit(LineIn);
    CheckforConfig(LineIn);
    return TRUE;
}

BOOL CheckforConfig(CHAR *LineIn)
{
    if(!strcmp(LineIn,"config"))
    {
        LoadConfiguration();
    }
    return TRUE;
}


BOOL CheckForTimeInit(CHAR * LineIn)
{
    if(!strcmp(LineIn,"tinit"))
    {
        set_time(1256729737);
       PrintfEnqueue(&PCBackDoorTx,"\r\nTime Reset\r\n");
    }
    
    return TRUE;

}

BOOL CheckForTime(CHAR *LineIn)
{
    int Hour,Minute,Second=0;
    int Items;
    BOOL Error = FALSE;
     time_t TimeStampTemp;
    
    
    Items = sscanf(LineIn, "time=%d : %d  : %d", &Hour, &Minute, &Second);
    if(Items == 3)
    {
        PrintfEnqueue(&PCBackDoorTx,"\r\n");
        if(Hour>23)
        {
            PrintfEnqueue(&PCBackDoorTx,"Hour entry must be between 0 and 24\r\n");
            Error = TRUE;
        }
        if(Minute>60)
        {
            PrintfEnqueue(&PCBackDoorTx,"Minute entry must be between 0 and 60\r\n");
            Error = TRUE;
        }
        if(Second>60)
        {
            PrintfEnqueue(&PCBackDoorTx,"Second entry must be between 0 and 60\r\n");
            Error = TRUE;
        }
        
        if(Error == TRUE)
        {
         PrintfEnqueue(&PCBackDoorTx,"Error in time format.  Time not changed.\r\n");
        }
        else
        {
            TimeStampTemp = time(NULL);
            //convert to tm struct 
            CurrentTime = localtime(&TimeStampTemp);
            //dump in our new valus
            CurrentTime->tm_sec = Second;
            CurrentTime->tm_min = Minute;
            CurrentTime->tm_hour = Hour;
            //set the new time
            set_time(mktime(CurrentTime));
            PrintfEnqueue(&PCBackDoorTx,"Time set to %d:%d:%d\r\n",Hour,Minute,Second);
        }
     
      }
   return FALSE;
}

BOOL CheckForDate(CHAR *LineIn)
{
    int Day,Month,Year=0;
    int Items;
    BOOL Error = FALSE;
    time_t TimeStampTemp;
    
    Items = sscanf(LineIn, "date=%d / %d  / %d", &Month, &Day, &Year);
    if(Items == 3)
    {
        PrintfEnqueue(&PCBackDoorTx,"\r\n");
        if(Month>12 || Month < 1)
        {
            PrintfEnqueue(&PCBackDoorTx,"Month entry must be between 1 and 12\r\n");
            Error = TRUE;
        }
        if(Day>31 || Day<1)
        {
            PrintfEnqueue(&PCBackDoorTx,"Day entry must be between 1 and 31\r\n");
            Error = TRUE;
        }
        if(Year<1900)
        {
            PrintfEnqueue(&PCBackDoorTx,"Year entry must be greater than 1900\r\n");
            Error = TRUE;
        }
        
        if(Error == TRUE)
        {
         PrintfEnqueue(&PCBackDoorTx,"Error in time format.  Date not changed.\r\n");
        }
        else
        {
            //Get the current time in seconds since unix epoch
            TimeStampTemp = time(NULL);
            //convert to tm struct fom
            CurrentTime = localtime(&TimeStampTemp);
            //dump in our new valus
            CurrentTime->tm_mon = Month-1;
            CurrentTime->tm_mday = Day;
            CurrentTime->tm_year = Year - 1900;
            //set the new time
            set_time(mktime(CurrentTime));
            PrintfEnqueue(&PCBackDoorTx,"Date set to %d/%d/%d\r\n",Month,Day,Year);
        }
     
      }
   return FALSE;
}



void UpdateDisplay()
{

    if(DisplayShutOffTick > DISPLAY_SHUTOFF_TIME)
    {
        DisplayMode = DISPLAY_OFF;
        SmartSwitchClear();
       PowerDownSmartSwitch();
    }
    else
    {
        if(DisplayUpdateTick > 25)
        {
            GFX_FullDisplayBufferClear(&BackBuffer);
            DisplayUpdateTick = 0;
                switch(DisplayMode)
                {
                    default:
                    case DISPLAY_MEASUREMENTS:
                      SmartSwitch_SetBackLightColor(3,3,3);
                       GFX_DrawString(&BackBuffer,"Robot Bus",0,0,&Font5x7);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                        
                       GFX_printf(&BackBuffer,0,16,&Font5x7,"V: %.2fv",RobotBusVoltageHR);
                       GFX_printf(&BackBuffer,0,24,&Font5x7,"I: %.2fa",RobotBusCurrentHR);
                    break;
                    
                   
                    case DISPLAY_BATTERY:
                       SmartSwitch_SetBackLightColor(3,3,0);
                       GFX_DrawString(&BackBuffer,"Battery",0,0,&Font5x7);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                        
                       GFX_printf(&BackBuffer,0,16,&Font5x7,"V: %.1fv",BatteryVoltage);
                      
                    break;
                    
                     case DISPLAY_DATE_TIME:
                       SmartSwitch_SetBackLightColor(1,3,0);
                       GFX_DrawString(&BackBuffer,"Date/Time",0,0,&Font5x7);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                        
                       time(&CurrentTime_InSec);
                       strftime(DTBuf, 32, "%m.%d.%Y", localtime(&CurrentTime_InSec));
                       GFX_printf(&BackBuffer,0,16,&Font5x7,"%s",DTBuf);
                      
                       strftime(DTBuf, 32, "%H:%M:%S", localtime(&CurrentTime_InSec));
                       GFX_printf(&BackBuffer,0,24,&Font5x7,"%s",DTBuf);
                    break;
                    
                     case DISPLAY_BUFFER_STATS:
                     SmartSwitch_SetBackLightColor(3,3,3);
                     GFX_DrawString(&BackBuffer,"Buf Status",0,0,&Font5x7);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                     GFX_printf(&BackBuffer,0,16,&Font3x5,"R/W Diff:");
                     GFX_printf(&BackBuffer,0,24,&Font3x5,"%04d/%d",ReadWriteDifferential,DATA_BLOCK_SIZE);
                    break;
                    
                    case DISPLAY_FIRMWARE_VERSION:
                     SmartSwitch_SetBackLightColor(3,3,3);
                     GFX_DrawString(&BackBuffer,"Firmware Version",0,0,&Font3x5);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                     GFX_printf(&BackBuffer,19,20,&Font5x7,"%d.%d",FIRMWARE_VERSION_MAJOR,FIRMWARE_VERSION_MINOR);
                    break;
                    
                    case DISPLAY_ID:
                     SmartSwitch_SetBackLightColor(3,3,3);
                     GFX_DrawString(&BackBuffer,"ID",0,0,&Font3x5);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                     GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                     GFX_printf(&BackBuffer,0,20,&Font5x7,"%s",ID);
                    break;
                    
                    case DISPLAY_CARD_STATUS:
                                         
                      if(SDCardDetect == 1)
                      {
                        
                          switch(SystemState)
                          {
                            default:
                            case SYSTEM_STATE_IDLE:
                                switch(LastBackLightColor)
                                 {
                                    default:
                                    case SMART_SWITCH_BACKLIGHT_GREEN:
                                         LastBackLightColor = SMART_SWITCH_BACKLIGHT_YELLOW;  
                                         SmartSwitch_SetBackLightColor2(LastBackLightColor);
                                    break;
                                    
                                    case SMART_SWITCH_BACKLIGHT_YELLOW:
                                        LastBackLightColor = SMART_SWITCH_BACKLIGHT_GREEN;
                                        SmartSwitch_SetBackLightColor2(LastBackLightColor);
                                    break;
                                  }
                               
                               
                              if(DataLogError == TRUE)
                              {
                                   GFX_DrawString(&BackBuffer,"Error!",0,0,&Font5x7); 
                                   GFX_DrawString(&BackBuffer,ErrorMsg,0,16,&Font3x5);
                              }  
                              else
                              { 
                                  GFX_DrawString(&BackBuffer,"SD Detected",0,16,&Font5x7);
                                  GFX_DrawString(&BackBuffer,"Idle....",0,0,&Font5x7);
                                  GFX_DrawString(&BackBuffer,"Not Logging",0,24,&Font5x7);    
                              }
                            break;
                         
                         
                            case SYSTEM_STATE_LOGGING:
                                SmartSwitch_SetBackLightColor2(SMART_SWITCH_BACKLIGHT_GREEN);
                               
                                GFX_DrawString(&BackBuffer,"Logging Data....",0,0,&Font5x7);
                                GFX_DrawString(&BackBuffer,&CurrentLogFileName[4],0,16,&Font5x7);
                                GFX_printf(&BackBuffer,0,26,&Font3x5,"Block: %d",DataBlocksWritten);
                                
                            break;
                         }
                      }
                      else
                      {
                          GFX_DrawString(&BackBuffer,"No SD Card!",0,0,&Font5x7);
                          
                            switch(LastBackLightColor)
                            {
                                default:
                                case SMART_SWITCH_BACKLIGHT_RED:
                                     LastBackLightColor = SMART_SWITCH_BACKLIGHT_YELLOW;  
                                     SmartSwitch_SetBackLightColor2(LastBackLightColor);
                                break;
                                
                                case SMART_SWITCH_BACKLIGHT_YELLOW:
                                    LastBackLightColor = SMART_SWITCH_BACKLIGHT_RED;
                                    SmartSwitch_SetBackLightColor2(LastBackLightColor);
                                break;
                              }
                      } 
                    
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,10);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,11);
                       GFX_DrawHline(&BackBuffer,0,PHYSICAL_DISPLAY_XRES-1,12);
                    
                    break;
                }
             GFX_DumpRenderContextToPhysicalScreen(&BackBuffer);
        }
    }
}


void CheckSDCardStatus()
{
    //Make sure that the SD card stays in while logging
    switch(SystemState)
    {
        case SYSTEM_STATE_LOGGING:
            if(SDCardDetect == 0)
            {
                //Gracefully shut the logging system down.....
                EnterSystemState(SYSTEM_STATE_IDLE);
            }
        break;
        
        default:
        break;
    } 
}


void LogData()
{
    WORD i;
    int ElementsToWrite;
    UINT BytesWritten;
    
    if(RobotBusVoltageHR < 9)
    {
        EnterSystemState(SYSTEM_STATE_IDLE);
        return;
    }
    
    if(DataLogError == TRUE)
    {
        EnterSystemState(SYSTEM_STATE_IDLE);
    }
    else
    {
        if(MyDataBlock.ReadInPtr < MyDataBlock.WriteOutPtr)
        {
           ElementsToWrite =  MyDataBlock.ReadInPtr + (DATA_BLOCK_SIZE - MyDataBlock.WriteOutPtr);
        }
        else
        {
            ElementsToWrite = MyDataBlock.ReadInPtr - MyDataBlock.WriteOutPtr;
        }
        
        if(ElementsToWrite > WRITE_BLOCK_THRESH)
        {
                for(i=0;i<ElementsToWrite;i++)
                {
                    BinaryDataCachePtr += sprintf((char *)&BinaryDataCache[BinaryDataCachePtr],"%d,%.2f,%.2f\r\n",DataPointIndex,MyDataBlock.Voltage[MyDataBlock.WriteOutPtr],MyDataBlock.Current[MyDataBlock.WriteOutPtr]);
                    if(BinaryDataCachePtr>=BINARY_WRITE_CACHE_THRESHOLD)
                    {
                        EXT_LED0 = 1;  
                        f_write(&CurrentLogFileHandle,BinaryDataCache,BinaryDataCachePtr,&BytesWritten);
                        
                        BinaryDataCachePtr = 0;
                      
                        EXT_LED0=0;
                    }
                    DataPointIndex++;
                    MyDataBlock.WriteOutPtr++;
                    if(MyDataBlock.WriteOutPtr == DATA_BLOCK_SIZE)
                    {
                        MyDataBlock.WriteOutPtr = 0;
                    }
                }
                if(WritesSinceLastFlush > NUM_WRITES_BEFORE_FLUSH)
                 {
                            f_close(&CurrentLogFileHandle);
                            WritesSinceLastFlush = 0;
                            f_open(&CurrentLogFileHandle,&CurrentLogFileName[0],FA_WRITE | FA_OPEN_ALWAYS);
                            f_lseek(&CurrentLogFileHandle, CurrentLogFileHandle.fsize);
                 }
               DataBlocksWritten++;
      }
    }
}



void DisplayBootMsg()
{
   PrintfEnqueue(&PCBackDoorTx,"\r\n\r\n");
   PrintfEnqueue(&PCBackDoorTx,".______     _______. __    __            ___      .______       __   \r\n");
   PrintfEnqueue(&PCBackDoorTx,"|   _  \\   /       ||  |  |  |          /   \\     |   _  \\     |  |  \r\n");
   PrintfEnqueue(&PCBackDoorTx,"|  |_)  | |   (----`|  |  |  |  ______ /  ^  \\    |  |_)  |    |  |  \r\n");   
   PrintfEnqueue(&PCBackDoorTx,"|   ___/   \\   \\    |  |  |  | |______/  /_\\  \\   |      /     |  |  \r\n");
   PrintfEnqueue(&PCBackDoorTx,"|  |   .----)   |   |  `--'  |       /  _____  \\  |  |\\  \\----.|  `----.\r\n");
   PrintfEnqueue(&PCBackDoorTx,"| _|   |_______/     \\______/       /__/     \\__\\ | _| `._____||_______|\r\n");
   PrintfEnqueue(&PCBackDoorTx,"---------------------------------------------------------------------------\r\n");
   PrintfEnqueue(&PCBackDoorTx,"HyPER MPMC Control Terminal\r\n\r\n>");
}