/* sioosl.c - simple serial output code */
/* based on sio.c - adds abilty to read \r as terminator for OSL */
/* it sends a \r but it is received as a \n */
/* based on code at: http://www.easysw.com/~mike/serial/ */
/* type shit- hit return and it gets sent out ttyC1 */
/* also checks for input after each character typed */
/* send a Z to exit */

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int open_port (void);

main ()
    {
    int sfd; /*serial port file descriptor*/
    struct termios o_opts, n_opts; 
    int n=0;
    int ni=0;
    int c;
    int i;
    char buf[80], ibuf[80];

    sfd = open_port(); /*open serial port*/

    /*make read return 0 bytes if none available*/
    fcntl(sfd, F_SETFL, FNDELAY);

    /* set some port parameters */
    tcgetattr(sfd, &o_opts);
    n_opts=o_opts;

    /*turn off echo*/
    n_opts.c_lflag &= ~(ECHO);

    /*set canonical (line at a time mode)*/
    n_opts.c_lflag |= ICANON;

    /*maps input cr to nl*/
    n_opts.c_iflag |= ICRNL;
    /*n_opts.c_iflag &= ~(ICRNL); */
    n_opts.c_iflag &= ~(IGNCR); 
    n_opts.c_iflag &= ~(INLCR); 
  printf("ICRNL=%d\n",(n_opts.c_iflag & ICRNL));
  printf("IGNCR=%d\n",(n_opts.c_iflag & IGNCR));
  printf("INLCR=%d\n",(n_opts.c_iflag & INLCR));
 
   /*accept \r as EOL in addition to \n*/
   n_opts.c_cc[VEOL]='\r';

    /*turn on output processing so other o_flags have an effect*/
    n_opts.c_oflag |= (OPOST);
    /*don't do any NL mapping*/
    /*n_opts.c_oflag |= ONLRET;*/ /*this turns nl to nl/cr*/
    n_opts.c_oflag &= ~ONLRET;
    n_opts.c_oflag &= ~ONLCR;
    n_opts.c_oflag &= ~OCRNL;
  printf("ONLRET=%d\n",(n_opts.c_oflag & ONLRET));
  printf("ONLCR=%d\n",(n_opts.c_oflag & ONLCR));
  printf("OCRNL=%d\n",(n_opts.c_oflag & OCRNL));

    /*now baud rates*/
    cfsetispeed(&n_opts,B9600);
    cfsetospeed(&n_opts,B9600);
    /* now set to 8N1 */
    n_opts.c_cflag &= ~CSIZE;
    n_opts.c_cflag |= CS8;
    n_opts.c_cflag &= ~PARENB;
    n_opts.c_cflag &= ~CSTOPB;
    
    /*turn off software flow control on input and output*/
    n_opts.c_iflag &= ~IXON;
    n_opts.c_iflag &= ~IXOFF;
    /*turn off hardware flow control*/
    n_opts.c_cflag &= ~CRTSCTS;

    /*now make these settings active now*/
    tcsetattr(sfd, TCSANOW, &n_opts);

    while ((c=getchar())!='Z')
        {
        buf[n++]=c;
        if (c=='\n')
            {
            buf[n-1]='\r';
            buf[n]='\0'; 
            if (write(sfd,buf,n)<0)
                fprintf(stderr,"write() of %d bytes failed.\n",n);
            /*for (i=0;i<=n;i++)*/
                /*printf("sent %c: %d\n",buf[i],buf[i]);*/
            n=0;
            }
        /*check for input*/
        if ((ni=read(sfd,ibuf,80))>0)
            {
            ibuf[ni]='\0';
            printf("I read %d bytes: %s\n",ni,ibuf);
            /*for (i=0;i<=ni;i++)*/
                /*printf(" char %d is %c or %d.\n",i,ibuf[i],ibuf[i]);*/
                printf("Terminator was %d.\n",ibuf[ni-1]);
            }

        }
  
   /* tell sio to stop with a Z*/
   strcpy(buf,"Z\n\0");
    printf("XXXGot a Z - Exiting\n");
   if (write(sfd, buf, 2)<0)
        puts("ending write failed");

     printf("XXXsetting attributes\n");
    tcsetattr(sfd, TCSANOW, &o_opts);
     printf("XXXclosing\n");
    close (sfd);
     printf("XXXclosed\n");
    }

int open_port(void)

    {
    int fd; /*file descriptor*/
    
   fd = open("/dev/ttyC1", O_RDWR | O_NOCTTY | O_NDELAY);
   if (fd == -1)
     fprintf(stderr, "open_port: Unable to open /dev/ttyC1 - %s\n",
             strerror(errno));

   return (fd);
 }
