#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> 
#include <string.h>

int open_port(void);   
int close_port(int fd);
int initialize_baratron(int fd);
char *do_command(int fd, const char *command);
char *format_command(char *data, int offset);

int debug = 0;

int main()
{
  int fd;
  char *pressure;
  char command[256];

  fd = open_port();  
 
  do_command(fd, "L;"); 
  while(1) 
  {
    pressure = format_command(do_command(fd, "D1;"), 7);
    snprintf(command, 256, "/usr/local/bin/rrdtool update /home/raymond/software/MKS/RRD/pressure.rrd N:%s", pressure);
    printf("%s\n", command);
    system(command);        
    sleep(1); 
  }
  close_port(fd);
  
  exit(0);
}

int open_port(void)
{
  int fd;
  struct termios options;
  
  if (!(fd = open("/dev/cuad0", O_RDWR | O_NOCTTY | O_NDELAY)))
  {
    perror("couldn't open tty");
    exit(1);
  } else 
  {
    fcntl(fd, F_SETFL, 0);
if(debug)    printf("successfully opened tty\n");
  }

  tcgetattr(fd, &options);
  cfsetispeed(&options, B9600);  
  cfsetospeed(&options, B9600);  

  options.c_cflag |= PARENB;
  options.c_cflag &= ~PARODD;
  options.c_cflag &= ~CSTOPB; 
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS7;
  
  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
 
  options.c_iflag |= (INPCK | ISTRIP);
  options.c_iflag &= ~(IXON | IXOFF | IXANY);

  options.c_oflag &= ~OPOST;
  
  options.c_cc[VTIME] = 10;
  options.c_cc[VMIN] = 0;
 
  if((tcsetattr(fd, TCSANOW, &options))==0)
  {
if(debug)    printf("successfully set tty mode\n");
  } else
  {
    perror("couldn't set tty mode");
    exit(1);
  }

  return fd;
}

int close_port(int fd)
{
  if (!(close(fd)==0))
  {
    perror("couldn't close tty\n");
    exit(1);
  } else
  {
if(debug)    printf("successfuly closed tty\n");
  }
  return 0;
}

int initialize_baratron(int fd)
{
  unsigned char buffer;
  char dropstring[] = { 0x7e, 0x3b, 0x3b, 0x00, 0x7f };  
  char initstring[] = { 0x7e, 0x39, 0x39, 0x00, 0x7f }; 
   
if(debug)  printf("initializing MKS 112A:\n");
   
  
if(debug)  printf("trying to disconnect:\n");
 
  write(fd, dropstring, 5);
  while(read(fd, &buffer, 1)) 
  {
if(debug)    printf("%x:", buffer);      
    if(buffer == 0x7f) {
if(debug)      printf("\n");
    }
    if(buffer == 0x7e)
    {
      read(fd, &buffer, 1);
if(debug)      printf("%x:", buffer);
      if(buffer == 0x3d)
      {
if(debug)        printf("%x:", buffer);
        while(buffer != 0x7f)
        {
          read(fd, &buffer, 1);
if(debug)          printf("%x:", buffer);
        }
if(debug)        printf(" (successfully disconnected)\n");
        break;  
      } else
      {
        write(fd, dropstring, 5);
      }
    }
  }

  
if(debug)  printf("trying to connect:\n");

  write(fd, initstring, 5);
  while(read(fd, &buffer, 1)) 
  {  
if(debug)    printf("%x:", buffer);
    if(buffer == 0x7f) {
if(debug)      printf("\n");
    }
    if(buffer == 0x7e)
    {
      read(fd, &buffer, 1);
if(debug)      printf("%x:", buffer);
      if(buffer == 0x3d)
      {
if(debug)        printf("%x:", buffer);
        while(buffer != 0x7f)
        {
          read(fd, &buffer, 1);
if(debug)          printf("%x:", buffer);
        }
if(debug)        printf(" (successfully connected)\n");
        break;  
      } else
      {
        write(fd, initstring, 5);
      }
    }
  }
  
  return(0);
}

char *do_command(int fd, const char *command)
{
  unsigned char buffer, tcc = 0, rcc = 0, acs = 0, scs = 0, ms = 0, rc = 0, sc = 0, sf = 0x7e, ef = 0x7f;
  static char data[256];
  int x = 0;

  tcc = 0x41 | (ms & 0x36);


  initialize_baratron(fd);
 
  while(1) 
  {
    acs = tcc;
    for(x=0;x<=(strlen(command)-1);x++)
    { 
      acs += command[x];
    }
    acs &= 0x3f;
  
    scs = tcc;
    for(x=0;x<=(strlen(command)-1);x++)
    {
      scs += command[x];
    }
    scs >>= 0x06;
  
if(debug)    printf("%x:%x %s %x:%x:%x\n", sf, tcc, command, acs, scs, ef);

    write(fd,&sf,1);
    write(fd,&tcc,1);
    write(fd,command,strlen(command));
    write(fd,&acs,1);
    write(fd,&scs,1);
    write(fd,&ef,1);
if(debug)    printf("wrote command\n");
   
    x=0;
    while(read(fd,&buffer,1))
    {
if(debug)      printf("%c", buffer);       
      data[x]=buffer;
      x++;
      if(buffer==0x7f) 
      {
if(debug)        printf("\n");
        break;
      }
    }
    data[x+1] = '\0';
    rcc = data[1];
    if((rcc & 0xc9) == 0x41)
    {
if(debug)      printf("we have information\n");
      rc = rcc & 0x30;
      sc = ms & 0x03;
      if (rc == sc) 
      {
        ms = 0xbf & (ms + 0x10);
      }
      break;
    }
    if((rcc & 0xf9) == 0x21) 
    { 
if(debug)      printf("command transmitted successfully\n");
if(debug)      printf("extracting rc and sc\n");
      rc = (rcc & 0x06);
      sc = (ms & 0x06);
    } else 
    {
if(debug)      printf("command transmission failed\n");
      break;
    }
    if(rc == (0x06 & (sc + 0x02)))
    {
if(debug)      printf("more work to be done\n");
      ms = 0xf7 & (ms + 0x02);
      tcc = 0x21 | ((ms >> 0x03) & 0x06);
    }     
  }

  return &data;
}

char *format_command(char *data, int offset)
{
  int x = 1;
  while(1)
  {
     if(x==256) { break; }
     *(data+x-offset)=*(data+x);
     x++;
  }
  x = 2;
  while(1)
  {
     if(x==256) { break; }
     *(data+x-1)=*(data+x);
     x++;
  }
  for(x=0;x<255;x++)
  {
     if(*(data+x) == 0x3b) 
     {
       *(data+x)='\0';
       break;
     }
  } 

  return data;
}
