#include "MainBrain.h"
#include <stdbool.h>
#include <stdint.h>

#pragma config FMIIEN = OFF             // Ethernet RMII/MII Enable (MII Enabled)
#pragma config FETHIO = OFF             // Ethernet I/O Pin Select (Default Ethernet I/O)
#pragma config FUSBIDIO = OFF           // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = OFF          // USB VBUS ON Selection (Controlled by USB Module)
#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits 
#pragma config POSCMOD = EC             // Primary Oscillator Configuration
#pragma config FPLLIDIV = DIV_5         // PLL Input Divider
#pragma config FSOSCEN = ON             // Secondary Oscillator Enable
#pragma config FPLLMUL = MUL_24         // PLL Multiplier 
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider 
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor 
#pragma config UPLLIDIV = DIV_5         // USB PLL Input Divider
#pragma config UPLLEN = ON              // USB PLL Enable (Enabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Enabled)
#pragma config OSCIOFNC = ON            // CLKO Output Signal Active on the OSCO Pin 
#pragma config WDTPS = PS128            // Watchdog Timer Postscaler (1:1048576)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM)
#pragma config DEBUG = OFF              // Background Debugger
#pragma config FSRSSEL = PRIORITY_7     // All interrupt priorities are assigned to a shadow register set
#pragma config ICESEL = ICS_PGx1 

void* USBGenericOutHandle; //USB handle.  Must be initialized to 0 at startup.
void* USBGenericInHandle;  //USB handle.  Must be initialized to 0 at startup.

unsigned char INPacket[64];     //buffer for sending IN packets to the host
unsigned char  OUTPacket[64];	//buffer for receiving and holding OUT packets sent from the host

DISPLAY_STATE displayState;
CONTROL_BITS ControlByte;
STATUS_BITS StatusByte;

int j = 0;
int StatusPosition = 0;
int SRAMposition = 0;
int SRAMAddHigh = 0;
int SRAMAddLow = 0;
int MemoryAddress;
volatile unsigned RTC_delay_counter = 0;

unsigned char usbInBuffer[64];
unsigned int dummy;

uint8_t OSCFREQ = 20;
uint8_t NameArray[10] = {"MainBrain"};
uint8_t RevArray[9] = {"1.9.0001"};
uint8_t ProcessorRev = 0xA5;

bool MotionBoardPresent = false;
bool DeviceIsConnected = false;
bool DumpBDT = false;
bool GetADCISense = false;
bool GetRegData = false;
bool GetSRAMData = false;
bool GetBackLight = false;

char ConnectedStr[10] = {"Connected"};
char ReadyStr[10] = {"Ready    "};
char OfflineStr[10] = {"Offline  "};
char ProcessorArray[18] = {"PIC32MX695F512L-80"};
char SRAMsize[10] = {"8Kx8 SRAM"};
char FlashSize[13] = {"512Kx8 Flash"};
char USBver[8] = {"USB 2.0"};

int main(void)
{   
    SRAMposition = 0;
    j = 0;
    //Hardware Initialization begins
    //Wait for PLL Lock
    while(!OSCCONbits.SLOCK);
    
    SYSKEY = 0x0;               // ensure OSCCON is locked
    SYSKEY = 0xAA996655;        // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA;        // Write Key2 to SYSKEY

    //enable secondary oscillator
    OSCCONbits.SOSCEN = 1;
    
    //wait for warm up
    while(OSCCONbits.SOSCRDY == 0);
    
    //Data Memory SRAM wait states: Default Setting = 1; set it to 0
    BMXCONbits.BMXWSDRM = 0;

    //Flash PM Wait States: MX Flash runs at 2 wait states @ 80 MHz
    CHECONbits.PFMWS = 2;

    //Prefetch-cache: Enable prefetch for cacheable PFM instructions
    CHECONbits.PREFEN = 1;

    //Disable JTAG Port
    DDPCONbits.JTAGEN = 0;

    //External Boards Reset
    TRISDbits.TRISD1 = 0;
    PORTDbits.RD1 = 1;
    
    //Setup the GPO-2 pins as inputs
    //GP0
    TRISCbits.TRISC15 = 1;
    //GP1
    TRISAbits.TRISA15 = 1;
    //GP2
    TRISDbits.TRISD8 = 1;
    
    Timer2_Init();
    Timer5_Init();

    ADC_Init();
    
    //Beep speaker
    TRISDbits.TRISD14 = 0;
    int i;
    for(i=0;i<500;i++)
    {
        PORTDbits.RD14 = 1;
        Delay(20000);
        PORTDbits.RD14 = 0;
        Delay(20000);
    }

    //Initialize the Parallel Master Port
    PMP_Init();
    
    //SRAM Init
    REN70V05_Init();
    
    //SRAM Test
    //memtest_70V05();
    
    SRAMposition = 0;
    
    //Flash Init
    Flash_Init();
    
    //Initialize the Display
    HX8357B_Init();            
    
    //control is with a P-channel MOSFET
    //so the higher the number, the dimmer
    //the screen
    Backlight_Control(10);
                
    //Clear the Screen
    HX8357B_CLRSCN(white);
    
    //Turn on the Display
    HX8357B_DISPON();
    
    //Real time clock
    RTC_Init();

    InterruptsInit();

    //Intialize LED Port
    LED_Port_Init();
    
    LED_Port(0xff);

    ShowSplashScreen();

    LED_Port(0x0);
    
    USBGenericOutHandle = 0;	
	USBGenericInHandle = 0;		
    
    USB_Init();
    
    USBDeviceAttach();

    displayState = MAIN;
    
    //Reset Motion Board
//    PORTDbits.RD1 = 0;
//    Delay(10000);
//    PORTDbits.RD1 = 1;
    
    //Motor Speed
    //Value = 1 to 255
    REN70V05_WR(0x3f8, 100);
    
    while(1)
    {
        //USB I/O 
        ProcessIO();
        
        //this switches to the various program screens
        switch(displayState)
        {
            case MAIN:
                if(USBDeviceState == CONFIGURED_STATE)
                {             
                    vchar = 200;
                    hchar = 10;

                    if(DeviceIsConnected == true)
                    {
                        WriteString(hchar, vchar, ConnectedStr, blue);          
                    }
                    else
                    {
                        WriteString(hchar, vchar, ReadyStr, black);          
                    }
                }  
                if(USBDeviceState == DEFAULT_STATE)
                {
                    vchar = 200;
                    hchar = 10;

                    WriteString(hchar, vchar, OfflineStr, red);
                }

                break;
            case DUMP_BDT:
                DisplayUSBData();
                //displayState = MAIN;
                break;
            case DUMP_MEM:
                
                break;
            case CLOCK:
                //Clock(ClockData);
                break;
            case DUMP_SRAM:
                
                break;
            case MOTION:
                MotionInterface();
                break;
        }
    } 
} 

