/*
 	TSA Liedetector project.
		-- RKeene
*/

#include <stdio.h>
#ifndef GO32
#include <asm/io.h>
#define OUTBYTE(x,y) outb(x,y)
#define INBYTE(x) inb(x)
#define IOPERM(x,y,z) ioperm(x,y,z)
#else
#include <inlines/pc.h>
#define OUTBYTE(x,y) outportb(x,y)
#define INBYTE(x) inportb(x)
#define IOPERM(x,y,z) (1)
#endif
#include <unistd.h>
#include <string.h>
#include <signal.h>
#define CNT 8
#define DEBUG 0
int BASE=0x2f8;			/*     default to ttyS1 (COM2)    */
int NOTERM=0;


/* Clear the screen with ANSI escape sequences.  */
void clear(void) {
	write(STDOUT_FILENO, "\033[2J\033[H",7);
	fsync(STDOUT_FILENO);
}


/*  Reset the port turnning OFF the led. */
void handleC(void) {  
	if (NOTERM==1) { 
		signal(SIGINT,(void *)handleC);
#ifndef GO32
		signal(SIGTSTP,(void *)handleC);
#endif
		return; 
	}
	OUTBYTE(2,BASE+4);
	IOPERM(BASE,CNT,0);
	printf("\033[0m");
	clear();
	printf("Killed\n");
	exit(1);
}

void killed(void) {
	NOTERM=0;
	handleC();
	printf("Hmm.. handleC() failed to terminate!  This is bad.. exiting.\n");
	while(1) { exit(127); }
}

void printstatus(int online, int value) {
  char sonline[31];
  char liar[31];
  int trueValue;
  if (online==1) { strcpy(sonline,"Connected    "); } else { strcpy(sonline,"Not connected"); }
  trueValue=((value-61)*-1);
  if (trueValue<30) { strcpy(liar,"the truth"); } else { strcpy(liar,"a lie    "); }
  printf("%c[0m%c[H",27,27);
  printf("%c[1;37;44m%c[KStatus: %s   %c[%i;37;44m Measuring: %i\n%c[%i;37;41m%c[KSubject is telling %s",27,27,sonline,27,online,trueValue,27,online,27,liar);
  printf("\n");
}

/* I was REALLY bored... */
void flashled(char morse[128]) {
	int i,online,length=0,delay=150000;
	int lenstr=strlen(morse);
	OUTBYTE(1,BASE+4);
	for (i=0;i<5;i++) { online=INBYTE(BASE+6); }
	if (online!=128) { return; }
	for (i=0;i<lenstr;i++) {
		if (morse[i]=='.') length=150000;
		if (morse[i]=='-') length=450000;
		if (morse[i]==',') { usleep(650000); }
		if (morse[i]<=46 && morse[i]>=45) {
			OUTBYTE(1,BASE+4);
		 	usleep(length);
			OUTBYTE(2,BASE+4);
			usleep(delay);
		}
	}
}

int main(int argc, char *argv[]) {
	int i;
	int val[CNT];
	int online=2;
	int ionline;
	int valueLie=0;
	if (argc>=2) {
		if (strncasecmp("COM1",argv[1],4)==0) { BASE=0x3f8; }
		if (strncasecmp("COM2",argv[1],4)==0) { BASE=0x2f8; }
	}
#if (DEBUG==1)
	oldmain();
	return(0);
#endif
	signal(SIGINT,(void *)handleC);
	signal(SIGTERM,(void *)killed);
#ifndef GO32
	signal(SIGTSTP,(void *)handleC);
	if (IOPERM(BASE,CNT,1)==-1) { printf("%c[0mYou must be %c[1;37mroot%c[0m to run this program.\n",27,27,27); return(1); }
#endif
	flashled(".-.,---,-.--,-.-,.,.,-.,.,");
	clear();
	while(1) {
		usleep(1);
		for (i=0;i<CNT;i++) {
			OUTBYTE(1,BASE+i);
			val[i]=INBYTE(BASE+i);
		}
		ionline=((val[6]-1)/128);
		if (online!=ionline || val[0]!=valueLie) {  
			online=ionline;
			valueLie=val[0];
			printstatus(online,val[0]);
		}
	}
	return(0);
}


/*
  Old main, used for learning what pins do what and what not, prints
     status.
*/
int oldmain(void) 
{
  int val[CNT];
  int i;
  IOPERM(BASE,CNT,1);
  while (1) {
    for (i=0;i<CNT;i++)
    {
      OUTBYTE(1,BASE+i);
      val[i]=INBYTE(BASE+i);
      printf("%i  ",val[i]);
    }
    printf("\n");
  }
  return 0;
}
