/*
DEMO98.c: Shows how to use the uPAC-7186 timer function to send/receive data to or from 7000 series modules.
          And set timeout in time unit ms.

Compiler: BC++ 3.1, 
          Turbo C++ 1.01(3.01) (free from http://cc.codegear.com/free/cpp)
          MSC 6.0,
          MSVC 1.52.

Compile mode: Large

Project: DEMO98.c
         ..\..\Lib\(8000e.Lib, 7188el.Lib or 7186el.Lib)

Hardware: i-7188/uPAC-7186/i-8000

Note: COM2(RS-485) 9600,N,8,1

[Oct 30, 2008] by Liam
*/

#include <stdio.h>
#include <stdlib.h>
#include "..\..\lib\7186e.h"

unsigned char Com2Buf[80]={0};
int Com2Idx=0;
int fCom2HasDataIn=0;
unsigned char Com4InBuf[80]={0};
int Com4Idx=0;
int CheckSum=0;
unsigned long Timeout=500;  // default timeout=0.5 sec
int bWait485Echo=0;
int fTimeOut=0;

void MonitorCom2(void)
{
    unsigned char data;
    while(IsCom(2))
    {
        data=ReadCom(2);
        if(data=='\r')
        {
            Com2Buf[Com2Idx]=0;
            fCom2HasDataIn=1;
            break;
        }
        else
                Com2Buf[Com2Idx++]=data;
    }
    
    if(bWait485Echo && !fCom2HasDataIn)
    {
        unsigned long t;
        StopWatchReadValue(0,&t);
        if(t>Timeout)
        {
            fTimeOut=1;
            bWait485Echo=0;
        }
    }
}

void ToCom485(int port,unsigned char *buf,int checksum)
{
    unsigned char sum=0;

    if(!(*buf)) return;

    while(*buf)
    {
        ToCom(port,*buf);
        if(checksum)
            sum+=*buf;
            
        buf++;
    }
    if(checksum)
    {
        ToCom(port,hex_to_ascii[sum>>4]);
        ToCom(port,hex_to_ascii[sum&0x0f]);
    }
    
    ToCom(port,'\r');
}

void CheckCom2Data(int checksum)
{
    unsigned char sum=0;
    int i;
    
    for(i=0;i<Com2Idx-2;i++)
    {
        if(checksum)
            sum+=Com2Buf[i];
        Putch(Com2Buf[i]);
    }
    if(checksum)
    {
        if(ascii_to_hex(Com2Buf[i])!=(sum>>4) || ascii_to_hex(Com2Buf[i+1])!=(sum&0x0f))
        {
            Print("!!! Checksum error !!! (%02X)-->%c%c",sum,Com2Buf[i],Com2Buf[i+1]);
        }
    }
    else
    {
        Putch(Com2Buf[i++]);
        Putch(Com2Buf[i++]);
    }
    
    Putch('\r');
    Putch('\n');
    Com2Idx=0;
}

void main(int argc, char *argv[])
{
    int quit=0;
    unsigned char data;
    long baud=9600;
    
    InitLib();
    
    if(argc>1)
    {
        baud=atol(argv[1]);
        if(baud<1200 || baud>115200) baud=9600;
    }
    
    Print("COM2, %ld, N, 8, 1\r\n", baud);
    
    InstallCom(2, baud, 8, 0, 1);
    TimerOpen();
    InstallUserTimer(MonitorCom2);
    
    while(!quit)
    {
        if(Kbhit())
        {
            data=Getch();
            switch(data)
            {
                case 'q':
                    quit=1;
                    break;
                    
                case 's':
                    CheckSum=!CheckSum;
                    Print("\n\rCheckSum=%d\r\n", CheckSum);
                    break;
                    
                case '\r':
                    if(Com4Idx)
                    {
                        Com4InBuf[Com4Idx]=0;
                        Com4Idx=0;
                    }
                    Putch('\r');
                    Putch('\n');
                    ToCom485(2, Com4InBuf, CheckSum);
                    bWait485Echo=1;
                    StopWatchStart(0);
                    break;
                    
                case '\b':
                    if(Com4Idx)
                    {
                        Com4Idx--;
                        Putch('\b');
                    }
                    break;
                    
                default:
                    Com4InBuf[Com4Idx++]=data;
                    Putch(data);
                    break;
            }
        }
        
        if(fTimeOut)
        {
            fTimeOut=0;
            bWait485Echo=0;
            Print(" !!! Timeout !!! \r\n");
        }
        
        if(fCom2HasDataIn)
        {
            CheckCom2Data(CheckSum);
            fCom2HasDataIn=0;
            bWait485Echo=0;
        }
    }
    
    TimerClose();
    RestoreCom(2);
}