void ProcessIO(void)
{   
    uint8_t ctrl = 0;
    //User Application USB tasks below.
    //Note: The user application should not begin attempting to read/write over the USB
    //until after the device has been fully enumerated.  After the device is fully
    //enumerated, the USBDeviceState will be set to "CONFIGURED_STATE".
    if((USBDeviceState < CONFIGURED_STATE)||(U1PWRCbits.USUSPEND == 1))
    {
        return;
    }
    
    //As the device completes the enumeration process, the USBCBInitEP() function will
    //get called.  In this function, we initialize the user application endpoints (in this
    //example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT).
    //The USBGenRead() function call in the USBCBInitEP() function initializes endpoint 1 OUT
    //and "arms" it so that it can receive a packet of data from the host.  Once the endpoint
    //has been armed, the host can then send data to it (assuming some kind of application software
    //is running on the host, and the application software tries to send data to the USB device).
    
    //If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will
    //automatically receive it and store the data at the memory location pointed to when we called
    //USBGenRead().  Additionally, the endpoint handle (in this case USBGenericOutHandle) will indicate
    //that the endpoint is no longer busy.  At this point, it is safe for this firmware to begin reading
    //from the endpoint buffer, and processing the data.  In this example, we have implemented a few very
    //simple commands.  For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the
    //first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)".
    
    //Check if the endpoint has received any data from the host.
    //if(!USBHandleBusy(USBGenericOutHandle))		
    if(!(USBGenericOutHandle==0?0:((volatile BDT_ENTRY*)USBGenericOutHandle)->STAT.UOWN))
    {   
        //Turn on LED10 to show data transfer
        LED9 = !LED9;
        
        //Data arrived, check what kind of command might be in the packet of data.
        switch(OUTPacket[0])					
        {
            int i;
            //These are the Device Program Commands 0x20 - 0x2f
            
             /*The Program List
                0 Dump BDT
                1 Dump Device Memory
                2 Clock
                3 Set Time
                4 Get Device Info
                5 Read SRAM
                6 Dump SRAM to Display
                7 Write File to SRAM
                8 Read Flash
                9 Write Flash
                10 Restart Device
                11 Set LEDs
                12 Update Firmware
                13 Exit
                14 Motion Interface
             */
            
            case 0x20:
                //Dump BDT
                HX8357B_CLRSCN(white);
                displayState = DUMP_BDT;
                break;
            case 0x21:
                //Dump Device Memory
                displayState = DUMP_MEM;
                int temp = 0;
                
                //Get the address
                temp  = OUTPacket[1];
                MemoryAddress = temp << 24;
                        
                temp = OUTPacket[2];
                temp = temp << 16;
                MemoryAddress = MemoryAddress | temp;
                            
                temp = OUTPacket[3];
                temp = temp << 8;
                
                MemoryAddress = MemoryAddress | temp;
                
                MemoryAddress = MemoryAddress | OUTPacket[4];
                
                DumpMemory();
                break;
            case 0x22:
                //Clock
                HX8357B_CLRSCN(white);
                displayState = CLOCK;                
                break;
            case 0x23:
                //Set Time
                setTime();
                break;
            case 0x24:
                //Get Device Information
                
                break;
            case 0x25:
                //Read SRAM
                SRAMAddHigh = OUTPacket[1];
                SRAMAddLow = OUTPacket[2];
                //SRAMAddLow = SRAMAddLow & 0xff;
                
                //now combine the 2 bytes to form a word
                SRAMAddHigh = SRAMAddHigh << 8;
                //SRAMAddHigh = SRAMAddHigh & 0xff00;
                SRAMposition = SRAMAddHigh + SRAMAddLow;
                GetSRAMData = true;                
                break;
            case 0x26:
                //Dump SRAM to Display
                displayState = DUMP_SRAM;
                //OUTPacket[1] = SRAM Block to display
                SRAM_Block = OUTPacket[1];
                DumpSRAM();
                break;
            case 0x27:
                HX8357B_CLRSCN(white);
                hchar = 10;
                vchar = 20;
                Binary2ASCIIHex(OUTPacket[1]);
                WriteChar(hchar, vchar, d_hex[7], 0x0);
                WriteChar(hchar, vchar, d_hex[6], 0x0);
                WriteChar(hchar, vchar, d_hex[5], 0x0);
                WriteChar(hchar, vchar, d_hex[4], 0x0);
                WriteChar(hchar, vchar, d_hex[3], 0x0);
                WriteChar(hchar, vchar, d_hex[2], 0x0);
                WriteChar(hchar, vchar, d_hex[1], 0x0);
                WriteChar(hchar, vchar, d_hex[0], 0x0);

                //Write File to SRAM
                for(i=1;i<64;i++)
                {                 
                    //Write Data to SRAM
                    REN70V05_WR((j), OUTPacket[i]);
                    j++;
                }       
                i = 1;
                j = 0;
                LED6 = 1;
                break;
            case 0x28:
                break;
            case 0x29:
                break;
            case 0x2a:
                //Reset Device
                SystemReset();
                break;
                //Set LEDs
            case 0x2b:
                LED0 = OUTPacket[8];
                LED1 = OUTPacket[7];
                LED2 = OUTPacket[6];
                LED3 = OUTPacket[5];
                LED4 = OUTPacket[4];
                LED5 = OUTPacket[3];
                LED6 = OUTPacket[2];
                LED7 = OUTPacket[1];
                break;
            case 0x2d:
                //Exit           
                displayState = MAIN;    
                ShowSplashScreen();
                break;
            case 0x2e:
                //Clear the Screen
                HX8357B_CLRSCN(white);
                displayState = MOTION;                
                break;
                //Motor Run Command
            case 0x2f:
                ControlByte.run = 1;
                REN70V05_WR(0x3ff, ControlByte.byte);
                break;
                //Motor Stop Command
            case 0x30:
                ControlByte.run = 0;
                REN70V05_WR(0x3ff, ControlByte.run);
                break;
                //Motor DIR Toggle Command
            case 0x31:
                ControlByte.dir = !ControlByte.dir;
                REN70V05_WR(0x3ff, ControlByte.byte);
                break;
                //Set Back light 
            case 0x61:
                Backlight_Control(OUTPacket[1]);
                break;
            //Set Connected = true
            case 0x62:
                DeviceIsConnected = true;
                break;
            case 0x63:
                DeviceIsConnected = false;
                break;
            case 0x64:
                SetMotorSpeed(OUTPacket[1]);
                break;                
            //Set SRAM read start address
            case 0x70:
                if(displayState == DUMP_BDT)
                {
                    HX8357B_CLRSCN(white);
                    displayState = MAIN;
                    ShowSplashScreen();                                    
                }
                GetSRAMData = true;
                break;
            case 0x71:
                GetRegData = true; 
                break;
            case 0x72:
                GetBackLight = true; 
                break;
            case 0x73:
                GetADCISense = true; 
                break;
            case 0x74:
                SRAMposition = 0;
                GetSRAMData = false;
                break;
            case 0x75:
                //Find Motion Interface
                REN70V05_RD(0x3ec);
                if(mdata_70V05 == 0x99)
                {
                    MotionBoardPresent = true;
                }
                break;
            //Read SRAM starting from SRAMposition
            case 0x81:
                //Turn on LED10 to show data transfer
                LED10 = !LED10;
                
                //If any attempts are still pending, we do not want to write to the endpoint 1 IN buffer again, until the previous 
                //transaction is complete.
				//Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior.    
                //if(!USBHandleBusy(USBGenericInHandle))
                if(!(USBGenericInHandle==0?0:((volatile BDT_ENTRY*)USBGenericInHandle)->STAT.UOWN))
    	        {	
    	            //The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint.
                    int temp;
                    if(GetADCISense == true)
                    {
                        //ADC reads the voltage on pin #33 (AN9)
                        TRISBbits.TRISB9 = 1;
                        AD1PCFGbits.PCFG9 = 0;           
                        AD1CHSbits.CH0SA = 9;           //Channel 0 positive input is AN9
                        //wait for ADC
                        Delay(5000);

                        /**************************************************************************/
                        IFS1bits.AD1IF = 0;             //Clear interrupt flag
                    
                        AD1CON1bits.ASAM = 1;           //Auto start sampling for 31 TAD, then convert   

                        while(!IFS1bits.AD1IF);         //Wait for conversion to complete
                        AD1CON1bits.ASAM = 0;           //Stop sample/convert

                        INPacket[0] = ADC1BUF0;
                        INPacket[1] = ADC1BUF0 >> 8;
                        
                        //ADC reads the voltage on pin #21 (AN4)
                        TRISBbits.TRISB4 = 1;
                        AD1PCFGbits.PCFG4 = 0;           
                        AD1CHSbits.CH0SA = 4;           //Channel 0 positive input is AN4

                        Delay(5000);

                        ADC1BUF0 = 0;
                        IFS1bits.AD1IF = 0;             //Clear interrupt flag
                        AD1CON1bits.ASAM = 1;           //Auto start sampling for 31 TAD, then convert
                        while(!IFS1bits.AD1IF);         //Wait for conversion to complete
                        AD1CON1bits.ASAM = 0;           //Stop sample/convert

                        //Read the buffer
                        
                        INPacket[2] = ADC1BUF0;
                        INPacket[3] = ADC1BUF0 >> 8;

                        GetADCISense = false;
                    }
                    if(GetBackLight == true)
                    {
                        INPacket[0] = back_level;
                        //GetBackLight == false;
                    }
                    if(GetRegData == true)
                    {
                        //Device Name Array
                        int i;
                        for(i=0;i<10;i++)
                        {
                            INPacket[i] = NameArray[i];
                        }
                        
                        //Revision Array
                        for(i=0;i<9;i++)
                        {
                            INPacket[i + 10] = RevArray[i];
                        }
                        
                        //Processor Array
                        for(i=0;i<16;i++)
                        {
                            INPacket[i + 19] = ProcessorArray[i];
                        }
                        
                        //Processor Revision
                        INPacket[35] = ProcessorRev;
                        
                        //Primary Oscillator Mode
                        INPacket[36] = DEVCFG1bits.POSCMOD;
                        
                        //Current Primary Oscillator Source
                        INPacket[37] = DEVCFG1bits.FNOSC;
                        
                        //OSCCON
                        INPacket[38] = (char)OSCCON;
                        temp = OSCCON >> 8;
                        INPacket[39] = (char)temp;
                        temp = OSCCON >> 16;
                        INPacket[40] = (char)temp;
                        temp = OSCCON >> 24;
                        INPacket[41] = (char)temp;
                        
                        //Oscillator frequency
                        INPacket[42] = OSCFREQ;
                        
                        //PLL out divisor
                        INPacket[43] = OSCCONbits.PLLODIV;
                        
                        //PLL multiplier
                        INPacket[44] = OSCCONbits.PLLMULT;
                        
                        //PLL in divisor
                        INPacket[45] =  DEVCFG2bits.FPLLIDIV;
                        
                        GetRegData = false;
                    }
                    
                    if(GetSRAMData == true)
                    {
                        for(i=0;i<64;i++)
                        {
                            REN70V05_RD((SRAMposition + i));
                            INPacket[i] = mdata_70V05; 	
                        }
                        SRAMposition = SRAMposition + 64;
                    }
                    
                    if(MotionBoardPresent == true)
                    {
                        INPacket[0] = 0x99;
                        MotionBoardPresent = false;
                    }
                    //The USBGenWrite() function call "arms" the endpoint (and makes the handle indicate the endpoint is busy).
	                //Once armed, the data will be automatically sent to the host (in hardware by the SIE) the next time the 
	                //host polls the endpoint.  Once the data is successfully sent, the handle (in this case USBGenericInHandle) 
	                //will indicate the the endpoint is no longer busy.
                    
					USBGenericInHandle = USBTransferOnePacket(1,1,(uint8_t*)&INPacket,64);	
                }
        }
        //Clear the LEDs
        //LED9 = _OFF;
        //LED10 = _OFF;
        
        //Re-arm the OUT endpoint for the next packet:
	    //The USBGenRead() function call "arms" the endpoint (and makes it "busy").  If the endpoint is armed, the SIE will 
	    //automatically accept data from the host, if the host tries to send a packet of data to the endpoint.  Once a data 
	    //packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application
	    //can read the data which will be sitting in the buffer.
        USBGenericOutHandle = USBTransferOnePacket(1, 0, (uint8_t*)&OUTPacket, 64);
        //#define USBRxOnePacket(ep,data,len)      USBTransferOnePacket(ep,OUT_FROM_HOST,data,len)
    }
                
}

