
/* 
-----------------------------------------------------
  www.tctec.net
  
  18-Nov-2023
  
  
  top16AT linux c example using linux serial port
  
  

------------------------------------------------------ 
*/
 
// C library headers
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Linux headers
//
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()


#define SERIAL_PORT ( "/dev/ttyUSB0")

// set an output pwm, serial port has already been opened
//
int setPWM(int thePort, int output, int setting)
{
  
  char msg[10] ;
  unsigned char read_buf[10];
  int num_bytes = 0;
  
  sprintf(msg, "#p%d%02X\r", output, setting);
  //printf(msg);
  //printf("\n");
  write(thePort, msg, 6);
  
  // hardcoded 20 millisecond delay
  //
  sleep(0.02);
  
  num_bytes = read(thePort, &read_buf, 5);   //'>OK\r\n'
  
  return(0);
}

// set a digital output , serial port has already been opened
//
int setDigOut(int thePort, int output, int mask)
{
  
  char msg[10] ;
  unsigned char read_buf[10];
  int num_bytes = 0;
  
  sprintf(msg, "#%02X%02X\r", output, mask);
  //printf(msg);
  //printf("\n");
  write(thePort, msg, 6);
  
  // hardcoded 20 millisecond delay
  //
  sleep(0.02);
  
  num_bytes = read(thePort, &read_buf, 5);  //'>OK\r\n'
  
  return(0);
}

// Read analog (millivolts) input
// serial port has already been opened
//
float readAnalog(int thePort, int input)
{
  
  char msg[10] ;
  unsigned char read_buf[15];
  int num_bytes = 0;
  
  if(input <=0)
  {	  
    // invalid input pin
	//
	return(-1);	  
  }
  
  if(input > 8)
  {
	// invalid input pin
	//
	return(-1);
  }
  
  sprintf(msg, "#z%d\r", input);  
  write(thePort, msg, 4);
  
  // hardcoded 20 millisecond delay
  //
  sleep(0.02);
  
  num_bytes = read(thePort, &read_buf, 10);  //> XXXX.XX\r\n'
  //printf("Read %d   bytes \n", num_bytes);
  
  if(read_buf[0] == '>')
  {
	  read_buf[0] = ' ';  // remove '>' character
	  return(atof((char*) read_buf));
  }
	  
  
  return(0);
}





int openSerialPort()
{
  // Open the serial port
  int serial_port = open(SERIAL_PORT, O_RDWR);

  // Create new termios struct, we call it 'tty' for convention
  struct termios tty;
  
 
  // Read in existing settings, and handle any error
  if(tcgetattr(serial_port, &tty) != 0) {
      printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
      return 1;
  }

  tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
  tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
  tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size 
  tty.c_cflag |= CS8; // 8 bits per byte (most common)
  tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
  tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

  tty.c_lflag &= ~ICANON;
  tty.c_lflag &= ~ECHO; // Disable echo
  tty.c_lflag &= ~ECHOE; // Disable erasure
  tty.c_lflag &= ~ECHONL; // Disable new-line echo
  tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
  tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
  tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

  tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
  tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
  
  tty.c_cc[VTIME] = 1;    // Wait for up to 0.1s (1 deciseconds), returning as soon as any data is received.
  tty.c_cc[VMIN] = 0;

  // Set in/out baud rate to be 115200
  cfsetispeed(&tty, B115200);
  cfsetospeed(&tty, B115200);

  // Save tty settings, also checking for error
  if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
      printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
      return 1;
  }

  
  return (serial_port);
}


int main() {
	int serial_port;
	float a1,a2,a3,a4,a5,a6,a7,a8;
	
	printf("Start \n");
	
	serial_port = openSerialPort();	
	
	printf("Set PWMs \n");
	
	
	setPWM(serial_port, 1, 10);	
		
	setPWM(serial_port, 2, 20);
	
	setPWM(serial_port, 3, 50);
	
	setPWM(serial_port, 4, 100);	
	
	setPWM(serial_port, 5, 130);
	
	setPWM(serial_port, 6, 200);	
	
	setPWM(serial_port, 7, 220);
	
	setPWM(serial_port, 8, 255);
	
	sleep(2);
	
	// set digital outputs
	//
	setDigOut(serial_port,0b10101010, 0b11111111);
	sleep(1);
	setDigOut(serial_port,0b01010101, 0b11111111);
	sleep(1);
	
	for(int i = 0 ; i < 10; i++)
	{
	  setDigOut(serial_port,0b00000000, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b00000010, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b00000100, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b00001000, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b00010000, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b00100000, 0b11111111);
	  sleep(0.1);
	  setDigOut(serial_port,0b01000000, 0b11111111);
	  sleep(0.1);	  
	  setDigOut(serial_port,0b10000000, 0b11111111);
    }
	sleep(1);
	
	
	printf("Read analog inputs \n");
	
	for(int i = 0 ; i < 100; i++)
	{
	
	  a1 = readAnalog(serial_port, 1);
	  a2 = readAnalog(serial_port, 2);
	  a3 = readAnalog(serial_port, 3);
	  a4 = readAnalog(serial_port, 4);
	  a5 = readAnalog(serial_port, 5);
	  a6 = readAnalog(serial_port, 6);
	  a7 = readAnalog(serial_port, 7);
	  a8 = readAnalog(serial_port, 8);
	  sleep(0.5);
	
	  	
	  printf("%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t\n", a1, a2, a3, a4, a5, a6, a7, a8);
    }
	
	close(serial_port);
  
};
