#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include "_mpusbapi.h"

#define EPSIZE 64               // endpoint packet size in bytes
#define USBTIMEOUT 200          // in milliseconds...
#define BOOT_EP_SIZE 64

typedef enum{
            READ_VERSION            = 0x00,
            READ_FLASH              = 0x01,
            WRITE_FLASH             = 0x02,
            ERASE_FLASH             = 0x03,
            READ_EEDATA             = 0x04,
            WRITE_EEDATA            = 0x05,
            READ_CONFIG             = 0x06,
            WRITE_CONFIG            = 0x07,
            UPDATE_LED              = 0x32,
			WINPIC_GETOKBUTTON 		= 0x50,
			WINPIC_GETDATAINBIT 	= 0x51,
			WINPIC_SETLEDS			= 0x52,
			WINPIC_SETVPP			= 0x53,
			WINPIC_SETVDD			= 0x54,
			WINPIC_SETCLOCKANDDATA	= 0x55,
			WINPIC_SETCLOCKENABLE	= 0x56,
			WINPIC_SETDATAENABLE	= 0x57,
			WINPIC_PULLMCLRTOGND	= 0x58,
			WINPIC_CONNECTTARGET	= 0x59,
		    CAR_DISPLAY_SET_TIME      =0xA0,
		    CAR_DISPLAY_SET_STRING    =0xA1,
		    RESET                           = 0xFF
        }CMD;


typedef struct
            {
                byte low;                   //Little-endian order
                byte high;
                byte upper;
            }ADR;
        
typedef union _BOOT_DATA_PACKET
{
    byte _byte[BOOT_EP_SIZE];  // For Byte Access
    struct
    {
        byte cmd;
        byte len;
        ADR pAdr;
        byte data[EPSIZE-5];
    };
    
    	// for USB_CLOCK_SET_TIME
	struct
	{
		unsigned :8;

        byte 	hours;
		byte	minutes;
		byte 	seconds;
		byte	ydaylow;
		byte	ydayhigh;
		byte    mday;
		byte    wday;
		byte	month;
		byte	yearlow;
		byte	yearhigh;
		byte    isdst;
	};


    // for CAR_DISPLAY_SET_STRING
    struct
    {
        unsigned :8;
		byte	length;
		byte	index;
		byte	start;
    };
} BOOT_DATA_PACKET;

//
// Global Vars
//
DWORD temp;
char vid_pid[]= "vid_04d8&pid_000b";    
char out_pipe[]= "\\MCHP_EP1";
char in_pipe[]= "\\MCHP_EP1";
HANDLE myOutPipe;
HANDLE myInPipe;
tm theLocalTime;
tm myUSBTime;
tm myLastTime;
int open=0;
byte current_command;                   // default value...
BOOLEAN bQuit=false;
char selection;
DWORD maxn;
DWORD res;
DWORD nb;
BOOT_DATA_PACKET datapacket;
BOOT_DATA_PACKET indatapacket;

void GetSummary(void)
{
    HANDLE tempPipe = INVALID_HANDLE_VALUE;
    DWORD count = 0;
    DWORD max_count;

    max_count = MPUSBGetDeviceCount(vid_pid);

    printf("\r\n%d device(s) with %s currently attached\r\n",max_count,vid_pid);

    // Note:
    // The total number of devices using the generic driver could be
    // bigger than max_count. They could have different vid & pid numbers.
    // This means if max_count is 2, the valid instance index do not
    // necessary have to be '0' and '1'.
    //
    // Below is a sample code for searching for all valid instance indexes.
    // MAX_NUM_MPUSB_DEV is defined in _mpusbapi.h
    
    count = 0;
    for(int i = 0; i < MAX_NUM_MPUSB_DEV; i++)
    {
        tempPipe = MPUSBOpen(i,vid_pid,NULL,MP_READ,0);
        if(tempPipe != INVALID_HANDLE_VALUE)
        {
            printf("Instance Index # %d\r\n",i);
            MPUSBClose(tempPipe);
            count++;
        }
        if(count == max_count) break;
    }//end for
    printf("\r\n");
}//end GetSummary

void
hex_print(byte* data, int length)
{
	int ptr = 0;
	for(;ptr < length;ptr++)
	{
		printf("0x%02x ",(unsigned char)*(data+ptr));
	}
}