void MotionInterface(void)
{

    hchar = 10;
    vchar = 20;
    
    char MotionBuffer[18] = {"Motion Registers:"};   
    WriteString(hchar, vchar, MotionBuffer, black);
    
    hchar = 10;
    vchar = vchar + 30;
    
    char MotionBuffer1[11] = {"Control - "};
    WriteString(hchar, vchar, MotionBuffer1, black);
    
    REN70V05_RD(0x3ff);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], black);
    WriteChar(hchar, vchar, d_hex[0], black);

    hchar = 10;
    vchar = vchar + 30;

    char MotionBuffer2[10] = {"Status - "};
    WriteString(hchar, vchar, MotionBuffer2, black);
    
    REN70V05_RD(0x3fe);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], black);
    WriteChar(hchar, vchar, d_hex[0], black);
    
    hchar = 10;
    vchar = vchar + 30;

    char MotionBuffer3[10] = {"Info - "};
    WriteString(hchar, vchar, MotionBuffer3, black);
    
    REN70V05_RD(0x3fd);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], black);
    WriteChar(hchar, vchar, d_hex[0], black);
    
    hchar = 10;
    vchar = vchar + 30;

    char MotionBuffer4[10] = {"Position:"};
    WriteString(hchar, vchar, MotionBuffer4, blue);

    hchar = 10;
    vchar = vchar + 30;

    //Display the position
    REN70V05_RD(0x3f3);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], red);
    WriteChar(hchar, vchar, d_hex[0], red);

    REN70V05_RD(0x3f2);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], red);
    WriteChar(hchar, vchar, d_hex[0], red);

    REN70V05_RD(0x3f1);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], red);
    WriteChar(hchar, vchar, d_hex[0], red);

    REN70V05_RD(0x3f0);
    Binary2ASCIIHex(mdata_70V05);
    WriteChar(hchar, vchar, d_hex[1], red);
    WriteChar(hchar, vchar, d_hex[0], red);
    
}

