/*
ALCOR-SYSTEM
 
This sample file was created on Sep 03 2019
It compiles using gcc under any Linux platform you
want (PC, Raspberry..).

Serial port definition is here 

*portname = "/dev/serial0";
see /dev for available serial ports

It gives a sample to use the OMEA/EUDA weather board with basic 
commands.

Use the lazarus project to have a full implementation of commands.

*/

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


int set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        
        memset (&tty, 0, sizeof tty);
        
        if (tcgetattr (fd, &tty) != 0)
        {
                printf("error %d from tcgetattr\n", errno);
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                printf("error %d from tcsetattr\n", errno);
                return -1;
        }
        return 0;
}

void set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                printf("error %d from tggetattr\n", errno);
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                printf("error %d setting term attributes\n", errno);
}

////////////////////////////////////////////////////////////////////////////////

#define DebutRame               0x1D    
  
#define REQ_ORDER_VERSION       0x9C   
#define REQ_GET_DATA            0x9D
#define REQ_SET_CONFIG          0x9E
#define REQ_GET_CONFIG          0x9F
#define REQ_ENABLE_HEATER       0xA0
#define SET_MANUAL_COOLER_ORDER 0xA1
#define SET_AUTO_COOLER_ORDER   0xA2
#define GET_INFOS_EF_CANON      0xA3
#define SET_CANON_DIAPH         0xA4
#define SET_CANON_FOCUS         0xA5
#define REQ_GET_DATAEXT         0xA6   


#define  _5V_         5.0F
#define  Iters       16.0F   
#define  _10bits_  1024.0F    


#define Global_Offset_RH  0.1515F
#define Global_Factor_RH  1.0/0.00636 

///////////////////////////////////////////////////////////////////////////////


unsigned char ComputeCheckSum(unsigned char B[], int sz)
{
 int k;
 unsigned char CRC;
 CRC=0;
 
 printf("Size checksum %d chars\n",sz );
 
 for (k=1;k<sz;k++) 
   CRC=CRC+B[k-1];       
 
 printf("Checksum is %d\n",CRC);
  
 
 return CRC;
}  

///////////////////////////////////////////////////////////////////////////////

double ADU_ToTemp(unsigned short int Value)
{
  double valout=((double)Value/(Iters*_10bits_))*_5V_; // Volts

  valout=(valout-0.5)*100.0;
  
  return valout;
}  

///////////////////////////////////////////////////////////////////////////////

double  ADU_ToRH(unsigned short int Value)
{
  double valout=((double)Value/(Iters*_10bits_));

  valout=(valout-Global_Offset_RH)*Global_Factor_RH;
  
  return valout;
}   

///////////////////////////////////////////////////////////////////////////////

int main()
{
	
printf("Starting test software\n");


char *portname = "/dev/serial0";
char buf [100];
int  k;
int  fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);


printf("Serial port opened OK\n");


if (fd < 0)
{
  printf("error %d opening %s: %s\n", errno, portname, strerror (errno));
  return 4; 
}

set_interface_attribs (fd, B115200, 0); // set speed to 115200 bps, 8n1 (no parity)
set_blocking (fd,0);                   // set to blocking

unsigned char bufout [4];

// GET FIRMWARE VERSION /////////////////////////////////////////////////////////////////////////

bufout[0]=DebutRame;                 // Beginning of frame
bufout[1]=2;                         // Length =2 because of 2 bytes as bufout[1] and bufout[2] 
bufout[2]=REQ_ORDER_VERSION;         // Order to do execute
bufout[3]=ComputeCheckSum(bufout,4); // Last byte is CRC 


int n = write (fd, bufout, sizeof bufout);      // send bytes to weather board

printf("Send %d chars OK\n",n );


usleep ((3 + 25) * 100);                // sleep enough to transmit the 7 plus
                                        // receive 25:  approx 100 uS per char transmit

 
n = read (fd, buf, sizeof buf);         // read up to 100 characters if ready to read

printf("Returned %d bytes\n",n);


if (n=7)
{
 for (k=0;k<n;k++) 
 {   
 printf("Value (%d) -> %d -> 0x%x \n",k,buf[k],buf[k]);
 
 } 
 printf("Weather board firmware version is %d.%d\n",buf[2],buf[3]);
  
}

//////////////////////////////////////////////////////////////////////////////

printf("Get main data\n");


bufout[0]=DebutRame;                 // Beginning of frame
bufout[1]=2;                         // Length Norder+1  
bufout[2]=REQ_GET_DATA;              // Order to do
bufout[3]=ComputeCheckSum(bufout,4); // Last byte is CRC 

write (fd, bufout, sizeof bufout);  

usleep ((3 + 25) * 100); 

n = read (fd, buf, sizeof buf);         // read up to 100 characters if ready to read

printf("Returned %d bytes\n",n);

                                       // buf[0] and buf[1] are not used    

 for (k=0;k<n;k++) 
 {   
 printf("Value (%d) -> %d -> 0x%x \n",k,buf[k],buf[k]);
 
 } 


unsigned short int Value16b=
               ((unsigned short int)(buf[2]) <<  8 ) |
               ((unsigned short int)(buf[3])        );

double TempExt=ADU_ToTemp(Value16b);  

printf("External temperature is %1.2f °C Raw is 0x%x (0x%x 0x%x)\n",TempExt,Value16b,buf[2],buf[3]);


Value16b=
               ((unsigned short int)(buf[4]) <<  8 ) |
               ((unsigned short int)(buf[5])        );

double RHExt=ADU_ToRH(Value16b);  

printf("External relative humidity is %1.1f %% Raw is 0x%x\n",RHExt,Value16b);


//////////////////////////////////////////////////////////////////////////////

printf("Exiting this test app, bye!\n");

return 0;

}
