/**************************************************************************
**
**  Name:  emucomm.c
**
**  Description:
**     Michelle command or data communication routines(Parallel).
**     include:
**
**  Status:  preliminary
**
** Copyright (C) 1992 Microtek International, Inc.
**
***************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#ifndef _CONST_
#include "const.h"
#endif

#ifndef _LLFW_
#include "emullfw.h"
#endif

#ifndef _EMU_COMM_
#include "emucomm.h"
#endif

#ifndef _EMU_LIB_
#include "emulib.h"
#endif

#ifndef _EMU_EXTERNAL_
#include "emuext.h"
#endif

#ifndef _COMM_DATA_
#include "commdata.h"
#endif

#include <conio.h>
#include <string.h>

#define CR             0x0D
#define LF             0x0A
#define LEAD_CODE      ':'
#define DMA0TC         0xffc8

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
U8 checksum,receiveBuf[MAX_BUF_SIZE];
#define LINK_TIMEOUT   20
                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

                        /****************************
                         *                          *
                         *      EXECUTABLE CODE     *
                         *                          *
                         ****************************/

/****************************************************************************
**
**  EmuCommRecover
**
**  Description: Initialize communication point and size.
**
**  Parameters:
**     input:
**     output:
**
*****************************************************************************/
VOID EmuCommRecover(VOID) {
//   outSizePtr = TxWrPtr = TxRdPtr = 0;
   CommRecover();
}

/****************************************************************************
**
**  ReceiveStream
**
**  Description: Receive data from communication and check the length and
**               checksum, the data format is :       XXXXxxx....xxxX
**                                                  length   data   checksum
**
**  Parameters:
**     input:
**     output:
**
*****************************************************************************/
// commCFG | m0 m1 m2 |  m0: clear buffer before receive
//    0    | +  +  -  |  m1: stop transfer after request match
//    1    | +  -  -  |  m2: change commCFG to 0
//    2    | -  +  +  |   +: enable
//    3    | -  -  -  |   -: disable

VOID DebugPulse(U16);

extern U8 sNo,preNo;

VOID ReceiveStream(VOID) {
U8 aa[4],MICE[4] = {'M','I','C','E'};
S16 len;
register lp;


   for (;;) {
      if(commCFG)
        commCFG=3;
      else
        commCFG=1;
      SetDmaCount(4); // receive leading code and data length and checksum.
      for (lp =0; lp < 4; lp++) {
         aa[lp] = ReceiveByte();
         if (timeOut) break;
      }
      if (timeOut) continue;
      HltWatchDog();
      checksum = 0;
      for (lp = 1; lp < 4; lp++) checksum += aa[lp];
      if ((aa[0] == LEAD_CODE) && (checksum == 0)) // command length.
         len = *(U16 *)&aa[1];   // data length 
      else if (memicmp(MICE,aa,4) == 0) { // warn start
         preNo=0;
         TransmitByte(ACK);
         commCFG=2;
         SetDmaCount(1);
         aa[0] = ReceiveByte();
         HltWatchDog();
         continue;
      } else
          continue; // gene

      if (len > 1024) continue;
      commCFG=2;
      SetDmaCount(len);
      checksum = sNo = ReceiveByte();
      //tempDmaLen = dmaLen;
      for (lp = 0; lp < (len-1); lp++) {
         receiveBuf[lp] = ReceiveByte();
         if (timeOut) break;
         checksum += receiveBuf[lp];
      }
//      if (timeOut)
//      {
//        DebugPulse();
//        TransmitByte(NACK);
//        EmuCommRecover();
//        continue;
//      }
      HltWatchDog();
      if (checksum == 0 && !timeOut) {
         memcpy(commandStream,receiveBuf,len);
         commandStreamLen = len;
         TransmitByte(ACK);
         return;
      } else {
         TransmitByte(NACK);
//         EmuCommRecover();
      }
   }
}

/****************************************************************************
**
**  TransmitStream
**
**  Description: Transmit data(length + data + checksum) to
**               communication port.
**               the data format is :  XXXXxxx....xxxX
**                                   length   data   checksum
**
**  Parameters:
**     input:
**     output:
**
*****************************************************************************/
/*
   Transmit data(length + data + checksum) to communication port.
   the data format is : LENGTH(2 bytes)DATA(number of length)CHECKSUM(1 byte)
*/
VOID TransmitStream(VOID) {
   register lp;
   U8 highLen,lowLen,finalFlag,aa;

   checksum = 0;
   for (lp = 0; lp < outputStreamLen; lp++)
      checksum += outputStream[lp];
   outputStream[outputStreamLen] = (U8)(~checksum+1);
   outputStreamLen++;

   lowLen = LowByte(outputStreamLen);
   highLen = HighByte(outputStreamLen);
   checksum = (U8)(~(lowLen+highLen) + 1);

   for (;;) {
      EmuCommRecover();
      TransmitByte(LEAD_CODE);
      TransmitByte(lowLen);
      TransmitByte(highLen);
      TransmitByte(checksum);
      for (lp = 0; lp < outputStreamLen; lp++)
         TransmitByte(outputStream[lp]);
      finalFlag = OFF;
      for (;;)
         if(outSize() == 0) {
            finalFlag = ON;
            break;
         }
//      if (finalFlag == OFF) {
//         EmuCommRecover();
//         break;
//         return;
//      }
      commCFG=1;
      SetDmaCount(1);
      SetWatchDog(15);
      aa = ReceiveByte();
      if (((aa & 0x1F) == NACK) || timeOut) {
         HltWatchDog();
//         EmuCommRecover();
         continue;
      }
//      if ((aa & 0x1F) != ACK)
//         DebugPulse(1);
      HltWatchDog();
      break;
   }
}

/****************************************************************************
**
**  CommSync
**
**  Description: Initialize communication point and size.
**
**  Parameters:
**     input:
**     output:
**
*****************************************************************************/
int CommSync(int len,U8 *buf[]) {
   int i; //j
   U8 tmp[8], aa, linkState;
   BOOLEAN syncOK = FALSE;
   char cmd=0;
   U16 syncBRate[5] = {Baud_96,Baud_192,Baud_384,Baud_576,Baud_1152};

   BaudRate_timeOut = 0;
   preNo=0;
   linkState = 0;
   while(1) {
      if (!syncOK)
         CommCtrl(cmd&=1);
      commCFG=0;
      SetDmaCount(len);
      SetWatchDog(16);
      i=0;
      while (i<len) {
         tmp[i++] = ReceiveByte();
         if (timeOut)
            break;
      }
      CommRecover();
      if (i==len) {
         for (i=0;buf[i];i++) {
            if (strncmp(buf[i],tmp,len)==0) {
               HltWatchDog();
               CommCtrl(CommFix);
               syncOK = TRUE;
               TransmitByte(ACK);
               if (i != 0) return i;
               SetDmaCount(1);
               aa = ReceiveByte();
               HltWatchDog();
               if (aa == ACK) {
                  linkState++;
                  BaudRate(syncBRate[linkState]);
                  SetBaudRateTimer(LINK_TIMEOUT);
                  break;
               } else {
                  return i;
               }
            }
         }
         if (i) TransmitByte(NACK);
       }
       if (BaudRate_timeOut && syncOK) {
          while (outSize() != 0);
          BaudRate(syncBRate[linkState-1]);
          BaudRate_timeOut = 0;
       }
      cmd++;
   }
}

/******************************** E O F ***********************************/