void SetMotorSpeed(uint8_t MotorSpeed)
{
//    MotorSpeed = MotorSpeed * 24;
    REN70V05_WR(0x3f8, MotorSpeed);
}

void SystemReset(void)
{
    //unlock the system
    SYSKEY = 0x00000000;
    //write invalid key to force lock 
    SYSKEY = 0xAA996655;
    //write key1 to SYSKEY 
    SYSKEY = 0x556699AA;
    //write key2 to SYSKEY
    // OSCCON is now unlocked
    /* set SWRST bit to arm reset */ 
    RSWRSTSET = 1;
    /* read RSWRST register to trigger reset */ 
    dummy = RSWRST;
    /* prevent any unwanted code execution until reset occurs*/ 
    while(1);
}

void ShowSplashScreen(void)
{
    int i;

    //Clear the Screen
    HX8357B_CLRSCN(white);
        
    //Load Splash Image
    /****************************/
    HX8357B_CASET(0, 479);
    HX8357B_RASET(120, 170);
    HX8357B_RAMWR();

    //Data
    //RF3 = D/C 1=Data, 0=Command
    PORTFbits.RF3 = 1;        
    
    for(i=0;i<=23040; i++)
    {
        PMDIN = ~SplashImage[i*2];
        while(PMMODEbits.BUSY == 1);    
    }
    
    LongDelay(2);
    /****************************/

    //Clear the Screen
    HX8357B_CLRSCN(white);

    //Draw header
    fore_color = black;

    //Draw Header Bar
    back_color = 0x2D1B;
    HX8357B_Rect(0, 480, 0, 40, back_color);  
    
    hchar = 145;
    vchar = 7;
    
    //Display Header Text = "MainBrain 1.7"
    char MyString[14] = {"MainBrain 1.8"};
    
    WriteString(hchar, vchar, MyString, black);
    
    back_color = white;
    hchar = 10;
    vchar = 50; 
    
    //Display device information       
    //Processor
    hchar = 10;
    vchar = 50;
    WriteString(hchar, vchar, ProcessorArray, black);

    //SRAM size
    hchar = 10;
    vchar = vchar + 25;
    WriteString(hchar, vchar, SRAMsize, black);

    //Flash Size
    hchar = 10;
    vchar = vchar + 25;
    WriteString(hchar, vchar, FlashSize, black);

    //USB ver
    hchar = 10;
    vchar = vchar + 25;
    WriteString(hchar, vchar, USBver, black);
}

