// OWC_1.CPP (Bloodshed Dev-Cpp)
//
// Flashes an LED on CH 5 ten times.
//
// Performs a temperature measurement using a DS18B20 on CH 0 and a
// voltage measurement on CH 1.
//
// If the voltage is greater than 2.8 VDC, an LED on CH 5 is truned on.
// The LED is turned off if the voltage is less than 2.3 VDC.
// 
// copyright, Peter H Anderson, Aug 27, '07, Sept 9, '07
//
#include 
#include 
#include 
#include 
#include 

#define COM_PORT 1 // <<<<<<<<<<<< Modify as required.

float meas_temp_ds18b20(int ch);
float meas_ad_v(int ch);
int output_state(int ch, int state);

// RS232 Routines
HANDLE rs_initialise (const long int BaudRate, 
                      const char parity, const char data);
void rs_flush(void);
void rs_terminate(void);
char rs_getch(void);
int rs_getline(char line[], clock_t timeout);
void rs_putch(int txchar);
void rs_putstr(const char *string);

// delay_routines
void delay_ms(clock_t millis);

HANDLE hCom;           //handle for serial port I/O
int io_port;

int main()
{    
    io_port = COM_PORT;
    clock_t timeout;
	float Tc, volts;
	int n;
	
    if(!rs_initialise(9600, '8', 'N')) // open the COM port
    { 
         printf("Opening Port Failed");
         delay_ms(5000);
         exit(1); 
    }
       
    for (n=0; n<10; n++) // flash an LED for show
    {
        output_state(5, 1);
        delay_ms(100);
        output_state(5, 0);
        delay_ms(100);
    }    

    timeout = clock() + 60000;  // every 60 secs
    while(1) // forever
    {
         Tc = meas_temp_ds18b20(0);   // perform a temperature measurement on channel 0
         if (Tc < -300.0)
         {
             printf("Error\n");
         }
         else
         {
             printf("Tc = %.2f\n", Tc);
         }  
         
         volts = meas_ad_v(1);   // channel 1
         if (volts < 0.0)
         {
             printf("Error\n");
         }
         else
         {
             printf("VDC = %.2f\n", volts);
         }  
         
         if (volts >= 2.8)
         {
             output_state(5, 1);
         }
         if (volts <= 2.3)
         {
             output_state(5, 0);
         }                                       
                           
         while(clock() < timeout) // wait for the balance of the 60 seconds
         {
         }
         timeout = timeout + 60000; // new timeout value
    }
    // as written, the program never really gets to this point
    rs_terminate();
    while(getchar() != 'x')
    {
    }
    return 0;
}

float meas_temp_ds18b20(int ch)
{
    char s[25], line[25];
    int num_chars, high, low, word; 
    float Tc;

    sprintf(s, "P%1dW%1dccS%1d44", ch, ch, ch); 
                // presence, 0xcc, 0x44 followed by one second of strong pullup

    rs_putstr(s);
    delay_ms(1200);
    
    sprintf(s, "P%1dW%1dccW%1dbe", ch, ch, ch); 
              // presence,, 0xcc, 0xbe
    rs_putstr(s);
    delay_ms(200);
    
    rs_flush(); // flush the buffer prior to a read
    sprintf(s, "R%1d", ch);
    rs_putstr(s);
    
    delay_ms(50);
    num_chars = rs_getline(line, 100); 
    // printf("%d %s\n", num_chars, line);
    sscanf(line, "%x", &low);  
    //printf("....%x\n", low);

    rs_flush();  // flush buffer
    sprintf(s, "R%1d", ch); 
    rs_putstr(s);
    
    delay_ms(50);
    num_chars = rs_getline(line, 100);
    // printf("%d %s\n", num_chars, line);
    
    sscanf(line, "%x", &high);  
    // printf("....%x\n", high); 
    word = (high << 8) | low;
    if (word & 0x8000)
    {
        word = (word ^ 0xffff) + 1;
        Tc = -0.0625 * (float) word;
    }        
    else
    {
         Tc = 0.0625 * (float)(word);
    }    
    return(Tc);
}

float meas_ad_v(int ch)
{
    char s[25], line[25];
    int num_chars, ad_val; 
    float volts;

    rs_flush();
    sprintf(s, "A%1d", ch); 
                // A followed by the channel

    rs_putstr(s);
           
    num_chars = rs_getline(line, 250); 
    
    
    // printf("%d %s\n", num_chars, line);
    if(sscanf(line, "%x", &ad_val) != 1)
    {
        return(-1.0);
    }
    else
    {
       volts = (float) ad_val * 5.0 / 1024.0;        
       return(volts);
    }
}

