/*****************************************************************************
 * FILE:	digital_in.c
 * BASED ON sample program from ICS ADVENT PCI-DIO96 Documentation
 * Description:	This componenet will read the channel based on the
 *		group, port and channel.
 * NOTE:	The control byte written is different for testing
 *		purposes, REMEMBER TO CHANGE IT when delivering the
 *		product. - Kenny
 ****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "digital_in.h"
#include <asm/io.h>

#ifdef __GLIBC__
	#include <sys/perm.h>
#endif

#define PORT_FILE "/dev/port"

unsigned long BASEADDRESS = 0;


int readDigitalChannel(int group, int port, unsigned char channel)
{
static int fd = -1;

enum GROUPCHOICE {group0, group1, group2, group3}; 
enum PORTCHOICE {portA, portB, portC};

	unsigned int PortA;
	unsigned int PortB;
	unsigned int PortC;
	unsigned int PortControl;

	unsigned int readPort;

	unsigned char b, res;

    	if (fd < 0)
		fd = open(PORT_FILE, O_RDONLY);
	if (fd < 0) {
		printf("digital_in: Digital Channel: error opening file\n");
		exit(1);
	}



	switch (group) {
		case group0:
			PortA = BASEADDRESS;
			break;
		case group1:
			PortA = BASEADDRESS + 4;
			break;
		case group2:
			PortA = BASEADDRESS + 8;
			break;
		case group3:
			PortA = BASEADDRESS + 12;
			break;
	}

	PortB = PortA + 1;
	PortC = PortA + 2;
	PortControl = PortA + 3;

	switch (port) {
		case portA:
			readPort = PortA;
			break;
		case portB:
			readPort = PortB;
			break;
		case portC:
			readPort = PortC;
			break;
	}	


//	printf("digital_in: Base Adress is %X in hex.\n", PortA);

//	printf("digital_in: readPort: %X\n", readPort);
	b = 0;
	lseek(fd, readPort, SEEK_SET);
	if (read(fd, &b, 1) < 0) {
		//printf("ERROR*** reading byte...\n");
		return -1;
	}

	
	//printf("read sucessfully.\n");
	//printf("digital_in: byte read: %X\n", b);
	//printf("digital_in: channel: %X\n", channel);
	//printf("digital_in: res: %X\n", (b&channel));
  
	if ((b & channel) ==  channel) {  
		return 1;
	}
	else {
		return 0;
	}

} 



bool initializePort(int group)
{

enum GROUPCHOICE {group0, group1, group2, group3}; 
enum PORTCHOICE {portA, portB, portC};


	unsigned int PortA;
	unsigned int PortB;
	unsigned int PortC;
	unsigned int PortControl;
	unsigned char b;
	static int fd = -1;
	char strbase[32];
	int size;

	switch (group) {
		case group0:
			PortA = BASEADDRESS;
			break;
		case group1:
			PortA = BASEADDRESS + 4;
			break;
		case group2:
			PortA = BASEADDRESS + 8;
			break;
		case group3:
			PortA = BASEADDRESS + 12;
			break;
	}

	PortB = PortA + 1;
	PortC = PortA + 2;
	PortControl = PortA + 3;


	if (fd < 0)
		fd = open(PORT_FILE, O_RDWR);
	if (fd < 0) {
		printf("error opening IOPort file\n");
		return false;
	}

	b = 0x80;
	lseek(fd, PortControl, SEEK_SET);
	if (write(fd, &b, 1) < 0) { 
		return false;
	}
	b = 0x00;
	lseek(fd, PortA, SEEK_SET);
	if (write(fd, &b, 1) < 0) { 
		return false;
	}
	lseek(fd, PortB, SEEK_SET);
	if (write(fd, &b, 1) < 0) { 
		return false;
	}
	lseek(fd, PortC, SEEK_SET);
	if (write(fd, &b, 1) < 0) { 
		return false;
	}
	
	usleep(500);
	close(fd);
	return false;

}



bool writeControlPort(int group)
{

enum GROUPCHOICE {group0, group1, group2, group3}; 
enum PORTCHOICE {portA, portB, portC};


	unsigned int PortA;
	unsigned int PortB;
	unsigned int PortC;
	unsigned int PortControl;
	unsigned char b;
	unsigned long baseRet;

	static int fd = -1;
	int fdPC = -1;
	char strbase[32];
	int size;

	if ((fdPC = open("/dev/PCIO", O_RDONLY)) < 0)
		printf("couldn't open PCIO\n");
	
	BASEADDRESS = (unsigned long) read(fdPC, strbase, 32);

	//strbase[5] = 0;
	//baseRet = atoi(strbase);
	
	printf("RET baseaddress: %X\n", BASEADDRESS);
	

	close(fdPC);
	
	switch (group) {
		case group0:
			PortA = BASEADDRESS;
			break;
		case group1:
			PortA = BASEADDRESS + 4;
			break;
		case group2:
			PortA = BASEADDRESS + 8;
			break;
		case group3:
			PortA = BASEADDRESS + 12;
			break;
	}

	PortB = PortA + 1;
	PortC = PortA + 2;
	PortControl = PortA + 3;

	printf("baseaddress: %X\n", PortA);
        printf("Port control: %X\n", PortControl);

	if (fd < 0)
		fd = open(PORT_FILE, O_RDWR);
	if (fd < 0) {
		printf("error opening IOPort file\n");
		return false;
	}

	/* now set them all to be input */
	b = 0x9B;					 
	lseek(fd, PortControl, SEEK_SET);
	if (write(fd, &b, 1) > 0) { 
		printf("written control byte successfully\n"); 	
		return true;
	}


	return false;

}



