/*
 * $Source $
 * $Log: plc.c,v $
 * Revision 1.11  1999/09/21 22:47:22  richy
 * just added a print statement and updated the comments
 *
 * Revision 1.10  1998/07/16 20:36:34  richy
 * took out press s to stop in the text
 *
 * Revision 1.9  1998/07/16 03:42:45  richy
 * took out ability to stop in the middle of opening the door
 *
 * Revision 1.8  1998/07/02 00:55:50  wiencke
 * changed door to cover in print statements
 * added \n to print statements that said the cover has stopped
 *
 * Revision 1.7  1998/07/01 21:48:02  richy
 * a bunch of little things
 *
 * Revision 1.6  1998/06/29 21:26:48  richy
 * added function rad_cycle that cycles radiometer power with dc pulse
 *
 * Revision 1.5  1998/06/26 23:31:40  richy
 * I reserved this a while ago and I can't quite remember what I changed on it
 * I think I changed dooropen and door close commands so that their user
 * input part works correctly
 *
 * Revision 1.4  1998/05/05 19:08:11  richy
 * I changed the name in the time structures in the door open and the door
 * close functions because I think they might be interfering with each other
 *
 * Revision 1.3  1998/04/24 21:52:53  richy
 * forgot to include time.h
 *
 * Revision 1.2  1998/04/24 20:48:28  richy
 * this has door_open() and door_close() added to it
 *
 * Revision 1.1  1997/02/24 17:41:13  richy
 * Initial revision
 *
*/



/*This is going to be functions that are used to talk to the Toshiba T1 PLC*/
/*The functions are going to be one that initializes a port to be used for*/
/*PLC PLC_init() initializes the plc and gets the file descriptor for the*/
/*other functions to use, it will be written to like a file*/
/*There will be one to write to the PLC registers that will return output*/
/*PLC_write(registers,value) PLC_write("D140","0001");*/
/*PLC_relay_stat(relay) PLC_relay_stat("R100")*/
/*returns status of relay 1=on 0=off*/
/*PLC_status() will tell the status of PLC*/
/* -1 is error in communication or hardware*/
/* 1 is run mode 5 is halt mode and 6 is error mode*/
/*For 5 or 6 message is printed to screen telling you that the hardware must*/
/*be adjusted from it's present location to be used  probably will be Dugway*/
/*ORIGINAL AUTHOR(written 1998): Richard C. Gray
 *Undergraduate Research Assistant
 *HiResolution Fly's Eye, High Energy Cosmic Ray group
 *University of Utah
 *email:richy@cosmic.utah.edu
 */





#include <stdlib.h>
#include <time.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include "plc_cb98.h"

plc_cb98_common plc_;


int plc_init() {
 
  struct termios options;
  /*this function initializes a port to use the plc*/
  plc_.pd=open(PLC_DEVICE, O_RDWR | O_NDELAY);
  if(plc_.pd<0){return(-1);}
  /*This following function could not have been written without the help
   *of Linux How To's posted on the web for serial port programming.
   *PLEASE KEEP THIS SORT OF THING GOING. If you know how to make
   *a driver for something or make a program to do something that isn't
   *in the average C book, PLEASE write a How To and post it on the web
   */
  
  fcntl(plc_.pd, F_SETFL, FNDELAY); /*configure port reading*/
  tcgetattr(plc_.pd, &options);  /*get current options for the port*/
  
  cfsetispeed(&options, B9600); /*set baud rates to 9600*/
  cfsetospeed(&options, B9600);
  /*Makes it so that the program dosen't own the port and other things can use it*/
  options.c_cflag |= (CLOCAL | CREAD);
  
  /*the following five lines set odd parity*/
  options.c_cflag |= PARENB;
  options.c_cflag |= PARODD;
  options.c_cflag &= ~CSTOPB;
  options.c_cflag |= CREAD;
  options.c_cflag |=PARENB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;
  /*This enables or disables  clear to send and request to send stuff*/
  options.c_cflag &= ~CRTSCTS;
  
  
  /* Enable data to be processed as raw input would be an & */
  /*before =* and an ISIG instead of an ECHOE*/
  /*a | before equal sets it so data isn't taken until a cariage return*/
  options.c_lflag &= ~(ICANON | ECHOE | ISIG);
  
  /* this will set new line as carriage return*/
  options.c_oflag |=ONLCR;
  
  
  /* Set the new options for the port */
  tcsetattr(plc_.pd, TCSANOW, &options);
  return(1);
}



/*The following functions will all hold several varialbles in common*/
/* n will = number of charectors sent*/
/* c will = number of charectors recieved*/
/* bufin = the string recieved from the plc or port*/
/* bufout = the string sent to the plc or port*/
/* x and s will be used for miscellaneous tasks, such as for loops or holding*/
/*     VAlues to be returned*/
/* plc_.pd is the file descriptor used to send data to the plc as if it were a file*/




int plc_write(char reg[10], char value[10]) {
  int n,c,x;
  char bufout[50], bufin[50];
  sprintf(bufout,"(A01DW%s,1,%s)\r", reg,value);
  /*A01 specifies the plc meant to execute the instruction*/
  /*DW means data write in the plc's language*/
  n=write(plc_.pd,bufout,sizeof(bufout));
  usleep(200000);
  /*The amount of time to wait before reading was determined by trial and error*/
  c=read(plc_.pd,&bufin,sizeof(bufin));
  if(bufin[5]=='E'){n=-1;} /*All error messages sent from the plc have an 'E'*/
  /*As the sixth charector, in buffer 0 is counted as a charector*/
  
  return(n);
}


