//---------------------------------------------------------------------------
//
//  Module: DVM
//
//  Purpose:
//
//---------------------------------------------------------------------------

#include  <windows.h>
#include  <stdio.h>
#include  <string.h>

char     gszTTYClass[] = "DVMWndClass" ;
char     gszAppName[] = "PIC16C71 : DVM" ;

#define MAXBLOCK        80

BOOL  InitApplication( HANDLE ) ;
HWND  InitInstance( HANDLE, int ) ;
// function prototypes (public)
long FAR PASCAL __export DVMWndProc( HWND, UINT, WPARAM, LPARAM ) ;
void readCommandLineOptions(LPSTR lpszCmdLine);
BOOL GetDataFromPIC(void);

extern LRESULT  CreateTTYInfo( HWND ) ;
extern BOOL  DestroyTTYInfo( HWND ) ;
extern int  ReadCommBlock( HWND, LPSTR, int ) ;
extern BOOL  WriteCommByte( HWND, BYTE ) ;
extern BOOL  OpenConnection( HWND ) ;
extern BOOL  SetupConnection( HWND ) ;
extern BOOL  CloseConnection( HWND ) ;
extern void delayMilliSeconds(DWORD mSec);


HWND  hwndMain ;
HANDLE	hinstance;
WORD	wBaudRate, wCommPortID;
float	fVolts[4], fScale = 5.0;
WORD	wChannels = 1;		// init #of A/D channels to 1
WORD	nChannel = 0;		// Init channel sel to A/D Channel 0



//---------------------------------------------------------------------------
//  int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
//                      LPSTR lpszCmdLine, int nCmdShow )
//
//  Description:
//     This is the main window loop!
//
//  Parameters:
//     As documented for all WinMain() functions.
//
//---------------------------------------------------------------------------

int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow )
{
   MSG   msg ;
  WNDCLASS  	wndIceClass ;


  hinstance = hInstance ;
   if (!hPrevInstance) {
	    // Go init this application.
	    // Define the window class for this application.
	    wndIceClass.style         = CS_HREDRAW | CS_VREDRAW;
	    wndIceClass.lpfnWndProc   = DVMWndProc;
	    wndIceClass.cbClsExtra    = 0;
	    wndIceClass.cbWndExtra    = sizeof(WORD);
	    wndIceClass.hInstance     = hInstance;
	    wndIceClass.hIcon         = NULL;
	    wndIceClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	    wndIceClass.hbrBackground = GetStockObject(WHITE_BRUSH);
	    wndIceClass.lpszMenuName  = NULL;
	    wndIceClass.lpszClassName = gszTTYClass;

	    // Register the class
	    if( !RegisterClass(&wndIceClass) )
				      return( FALSE );
   }
   else
   	return (FALSE);

	wBaudRate = CBR_1200;
	wCommPortID = 1;
    if(lpszCmdLine[0] != '\0')
		readCommandLineOptions(lpszCmdLine) ;

   if (NULL == (hwndMain = InitInstance( hinstance, nCmdShow )))
      return ( FALSE ) ;

   while (GetMessage( &msg, NULL, 0, 0 ))
   {
	 TranslateMessage( &msg ) ;
         DispatchMessage( &msg ) ;
   }
   return ( (int) msg.wParam ) ;

} // end of WinMain()

//---------------------------------------------------------------------------
//  HWND InitInstance( HANDLE hInstance, int nCmdShow )
//
//  Description:
//     Initializes instance specific information.
//
//  Parameters:
//     HANDLE hInstance
//        Handle to instance
//
//     int nCmdShow
//        How do we show the window?
//
//---------------------------------------------------------------------------

HWND InitInstance( HANDLE hInstance, int nCmdShow )
{
   HWND  hwndMain ;
   short	xStart, yStart, xClient, yClient;
   HDC	hDc;
   TEXTMETRIC tm;

   // Get The Desired Size window using TextMetrics & DISPLAY Driver
	hDc = CreateIC("DISPLAY", NULL, NULL, NULL);
	GetTextMetrics(hDc, &tm);
	DeleteDC(hDc);

	xClient = 2 * GetSystemMetrics(SM_CXDLGFRAME) + 18*tm.tmAveCharWidth;  // WIDTH
	xStart =  GetSystemMetrics(SM_CXSCREEN) - xClient;

	yClient = 2 * GetSystemMetrics(SM_CYDLGFRAME) + (wChannels+1)*tm.tmHeight;  // #of Lines
	yStart =  GetSystemMetrics(SM_CYSCREEN) - yClient;


   // create the window
   hwndMain = CreateWindow( gszTTYClass, gszAppName,
			   WS_POPUP | WS_DLGFRAME | WS_SYSMENU | WS_CAPTION,
                           xStart, yStart,
                           xClient, yClient,
                           NULL, NULL, hInstance, NULL ) ;

   if (NULL == hwndMain)
      return ( NULL ) ;

   // Create A Timer Interrupt (200 mS) For Display Of Data From RS-232 Port
   if(!SetTimer(hwndMain, 1, 200, NULL)) {
	MessageBox(hwndMain, "Timers Not Available, Close One Or More Applications",
					gszAppName, MB_ICONEXCLAMATION | MB_OK);
	return (FALSE);  
   } 

   ShowWindow( hwndMain, SW_SHOWNOACTIVATE ) ;
   UpdateWindow( hwndMain ) ;

   return ( hwndMain ) ;

} // end of InitInstance()

//---------------------------------------------------------------------------
//  LRESULT FAR PASCAL DVMWndProc( HWND hWnd, UINT uMsg,
//                                 WPARAM wParam, LPARAM lParam )
//
//  Description:
//     This is the TTY Window Proc.  This handles ALL messages
//     to the tty window.
//
//  Parameters:
//     As documented for Window procedures.
//
//---------------------------------------------------------------------------