void Clock(int ClockData)
{       
    fore_color = 0x06cc;
    
    //Colon 1
    HX8357B_Rect(151, 163, 120, 130, black);  
    HX8357B_Rect(151, 163, 160, 170, black);  

    //Colon 2
    HX8357B_Rect(317, 329, 120, 130, black);  
    HX8357B_Rect(317, 329, 160, 170, black);  
    
    if(ClockData == 0)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, fore_color);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, 0xffff);    

    }

    if(ClockData == 1)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, 0xffff);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, 0xffff);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, 0xffff);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, 0xffff);    

    }

    if(ClockData == 2)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, 0xffff);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, fore_color);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, 0xffff);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 3)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, 0xffff);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 4)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, 0xffff);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, 0xffff);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 5)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, 0xffff);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 6)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, 0xffff);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, 0xffff);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, fore_color);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 7)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, 0xffff);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, 0xffff);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, 0xffff);    

    }

    if(ClockData == 8)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, fore_color);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, fore_color);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    

    }

    if(ClockData == 9)
    {
            //segment A
            HX8357B_Rect(hchar + 10, hchar + 50, vchar, vchar + 10, fore_color);    
            //segment B
            HX8357B_Rect(hchar + 50, hchar + 60, vchar, vchar + 50, fore_color);
            //Segment C
            HX8357B_Rect(hchar + 50, hchar + 60, vchar + 60, vchar + 110, fore_color);
            //Segment D
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 100, vchar + 110, 0xffff);    
            //Segment E
            HX8357B_Rect(hchar, hchar + 10, vchar + 60, vchar + 110, 0xffff);
            //Segment F
            HX8357B_Rect(hchar, hchar + 10, vchar, vchar + 50, fore_color);
            //Segment G
            HX8357B_Rect(hchar + 10, hchar + 50, vchar + 50, vchar + 60, fore_color);    
    }
}

