//
// ring.termios.c
//
// termios communication ring test
//
// Neil Gershenfeld 4/4/21
//
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose, but must
// acknowledge this project. Copyright is retained and
// must be preserved. The work is provided as is; no
// warranty is provided, and users accept all liability.
//
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
//
#define nloop 100
//
int main(int argc,char *argv[]) {
   if (argc != 3) {
      printf("command line: ring.termios serial_port port_speed\n");
      return -1;
      }
   int speed = atoi(argv[2]);
   int port = open(argv[1],O_RDWR|O_NOCTTY|O_NDELAY);
   fcntl(port,F_SETFL,0);
   struct termios term;
   tcgetattr(port,&term);
   term.c_cflag &= ~(PARENB|CSTOPB|CSIZE|CRTSCTS);
   term.c_cflag |= (CS8|CREAD|CLOCAL);
   term.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL|ISIG);
   term.c_iflag &= ~(IXON|IXOFF|IXANY|IGNBRK|BRKINT
      |PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
   term.c_oflag &= ~(OPOST|ONLCR);
   term.c_cc[VTIME] = 0;
   term.c_cc[VMIN] = 1;
   cfsetispeed(&term,speed);
   cfsetospeed(&term,speed);
   tcsetattr(port,TCSANOW,&term);
   unsigned char chr = 0;
   struct timeval start,end;
   tcflush(port,TCIOFLUSH);
   gettimeofday(&start,NULL);
   for (int i = 0; i < nloop; ++i) {
      while (1) {
         write(port,&chr,1);
         read(port,&chr,1);
         if (chr == 0)
            break;
         }
      }
   gettimeofday(&end,NULL);
   printf("byte ring cycles per second: %6.3g\n",nloop*256/((end.tv_sec+end.tv_usec/1e6)-(start.tv_sec+start.tv_usec/1e6)));
   close(port);
   return 0; 
   }