long FAR PASCAL DVMWndProc( HWND hWnd, UINT uMsg,
                               WPARAM wParam, LPARAM lParam )
{
	LRESULT	lResult;
	static	RECT	rect;
	HDC	hDc;
	PAINTSTRUCT	ps;
	char	szBuffer[128], szBufTemp[32];
        int	i;

   switch (uMsg)
   {
      case WM_CREATE:
	    hwndMain = hWnd;
	    lResult = CreateTTYInfo( hwndMain );
	    if(lResult) {
		   if (!OpenConnection( hwndMain )) {
			    MessageBeep(MB_ICONHAND); MessageBeep(MB_ICONHAND);
			    MessageBox( hwndMain, "Serial Connection Failed.", gszAppName, MB_ICONHAND) ;
		            return (FALSE);
		   }
		   else {
			    WriteCommByte(hwndMain, nChannel);  // Select Channel 0 at first
                   }
            }           
	    return (lResult);

      case WM_TIMER :
      		GetDataFromPIC();   // Send Start Command to PIC16C71 & Get Data via RS-232
		InvalidateRect(hwndMain, NULL, FALSE);
		UpdateWindow( hwndMain ) ;
		break;

      case WM_QUERYOPEN :
		return 0L;

      case WM_PAINT:
	 hDc = BeginPaint(hWnd, &ps);
         szBuffer[0] = '\0';
	 for(i = 0; i < wChannels; i++) {
         	if(fScale)
			sprintf(szBufTemp, "Chan#%d ->  %2.2f Volts\n", i, fVolts[i]);
		else
			sprintf(szBufTemp, "Chan#%d ->  %d\n", i, (unsigned)fVolts[i]);

                lstrcat(szBuffer, szBufTemp);
         }
         GetClientRect(hWnd, &rect);
	 DrawText(hDc, szBuffer, -1, &rect, DT_CENTER | DT_NOCLIP);
	 EndPaint(hWnd, &ps);
	 break ;

      case WM_DESTROY:
         DestroyTTYInfo( hWnd ) ;
         PostQuitMessage( 0 ) ;
         break ;

      case WM_CLOSE:
	    DestroyWindow(hWnd);
	    break ;

         // fall through

      default:
         return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
   }
   return 0L ;

} // end of DVMWndProc()


// Set COM port # (1, 2 or 3)
// Very crude way of reading command line
// Parse the command line if time permits
// -p followed by COMM Port Number

void readCommandLineOptions(LPSTR lpszCmdLine)
{
    unsigned int 	i = 1 ;
    char	szPortString[100] ;
    char	*ptr ;

	lstrcpy((LPSTR)szPortString, lpszCmdLine) ;
	ptr = strstr(szPortString, "-p") ;
	if(!ptr)
		ptr = strstr(szPortString, "-P") ;
	if(ptr) {
		ptr += 2 ;  // -P
		sscanf(ptr, " %d", &i) ;
	}
	switch(i) {
		case 1 :
		case 2 :
		case 3 :
		case 4 :
			wCommPortID = i ;
                        break ;
		default :
			wCommPortID = 1 ;
			break ;
	}

        // check for default baud rate
	ptr = strstr(szPortString, "-b") ;
	if(!ptr)
		ptr = strstr(szPortString, "-B") ;
	if(ptr) {
		ptr += 2 ;  // -P
		sscanf(ptr, " %d", &i) ;
		switch(i) {
			case 9600 :
				wBaudRate = CBR_9600;
				break;
			case 19200:
				wBaudRate = CBR_19200;
				break;
			case 38400:
				wBaudRate = CBR_38400;
				break;
			case 57600:
				wBaudRate = CBR_56000;
				break;
			case 128000:
				wBaudRate = CBR_128000;
				break;
			case 256000:
				wBaudRate = CBR_256000;
				break;

			default :
				wBaudRate = CBR_1200 ;
		}        	
	}
	else
		wBaudRate = CBR_1200;


	ptr = strstr(szPortString, "-c") ;
	if(!ptr)
		ptr = strstr(szPortString, "-C") ;
	if(ptr) {
		ptr += 2 ;  // -C
		sscanf(ptr, " %d", &wChannels) ;
		if(!wChannels)
			wChannels = 1;
		else if(wChannels > 4)
			wChannels = 4;
	}
	else
        	wChannels = 1;


	ptr = strstr(szPortString, "-s") ;
	if(!ptr)
		ptr = strstr(szPortString, "-S") ;
	if(ptr) {
		ptr += 2 ;  // -S
		sscanf(ptr, " %f", &fScale) ;
	}
	else
        	fScale = 5.0;

}


//******************************************************************************************
//				Send Command & Get Data From PIC16C71
//******************************************************************************************

BOOL GetDataFromPIC(void)
{
   BYTE       abIn[ MAXBLOCK + 1] ;
   int	      i, nLength;
   static unsigned int wPICResponse = 0;

	if (nLength = ReadCommBlock( hwndMain, (LPSTR) abIn, 1)) {
		wPICResponse = 0;

                if(fScale)
			fVolts[nChannel] = (float)abIn[0]*fScale/256.0 ;
		else
			fVolts[nChannel] = (float)abIn[0]
			;
		nChannel++;
		if(nChannel > (wChannels-1))
			    nChannel = 0;
                WriteCommByte(hwndMain, nChannel);  // Select Next Channel
	}
	else if(wPICResponse++ > 25) {
		wPICResponse = 0;
		nChannel = 0;
		WriteCommByte(hwndMain, nChannel);  // Try Channel 0 again
        }


   return (TRUE);
}