void setTime(void)
{
    //Unlock the registers
    RTCCONbits.RTCWREN = 1;
    
    hchar = 10;
    vchar = 280;
    
    //24 to 12 hour conversion
    if(OUTPacket[1] > 12)
    {
        Binary2ASCIIBCD(OUTPacket[1] - 12);
    }
    else
    {
        Binary2ASCIIBCD(OUTPacket[1]);
    }
//    WriteChar(hchar, vchar, d1, 0x0);
//    WriteChar(hchar, vchar, d0, 0x0);
        
    RTCTIMEbits.HR10 = d1;
    RTCTIMEbits.HR01 = d0;
    
    hchar = hchar + 20;
    Binary2ASCIIBCD(OUTPacket[2]);
//    WriteChar(hchar, vchar, d1, 0x0);
//    WriteChar(hchar, vchar, d0, 0x0);
   
    RTCTIMEbits.MIN10 = d1;
    RTCTIMEbits.MIN01 = d0;

    hchar = hchar + 20;
    Binary2ASCIIBCD(OUTPacket[3]);
//    WriteChar(hchar, vchar, d1, 0x0);
//    WriteChar(hchar, vchar, d0, 0x0);
   
    
    RTCTIMEbits.SEC10 = d1;
    RTCTIMEbits.SEC01 = d0;    

    //Re-lock the registers
    RTCCONbits.RTCWREN = 0;
}


void USBCBSuspend(void)
{
	//Example power saving code.  Insert appropriate code here for the desired
	//application behavior.  If the microcontroller will be put to sleep, a
	//process similar to that shown below may be used:
	
	//ConfigureIOPinsForLowPower();
	//SaveStateOfAllInterruptEnableBits();
	//DisableAllInterruptEnableBits();
	//EnableOnlyTheInterruptsWhichWillBeUsedToWakeTheMicro();	//should enable at least USBActivityIF as a wake source
	//Sleep();
	//RestoreStateOfAllPreviouslySavedInterruptEnableBits();	//Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
	//RestoreIOPinsToNormal();									//Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.

	//Alternatively, the microcontorller may use clock switching to reduce current consumption.

	//IMPORTANT NOTE: Do not clear the USBActivityIF (ACTVIF) bit here.  This bit is 
	//cleared inside the usb_device.c file.  Clearing USBActivityIF here will cause 
	//things to not work as intended.	
	
}

/******************************************************************************
 * Function:        void USBCBWakeFromSuspend(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The host may put USB peripheral devices in low power
 *					suspend mode (by "sending" 3+ms of idle).  Once in suspend
 *					mode, the host may wake the device back up by sending non-
 *					idle state signalling.
 *					
 *					This call back is invoked when a wakeup from USB suspend 
 *					is detected.
 *
 * Note:            None
 *****************************************************************************/
void USBCBWakeFromSuspend(void)
{
	// If clock switching or other power savings measures were taken when
	// executing the USBCBSuspend() function, now would be a good time to
	// switch back to normal full power run mode conditions.  The host allows
	// 10+ milliseconds of wakeup time, after which the device must be 
	// fully back to normal, and capable of receiving and processing USB
	// packets.  In order to do this, the USB module must receive proper
	// clocking (IE: 48MHz clock must be available to SIE for full speed USB
	// operation).  
	// Make sure the selected oscillator settings are consistent with USB 
    // operation before returning from this function.

	//Switch clock back to main clock source necessary for USB operation
	//Previous clock source was something low frequency as set in the 
	//USBCBSuspend() function.
}

/********************************************************************
 * Function:        void USBCB_SOF_Handler(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The USB host sends out a SOF packet to full-speed
 *                  devices every 1 ms. This interrupt may be useful
 *                  for isochronous pipes. End designers should
 *                  implement callback routine as necessary.
 *
 * Note:            None
 *******************************************************************/
void USBCB_SOF_Handler(void)
{
    // No need to clear UIRbits.SOFIF to 0 here.
    // Callback caller is already doing that.
}

/*******************************************************************
 * Function:        void USBCBErrorHandler(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The purpose of this callback is mainly for
 *                  debugging during development. Check UEIR to see
 *                  which error causes the interrupt.
 *
 * Note:            None
 *******************************************************************/
void USBCBErrorHandler(void)
{
    // No need to clear UEIR to 0 here.
    // Callback caller is already doing that.

	// Typically, user firmware does not need to do anything special
	// if a USB error occurs.  For example, if the host sends an OUT
	// packet to your device, but the packet gets corrupted (ex:
	// because of a bad connection, or the user unplugs the
	// USB cable during the transmission) this will typically set
	// one or more USB error interrupt flags.  Nothing specific
	// needs to be done however, since the SIE will automatically
	// send a "NAK" packet to the host.  In response to this, the
	// host will normally retry to send the packet again, and no
	// data loss occurs.  The system will typically recover
	// automatically, without the need for application firmware
	// intervention.
	
	// Nevertheless, this callback function is provided, such as
	// for debugging purposes.
}


/*******************************************************************
 * Function:        void USBCBCheckOtherReq(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        When SETUP packets arrive from the host, some
 * 					firmware must process the request and respond
 *					appropriately to fulfill the request.  Some of
 *					the SETUP packets will be for standard
 *					USB "chapter 9" (as in, fulfilling chapter 9 of
 *					the official USB specifications) requests, while
 *					others may be specific to the USB device class
 *					that is being implemented.  For example, a HID
 *					class device needs to be able to respond to
 *					"GET REPORT" type of requests.  This
 *					is not a standard USB chapter 9 request, and 
 *					therefore not handled by usb_device.c.  Instead
 *					this request should be handled by class specific 
 *					firmware, such as that contained in usb_function_hid.c.
 *
 * Note:            None
 *****************************************************************************/
