/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/UISERIAL.CPP   1.2.1.4   17 Apr 1997 16:08:44   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/UISERIAL.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 16:08:44   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:44:10   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:48:46   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:27:52   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:31:12   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:40:22   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:53:18   ZJRD
** Initial revision.
** 
**    Rev 1.6   21 Oct 1996 09:19:22   ZJRD
** No change.
** 
**    Rev 1.5   09 Oct 1996 13:51:46   ZJRD
** No change.
** 
**    Rev 1.4   23 Sep 1996 10:39:02   ZJRD
** No change.
** 
**    Rev 1.3   06 Sep 1996 13:53:08   ZJRD
** No change.
** 
**    Rev 1.2   02 Sep 1996 11:34:24   ZJRD
** PIC-SLD Version 0.50
** 
**    Rev 1.0   13 Aug 1996 09:20:14   ZJRD
** Initial revision.
** 
****************************************************************************/

/***************************************************************************
**
** File name : UISERIAL.CPP
** Author:john chow
** Description:
**    Descript the function of serial communication for PIC-SLD
**
**    Finished date: 96.7
**    modifed date:
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/

#include "stdafx.h"

#include "uiserial.h"
#include "conio.h"
#include "resource.h"
#include "communic.h"
#include "abitype.h"
//#include "abiextfn.h"

extern int OpenAbiComDlg(int fHelpComm);
extern void ExitEpsld(void);
//STATUS AbiTestCom(char* pTestData,char* pRetData);   
extern STATUS AbiSelectBaud(BYTE bOption);
extern "C" {
	WORD FAR PASCAL _export WhatCpu();    
}	

//implemention of class CWinSerialPICAgree

CWinSerialPICAgree::CWinSerialPICAgree()
{                     
    for(int i=0;i<=COM_PORT_4;i++) {
        char strTmp[10];
        int nTmpID;
        sprintf(strTmp,"COM%01d",i+1);
        nTmpID = OpenComm(strTmp,128,128);
        if (nTmpID <0) SerialInfor[i] = FALSE;
        else {
            SerialInfor[i] = TRUE;
            CloseComm(nTmpID);
        }
    }       
                
    m_nDeviceID = -1;
    m_bDefaultBaudRate = BAUD_19200;
 }
 
CWinSerialPICAgree::~CWinSerialPICAgree()
{   
    if(m_nDeviceID >= 0) CloseComm(m_nDeviceID);
 }

BOOL CWinSerialPICAgree::SetSerialOption()
{                     
   m_DCB.Id = 0x01;
   m_DCB.BaudRate = 0xff18;
   m_DCB.ByteSize = 0x08;
   m_DCB.Parity = 0x00;
   m_DCB.StopBits = 0x00;
   m_DCB.RlsTimeout = 0x0000;
   m_DCB.CtsTimeout = 0x0000;
   m_DCB.DsrTimeout = 0x0000;
   m_DCB.fBinary = 0x0001;
   m_DCB.fRtsDisable = 0x0000;
   m_DCB.fParity = 0x0000;
   m_DCB.fOutxCtsFlow = 0x0000;
   m_DCB.fOutxDsrFlow = 0x0000;
   m_DCB.fDummy = 0x0000;
   m_DCB.fDtrDisable = 0x0000;
   m_DCB.fOutX = 0x0000;
   m_DCB.fInX = 0x0000;
   m_DCB.fPeChar = 0x0000;
   m_DCB.fNull = 0x0000;
   m_DCB.fChEvt = 0x0000;
   m_DCB.fDtrflow = 0x0000;
   m_DCB.fRtsflow = 0x0000;
   m_DCB.fDummy2 = 0x0000;
   m_DCB.XonChar = 0x00;
   m_DCB.XoffChar = 0x00;
   m_DCB.XonLim = 0x007f;
   m_DCB.XoffLim = 0x007f;
   m_DCB.PeChar = 0x00;
   m_DCB.EofChar = 0x00;
   m_DCB.EvtChar = 0x00;
   m_DCB.TxDelay = 0x0000;
   return TRUE;
 }
 
BOOL CWinSerialPICAgree::SetSerialPortBaud(BYTE bPortNum,BYTE bBaudRate) 
{                                                
    if(m_nDeviceID>=0) CloseComm(m_nDeviceID);
    m_nDeviceID = -1;
    
    isConnected = FALSE;
    m_isCanBeUsed = FALSE;
    
    switch (bBaudRate) {
        case BAUD_9600  : m_DCB.BaudRate = CBR_9600; break;
        case BAUD_19200 : m_DCB.BaudRate = CBR_19200; break;
        case BAUD_38400 : m_DCB.BaudRate = CBR_38400; break;
        case BAUD_57600 : m_DCB.BaudRate = CBR_56000; break;
        case BAUD_115200: m_DCB.BaudRate = CBR_128000; break;
    }                                         
    
    char strTmp[10];
    int nTmpID;
    sprintf(strTmp,"COM%01d",bPortNum+1-4);
    nTmpID = OpenComm(strTmp,INPUTLEN,OUTPUTLEN);
    if (nTmpID <0) { 
        SerialInfor[bPortNum] = FALSE; 
        m_nError = ERR_OPEN;
        return FALSE; 
    }
    
    m_DCB.Id = nTmpID;                     
    nTmpID = SetCommState(&m_DCB);
    if (nTmpID <0) {
        CloseComm(m_DCB.Id);  
        m_nError = ERR_BAUD;
        return FALSE;
    }   
    
    m_isCanBeUsed = TRUE;
    m_nDeviceID = m_DCB.Id;
    
    m_bBaudRate = bBaudRate;
    m_bPortNum = bPortNum;  
    
    m_nError = m_nDetailError = ERR_NO;
    
    return TRUE;
 }                            
 
BOOL CWinSerialPICAgree::TryInit()      
{                                            
    if (!SetSerialOption()) return FALSE;
    for (char j=BAUD_115200; j>=BAUD_9600; j--) {
        SetSerialPortBaud(m_bPortNum,j);
        BYTE bTmp;
        for (BYTE i=0; i<3; i++) {
            SetTimer(80);
            if(FALSE == SendByte('?')) continue;
            SetTimer(100);
            if(!ReceiveByte(bTmp)) {
                if (ERR_ESC == m_nError) break;
                else continue;
            } else {
                if ('!' == bTmp) {
                    isConnected = TRUE;
                    m_nError = m_nDetailError = ERR_NO;
                    return TRUE;
                } else return FALSE;
            }    
        }// send '?' and receive '!'      
    }//baud for                    
    
    isConnected = FALSE;
    m_nError = ERR_TRYINIT;
    return FALSE;

 }

BOOL CWinSerialPICAgree::CommInit()
{            
    //read init savings                        
    m_bPortNum = AfxGetApp()->GetProfileInt("COMM", "Type", COM_PORT_2);
    if(m_bPortNum < COM_PORT_1 || m_bPortNum > COM_PORT_4) {
        m_bPortNum =  COM_PORT_2;    
    }
    
    m_bBaudRate = AfxGetApp()->GetProfileInt("COMM", "BaudRate",BAUD_115200);
    if(m_bBaudRate < BAUD_9600 || m_bBaudRate > BAUD_115200) {
        m_bBaudRate = BAUD_19200;    
    }                               
    m_bBaudRate = BAUD_115200;
    BYTE bTmpBaudRate = m_bBaudRate;      
    
    m_bPICClockType = AfxGetApp()->GetProfileInt("CLOCK", "Type",CLOCK_HS);
    if(m_bPICClockType < CLOCK_LP || m_bPICClockType > CLOCK_RC) {
        m_bPICClockType = CLOCK_HS;    
    }                                                                      
    
    m_bPICCpuType = AfxGetApp()->GetProfileInt("CPU", "Type",0);
    
    //try to connect to PIC with the settings
    while (TRUE) {
        if (!SetSerialOption()) return FALSE;
        if (SetSerialPortBaud(m_bPortNum,m_bDefaultBaudRate)) {
            if (Init() || TryInit()) {  
                if (m_bBaudRate == bTmpBaudRate) break;
                
                BYTE bMaxBaudRate = BAUD_115200;
                switch (WhatCpu()) {
                	case 1 :
                	case 2 : bMaxBaudRate = BAUD_19200; break;
                	case 3 : bMaxBaudRate = BAUD_38400; break;
                	case 4 : bMaxBaudRate = BAUD_57600; break;
                	case 5 : 
                	default: bMaxBaudRate = BAUD_115200; break;
                }	
                bTmpBaudRate = (bTmpBaudRate > bMaxBaudRate)
                			   ? bMaxBaudRate : bTmpBaudRate;
                m_bBaudRate = bTmpBaudRate;  
                
                if (ICE_OK != AbiSelectBaud(m_bBaudRate)) return FALSE;
                if (SetSerialPortBaud(m_bPortNum,m_bBaudRate) 
                    && Init()) break;  
                if (0 != m_bBaudRate) {
                    m_bBaudRate--;   
                    bTmpBaudRate = m_bBaudRate;
                    continue;
                }    
                    
            }
        } 
        
        m_bPortNum++;
        if (m_bPortNum > COM_PORT_4) m_bPortNum = COM_PORT_1;
        
        CCommunicationDialog dlg;
        dlg.m_nType = m_bPortNum;
        if(dlg.DoModal() != IDOK) return FALSE;
        m_bPortNum = dlg.m_nType;
        bTmpBaudRate = m_bBaudRate;      
        //m_bPICClockType = dlg.m_nClockType;
    }
    
    AfxGetApp()->WriteProfileInt("COMM", "Type", m_bPortNum);
    AfxGetApp()->WriteProfileInt("COMM", "BaudRate", m_bBaudRate);
    return TRUE;
    
 }

void CWinSerialPICAgree::IsUnstable()
{ 
	return;
 }
 
CString CWinSerialPICAgree::GetSerialPortNum()
{         
    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 CWinSerialPICAgree::GetSerialBaudRate()
{                       
    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;      
 }
 
CString CWinSerialPICAgree::GetPICClockType() 
{ 
    CString strTmp;     
    switch (m_bPICClockType) {
        case CLOCK_LP  : strTmp = "LowPower"; break;
        case CLOCK_XT : strTmp = "XT"; break;
        case CLOCK_HS : strTmp = "HS"; break;
        case CLOCK_RC : strTmp = "RC"; break;
    }
    return strTmp;       
 }
    
BOOL CWinSerialPICAgree::SendByte(BYTE bSend)
{   
    if (!m_isCanBeUsed) {
        m_nError = m_isCanBeUsed;
        return FALSE;
    }
    
    if (1 != WriteComm(m_nDeviceID,&bSend,1)) {   
        m_nError = ERR_FATAL;
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        return FALSE;
    }   
        
    do {
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        if(0 == m_ComStatus.cbOutQue) {
            m_nError = m_nDetailError = ERR_NO;
            return TRUE;                       
        }               
        if (IsEscape()) {
            m_nError = ERR_ESC;
            return FALSE;
        }    
    } while(!IsTimeOut());
    m_nError = ERR_TIME_OUT;
    return FALSE;
 }
 
BOOL CWinSerialPICAgree::ReceiveByte(BYTE& bReceive)
{                    
    int nTmp;

    if (!m_isCanBeUsed) {
        m_nError = m_isCanBeUsed;
        return FALSE;
    }            
    
    do {
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        if(1 <= m_ComStatus.cbInQue) {
            if (1 == (nTmp = ReadComm(m_nDeviceID,&bReceive,1))) {
                m_nError = m_nDetailError = ERR_NO;
                return TRUE;                       
            }    
            m_nError = ERR_FATAL;
            m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
            return FALSE;
        }    
        if (IsEscape()) {
            m_nError = ERR_ESC;
            return FALSE;
        }    
    } while(!IsTimeOut());
    m_nError = ERR_TIME_OUT;
    return FALSE;
 }
 
BOOL CWinSerialPICAgree::SendString(BYTE *strSend,int nNum)
{       
    if (!m_isCanBeUsed) {
        m_nError = m_isCanBeUsed;
        return FALSE;
    }            
    
    if (nNum != WriteComm(m_nDeviceID,strSend,nNum)) {   
        m_nError = ERR_FATAL;
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        return FALSE;
    }   
    
    int nTmp = nNum;    
    do {
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        if(0 == m_ComStatus.cbOutQue) {
            m_nError = m_nDetailError = ERR_NO;
            return TRUE;  
        }    
        if(nTmp>m_ComStatus.cbOutQue) {
            RestartTimer();
            nTmp = m_ComStatus.cbOutQue;
        }    
        if (IsEscape()) {
            m_nError = ERR_ESC;
            return FALSE;
        }    
    } while(!IsTimeOut());
    
    m_nError = ERR_TIME_OUT;
    return FALSE;
    
 }
 
BOOL CWinSerialPICAgree::ReceiveString(BYTE *strReceive,int nNum)
{       
    if (!m_isCanBeUsed) {
        m_nError = m_isCanBeUsed;
        return FALSE;
    }            
    
    int nTmp = 0;
    
    do {
        m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
        
        if(nNum <= m_ComStatus.cbInQue) {
            if (nNum == ReadComm(m_nDeviceID,strReceive,nNum)) {
                m_nError = m_nDetailError = ERR_NO;
                return TRUE;                       
            }    
            m_nError = ERR_FATAL;
            m_nDetailError = GetCommError(m_nDeviceID,&m_ComStatus);
            return FALSE;
        }   
        
        if(nTmp<m_ComStatus.cbInQue) {
            RestartTimer();
            nTmp = m_ComStatus.cbInQue;
        }    
        if (IsEscape()) {
            m_nError = ERR_ESC;
            return FALSE;
        }                       
    } while(!IsTimeOut());
    
    FlushBufferIn();
    m_nError = ERR_TIME_OUT;
    return FALSE;
 }
    
BOOL CWinSerialPICAgree::IsEscape()
{    
    return FALSE;   
    //return TestKey(VK_ESCAPE);        
 }
 
BOOL CWinSerialPICAgree::IsRelink()
{   
    int nYesNo = OpenAbiComDlg(1);                              

    if (nYesNo == IDOK)
        return TRUE; 
    else {      
        if(m_nDeviceID>=0) CloseComm(m_nDeviceID);
    	m_nDeviceID = -1;
        ExitEpsld();
    }               
     
    return FALSE;
 }
    
void CWinSerialPICAgree::FlushBufferIn()
{                            
    FlushComm(m_nDeviceID,1);
 }
 
void CWinSerialPICAgree::FlushBufferOut()
{   
    FlushComm(m_nDeviceID,0);
 }
 