void showPacket(byte *pp, int total)
{
 int u, v;
     for(u=0; u<total; u++)
     {
     printf(" "); 
     hex_print(pp, 1); 
     pp++;
     if((u & 0x0007)==0x0007){
                pp-=8;
                printf("  ");
                for(v=0; v<8; v++)printf("%c",*pp++);
                printf("\n");
            }
     }  
}

void updateInfo(BOOT_DATA_PACKET* datap)
{
}

void showMode(int iclockmode)
{
    printf("Undefined");
}

void showInfo(BOOT_DATA_PACKET* datap)
{
    //
    //
    updateInfo(datap);
    printf("Car Scrolling Display Information\n");
    //
    printf("\n");
    //
}

int updateTime(void)
{

        int i;
        time_t t;
        const time_t *ltm;
        t=time(NULL);
        ltm=&t;
        theLocalTime=*localtime(ltm);
        i=theLocalTime.tm_sec;
        while(i==theLocalTime.tm_sec){
            t=time(NULL);
            ltm=&t;
            theLocalTime=*localtime(ltm);
        }
//        printf("Hours: %d Minutes: %d Seconds: %d\r\n",theLocalTime->tm_hour, theLocalTime->tm_min, theLocalTime->tm_sec);
        return 0;
}

void showTime(void)
{
        updateTime();
        printf("Time is: ");
        printf("%s", asctime(&theLocalTime));
}

int showHelpScreen(void)
{
 int i;
               
        printf("Usage      : cardisplay.exe <option> <option> .... <option>\n");
        printf(" -r        : reset the Car Scrolling Display and restore defaults, eg. cardisplay -r\n");
}

int openDevice(void)
{
 if(open==0){
                maxn = MPUSBGetDeviceCount(vid_pid);
                myOutPipe = INVALID_HANDLE_VALUE;
                myOutPipe = MPUSBOpen(0,vid_pid,out_pipe,MP_WRITE,0);
                myInPipe  = INVALID_HANDLE_VALUE;
                myInPipe  = MPUSBOpen(0,vid_pid,in_pipe,MP_READ,0);
                //printf("USB Device Open...... ");
                if((myInPipe!=INVALID_HANDLE_VALUE)&&(myOutPipe!=INVALID_HANDLE_VALUE))
                {
                 //printf("Ok.\n");
                 open=1;
                 }
                 else
                 {
                 //printf("Error.\n");
                 open=0;
                 }
                }
                //else printf("Device is already open.\n");
   return open;
}

void printFailedToOpenDeviceMessage(void)
{
printf("Failed to Open Device. Is the Car Scrolling Display connected? If so, try unplugging and reconnecting it.\n");
}

int stringlength(char *ptr)
{
 int i;
    i=0;
    while((*ptr++)!=0)i++;
       return i;      
}

int copystring(char *ptrs, byte* ptrd)
{
    while((*ptrs)!=0)
        {
           *ptrd++=(byte)*ptrs++;
        }
}