void USBCBCheckOtherReq(void)
{
    //Check for class specific requests, and if necessary, handle it.
    USBCheckVendorRequest();
}//end


/*******************************************************************
 * Function:        void USBCBStdSetDscHandler(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The USBCBStdSetDscHandler() callback function is
 *					called when a SETUP, bRequest: SET_DESCRIPTOR request
 *					arrives.  Typically SET_DESCRIPTOR requests are
 *					not used in most applications, and it is
 *					optional to support this type of request.
 *
 * Note:            None
 *****************************************************************************/
void USBCBStdSetDscHandler(void)
{
    // Must claim session ownership if supporting this request
}//end


/******************************************************************************
 * Function:        void USBCBInitEP(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is called when the device becomes
 *                  initialized, which occurs after the host sends a
 * 					SET_CONFIGURATION (wValue not = 0) request.  This 
 *					callback function should initialize the endpoints 
 *					for the device's usage according to the current 
 *					configuration.
 *
 * Note:            None
 *****************************************************************************/
void USBCBInitEP(void)
{
    //Enable the appplication data endpoint(s)
    USBEnableEndpoint(1,0x1d);
    //Prepare the OUT endpoint for the next packet that the host might try to send
    //USBGenericOutHandle = USBRxOnePacket(1,(uint8_t*)&OUTPacket,64);
    USBGenericOutHandle = USBTransferOnePacket(1, 0, (uint8_t*)&OUTPacket, 64);
}

/********************************************************************
 * Function:        void USBCBSendResume(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The USB specifications allow some types of USB
 * 					peripheral devices to wake up a host PC (such
 *					as if it is in a low power suspend to RAM state).
 *					This can be a very useful feature in some
 *					USB applications, such as an Infrared remote
 *					control	receiver.  If a user presses the "power"
 *					button on a remote control, it is nice that the
 *					IR receiver can detect this signalling, and then
 *					send a USB "command" to the PC to wake up.
 *					
 *					The USBCBSendResume() "callback" function is used
 *					to send this special USB signalling which wakes 
 *					up the PC.  This function may be called by
 *					application firmware to wake up the PC.  This
 *					function will only be able to wake up the host if
 *                  all of the below are true:
 *					
 *					1.  The USB driver used on the host PC supports
 *						the remote wakeup capability.
 *					2.  The USB configuration descriptor indicates
 *						the device is remote wakeup capable in the
 *						bmAttributes field.
 *					3.  The USB host PC is currently sleeping,
 *						and has previously sent your device a SET 
 *						FEATURE setup packet which "armed" the
 *						remote wakeup capability.   
 *
 *                  If the host has not armed the device to perform remote wakeup,
 *                  then this function will return without actually performing a
 *                  remote wakeup sequence.  This is the required behavior, 
 *                  as a USB device that has not been armed to perform remote 
 *                  wakeup must not drive remote wakeup signalling onto the bus;
 *                  doing so will cause USB compliance testing failure.
 *                  
 *					This callback should send a RESUME signal that
 *                  has the period of 1-15ms.
 *
 * Note:            This function does nothing and returns quickly, if the USB
 *                  bus and host are not in a suspended condition, or are 
 *                  otherwise not in a remote wakeup ready state.  Therefore, it
 *                  is safe to optionally call this function regularly, ex: 
 *                  anytime application stimulus occurs, as the function will
 *                  have no effect, until the bus really is in a state ready
 *                  to accept remote wakeup. 
 *
 *                  When this function executes, it may perform clock switching,
 *                  depending upon the application specific code in 
 *                  USBCBWakeFromSuspend().  This is needed, since the USB
 *                  bus will no longer be suspended by the time this function
 *                  returns.  Therefore, the USB module will need to be ready
 *                  to receive traffic from the host.
 *
 *                  The modifiable section in this routine may be changed
 *                  to meet the application needs. Current implementation
 *                  temporary blocks other functions from executing for a
 *                  period of ~3-15 ms depending on the core frequency.
 *
 *                  According to USB 2.0 specification section 7.1.7.7,
 *                  "The remote wakeup device must hold the resume signaling
 *                  for at least 1 ms but for no more than 15 ms."
 *                  The idea here is to use a delay counter loop, using a
 *                  common value that would work over a wide range of core
 *                  frequencies.
 *                  That value selected is 1800. See table below:
 *                  ==========================================================
 *                  Core Freq(MHz)      MIP         RESUME Signal Period (ms)
 *                  ==========================================================
 *                      48              12          1.05
 *                       4              1           12.6
 *                  ==========================================================
 *                  * These timing could be incorrect when using code
 *                    optimization or extended instruction mode,
 *                    or when having other interrupts enabled.
 *                    Make sure to verify using the MPLAB SIM's Stopwatch
 *                    and verify the actual signal on an oscilloscope.
 *******************************************************************/
