// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

/* alle Funktionen liefern bei Erfolg 0, im Fehlerfalle einen Wert ungleich 0 */


/* vom USB-Treiber verwendeter Steuercode */
#define COMPULAB_IOCTL 4

int port;
int value;
int channel;
unsigned char out;
unsigned char out_array[8];
int error;


/* Handle auf GeräteTreiber */
HANDLE  hgDriver = INVALID_HANDLE_VALUE; 

/***
 * USB-Treiber öffnen
 ***/
BOOL USBOpenDriver()
{
  
  /* Treiber bereits geöffnet? */	
  if(hgDriver != INVALID_HANDLE_VALUE)
	/* dann zur Fehlerbehandlung erneut öffnen */
    USBCloseDriver();
	
  /* Gerätetreiber mit passenden Dateinamen öffnen */
  hgDriver = CreateFile("\\\\.\\CompuLABusb_0",	GENERIC_WRITE || GENERIC_READ, 
						 FILE_SHARE_WRITE || FILE_SHARE_READ,	NULL, OPEN_EXISTING, 0, 0); 

  return hgDriver == INVALID_HANDLE_VALUE;
}

/***
 * USB-Treiber schließen 
 ***/
BOOL USBCloseDriver()
{
  BOOL ret=CloseHandle(hgDriver);
  hgDriver = INVALID_HANDLE_VALUE;

  return !ret;
}


/***
 * Port setzen              
 *							
 * Port:  zu setzender Port (0,1)  
 * Value: auszugebender Wert 
 ***/
BOOL USBWritePort(unsigned char Port, unsigned char Value)
{
  DWORD		command, inDummy, count;
  
  /* Befehl für Treiber berechnen: */
  /* 21: Port setzen */
  command = (Value<<16) + Port * 256 + 21;   
  inDummy = 0;

  /* Ausgabe */
  return !DeviceIoControl(hgDriver, COMPULAB_IOCTL, &command, sizeof(command), 
							&inDummy, sizeof(inDummy), &count, NULL); 
  
}

/***
 * Port auslesen            
 *							
 * Port:  zu lesender Port (0,1)  
 * Value: nimmt den Wert auf
 ***/
BOOL USBReadPort(unsigned char Port, unsigned char *Value)
{
 DWORD	command, count;
 BOOL ok;
 unsigned char	inBytes[2];
 
 /* Befehl für den Treiber berechnen */
 /* 20: Port auslesen */
 command = 20 + Port*256; 
 
 ok = DeviceIoControl(	hgDriver, COMPULAB_IOCTL, &command, sizeof(command), 
							&inBytes, sizeof(inBytes), &count, NULL); 
 if ( ok )
   *Value=(unsigned char)inBytes[1];

 return !ok;
}


int read_analog_channel(int channel)
{
	int error;
	error = 0;
    if(USBWritePort(0,channel) != 0) error = 260;   // set P0 to channel
    else if(USBWritePort(1,0x0E) != 0) error = 260; // set bus address to 6 and enable=high
    else if(USBWritePort(1,0x06) != 0) error = 260; // set bus address to 6 and enable=low
    else if(USBWritePort(1,0x0E) != 0) error = 260; // set bus address to 6 and enable=high
	else if(USBWritePort(0,0xFF) != 0) error = 260; // set P0 to FF (necessary for reading)
    else if(USBWritePort(1,0x0F) != 0) error = 260; // set bus address to 5 (analog input) and enable=high
    else if(USBWritePort(1,0x07) != 0) error = 260; // set bus address and enable=low
    else if(USBReadPort(0,&out) != 0) error = 260;  // read P0
    else if(USBWritePort(1,0x0F) != 0) error = 260; // set bus address and enable=high
	if (error == 0) return out; 
	else return error;
}