int output_state(int ch, int state)
{
    char s[25], line[25];
    int num_chars, relay_state;  
    rs_flush();
    
    if (state == 1)
    {
        sprintf(s, "H%1d", ch);  // H followed by the channel
    }
    else
    {
        sprintf(s, "L%1d", ch);
    }        

    rs_putstr(s);
           
    num_chars = rs_getline(line, 250); 
    sscanf(line, "%d", &relay_state);
    return(relay_state);
}
HANDLE rs_initialise (const long int BaudRate, const char parity, const char data)
{
    BOOL bPortReady;
    DCB dcb;
	COMMTIMEOUTS CommTimeouts;

    char ComPortName[5]="COM ";           
    ComPortName[3]='0'+ io_port;
    hCom = CreateFile(ComPortName, GENERIC_READ | GENERIC_WRITE,
                                  0,            // exclusive access
                                  NULL,         // no security
                                  OPEN_EXISTING,
                                  0,            // no overlapped I/O
                                  NULL);        // null template
                                  
  
    if ((int)hCom <= 0) 
    { 
        printf("serial port COM%d connect fail %s error %d\n\r", io_port, ComPortName, GetLastError()); 
        return 0;   
    } 
    //else                printf(" serial port COM%d connect OK \n\r", io_port); 
                 
    bPortReady = SetupComm(hCom, 128, 128); // set buffer sizes
    if (!bPortReady ) 
    { 
        printf("serial port COM%d SetupComm fail  %d\n\r", io_port,  GetLastError()); 
        return 0; 
    } 
    //else                printf(" serial port COM%d connect OK \n\r", io_port); 

    bPortReady = GetCommState(hCom, &dcb);
    if (!bPortReady ) 
    { 
        printf("serial port COM%d  GetCommState fail  %d\n\r", io_port,  GetLastError()); 
        return 0;   
    } 
    //  else                printf(" serial port COM%d connect OK \n\r", io_port); 
    dcb.BaudRate = BaudRate;
    if( data == '7') dcb.ByteSize = 7;
    else             dcb.ByteSize = 8;
    if( parity == 'E') dcb.Parity = EVENPARITY;
    if( parity == 'O') dcb.Parity = ODDPARITY;
    else               dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.fAbortOnError = TRUE;

    // set XON/XOFF
    dcb.fOutX = FALSE;                       // XON/XOFF off for transmit
    dcb.fInX = FALSE;                        // XON/XOFF off for receive
    // set RTSCTS
    dcb.fOutxCtsFlow = FALSE;               // turn off CTS flow control
    dcb.fRtsControl = FALSE;                // RTS_CONTROL_HANDSHAKE; //
    // set DSRDTR
    dcb.fOutxDsrFlow = FALSE;               // turn off DSR flow control
    //dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR handshake
    dcb.fDtrControl = DTR_CONTROL_DISABLE;  //
    // dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; //

    bPortReady = SetCommState(hCom, &dcb);
    if (!bPortReady ) 
    { 
        printf("serial port COM%d  SetCommState fail  %d\n\r", io_port,  GetLastError()); 
        return 0;   
    } 

    // Communication timeouts 
    //COMMTIMEOUTS CommTimeouts;
    bPortReady = GetCommTimeouts (hCom, &CommTimeouts);
    CommTimeouts.ReadIntervalTimeout = 5 ;
    CommTimeouts.ReadTotalTimeoutConstant = 5 ;
    CommTimeouts.ReadTotalTimeoutMultiplier = 1 ;
    CommTimeouts.WriteTotalTimeoutConstant = 5 ;
    CommTimeouts.WriteTotalTimeoutMultiplier = 1 ;
    bPortReady = SetCommTimeouts (hCom, &CommTimeouts);
    if (!bPortReady ) 
    { 
        printf("serial port COM%d SetCommTimeouts fail  %d\n\r", io_port,  GetLastError()); 
        return 0;   
    } 
    else
    {
        printf(" serial port COM%d connect OK \n\r", io_port); 
    }
    return (hCom);
}

void rs_terminate(void)
{
   CloseHandle(hCom);
}

char rs_getch(void)
{
    char rxchar;
    BOOL bReadRC;
    static DWORD iBytesRead;
    bReadRC = ReadFile(hCom, &rxchar, 1, &iBytesRead, NULL);
    if (iBytesRead) 
    {
        return rxchar; 
    }
    else 
    {
        return 0;         // return 0 if no character read
    }
}

void rs_flush(void)
{
    while(rs_getch()!=0)   ;
}

int rs_getline(char line[], clock_t timeout)
{
    int num_chars = 0;
    char ch;
    clock_t endtime;
    endtime = timeout + clock();
    //printf("%ld %ld\n", clock(), endtime);
    while(endtime > clock())
    {   
        //printf("!");
        ch = rs_getch();
        //printf("%d ", ch);
        if (ch != 0)
        {
            //printf("%c", ch);
            if ((ch == 10) || (ch == 13))
            {
                line[num_chars] = '\0'; // terminate the string
                return(num_chars);
            }    
                                  
            else
            {
                line[num_chars] = ch;
                ++num_chars;
            }
        }
       
    } // end of while
    line[num_chars] = '\0';
    return(-1);  // timeout
}                 

void rs_putch(int txchar)
{
    BOOL bWriteRC;
    static DWORD iBytesWritten;
    bWriteRC = WriteFile(hCom, &txchar, 1, &iBytesWritten,NULL);
    return;
}

void rs_putstr(const char *string)
{
    while (*string != '\0')
    {
        delay_ms(5);
        rs_putch(*string++);
    }    
}

void delay_ms(clock_t millis)
{
   clock_t endtime;
   endtime = millis + clock();
   while( endtime > clock() )        ;
   
}