void USBCBSendResume(void)
{
    static uint16_t delay_count;
    
    //First verify that the host has armed us to perform remote wakeup.
    //It does this by sending a SET_FEATURE request to enable remote wakeup,
    //usually just before the host goes to standby mode (note: it will only
    //send this SET_FEATURE request if the configuration descriptor declares
    //the device as remote wakeup capable, AND, if the feature is enabled
    //on the host (ex: on Windows based hosts, in the device manager 
    //properties page for the USB device, power management tab, the 
    //"Allow this device to bring the computer out of standby." checkbox 
    //should be checked).
    if(RemoteWakeup == true) 
    {
        //Verify that the USB bus is in fact suspended, before we send
        //remote wakeup signalling.
        if(USBBusIsSuspended == true)
        {
            IEC1CLR = 0x02000000;;
            
            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            U1PWRCbits.USUSPEND = 0; 
            USBBusIsSuspended = false;  //So we don't execute this code again, 
                                        //until a new suspend condition is detected.

            //Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
            //device must continuously see 5ms+ of idle on the bus, before it sends
            //remote wakeup signalling.  One way to be certain that this parameter
            //gets met, is to add a 2ms+ blocking delay here (2ms plus at 
            //least 3ms from bus idle to USBIsBusSuspended() == true, yeilds
            //5ms+ total delay since start of idle).
            delay_count = 3600U;        
            do
            {
                delay_count--;
            }while(delay_count);
            
            //Now drive the resume K-state signalling onto the USB bus.
            U1CONbits.RESUME = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            U1CONbits.RESUME = 0;       //Finished driving resume signalling

            IEC1SET = 0x02000000;;
        }
    }
}


/*******************************************************************
 * Function:        bool USER_USB_CALLBACK_EVENT_HANDLER(
 *                        int event, void *pdata, uint16_t size)
 *
 * PreCondition:    None
 *
 * Input:           int event - the type of event
 *                  void *pdata - pointer to the event data
 *                  uint16_t size - size of the event data
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is called from the USB stack to
 *                  notify a user application that a USB event
 *                  occured.  This callback is in interrupt context
 *                  when the USB_INTERRUPT option is selected.
 *
 * Note:            None
 *******************************************************************/
bool USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, uint16_t size)
{
    switch( event )
    {
        case EVENT_TRANSFER:
            //Add application specific callback task or callback function here if desired.
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED: 
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:
            //Add application specific callback task or callback function here if desired.
            //The EVENT_TRANSFER_TERMINATED event occurs when the host performs a CLEAR
            //FEATURE (endpoint halt) request on an application endpoint which was 
            //previously armed (UOWN was = 1).  Here would be a good place to:
            //1.  Determine which endpoint the transaction that just got terminated was 
            //      on, by checking the handle value in the *pdata.
            //2.  Re-arm the endpoint if desired (typically would be the case for OUT 
            //      endpoints).
            break;            
        default:
            break;
    }      
    return true; 
}

void DumpSRAM(void)
{
    //Clear the Screen
    HX8357B_CLRSCN(white);

    hchar = 10;
    vchar = 10;
    
    int i;
    char MyBuffer10[6] = {"SRAM:"};
    WriteString(hchar, vchar, MyBuffer10, black);
    
    hchar = 10;
    vchar = 35;
    
    //SRAM Block must be 0 - 127
    SRAM_Block = SRAM_Block * 64;
    
    for(i=1;i<=64;i++)
    {        
        REN70V05_RD(SRAM_Block);
        Binary2ASCIIHex(mdata_70V05);
        WriteChar(hchar, vchar, d_hex[1], 0x0);
        WriteChar(hchar, vchar, d_hex[0], 0x0);
        SRAM_Block++;
        hchar = hchar + 10;
        if(hchar > 430)
        {
            vchar = vchar + 20;
            hchar = 10;
        }
    }


}

void DumpMemory(void)
{
    //Clear the Screen
    HX8357B_CLRSCN(white);

    hchar = 10;
    vchar = 10;
    
    char MyBuffer11[8] = {"Memory:"};
    WriteString(hchar, vchar, MyBuffer11, red);
    
    hchar = hchar + 15;
    //display the address
        Binary2ASCIIHex(MemoryAddress);
        WriteChar(hchar, vchar, d_hex[7], 0x0);
        WriteChar(hchar, vchar, d_hex[6], 0x0);
        WriteChar(hchar, vchar, d_hex[5], 0x0);
        WriteChar(hchar, vchar, d_hex[4], 0x0);
        WriteChar(hchar, vchar, d_hex[3], 0x0);
        WriteChar(hchar, vchar, d_hex[2], 0x0);
        WriteChar(hchar, vchar, d_hex[1], 0x0);
        WriteChar(hchar, vchar, d_hex[0], 0x0);

    //My Pointer
    int i;
    
    vchar = 50;
    hchar = 30;
    
    //Pointer
    int *pTest;
    pTest = (int*)MemoryAddress;//MemoryAddress;//0xa0000220

    for(i=0;i<36;i++)
    {
        Binary2ASCIIHex(*pTest);
        WriteChar(hchar, vchar, d_hex[7], 0x0);
        WriteChar(hchar, vchar, d_hex[6], 0x0);
        WriteChar(hchar, vchar, d_hex[5], 0x0);
        WriteChar(hchar, vchar, d_hex[4], 0x0);
        WriteChar(hchar, vchar, d_hex[3], 0x0);
        WriteChar(hchar, vchar, d_hex[2], 0x0);
        WriteChar(hchar, vchar, d_hex[1], 0x0);
        WriteChar(hchar, vchar, d_hex[0], 0x0);
        
        pTest++;
                
        hchar = hchar + 10;
        
        if(hchar > 360)
        {
            vchar = vchar + 20;
            hchar = 30;
        }
    }


}