int main(int argc, char *argv[])
{
    int i, j, k, m;
    unsigned int myargument;
    byte *ptrd;
    char *ptrs;
    open=0;
    printf("Car Scrolling Display Interface. MG Sep 2008. Ver: 1.0 ");
    temp=MPUSBGetDLLVersion();
    printf("MPUSBAPI Version: %d.%d",HIWORD(temp),LOWORD(temp));
    //printf("Size of datapacket......");
    if(sizeof(datapacket)==EPSIZE)printf("...Ok.\n"); else {
                                                    printf("...DataPacket Size Error.\n"); 
                                                    printf("Size is: %d.\nShould be: %d.\n", sizeof(datapacket), EPSIZE);
                                                  return -1; }
                                                        
    for(i=0; i<EPSIZE;i++){ datapacket._byte[i]=0; indatapacket._byte[i]=0; }
    myOutPipe= myInPipe = INVALID_HANDLE_VALUE;
 
    if(argc==1)
    {
           //  synchronise command if no arguments
                    i=openDevice();
                    if(i==0)
                    {
                        printFailedToOpenDeviceMessage();
                    } else
                    if(i==1)
                    {
                        showTime();
                        
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        printf("Verifying...");
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                    }
                 }
                 else   
                 {
                 printf("Device is not open!\n");
                 }                                        
    }
    else
    if(argc>1)
    { 
        m=1;
        while(m<argc)
        {
        if(argv[m][0]=='-')
            {
                if(argv[m][1]=='s')
                {
                    //  set string command
                    i=openDevice();
                    if(i==0)
                    {
                        printFailedToOpenDeviceMessage();
                    } else
                    if(i==1)
                    {
                        ptrs=(&argv[m][3]);
                        j=stringlength(ptrs);
                        datapacket.length=j;
                        datapacket.index=0;
                        datapacket.cmd=CAR_DISPLAY_SET_STRING;
                        ptrd=&datapacket.start;
                        copystring(ptrs, ptrd);
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        printf("Verifying...");
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                    }
                 }
                 else   
                 {
                        printf("Device is not open!\n");
                 }                              
                }          
                else
                if(argv[m][1]=='m')
                {
                    //  set the mode
                    myargument=0;
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the operating mode to: %d ...", (int)myargument);
                        //
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");
              
                } else
                if(argv[m][1]=='i')
                {
                    i=openDevice();
                    if(i==0)
                    {
                        printFailedToOpenDeviceMessage();    
                    } else
                    if(i==1)
                    {
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                    } else
                    {
                        printf("Device is not open!\n");
                    }  
                 
                } else
                if(argv[m][1]=='l')
                {
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        j=(int)(myargument);
                        printf("Setting the low voltage trip point to: %d mV ...",j);
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");
                } else
                if(argv[m][1]=='p')
                {
                    // set the PWM Duty cycle for low power mode
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the low power PWM duty to: %d %c ...", (myargument), '%');
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");      
                } else
                if(argv[m][1]=='t')
                {
                    // set the back lighting timeout period
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the Backlight timeout period to: %d second(s) ...", (int)(myargument));
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");                     
                } else
                if(argv[m][1]=='z')
                {
                    // set the scrolling mode
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the scrolling mode to: %d ...", (int)(myargument));
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");                     
                } else
                if(argv[m][1]=='a')
                {
                    // set the auto backlight mode
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the automatic backlight mode to: %d ...", (int)(myargument));
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");                     
                } else
                if(argv[m][1]=='y')
                {
                    // set the twenty four hour time mode
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the twenty four hour time mode to: %d ...", (int)(myargument));
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");                     
                } else
                if(argv[m][1]=='d')
                {
                    // set the display timeout period
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the display timeout period to: %d second(s) ...", (int)(myargument));
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");                     
                }
                else
                if(argv[m][1]=='r')
                {
                    i=openDevice();
                    if(i==0)
                    {
                        printFailedToOpenDeviceMessage();
                        
                    } else
                    if(i==1)
                    {
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                    } else
                    {
                        printf("Device is not open!\n");
                    }  
                } else
                if(argv[m][1]=='c')
                {
                    //  set the reference sense resistor in mOhms
                    myargument=0;
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the reference sense resistor value to: %d mOhms...", (int)myargument);
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");
              
                } else
                if(argv[m][1]=='v')
                {
                    //  set the reference voltage in mV
                    myargument=0;
                    if(argv[m][2]==':')
                    {
                        myargument=(int)atof(&argv[m][3]);
                        i=openDevice();
                        if(i==0)
                        {
                        printFailedToOpenDeviceMessage();
                        } else
                        if(i==1)
                        {
                        printf("Setting the reference voltage to: %d mV...", (int)myargument);
                        res=MPUSBWrite(myOutPipe,&datapacket,EPSIZE,&nb,USBTIMEOUT);
                        if(res==MPUSB_SUCCESS)
                        {
                        res=MPUSBRead(myInPipe, &indatapacket, 64, &nb, 500);
                        if(res==MPUSB_SUCCESS)
                        {
                        printf("Ok.\n");
                        if(m+1==argc)showInfo(&indatapacket);
                        }
                        else
                        {
                        printf("Error.\n");
                        }
                        } else printf("Error.\n");
                        
                        } else
                        {
                        printf("Device is not open!\n");
                        }
                    } else printf("Syntax error. Please provide an argument.\n");
              
                } else
                {
                    printf("Try one of the following options instead:\n");
                    showHelpScreen();
            }
            } else
            {
                printf("Syntax Error. Try one of the following options:\n");
                showHelpScreen();
            }
            m++;
        }  
}
    printf("Exiting...\n");
    // Always check to close all handles before exiting!
    if (myOutPipe != INVALID_HANDLE_VALUE)MPUSBClose(myOutPipe);
    if (myInPipe  != INVALID_HANDLE_VALUE)MPUSBClose(myInPipe);
    myOutPipe = myInPipe = INVALID_HANDLE_VALUE;
    return 0;
}//end main

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

