/*
 * (c) 1998, Ben Fuhrmannek <ben@fuhrmannek.de>
 * released under GPL (GNU General Public License)
*/

#include <stdio.h>
#include <termio.h>
#include <unistd.h>
#include <asm/io.h>

#define IOCTLVAL TCSETS

int li[7];
int in[4];

showhelp() {
  printf("--- icp - interface control program ---\n");
  printf("	(C) Ben Fuhrmannek <ben@fuhrmannek.de>, 1998\n\n");
  printf("  x	Quit\n");
  printf("  h	this helptext\n");
  printf("  s	statusmessage(s)\n");
  printf(" 0..9	switch leds\n");
  printf("\n");
}

setled(int sw) {
/*  printf(" %d",sw);*/
  outb(sw,IOPORT);
}

led(int l) { /* l = 1..8 */
  int i, setz = 0;
  if (l != 0) if (li[l-1] == 0) li[l-1] = 1; else li[l-1] = 0;
  setz = (1*li[0]) + (2*li[1]) + (4*li[2]) + (8*li[3]) +
               (16*li[4])+(32*li[5])+(64*li[6])+(128*li[7]);
  outb(setz,IOPORT);
}

getIN() {
  int i, wert;
  for (i=0; i <= 4; ++i) in[i] = 0;
  wert=inb(IOPORT+1)-7;
  if (wert >= 128) {wert = wert - 128; in[0] = 1;}
  wert = 127 - wert;
  if (wert > 64) {wert = wert - 64; in[1] = 1;}
  if (wert > 32) {wert = wert - 32; in[2] = 1;}
  if (wert > 16) {wert = wert - 16; in[3] = 1;}
  if (wert > 8) in[4] = 1;
}

showstatus() {
  printf("IOPORT: 0x%x\n",IOPORT);
  printf("LEDs: %d %d %d %d  %d %d %d %d\n",li[0],li[1],li[2],li[3],
                       li[4],li[5],li[6],li[7]);
  getIN();
  printf(" INs: %d %d %d %d %d\n",in[0],in[1],in[2],in[3],in[4]);
}

sm_vor1(int nulval) {
  int i,j;
  j = 100;
  for (i = 0; i <= 25; i++) {
    setled(nulval*1);
    usleep(j*100);
    setled(nulval*2);
    usleep(j*100);
    setled(nulval*4);
    usleep(j*100);
    setled(nulval*8);
    usleep(j*100);
  }
  led(0);
}

sm_vor2(int nulval) {
  int i,j;
  j = 100;
  for (i = 0; i <= 25; i++) {
    setled(nulval*3);
    usleep(j*100);
    setled(nulval*6);
    usleep(j*100);
    setled(nulval*12);
    usleep(j*100);
    setled(nulval*24);
    usleep(j*100);
  }
  led(0);
}

main()
{
  struct termio	cooked, raw;
  unsigned char	c;
  int progend = 0;
  int i;

  for (i = 0; i <= 7; ++i) li[i] = 0;
  if (ioperm(IOPORT,3,1)) {perror("ioperm");exit(1);}
  outb(0,IOPORT);

  (void) ioctl(0, IOCTLVAL, &raw);

  while (progend != 1)
  {
    read(0, &c, 1);

    switch(c) {
	case 'x': printf("Bye.\n"); progend = 1; break;
	case '0':
	  for (i = 0; i <= 7; ++i) li[i] = 0;
	  outb(0,IOPORT);
	  break;
	case '1': led(1); break;
	case '2': led(2); break;
	case '3': led(3); break;
	case '4': led(4); break;
	case '5': led(5); break;
	case '6': led(6); break;
	case '7': led(7); break;
	case '8': led(8); break;
	case '9':
	  for (i = 0; i <= 7; ++i) li[i] = 1;
	  outb(255,IOPORT);
	  break;
	case 'h': showhelp(); break;
	case 's': showstatus(); break;
	case 'q': sm_vor2(1); break;
	case 'a': sm_vor1(1); break;
	case 'e': sm_vor2(16); break;
	case 'd': sm_vor1(16); break;
	default: printf("Wrong input! (0x%x)\n",c);
    }
    fflush(stdout);
  }

  if (ioperm(IOPORT,3,0)) {perror("ioperm");exit(1);}

  (void) ioctl(0, IOCTLVAL, &cooked);

  printf("\n");
}