int main(int argc, char* argv[])
{
	// functions:
	// 1. output (port 0-4): camcontrol.exe write <port> <value>
	// 2. read digital (port 5): camcontrol.exe read_digital
	// 3. read analog (port 6/7): camcontrol.exe read_analog <channel>
	// 4. read all analog channels: camcontrol.exe read_all_analog
	// output:
	// 0: ok (plus output value(s) before, if read)
	// 256: parameters missing
	// 257: weder write noch read oder arg number falsch
	// 258: USB driver open error
	// 259: data range invalid
	// 260: read/write error
	// 261: USB port close error

	error = 0;

	if (argc < 2) error = 256; // no parameters
	else
	{
		// WRITE DIGITAL OUTPUT -> output = one line with error code (0 if ok)
		if ((strcmp(argv[1],"write")==0) && (argc == 4))
		{
			port = atoi(argv[2]);
			value = atoi(argv[3]);
			if ((port<0)||(port>4)||(value<0)||(value>255)) // output: 0,1,2,3,4
			     error = 259;//data range invalid
			else
			{
				if (USBOpenDriver() == 0)
			    {
				    if(USBWritePort(0,value) != 0) error = 260;            // set output value
				    else if(USBWritePort(1,port | 0x08) != 0) error = 260; // set bus address and enable=high
				    else if(USBWritePort(1,port & 0x07) != 0) error = 260; // set bus address and enable=low
				    else if(USBWritePort(1,port | 0x08) != 0) error = 260; // set bus address and enable=high
					if(USBCloseDriver() != 0) error = 261;
				}
				else
			    {
				     error = 258;//USB driver open error
				}
			}
		}
		// READ DIGITAL INPUT (channel 5)-> output = line with result plus 0, or one line > 255
		else if ((strcmp(argv[1],"read_digital")==0) && (argc == 2)) 
		{
			if (USBOpenDriver() == 0)
		    {
			    if(USBWritePort(0,0xFF) != 0) error = 260;      // set P0 to FF (necessary for reading)
			    else if(USBWritePort(1,0x0D) != 0) error = 260; // set bus address to 5 (digital input) and enable=high
			    else if(USBWritePort(1,0x05) != 0) error = 260; // set bus address and enable=low
			    else if(USBReadPort(0,&out) != 0) error = 260;  // read P0
			    else if(USBWritePort(1,0x0D) != 0) error = 260; // set bus address and enable=high
				if(USBCloseDriver() != 0) error = 261;
			    if (error == 0) printf("%d\n",out);
			}
			else
		    {
			     error = 258;//USB driver open error
			}
		}
		// READ ONE ANALOG INPUT -> output = line with result plus 0, or one line > 255
		else if ((strcmp(argv[1],"read_analog")==0) && (argc == 3)) 
		// 3rd argument is analog channel to be read out
		{
			channel = atoi(argv[2]);
			if ((channel<0)||(channel>7)) // analog channels 0-7
			     error = 259;//port (channel) range invalid
			else
			{
				if (USBOpenDriver() == 0)
			    {
					out = read_analog_channel(channel);
					if(USBCloseDriver() != 0) error = 261;
					if(out > 255) error = out; 					
				    if (error == 0) printf("%d\n",out);
				}
				else
			    {
				     error = 258;//USB driver open error
				}
			}
		}
		// READ ALL ANALOG INPUTS -> output = 8 lines plus 0, or one line > 255
		else if ((strcmp(argv[1],"read_all_analog")==0) && (argc == 2)) 
		{
			if (USBOpenDriver() == 0)
		    {
				for (channel=0;channel<=7;channel++)
				{
					out_array[channel] = read_analog_channel(channel);
					if (out_array[channel] > 255) error = out_array[channel];
				}
				if(USBCloseDriver() != 0) error = 261;
			    if (error == 0)
				{
					for (channel=0;channel<=7;channel++)
					{
						printf("%d\n",out_array[channel]);
					}
				}
			}
			else
		    {
			     error = 258;//USB driver open error
			}
		}
		else
		{
			 error = 257;//weder write noch read oder arg number falsch
		}
	}
	printf ("%d\n",error);
	return 0;
}