/*plc_relay_stat(char reg[10]) will be used to check the status of inputs and */
/*outputs, such as the state of limit switches or to confirm that the*/
/*signal to open or close the doors was recieved*/
/*it will return 1 for the relay is on and 0 for the relay is off*/
/*x=plc_relay_stat(plc_.pd, "Y23");*/


int plc_relay_stat(char reg[10]) {
  int n,c,x;
  char bufout[50], bufin[50];
  sprintf(bufout, "(A01DR%s,1)\r",reg);
  /*again A01 refers to which plc(adress 01 assumed)*/
  /*DR means data read*/
  n=write(plc_.pd,bufout,sizeof(bufout));
  usleep(100000);
  /*if you wish to try and speed up the function the time to wait was 
   *determined by trial and error. To experiment you can try lowering it
   */
  sprintf(bufin, " ");
  c=read(plc_.pd,&bufin,sizeof(bufin));
  x=-1; /*if the 10th place dosen't have a 1 or 0 something has gone wrong*/
  if(bufin[9]=='1'){x=1;}/*When testing the on off status of a relay the plc*/
  if(bufin[9]=='0'){x=0;}/*has the 1 or 0 always in the 10th place*/
  if(bufin[5]=='E'){x=-1;}/*All error messages from plc have E as 6th */
  return(x);
}


/*This is a function that should be run at the beginning of a program after */
/*plc_init(). This will return a 1 if the connection seems fine.*/
/* a -1 for a general error and a -2 for the plc responded but with an error*/
/*This function requires no arguments*/
/*It will send a string to the PLC RICHYISTHEMAN (after all everyone knows
 *Richy is the Man)
 */

int plc_test(){
  #define test_good "RICHYISTHEMAN" 
  int n,c,x,s;/*s will hold the status 1, -1, or -2*/
  char bufout[50], bufin[50], test[50];
  sprintf(bufout, "(A01TSRICHYISTHEMAN)\r");
  n=write(plc_.pd,bufout,sizeof(bufout));
  usleep(200000);
  c=read(plc_.pd,&bufin,sizeof(bufin));

  sprintf(test,"%c",bufin[6]);/*These 3 lines put RICHYISTHEMAN into the*/
/*These lines strip off the rest of the stuff the PLC sends back with the
 *return string*/
  for(x=1;x<=12;x++){ /*String test if the plc is working*/
    sprintf(test, "%s%c",test,bufin[6+x]);
  }
  s=-1;
  for(x=0;x<sizeof(test_good);x++){
    if(test[x]==test_good[x]){s=1;}
    else{return(-2);}
  }

  if(bufin[5]=='E'){s=-2;}
  if(n<=0){s=-1;}
  if(c<=0){s=-1;}
  return(s);
}
  
/*This should be dont after plc_test(plc_.pd) and after plc_init()*/
/*This function tests the plc's mode. It will return the status as*/
/*5= halt mode 1=run mode 6=error mode*/
/*6 happening is highly unlikely. However if 5 or 6 happens you have to */
/*physically either powere cycle the plc 6 or flick it in run mode 5*/

int plc_status() {
   int n, c,x;
   char bufout[50], bufin[50];
   sprintf(bufout, "(A01ST)\r");
   n=write(plc_.pd,bufout,sizeof(bufout));
   usleep(200000);
   c=read(plc_.pd,bufin,sizeof(bufout));
   x=-1;
   if(bufin[5]=='E'){x=-1;}
   if(bufin[9]=='1'){x=5;}
   if(bufin[9]=='2'){x=1;}
   if(bufin[9]=='6'){x=6;}
   if(x==6){
   printf("Do not pass go, Do not collect 200 dollars\n");
   printf("Go directly to Dugway and power cycle the plc\n");
   printf("plc is in ERROR mode");}
   if(x==5){
     printf("Do not pass go, Do not collect 200 dollars\n");
     printf("Go directly to Dugway and put the plc in RUN mode\n");
     printf("There is a small switch by where the RS232 attaches to the PLC\n");
printf("plc is now in HALT mode and is no good to you like that\n");
}
  

  return(x);

}



/********************************************************************
 **** Some example functions that may help***************************
*
*
*
int door_open() {
  int opening, open;
  char buf[50];
  int dstat;
  int inkey;
  
  plc_write(DOOR_REG,D_OPEN);
  usleep(99999);
  opening=plc_relay_stat(DOOR_PIN);
  if(opening<=0){printf("\nSome unknown error opening cover\n");return(-1);}
  printf("\nThe cover should be opening");
  printf("\nPlease wait while cover opens\n");

  open=0;
  
  for(;;){
   
    
   
    open=plc_relay_stat(DOOR_OPEN_PIN);
    if(open==1){
      printf("\nThe cover should be open\n");
      uti_.copen=TRUE;
      return(open);}
    
    
    
      
    
  }
  
}

int door_close() {
  int closing, close;
  char buf[50];
  int dstat;
  int inkey;
  plc_write(DOOR_REG,D_CLOSE);
  usleep(99999);
  closing=plc_relay_stat(DOOR_PIN);
  if(closing!=0){
    printf("\n Some unknown error closing the cover\n");
    return(-1);}
  printf("\n The cover should be closing");
  printf("\n Please wait for the cover to  close\n");

  close=0;
  for(;;) {
   
   
    close=plc_relay_stat(DOOR_CLOSE_PIN);
    if(close==1){
      printf("\nThe cover should be closed\n");
      uti_.copen=FALSE;
      return(close);}
    
    
    
      
    
  }
}



int rad_cycle() {
 
  plc_write(RAD_ON_REG,PIN_ON);
 
  usleep(10900000);
  return(1);
}


**************************************************************
*/












