/***************************************************************************
**
** File name : SERIALCM.CPP 
** Author:john chow
** Description:
**    Descript the base function of serial communication for 251,196
**
**    Finished date: 97.1
**    modifed date:
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

#include "stdafx.h"

#include "serialcm.h"    
//implemention of CBasePipe
void CBasePipe::AddByte(BYTE bByte)
{
	ASSERT(m_nPos<MAX_BUFFER);
	m_buffer[m_nPos++] = bByte;
 }                        
 
void CBasePipe::AddBytes(BYTE* pByte,int nLen)
{
	ASSERT(m_nPos+nLen<=MAX_BUFFER);
	memcpy(&(m_buffer[m_nPos]),pByte,nLen);
	m_nPos += nLen;
 }
 
void CBasePipe::GetByte(BYTE& bByte)
{ 
	ASSERT(m_nPos<MAX_BUFFER);
	bByte = m_buffer[m_nPos++];	
 }

void CBasePipe::GetBytes(BYTE* pByte,int nLen)
{                  
	ASSERT(m_nPos+nLen<=MAX_BUFFER);
	memcpy(pByte,&(m_buffer[m_nPos]),nLen);
	m_nPos += nLen;
 }

//implemention of CAbiPipe
void CAbiPipe::SetVar(BYTE* pByte,int nLen)
{
	AddByte((BYTE)nLen);              
	AddBytes(pByte,nLen);
 }
 
BOOL CAbiPipe::GetVar(BYTE* pByte,int nLen)
{                      
	BYTE bTmp;
	GetByte(bTmp);
	if((BYTE)nLen != bTmp) {
		ASSERT(FALSE);
		return FALSE;
	}
	GetBytes(pByte,nLen);
	return TRUE;
 }
 
void CAbiPipe::LoadBuffer(BYTE* pByte)
{                      
	BYTE bTmp;
	GetByte(bTmp);
	GetBytes(pByte,bTmp);
	return;
 }

void CAbiPipe::LoadBuffer(BYTE* pByte,BYTE& len)
{                      
	GetByte(len);
	GetBytes(pByte,len);
	return;
 }
 
void CAbiPipe::StartVar(BYTE bByte)
{                  
	Reflash();
	AddByte(bByte);
 }

void CAbiPipe::EndVar(BYTE bByte)
{                  
	AddByte(bByte);
 }             
 
WORD CAbiPipe::GetStatus()
{ 
	WORD nTmp;
	GetBytes((BYTE*)(&nTmp),2);
	return nTmp;
 }

//implemention of CBaseCom
void CBaseCom :: SetTimer(unsigned long lTimer)
{ 
    m_lTimer = lTimer;
    _ftime( &m_startTime ); 
 }
void CBaseCom :: RestartTimer()
{ 
    _ftime( &m_startTime ); 
 }
               
               
BOOL CBaseCom::IsTimeOut()
{ 
    _ftime(&m_currentTime);
    unsigned long lTmp1,lTmp2;
    lTmp1 = m_currentTime.time*1000 + m_currentTime.millitm;
    lTmp2 = m_startTime.time*1000 + m_startTime.millitm;
    unsigned long lResult = lTmp1 - lTmp2;
    if(lResult > m_lTimer) 
        return TRUE; else return FALSE;
 }                     
 
BOOL CBaseCom::SendString(BYTE *pBuff,int nLen) 
{       
    if(!m_isCanBeUsed) {
        m_nError = ERR_NOT_REPARE;
        return FALSE;
    }   
    for (int i=0;i<nLen;i++) {
       if (SendByte(pBuff[i])!=TRUE) return FALSE;
       RestartTimer();
    }          
    m_nError = m_nDetailError = ERR_NO;
    return TRUE;        
 }            
 
BOOL CBaseCom::ReceiveString(BYTE *pBuff,int nLen)
{                         
    if(!m_isCanBeUsed) {
        m_nError = ERR_NOT_REPARE;
        return FALSE;
    }   
    for (int i=0;i<nLen;i++) {
       if (ReceiveByte(pBuff[i])!=TRUE) return FALSE;
       RestartTimer();
    }                                  
    m_nError = m_nDetailError = ERR_NO;
    return TRUE;            
 } 
 
//implement of CBaseAgree
CBaseAgree::CBaseAgree()
{     
	m_pPipe = NULL; 
    bRelinkTimes = 0;
 } 
 
CBaseAgree::~CBaseAgree()
{ 
        
 }  
 
//implement of CTWAgree
BOOL CTWAgree::Init() 
{   
    char strTmp[20];
    BYTE bTmp;
    
    while (TRUE) {
    	CString strLinker = GetLinkerStr();                                  
	    CString strLinker_ = GetLinkerStr_(); 
	    int nLen = strLinker.GetLength();
	    strcpy(strTmp,strLinker.GetBuffer(nLen+2));
	    strLinker.ReleaseBuffer();
	    
    	if( IsEscape() && !IsRelink()) {  
        	isConnected = FALSE;    
        	m_nError = ERR_ESC;
        	return FALSE;
        }
        
        SetTimer(200);    
        FlushBufferIn();
        FlushBufferOut();
        if (FALSE == SendString((BYTE*)(strTmp),strlen(strTmp))) 
        	continue;
        SetTimer(300);
        if(TRUE == ReceiveByte(bTmp)) {
            if(bTmp == ACK) {  
                isConnected = TRUE;              
                m_nError = m_nDetailError = ERR_NO;
                return TRUE;
            }
        }       
        
    }       
    
    isConnected = FALSE;    
    return FALSE;           
        
 }               
                                         
BOOL CTWAgree::SendCommand()  
{       
    if (!isConnected) {
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }   
    
    FlushBufferIn();
    FlushBufferOut();
    
    WORD nOutputStrLen = (WORD)(m_pPipe->GetLen());
    BYTE bCheckSum;                   
    ASSERT(nOutputStrLen>0);
    ASSERT(0 == m_pPipe->GetAt(nOutputStrLen-1));
    
    BYTE strTmp[10];
    strTmp[0] = ':';
    strTmp[1] = (BYTE)(((nOutputStrLen+1)<<8)>>8);
    strTmp[2] = (BYTE)((nOutputStrLen+1)>>8);
    strTmp[3] = (BYTE)(~(strTmp[1]+strTmp[2])+1);    
    bCheckSum = 0;
    for(unsigned int i=0;i<nOutputStrLen;i++)
        bCheckSum = (BYTE)(bCheckSum + m_pPipe->GetAt(i));    
    m_pPipe->AddByte((BYTE)((~bCheckSum)+1));    
    
    while (TRUE) {
    	if( IsEscape() && !IsRelink()) {  
        	isConnected = FALSE;    
        	m_nError = ERR_ESC;
        	return FALSE;
        }
        SetTimer(200);
        if (FALSE == SendString(strTmp,4)) {
        	m_nErrorTime++;
        	continue;
        }	
        SetTimer(1000);
        if (FALSE == SendString(m_pPipe->GetBuffer(),nOutputStrLen+1)) {
        	m_nErrorTime++;
        	continue;
        }
        SetTimer(2000);
        if (FALSE == ReceiveByte(strTmp[0])) {
        	m_nErrorTime++;
        	continue;
        }	
        if (ACK == strTmp[0]) {
            m_nError = m_nDetailError = ERR_NO;
            return TRUE;                       
        }    
        if (NACK == strTmp[0]) {
            m_nErrorTime++;
            continue;
        }   
        
        //m_nError = ERR_RECEIVE_WRONGCODE;
        m_nErrorTime++;
        
        //return FALSE;
    }
    
 }
 
BOOL CTWAgree::ReceiveResult()  
{       
    if (!isConnected) {
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }   
    
    BYTE strTmp[10];  
    BYTE tmpBuf[MAX_BUFFER];       
    WORD nInputStrLen;
    
    while (TRUE) {
        SetTimer(nBackTime);
        if (FALSE == ReceiveByte(strTmp[0])) {
            m_nErrorTime++;  
            if( IsEscape() && !IsRelink()) {  
	        	isConnected = FALSE;    
	        	m_nError = ERR_ESC;
	        	return FALSE;
	        }
            continue;
        }        
        
        SetTimer(200);
        if (FALSE == ReceiveString(strTmp,3)) {
            m_nErrorTime++;
            //SetTimer(100);
            //if(FALSE == SendByte(NACK)) return FALSE;
            //m_nError = ERR_SEND_NACK;
            continue;                          
        }    
        
        if(0 == (BYTE)(strTmp[0] + strTmp[1] + strTmp[2]) ) {
            nInputStrLen = (BYTE)(256*strTmp[1] + strTmp[0]);
        } else {
        	m_nErrorTime++;
        	continue;  
        }	
                      
        SetTimer(1000);
        if (FALSE == ReceiveString(tmpBuf,nInputStrLen)) {
            m_nErrorTime++;
            SetTimer(100);
            SendByte(NACK);
            continue;    
        }    
                                        
        strTmp[0] = 0;                                
        for (unsigned int i=0;i<nInputStrLen;i++) 
            strTmp[0] = (BYTE)(strTmp[0] + tmpBuf[i]);
        if(0 == strTmp[0]) {
            nInputStrLen--;
            m_pPipe->Reflash();
            m_pPipe->AddBytes(tmpBuf,nInputStrLen);
            SetTimer(100);
            return SendByte(ACK);
        }   
                
        SetTimer(100);
        m_nErrorTime++;
        SendByte(NACK);
    }   
    
 } 

BOOL CTWAgree::Do() 
{ 
             
    if(!SendCommand()) return FALSE;
    
    return ReceiveResult();
}                     


 
//implement of C196Agree
BOOL C196Agree::Init() 
{   
    char strTmp[20];
    
    for (int i =0;i<8;i++) {
    	CString strLinker = GetLinkerStr();                                  
	    CString strLinker_ = GetLinkerStr_();  
	    int nLen = strLinker.GetLength();
	    strcpy(strTmp,strLinker.GetBuffer(nLen+2));
	    strLinker.ReleaseBuffer();
	    
        SetTimer(100);    
        FlushBufferIn();
        FlushBufferOut();
        if (FALSE == SendString((BYTE*)strTmp,strLinker.GetLength() )) continue;
        SetTimer(100);
        if(TRUE == ReceiveString((BYTE*)strTmp,strLinker_.GetLength() )) {
            strTmp[strLinker_.GetLength()] = 0;
            if(strLinker_ == strTmp) {  
                isConnected = TRUE;              
                m_nError = m_nDetailError = ERR_NO;
                return TRUE;
            }
        }       
        if( ERR_ESC == m_nError) break;
    }       
    
    isConnected = FALSE;    
    return FALSE;           
        
 }               

BOOL C196Agree::Shakehand(BYTE bTimers)              
{                                        
    if (!isConnected) {
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }
      
    //CLEAR BUFFER
    FlushBufferIn();
    FlushBufferOut();  
      
    BYTE bTmp;
    for (int i=0; i<bTimers; i++) {
        SetTimer(100);
        if(FALSE == SendByte('?')) continue;
        SetTimer(300);
        if(!ReceiveByte(bTmp)) continue;
        else {
            if ('!' == bTmp) {
                m_nError = m_nDetailError = ERR_NO;
                return TRUE;                       
            }    
            m_nError = ERR_RECEIVE_WRONGCODE;   
            return FALSE;
        }    
    }          
    
    m_nError = ERR_TIME_OUT;                            
    return FALSE;
        
 }
 
BOOL C196Agree::Shakehand_()
{       

    if (!isConnected) {
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }   
                  
    BYTE bTmp;
    
    SetTimer(nBackTime);
    if((FALSE == ReceiveByte(bTmp)) || '?' != bTmp )
        return FALSE;               
    SetTimer(100);
    if (FALSE == SendByte('!')) 
    	return FALSE;
    int j = 0;
    for (int i=0; i<20; i++) {
        SetTimer(100);  
        if (FALSE == ReceiveByte(bTmp)) continue;
        if (':' == bTmp) {
            m_nError = m_nDetailError = ERR_NO;
            return TRUE;                        
        }    
        if ('?' == bTmp) {
        	j++;
            if (FALSE == SendByte('!')) 
            	return FALSE;
        }    	
    }                       
    
    m_nError = ERR_TIME_OUT;                            
    return FALSE; 
        
 }  

BOOL C196Agree::SendCommand()  
{       
    if (!isConnected) {
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }   
    
    FlushBufferIn();
    FlushBufferOut();
    
    WORD nOutputStrLen = (WORD)(m_pPipe->GetLen());
    BYTE bCheckSum;                   
    ASSERT(nOutputStrLen>0);
    ASSERT(0 == m_pPipe->GetAt(nOutputStrLen-1));
    
    BYTE strTmp[10];
    
    bCheckSum = 0;
    for(unsigned int i=0;i<nOutputStrLen;i++)
        bCheckSum = (BYTE)(bCheckSum + m_pPipe->GetAt(i));
    bCheckSum = (BYTE)((~bCheckSum)+1);
    
    while (TRUE) {
    	strTmp[0] = ':';
	    strTmp[1] = (BYTE)(((nOutputStrLen+1)<<8)>>8);
	    strTmp[2] = (BYTE)((nOutputStrLen+1)>>8);
	    strTmp[3] = (BYTE)(~(strTmp[1]+strTmp[2])+1);    
    
        SetTimer(100);
        if (FALSE == SendString(strTmp,4)) return FALSE;
        SetTimer(1000);
        if (FALSE == SendString(m_pPipe->GetBuffer(),nOutputStrLen)) return FALSE;
        SetTimer(100);
        if (FALSE == SendByte(bCheckSum)) return FALSE;
        
        SetTimer(1000);
        if (FALSE == ReceiveByte(strTmp[0])) {
        	return FALSE;
        }	
        
        if (ACK == strTmp[0]) {
            m_nError = m_nDetailError = ERR_NO;
            return TRUE;                       
        } 
           
        if (NACK == strTmp[0]) {
        	m_nError = ERR_RECEIVE_NACK;
            m_nErrorTime++;
            return FALSE;
        }
           
        if ('$' == strTmp[0]) {
            m_nError = ERR_RECEIVE_DOLLAR;
            m_nErrorTime++;
            return FALSE;
        }
           
        m_nError = ERR_RECEIVE_WRONGCODE;
        m_nErrorTime++;
        return FALSE;
        
    }                       
    
    m_nError = ERR_TIME_OUT;
    return FALSE;
 }

BOOL C196Agree::ReceiveResult()  
{                            
    if (!isConnected) {      
        m_nError = ERR_NOT_CONNECTED;
        return FALSE;
    }   
    
    BYTE strTmp[20];  
    BYTE tmpBuf[MAX_BUFFER];       
    WORD nInputStrLen;
    
    while (TRUE) {    
    	SetTimer(1000);
        if (FALSE == ReceiveString(strTmp,3)) 
            if (ERR_TIME_OUT == m_nError) {
                m_nErrorTime++;
                if(FALSE == SendByte('$')) return FALSE;
                m_nError = ERR_SEND_DOLLAR;
                return FALSE;
            } else return FALSE;
                      
        if(0 == (BYTE)(strTmp[0] + strTmp[1] + strTmp[2]) ) {
            nInputStrLen = (BYTE)(256*strTmp[1] + strTmp[0]);
        } else {  
	        m_nErrorTime++;           
	        do { SetTimer(100); } while(ReceiveByte(strTmp[0]));
	        SetTimer(100);
	        if (FALSE == SendByte(NACK)) return FALSE;
	        m_nErrorTime++;
        	m_nError = ERR_RECEIVE_WRONGCODE;
        	return FALSE;                    
        }
        
        SetTimer(1000);
        if (FALSE == ReceiveString(tmpBuf,nInputStrLen)) 
            if (ERR_TIME_OUT == m_nError) {
                m_nErrorTime++;
                if(FALSE == SendByte('$')) 
                	return FALSE;
                m_nError = ERR_SEND_DOLLAR;
                return FALSE;
            } else return FALSE;
            	
        strTmp[0] = 0;                                
        for (unsigned int i=0;i<nInputStrLen;i++) 
            strTmp[0] = (BYTE)(strTmp[0] + tmpBuf[i]);
        if(0 == strTmp[0]) {
            nInputStrLen--;
            m_pPipe->Reflash();
            m_pPipe->AddBytes(tmpBuf,nInputStrLen);
            m_pPipe->Reflash();
            SetTimer(100);
            return SendByte(ACK);
        }                                
        
        SetTimer(100);
        if (FALSE == SendByte(NACK)) return FALSE;
        m_nErrorTime++;
    	m_nError = ERR_RECEIVE_WRONGCODE;
    	return FALSE;                           
    }           
 } 

BOOL C196Agree::Do() 
{           
	m_nErrorTime = 0;               
	m_bRelinkTimes = 0;
	while (TRUE) {          
		if (m_nErrorTime > 30) 
			return FALSE;
	    do {
	        if(Shakehand()) break;
	        if(ERR_TIME_OUT != m_nError)
	        	return FALSE;
	        if(!IsRelink()) {
	            m_nError = ERR_RELINKQUIT;
	            m_nDetailError = ERR_SHAKE_HAND;
	            return FALSE;
	        } else break;   
	    } while (TRUE);  
	    
	    if(ERR_TIME_OUT == m_nError) continue;
	    
	    do {         
	        if(SendCommand()) break;
	        if(ERR_RECEIVE_DOLLAR == m_nError ||
	           ERR_RECEIVE_NACK == m_nError) break;
	        if(ERR_TIME_OUT != m_nError) 
	        	return FALSE;
	        if(!IsRelink()) {
	            m_nError = ERR_RELINKQUIT;
	            m_nDetailError = ERR_SEND_COMMAND;
	            return FALSE;
	        } else break;   
	    } while (TRUE);
	    
	    if(ERR_TIME_OUT == m_nError || ERR_RECEIVE_DOLLAR == m_nError
	       || ERR_RECEIVE_NACK == m_nError) continue;
	       
	    do {         
	        if(Shakehand_()) break;
	        if(ERR_TIME_OUT != m_nError) 
	        	return FALSE;   
	        if(!IsRelink()) {
	            m_nError = ERR_RELINKQUIT;    
	            m_nDetailError = ERR_SHAKE_HAND_;
	            return FALSE;
	        } else break;   
	    } while (TRUE);         
	    
	    if(ERR_TIME_OUT == m_nError) continue;
	                     
	    do {         
	        if(ReceiveResult()) break;
	        if(ERR_SEND_DOLLAR == m_nError 
	           || ERR_RECEIVE_WRONGCODE == m_nError) break;
	        if(ERR_TIME_OUT != m_nError) 
	        	return FALSE;
	        if(!IsRelink()) {
	            m_nError = ERR_RELINKQUIT;  
	            m_nDetailError = ERR_RECEIVE_RESULT;
	            return FALSE;
	        } else break;   
	    } while (TRUE);
	                     
	    if(ERR_TIME_OUT == m_nError || ERR_SEND_DOLLAR == m_nError
	      || ERR_RECEIVE_WRONGCODE == m_nError ) continue;   
	    
	    return TRUE;
	}   
}                     
 
 
//implemention of CBaseSerialAgree
BYTE CBaseSerialAgree::GetSerialBaudRate()
{   
    return m_bBaudRate;            
 }
 
BYTE CBaseSerialAgree::GetSerialPortNum()
{                                        
    return m_bPortNum;
 } 
 

CString CBaseSerialAgree::GetSerialPortNumStr()
{         
    CString strTmp;     
    switch (m_bPortNum) {
        case COM_PORT_1 : strTmp = "COM1"; break;
        case COM_PORT_2 : strTmp = "COM2"; break;
        case COM_PORT_3 : strTmp = "COM3"; break;
        case COM_PORT_4 : strTmp = "COM4"; break;
    }
    return strTmp;      
 }
 
CString CBaseSerialAgree::GetSerialBaudRateStr()
{                       
    CString strTmp;     
    switch (m_bBaudRate) {
        case BAUD_9600  : strTmp = "9600"; break;
        case BAUD_19200 : strTmp = "19200"; break;
        case BAUD_38400 : strTmp = "38400"; break;
        case BAUD_57600 : strTmp = "57600"; break;
        case BAUD_115200: strTmp = "115200"; break;
    }
    return strTmp;      
 }
