/*
   7522.C
   Demo program for 7522 as an Addressable RS-485 to RS-232 converter.
   using COM1 as RS-232    --> RS-232 Address=A
	 COM2 as RS-485
	 COM3 as RS-232(2) --> RS-232 Address=A+1
   convert non-addressable RS-232 to addressable RS-485

   *** Please use 7188xs.lib Ver 1.16 or latter ****
   Setting COMMAND:
    (1) $AAAn[addr]	--> Read/Set Module address
    (2) $AABn[baudrate] --> Read/Set RS-485(n=0) RS-232(n=1) baudrate
    (3) $AADn[data bit] --> Read/Set Data bit
    (4) $AAPn[parity]	--> Read/Set Parity
    (5) $AAOn[parity]	--> Read/Set stOp bit
    (6) $AA6(ID)	--> Set ID-string
    (7) $AA7		--> Read ID-string
    (8) $AAC[delimiter] --> Read/Set Delimiter
    (9) $AAD		--> Read Delimiter
    (10)(delimiter)AA[by pass data] --> bypass comand-string to COM1/3/4
    (11)$AAKn[CRLF]	--> Read/Set checksum-status
    (12)$AATn[CRLF]	--> Read/Set the end-char-mode of command string
    (13)$AAW		--> Read CTS of COM-1/3
    (14)$AAXV		--> Set  RTS of COM-1/3
    (15)$AAYN		--> Read OnBoard DI-1/2/3
    (16)$AAZNV		--> Set  OnBoard DO-1/2/3
    (17)#**		--> Synchronized Sampling
    (18)$AA4		--> Read the synchronized data
    (19)$AA5		--> Read the reset-status
    (20)$AAM		--> Read Module name
    (21)$AAF		--> Read Firmwre Revsion Number
    (22)~**		--> Host is OK
    (23)~AA0		--> Read  the module Status
    (24)~AA1		--> Reset the module Status
    (25)~AA2		--> Reset the host watchdog status & timer
    (26)~AA3ETT 	--> Enable/Disable host watchdog timer
    (27)~AA4P/S 	--> Read PowerOn/Safe value
    (28)~AA5P/S 	--> Set  PowerOn/Safe value

   EEPROM data use block 7
   addr 0,1: save 7522 as a flag
	2  : RS-485 baudrate(1-10)
	3  : RS-485 parity(0,1,2)for(N,E,O)
	4  : RS-485 data bits (7,8)
	5  : RS-485 stop bit (always 1)
	6  : RS-232 baudrate(1-10)for(300-115200)
	7  : RS-232 parity(0,1,2)for(N,E,O)
	8  : RS-232 data bits (7,8)
	9  : RS-232 stop bit (always 1)
     **** 10-17 for 7522/7523
	10 : RS-232(2) baudrate(1-10)for(300-115200)
	11 : RS-232(2) parity(0,1,2)for(N,E,O)
	12 : RS-232(2) data bits (7,8)
	13 : RS-232(2) stop bit (always 1)
	14 : RS-232(3) baudrate(1-10)for(300-115200)
	15 : RS-232(3) parity(0,1,2)for(N,E,O)
	16 : RS-232(3) data bits (7,8)
	17 : RS-232(3) stop bit (always 1)
    ****
	20 : ChechSum(0:disable, 1:enable)
	21 : HostWdtEnable
	22 : HostWdtTimer
	23 : HostWdtPowerOnValue
	24 : HostWdtPowerSafeValue
    ****
	31 : delimiter
	32 : delimiter(2)
	33 : delimiter(3)
    ****
	40 : RS-485 CRLF mode
	41 : RS-232 CRLF mode
	42 : RS-232(2) CRLF mode
	43 : RS-232(3) CRLF mode
    ****
	50 : address
    ****
	100-149: ID for RS-232
	150-199: ID for RS-232(2)
	200-249: ID for RS-232(3)

Release Note:
[June/2000]
  1. User must send command to COM2(RS-485), if the command is used to
     set configuration of 7522, the 7522 will directly echo message to COM2.
     If the command is used to	bypass data to RS-232 device, the data will be
     sent to COM1/3(RS-232). Any message come from COM1/3(RS-232) will be
     echo to COM2(RS-485) at any time.
  2. The COM port address of 7521 is given as following:
     COM1=RS-232    --> RS-232 Address=AA
     COM2=RS-485
  3. The COM port address of 7522 is given as following:
     COM1=RS-232    --> RS-232 Address=AA
     COM2=RS-485
     COM3=RS-232    --> RS-232 Address=AA+1
     7522 is used as two   7521 with address AA, AA+1.	      And the two
     COM port must use the same ModeCrLf485 and the ModeCrLf232 can be different.
     The delimiters for these three COM port can be different.
  4. comparision table of COM1, COM3 & COM4 of 7522/7523
			COM1	       COM3&COM4
     ---------------------------------------------------
     start-bit		1	       1
     data-bit		7/8	       7/8
     parity-bit 	No/Even/Odd    No/Even/Odd
     stop-bit		1	       1/2
     baud rate		115.2K max.    115.2K max.
     interrupt		Yes	       Yes
     FIFO		double buffer  16 bytes
     connect HP34401A	No	       Yes    (HP34401A require two stop-bit)

     So 7521 can not link to HP34401A.
     7522 can link to one HP34401A.
     7523 can link to two HP34401A.
*/

/* ------------------------------------------------------------- */

#include<stdio.h>
#include<stdlib.h>
#include"..\lib\7188x.h"

#define InstallCom232 InstallCom1
#define IsCom232      IsCom1
#define ReadCom232    ReadCom1
#define ToCom232      ToCom1
#define ToCom232Str   ToCom1Str
#define ToComBufn232  ToCom1Bufn
#define RestoreCom232 RestoreCom1

#define InstallCom485 InstallCom2
#define IsCom485      IsCom2
#define ReadCom485    ReadCom2
#define ToCom485      ToCom2
#define ToCom485Str   ToCom2Str
#define ToComBufn485  ToCom2Bufn
#define RestoreCom485 RestoreCom2
#define WaitTransmitOver485 WaitTransmitOver2

#define InstallCom232_2 InstallCom3
#define IsCom232_2	IsCom3
#define ReadCom232_2	ReadCom3
#define ToCom232_2	ToCom3
#define ToCom232Str_2	ToCom3Str
#define ToComBufn232_2	ToCom3Bufn
#define RestoreCom232_2 RestoreCom3

#define dPrint	   Print
#define Putchd	   Putch
#define ReadComd   Getch
#define IsComd	   Kbhit

int DEBUG_7522=0;

int WaitToDo=0;
int NewCheckSum,NewDataBit,NewParity;
unsigned long NewBaudrate;
enum WaitToDoMode {
 _ChangeNothing=0,
 _ChangeCheckSum,
 _ChangeBaudrate,
 _ChangeDataBit,
 _ChangeParity,
};

int quit=0;
long BAUD[11]={
9600L,
300L,
600L,
1200L,
2400L,
4800L,
9600L,
19200L,
38400L,
57600L,
115200L
};

int Baud485=6;
int Parity485=0;
int Data485=8;
int Stop485=1;
int CheckSum=0;

int Baud232=6;
int Parity232=0;
int Data232=8;
int Stop232=1;

int Baud232_2=6;
int Parity232_2=0;
int Data232_2=8;
int Stop232_2=1;

unsigned char Delimiter=':';
unsigned char Delimiter_2=':';

int Address=1;
int CurAddress;
int ModeCrLf485=0;
int ModeCrLf232=0;
int ModeCrLf232_2=0;
// int ModeCrLf232_3=0;
int CurModeCrLf485=0;
int CurModeCrLf232=0;
int CurModeCrLf232_2=0;
// int CurModeCrLf232_3=0;
int CmdMode=0;

char ID[50]="ICPDAS-7522-1";    /* ID-string for COM1(RS232)    */
char ID2[50]="ICPDAS-7522-2";   /* ID-string for COM3(RS232)    */
// char ID3[50]="ICPDAS-7523-3";   /* ID-string for COM4(RS232)    */

unsigned long far * timetick=(unsigned long far *)0x0040006CL;
char ResetStatus=1,SyncData=0, FirstRead=0;
char HostWdtEnable,HostWdtModuleStatus=0,HostWdtTimer;
char HostWdtPowerOnValue,HostWdtSafeValue;
unsigned long HostTimerStart;

void SetAllDo(char);

/* -------------------------------------------------------------------- */

void Open7522(void)
{ int Is7522;
  unsigned char *dataptr=(unsigned char *)&Is7522;
  int addr;

/* step 1: read/write the configuration data from EEPROM	*/
/* if first-time RUN --> write INIT-DATA to EEPROM		*/
/* if not-first-time RUN --> load configuration from EEPROM	*/

  dataptr[0]=ReadEEP(7,0);	/* ID, high byte		*/
  dataptr[1]=ReadEEP(7,1);	/* ID, low  byte		*/

  if(Is7522==7522){/* this is not-first-time RUN		*/
		   /* --> load configuration data from EEPROM	*/
     Baud485=ReadEEP(7,2);	/* baud rate  of COM2		*/
     Parity485=ReadEEP(7,3);	/* Parity-bit of COM2		*/
     Data485=ReadEEP(7,4);	/* data-bit   of COM2		*/
     Stop485=ReadEEP(7,5);	/* stop-bit   of COM2		*/

     Baud232=ReadEEP(7,6);	/* baud rate  of COM1		*/
     Parity232=ReadEEP(7,7);	/* Parity-bit of COM1		*/
     Data232=ReadEEP(7,8);	/* data-bit   of COM1		*/
     Stop232=ReadEEP(7,9);	/* stop-bit   of COM1		*/
     Delimiter=ReadEEP(7,31);	/* delimiter  of COM1		*/

     Baud232_2=ReadEEP(7,10);	/* baud rate  of COM3		*/
     Parity232_2=ReadEEP(7,11); /* Parity-bit of COM3		*/
     Data232_2=ReadEEP(7,12);	/* data-bit   of COM3		*/
     Stop232_2=ReadEEP(7,13);	/* stop-bit   of COM3		*/
     Delimiter_2=ReadEEP(7,32); /* delimiter  of COM3		*/

     CheckSum=ReadEEP(7,20);	/* checksum enable/disable	*/
     HostWdtEnable=ReadEEP(7,21);/* HostWDT enable/disable	*/
     if (HostWdtEnable) 	/* enable HostWDT		*/
	{
	_asm cli
	HostTimerStart=*timetick;
	_asm sti
	}
     HostWdtTimer=ReadEEP(7,22);/* timer for HostWDT		*/

     HostWdtPowerOnValue=ReadEEP(7,23); /* PowerOn-value for	*/
     SetAllDo(HostWdtPowerOnValue);	/* OnBoard DO-1/2/3	*/

     /* if (HostWDT is enable & Host-is-failure 		*/
     /* all OnBoard-DO wil go to their safe-value immediately	*/
     HostWdtSafeValue=ReadEEP(7,24);	/* Safe-value for	*/
					/* OnBoard DO-1/2/3	*/

     Address=ReadEEP(7,50);	 /* COM1=AA,COM3=AA+1,COM4=AA+2 */
     ModeCrLf485=ReadEEP(7,40);  /* end-char mode of COM2	*/
     ModeCrLf232=ReadEEP(7,41);  /* end-char mode of COM1	*/
     ModeCrLf232_2=ReadEEP(7,42);/* end-char mode of COM3	*/
  }
  else{ /* this is first-time run --> write INIT-DATA to EEPROM */
    EnableEEP();
    Is7522=7522;
    WriteEEP(7,0,dataptr[0]);
    WriteEEP(7,1,dataptr[1]);
    WriteEEP(7,2,6); /* 9600	     */     /* COM2=RS-485 */
    WriteEEP(7,3,0); /* No parity    */
    WriteEEP(7,4,8); /* 8 data bits  */
    WriteEEP(7,5,1); /* 1 stop bit   */

    WriteEEP(7,6,6); /* 9600	     */     /* COM1=RS-232 */
    WriteEEP(7,7,0); /* No parity    */
    WriteEEP(7,8,8); /* 8 data bits  */
    WriteEEP(7,9,1); /* 1 stop bit   */

    WriteEEP(7,10,6); /* 9600	     */     /* COM3=RS-232 */
    WriteEEP(7,11,0); /* No parity   */
    WriteEEP(7,12,8); /* 8 data bits */
    WriteEEP(7,13,1); /* 1 stop bit  */

    WriteEEP(7,20,CheckSum); /* checksum = 0 = disable	*/
    WriteEEP(7,21,0); /* HostWdtEnable = disable  */
    WriteEEP(7,22,0); /* HostWdtTimer  = 0 ms	  */
    WriteEEP(7,23,0); /* HostWdtPowerOnValue =OFF */
    WriteEEP(7,24,0); /* HostWdtSafeValue    =OFF */

    WriteEEP(7,31,':'); /* delimiter=':' for COM1 */
    WriteEEP(7,32,':'); /* delimiter=':' for COM3 */

    WriteEEP(7,40,0); /* end-char=0=CR (for COM2) */
    WriteEEP(7,41,0); /* end-char=0=CR (for COM1) */
    WriteEEP(7,42,0); /* end-char=0=CR (for COM3) */

    WriteEEP(7,50,1); /* Address=1 --> AA=01	  */

    dataptr=ID;       /* ID-string of COM1(RS232) */
    for(addr=100; addr<150 && *dataptr; addr++){
	WriteEEP(7,addr,*dataptr++);
    }
    if(addr<150) WriteEEP(7,addr,0); /* end of ID */

    dataptr=ID2;      /* ID-string of COM3(RS232) */
    for(addr=150; addr<200 && *dataptr; addr++){
	WriteEEP(7,addr,*dataptr++);
    }
    if(addr<200) WriteEEP(7,addr,0); /* end of ID */

    ProtectEEP();
  }

/* step 2: check the init* pin is floating or connected to GND	     */

  if(ReadInitPin()){	/* Init* connect to GND --> goto INIT* state */
     CurAddress=0;	/* AA=00				     */
     CurModeCrLf485=0;	/* end-char-mode of COM2		     */
     CurModeCrLf232=0;	/* end-char-mode of COM1		     */
     CurModeCrLf232_2=0;/* end-char-mode of COM3		     */

     if(!DEBUG_7522)InstallCom232(BAUD[6],8,0); /* COM1, 9600, N81   */

     Baud485=6; 			/* short-code for 9600 is 6  */
     InstallCom485(BAUD[6],8,0);	/* COM2, RS-485, 9600, N81   */

     InstallCom232_2(BAUD[6],8,0,1);	/* COM3, RS-232, 9600, N81   */
     CheckSum=0;
  }
  else {		/* Init* float --> state saved in EEPROM     */
     CurAddress=Address;		/* load AA from EEPROM	     */
     CurModeCrLf485=ModeCrLf485;	/* load end-char-mode of COM2*/
     CurModeCrLf232=ModeCrLf232;	/* load end-char-mode of COM1*/
     CurModeCrLf232_2=ModeCrLf232_2;	/* load end-char-mode of COM3*/
					/* initiate COM1/2/3/4	     */
     if(!DEBUG_7522)InstallCom232(BAUD[Baud232],Data232,Parity232);
     InstallCom485(BAUD[Baud485],Data485,Parity485);
     InstallCom232_2(BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2);
  }

  if(DEBUG_7522){
     dPrint("Address=%02X Baud=%ld Data=%d Parity=%d Stop=%d CRmode=%d CheckSum=%d\n\r",
		CurAddress,BAUD[Baud485],Data485,Parity485,Stop485,ModeCrLf485,CheckSum);
     dPrint("232: Baud=%ld Data=%d Parity=%d Stop=%d CRmode=%d\n\r",
		BAUD[Baud232],Data232,Parity232,Stop232,ModeCrLf232);
     dPrint("232(2): Baud=%ld Data=%d Parity=%d Stop=%d CRmode=%d\n\r",
		BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2,ModeCrLf232_2);
  }

/* step 3: show address & baudrate of COM2 in 7-SEG LEDs       */

  Init5DigitLed();			  /* init 7-SEG LEDs   */
  Show5DigitLed(1,CurAddress>>4);	  /* high nibble of AA */
  Show5DigitLedWithDot(2,CurAddress&0x0F);/* low  nibble of AA */
  Show5DigitLedWithDot(3,Baud485);	  /* baud rate of COM2 */
  Show5DigitLed(4,16);			  /* for user	       */
  Show5DigitLed(5,16);			  /* for user	       */
}

void Close7522(void)
{
  if(!DEBUG_7522) RestoreCom232();	  /* COM1	       */
  RestoreCom485();			  /* COM2	       */
  RestoreCom232_2();			  /* COM3	       */

  Show5DigitLed(1,7);
  Show5DigitLed(2,5);
  Show5DigitLed(3,2);
  Show5DigitLedWithDot(4,3);
  Show5DigitLedSeg(5,0x37);
}

/* --- send a command string to RS485 port -------------------- */

void SendCmdToCom485Str(unsigned char *cmd)
{ unsigned char sum;

/*  step 1: send command-part			   */
    ToCom485Str(cmd);
    if(DEBUG_7522) dPrint(cmd);

/*  step 2: if checksumis-enable send checksum-part */
/*  note: this part is for COM2(RS485) only	    */

    if(CheckSum){
       unsigned char *dat=cmd;
       sum=0;
       while(*dat){
	 sum+=*dat;
	 dat++;
       }
       ToCom485(hex_to_ascii[sum >> 4]);
       ToCom485(hex_to_ascii[sum & 0x0F]);
       if(DEBUG_7522){
	  Putchd(hex_to_ascii[sum >> 4]);
	  Putchd(hex_to_ascii[sum & 0x0F]);
       }
    }

/*  step 3: send end-char-part			    */
    switch(CurModeCrLf485){
      case 0:
	   ToCom485('\r');
	   if(DEBUG_7522) dPrint("Cr\n");   // CrLfMode=0=CR
	   break;
      case 1:
	   ToCom485Str("\r\n");
	   if(DEBUG_7522) dPrint("CrLf\n"); // CrLfMode=1=CR+LF
	   break;
      case 2:
	   ToCom485('\n');
	   if(DEBUG_7522) dPrint("Lf\n");   // CrLfMode=2=LF
	   break;
      case 3:
	   ToCom485Str("\n\r");
	   if(DEBUG_7522) dPrint("LfCr\n"); // CrLfMode=3=LF+CR
	   break;
    }
}
int addr7522;

unsigned char Cmd485[256];
int Idx485=0;


/* --- if receive a commmad-string from COM1 --> bypass to COM2 -- */

/* --- if receive a commmad-string from COM1 --> bypass to COM2 -- */
void ByPassTo232_2(void);

unsigned char Cmd232[256];
unsigned char Echo232[80];
int Idx232=0;
int bypass_source=0;

int isvalid_com1_command()
{
   if(Cmd232[0]==Delimiter)
   {
      addr7522=(ascii_to_hex(Cmd232[1])<<4)+ascii_to_hex(Cmd232[2]);
      if(addr7522==CurAddress+1) return 1;
      else return 0;
   }
   else return 0;

}

void process232(int N_of232)
{
   char Me[3];


   if(bypass_source==2321)
   {
      if(isvalid_com1_command())
      {
	 strncpy(Cmd485,Cmd232,N_of232);
	 Idx485=N_of232; ////???????check the correct value
	 ByPassTo232_2();
	 Idx232=0;
	 Idx485=0;
      }
      else
      {
	 Idx232=0;//skip
      }
   }
   else
   {
      if(isvalid_com1_command())
      {
	 bypass_source=2321;
	 strncpy(Cmd485,Cmd232,N_of232);
	 Idx485=N_of232; ////???????check the correct value
	 ByPassTo232_2();
	 Idx232=0;
	 Idx485=0;
      }
      else
      {
	 if(bypass_source==2322)
	 {
	    sprintf(Me,"!%02X",CurAddress);/*!AA+1                            */
	    strncpy(Cmd485+3,Me,3);
	    strncpy(Cmd485+6,Cmd232,N_of232);
	    Idx485=N_of232+6;
	    ByPassTo232_2();
	    Idx232=0;
	    Idx485=0;
	 }
	 else
	 {
	    SendCmdToCom485Str("errCmd");
	    bypass_source=0;
	    Idx232=0;
	    Idx485=0;
	 }
      }
   }
}

void DoCom232(void) /* COM1=RS-232 */
{ int data;
  while(IsCom232()){
       data=ReadCom232();
       Cmd232[Idx232++]=data;

       if(data=='\r'){
	  if(CurModeCrLf232==0){		      /* CrLfMode=0=CR --> match     */
	     Cmd232[Idx232-1]=0;
	     process232(Idx232-1);
	  }
	  else if(CurModeCrLf232==3){	      /* CrLfMode=3=LF+CR --> match  */
		  if(Cmd232[Idx232-2]=='\n'){
		     Cmd232[Idx232-2]=0;
		     process232(Idx232-2);
		  }
	  }
       }
       else if(data=='\n'){
	       if(CurModeCrLf232==2){	      /* CrLfMode=2=LF --> match     */
		  Cmd232[Idx232-1]=0;
		  process232(Idx232-1);
	       }
	       else if(CurModeCrLf232==1){       /* CrLfMode=1=CR+LF --> match  */
		       if(Cmd232[Idx232-2]=='\r'){
			  Cmd232[Idx232-2]=0;
			  process232(Idx232-2);
		       }
	       }
       }

  }
}


/* --- if receive a commmad-string from COM3 --> bypass to COM2 -- */
void ByPassTo232(void);

unsigned char Cmd232_2[256];
unsigned char Echo232_2[80];
int Idx232_2=0;

int isvalid_com2_command()
{
   if(Cmd232_2[0]==Delimiter_2)
   {
      addr7522=(ascii_to_hex(Cmd232_2[1])<<4)+ascii_to_hex(Cmd232_2[2]);
      if(addr7522==CurAddress) return 1;
      else return 0;
   }
   else return 0;

}

void process232_2(int N_of232)
{
   char Me[3];
   if(isvalid_com2_command())
   {
	 bypass_source=2322;
	 strncpy(Cmd485,Cmd232_2,N_of232);
	 Idx485=N_of232;//////////?????check the correct value
	 ByPassTo232();
	 Idx232_2=0;
	 Idx485=0;
   }
   else
   {
      if(bypass_source==2321)
      {
	 sprintf(Me,"!%02X",CurAddress+1);/*!AA+1                            */
	 strncpy(Cmd485+3,Me,3);
	 strncpy(Cmd485+6,Cmd232_2,N_of232);
	 Idx485=N_of232+6;
	 ByPassTo232();
	 Idx232_2=0;
	 Idx485=0;
      }
      else
      {
	 if(bypass_source==485)
	 {
	    SendCmdToCom485Str(Cmd232_2);        /* send command-string to COM2 */
	    bypass_source=0;
	    Idx232_2=0;
	    Idx485=0;
	 }
	 else
	 {
	    Idx232_2=0;//skip
	 }
      }
   }


}
void DoCom232_2(void) /* COM3=RS-232 */
{ int data;

  while(IsCom232_2()){

      data=ReadCom232_2();
      Cmd232_2[Idx232_2++]=data;

      if(data=='\r'){
	if(CurModeCrLf232_2==0){ 	       /* CrLfMode=0=CR --> match     */
	  Cmd232_2[Idx232_2-1]=0;
	  process232_2(Idx232_2-1);
	}
	else if(CurModeCrLf232_2==3){	       /* CrLfMode=3=LF+CR --> match  */
	       if(Cmd232_2[Idx232_2-2]=='\n'){
		  Cmd232_2[Idx232_2-2]=0;
		  process232_2(Idx232_2-2);
	       }
	}
      }
      else if(data=='\n'){
	    if(CurModeCrLf232_2==2){	       /* CrLfMode=2=LF --> match     */
	       Cmd232_2[Idx232_2-1]=0;
	       process232_2(Idx232_2-1);
	    }
	    else if(CurModeCrLf232_2==1){	/* CrLfMode=1=CR+LF --> match  */
		 if(Cmd232_2[Idx232_2-2]=='\r'){
		   Cmd232_2[Idx232_2-2]=0;
		   process232_2(Idx232_2-2);

		 }
	    }
      }

  }


}


/* ------------------------------------------------------------- */

unsigned char Echo485[80];
void EchoErrorCmd(void) 		/* echo ?AA to host */
{
  sprintf(Echo485,"?%02X",addr7522);
  SendCmdToCom485Str(Echo485);
}

void EchoOkCmd(void)			/* echo !AA to host */
{
  sprintf(Echo485,"!%02X",addr7522);
  SendCmdToCom485Str(Echo485);
}

int EchoType=0;
/*
EchoType:
0: NoEcho
1: call EchoErrorCmd();
2: call EchoOkCmd();
3: Echo the string in Echo2
*/
enum ECHO_TYPE { NO_ECHO=0,ERROR_ECHO,OK_ECHO,ECHO2_ECHO };
int InitPin;  /* 1: Init* connect to GND */

void Quit(void)
{
   sprintf(Echo485,"!%02XQuit7522",CurAddress);
   EchoType=ECHO2_ECHO;
   quit=1;
}

/* --- set ID-string for COM1/3   ---------------------------------- */

void SetID(void)
{ int addr;
  int start,end;
  char *dataptr=Cmd485+4;

  EnableEEP();
  if(addr7522==CurAddress){		/* ID-string for COM1(RS232) */
     start=100;
     end=150;
  }
  else if(addr7522==CurAddress+1){	/* ID-string for COM3(RS232) */
     start=150;
     end=200;
  }

  for(addr=start; addr<end && *dataptr; addr++){
      WriteEEP(7,addr,*dataptr++);
  }
  WriteEEP(7,addr,0);
  ProtectEEP();
  EchoType=OK_ECHO;
}

void ReadID(void) /* read the ID-string of COM1/3		     */
{ int data;
  int addr;
  int end;
  char *ptr=Echo485+3;

   if(addr7522==CurAddress){	     /* ID-string of COM1(RS232)     */
      addr=100;
      end=150;
   }
   else if(addr7522==CurAddress+1){  /* ID-string of COM3(RS232)     */
      addr=150;
      end=200;
   }

   sprintf(Echo485,"!%02X",addr7522);/*!AA                            */
   do { 			     /*!AA(ID-string)		      */
     *ptr++=data=ReadEEP(7,addr++);
   } while(data && addr<end);
   *ptr=0;
  EchoType=ECHO2_ECHO;
}

/* --- Read/set module address (AA) --------------------------------- */

void ReadAddress(void)	/* read AA stored in EEPROM		      */
{
  sprintf(Echo485,"!%02X",ReadEEP(7,50));
  EchoType=ECHO2_ECHO;
}

void SetAddress(void)
{
  Address=(ascii_to_hex(Cmd485[4])<<4)+ascii_to_hex(Cmd485[5]);
  EnableEEP();
  WriteEEP(7,50,Address);
  ProtectEEP();
  CurAddress=Address;
					  /* AA show in (LED1,LED2)   */
  Show5DigitLed(1,CurAddress>>4);	  /* high nibble of AA	      */
  Show5DigitLedWithDot(2,CurAddress&0x0F);/* low  nibble of AA	      */

  EchoType=OK_ECHO;
}

/* --- read the baud-rate for COM1/2/3	 ---------------------------- */

void ReadComBaudrate(void)	/* read baudrate stored in EEPROM     */
{
   long data;
   if(addr7522==CurAddress){			      /* AA	      */
      if(Cmd485[4]=='0') data=BAUD[ReadEEP(7,2)];     /* COM2(RS485)  */
      else if(Cmd485[4]=='1') data=BAUD[ReadEEP(7,6)];/* COM1(RS232)  */
      else return;
      sprintf(Echo485,"!%02X%ld",addr7522,data);
   }
   else if(addr7522==CurAddress+1){		      /* AA+1	      */
      if(Cmd485[4]=='0') data=BAUD[ReadEEP(7,2)];     /* COM2(RS485)  */
      else if(Cmd485[4]=='1') data=BAUD[ReadEEP(7,10)];/* COM3(RS232) */
      else return;
      sprintf(Echo485,"!%02X%ld",addr7522,data);
   }
  EchoType=ECHO2_ECHO;
}

void SetComBaudrate(void)	/* set the baud-rate of COM-1/2/3/4   */
{
  long data;
  int i;

/*  if(!InitPin){
     EchoType=ERROR_ECHO;
     return;
  } */ /* mark for need not INIT* connect to GND */
  data=atol(Cmd485+5);
  for(i=1;i<=10;i++){
      if(data==BAUD[i]) goto SetBaud;
  }
  return;
SetBaud:
  if(addr7522==CurAddress){			/* AA		      */
     if(Cmd485[4]=='0'){                        /* COM2(RS485)        */
	Baud485=i;
	EnableEEP();
	WriteEEP(7,2,Baud485);
	ProtectEEP();
	WaitToDo=_ChangeBaudrate;		/* change after echo  */
	Show5DigitLedWithDot(3,Baud485);	/* baud rate of COM2  */
     }
     else if(Cmd485[4]=='1'){                   /* COM1(RS232)        */
	Baud232=i;
	EnableEEP();
	WriteEEP(7,6,Baud232);
	ProtectEEP();
	RestoreCom232();			/* change immediately */
	InstallCom232(BAUD[Baud232],Data232,Parity232);
     }
     else return;
  }
  else if(addr7522==CurAddress+1){		/* AA+1 	      */
     if(Cmd485[4]=='0'){                        /* COM2(RS485)        */
	Baud485=i;
	EnableEEP();
	WriteEEP(7,2,Baud485);
	ProtectEEP();
	WaitToDo=_ChangeBaudrate;		/* change after echo  */
	Show5DigitLedWithDot(3,Baud485);	/* baud rate of COM2  */
     }
     else if(Cmd485[4]=='1'){                   /* COM3(RS232)        */
	Baud232_2=i;
	EnableEEP();
	WriteEEP(7,10,Baud232_2);
	ProtectEEP();
	RestoreCom232_2();			/* change immediately */
	InstallCom232_2(BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2);
     }
     else return;
  }
  EchoType=OK_ECHO;
}

/* ------------------------------------------------------------------ */

void SetDelimiter(void)
{
  EnableEEP();
  if(addr7522==CurAddress){			/* AA		      */
     WriteEEP(7,31,(Delimiter=Cmd485[4]));	/* COM1(RS232)	      */
  }
  else if(addr7522==CurAddress+1){		/* AA+1 	      */
     WriteEEP(7,32,(Delimiter_2=Cmd485[4]));	/* COM3(RS232)	      */
  }
  ProtectEEP();
  EchoType=OK_ECHO;
}

void ReadDelimiter(void) /* read delimiter stored in EEPROM	      */
{
  sprintf(Echo485,"!%02X%c",addr7522,
	  addr7522==CurAddress?ReadEEP(7,31):(addr7522==CurAddress+1 ? ReadEEP(7,32):ReadEEP(7,33)));
  EchoType=ECHO2_ECHO;
}

/* --------------------------------------------------------------------- */

void ReadDataBit(void)	/* read data-bit stored in EEPROM		 */
{ int data;

  if(Cmd485[4]=='0') data=ReadEEP(7,4);                     /* COM2      */
  else if(Cmd485[4]=='1'){
	   if(addr7522==CurAddress) data= ReadEEP(7,8);     /* AA=COM1	 */
	   else if(addr7522==CurAddress+1) data=ReadEEP(7,12);/*AA+1=COM3*/
  }
  else return;
  sprintf(Echo485,"!%02X%d",addr7522,data);
  EchoType=ECHO2_ECHO;
}

void SetDataBit(void)
{ int data;

/*  if(!InitPin){
     EchoType=ERROR_ECHO;
     return;
  } */	/* mark for need not INIT* connect to GND	*/
  if(Cmd485[5]=='7') data=7;      /* only 7/8 are valid */
  else if(Cmd485[5]=='8') data=8; /* only 7/8 are valid */
  else return;

  if(Cmd485[4]=='0'){                           /* AA/AA+1/AA+2=COM2  */
     Data485=data;
     EnableEEP();
     WriteEEP(7,4,Data485);
     ProtectEEP();
     WaitToDo=_ChangeDataBit;			/* change after echo  */
  }
  else if(Cmd485[4]=='1'){
	  EnableEEP();
	  if(addr7522==CurAddress){		/* AA=COM1(RS232)     */
	     WriteEEP(7,8,(Data232=data));
	     RestoreCom232();			/* change immediately */
	     InstallCom232(BAUD[Baud232],Data232,Parity232);
	  }
	  else if(addr7522==CurAddress+1){	/* AA+1=COM3(RS232)   */
	     WriteEEP(7,12,(Data232_2=data));
	     RestoreCom232_2(); 		/* change immediately */
	     InstallCom232_2(BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2);
	  }
	  ProtectEEP();
  }
  else return;
  EchoType=OK_ECHO;
}

/* --- read the end-char mode ------------------------------------------ */

void ReadCRLF(void) /* read end-char-mode stored in EEPROM		 */
{
   int data;
   if(Cmd485[4]=='0') data=ReadEEP(7,40);                   /* COM2      */
   else if(Cmd485[4]=='1'){
      if(addr7522==CurAddress) data=ReadEEP(7,41);	    /* AA=COM1	 */
      else if(addr7522==CurAddress+1) data=ReadEEP(7,42);   /* AA+1=COM3 */
   }
   else return;
  sprintf(Echo485,"!%02X%d",addr7522,data);
  EchoType=ECHO2_ECHO;
}

void SetCRLF(void)
{
  int data;

/*  if(!InitPin){
     EchoType=ERROR_ECHO;
     return;
  } */ /* mark for need not INIT* connect to GND */
  if(Cmd485[5]>='0' && Cmd485[5]<='3') data=Cmd485[5]-'0';
  else return;
  if(Cmd485[4]=='0'){                           /* AA/AA+1/AA+2=COM2  */
     ModeCrLf485=data;
     EnableEEP();
     WriteEEP(7,40,ModeCrLf485);
     ProtectEEP();
  }
  else if(Cmd485[4]=='1'){
     EnableEEP();
     if(addr7522==CurAddress)			/* AA=COM1(RS232)     */
	WriteEEP(7, 41,(ModeCrLf232=data));
     else if(addr7522==CurAddress+1)		/* AA+1=COM3(RS232)   */
	WriteEEP(7, 42,(ModeCrLf232_2=data));
     ProtectEEP();
  }
  else return;
  EchoType=OK_ECHO;
}

/* --- read the parity-bit --------------------------------------------- */

void ReadParity(void) /* read parity-bit stored in EEPROM		 */
{ int data;

  if(Cmd485[4]=='0') data=ReadEEP(7,3);                    /* COM2       */
  else if(Cmd485[4]=='1'){
	 if(addr7522==CurAddress)  data=ReadEEP(7,7);	   /* AA=COM1	 */
	 else if(addr7522==CurAddress+1) data=ReadEEP(7,11);/* AA+1=COM3 */
  }
  else return;
  sprintf(Echo485,"!%02X%d",addr7522,data);
  EchoType=ECHO2_ECHO;
}

void SetParity(void)
{
 int data;

/* if(!InitPin){
    EchoType=ERROR_ECHO;
    return;
 } */	/* mark for need not INIT* connect to GND */
 if(Cmd485[5]=='0') data=0;     /* valid 0/1/2    */
 else if(Cmd485[5]=='1') data=1;/* 0=None         */
 else if(Cmd485[5]=='2') data=2;/* 1=Even         */
 else return;			/* 2=Odd	  */
 if(Cmd485[4]=='0'){                            /* COM2(RS485)        */
    Parity485=data;
    EnableEEP();
    WriteEEP(7,3,Parity485);
    ProtectEEP();
    WaitToDo=_ChangeParity;			/* change later       */
 }
 else if(Cmd485[4]=='1'){                       /* AA=COM1(RS232)     */
    EnableEEP();
    if(addr7522==CurAddress){
       WriteEEP(7,7,(Parity232=data));
       RestoreCom232(); 			/* change immediately */
       InstallCom232(BAUD[Baud232],Data232,Parity232);
    }
    else if(addr7522==CurAddress+1){		/* AA+1=COM3(RS232)   */
       WriteEEP(7,11,(Parity232_2=data));
       RestoreCom232_2();			/* change immediately */
       InstallCom232_2(BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2);
    }
    ProtectEEP();
 }
 else return;
 EchoType=OK_ECHO;
}

/* --- read the stop-bit -------------------------------------------- */

void ReadStopBit(void) /* read stop-bit stored in EEPROM	      */
{
   int data;					/* can't change    ?? */
   if(Cmd485[4]=='0') data=ReadEEP(7,5);        /* COM2(RS485)        */
   else if(Cmd485[4]=='1') {
	   if(addr7522==CurAddress)		/* AA=COM1(RS232)     */
	      data=ReadEEP(7,9);
	   else if(addr7522==CurAddress+1)
	      data=ReadEEP(7,13);		/* AA+1=COM2(RS232)   */
   }
   else return;
  sprintf(Echo485,"!%02X%d",addr7522,data);
  EchoType=ECHO2_ECHO;
}

void SetStopBit(void)
{
 int data;

/* if(!InitPin){
    EchoType=ERROR_ECHO;
    return;
 } */	/* mark for need not INIT* connect to GND */
 if(Cmd485[5]=='1') data=1;      /* valid 1/2     */
 else if(Cmd485[5]=='2') data=2; /* valid 1/2     */
 else return;

 if(Cmd485[4]=='0'){             /* can't change  */
    return;
 }
 else if(Cmd485[4]=='1'){        /* can't change ?*/
    EnableEEP();
    if(addr7522==CurAddress)
       {
       WriteEEP(7,9,(Stop232=data));
       RestoreCom232();
       InstallCom232(BAUD[Baud232],Data232,Parity232);
       }
    else if(addr7522==CurAddress+1)		/* AA+1=COM2(RS232)   */
       {
       WriteEEP(7,13,(Stop232_2=data));
       RestoreCom232_2();
       InstallCom232_2(BAUD[Baud232_2],Data232_2,Parity232_2,Stop232_2);
       }
    ProtectEEP();
 }
 else return;
 EchoType=OK_ECHO;
}

/* --- read the check-sum enable/disable ----------------------- */

void ReadCheckSumMode(void) /* read checksum status in EEPROM	 */
{
  int data=ReadEEP(7,20);

  sprintf(Echo485,"!%02X%d",addr7522,data);
  EchoType=ECHO2_ECHO;
}

void SetCheckSumMode(void)
{ int data;

  if(Cmd485[4]=='1') data=1;            /* enable checksum       */
  else if(Cmd485[4]=='0') data=0;       /* disable checksum      */
  else {
     return;
  }

  EnableEEP();
  NewCheckSum=data;
  WaitToDo=_ChangeCheckSum;		/* change after echo	 */
  WriteEEP(7,20,data);
  ProtectEEP();
  EchoType=OK_ECHO;
}

/* --- read the configuration of COM2(RS485) stored in EEPROM ---------- */

void ReadConfiguration(void)
{ int BB,DD,PP,KK;

  BB=ReadEEP(7,2); /* baud rate       */
  DD=ReadEEP(7,4); /* data-bit	      */
  PP=ReadEEP(7,3); /* parity-bit      */
  KK=ReadEEP(7,20);/* checksum status */
  sprintf(Echo485,"!%02X40%x%x%x%x",addr7522,BB,DD,PP,KK);
  EchoType=ECHO2_ECHO;
}

/* --- Read the CTS of COM1 & COM3 ----------------------------- */
/* return !AA0: CTS inactive now				 */
/* return !AA1: CTS active LOW now				 */

void ReadCts(void) /* valid address: AA & AA+1			 */
{
  int data;
  if  (addr7522==CurAddress)	   /* AA=COM1			 */
      sprintf(Echo485,"!%02X%d",addr7522,GetCtsStatus1()?1:0);
  else if(addr7522==CurAddress+1){ /* AA+1=COM3 		 */
      sprintf(Echo485,"!%02X%d",addr7522,GetCtsStatus3()?1:0);
  }
  else
      sprintf(Echo485,"?%02X",addr7522);
  EchoType=ECHO2_ECHO;
}

/* --- Set the RTS of COM1 & COM3 ------------------------------ */
/* $AAW0: RTS inactive						 */
/* $AAW1: RTS active LOW					 */

void SetRts(void) /* valid address: AA & AA+1			 */
{
  int data;
  if  (addr7522==CurAddress)	   /* AA=COM1			 */
      {
      if(Cmd485[4]=='0')           /* Rts of COM1 inactive       */
	{
	SetRtsInactive1();
	sprintf(Echo485,"!%02X",addr7522);
	}
      else if(Cmd485[4]=='1')      /* Rts of COM1 active LOW     */
	{
	SetRtsActive1();
	sprintf(Echo485,"!%02X",addr7522);
	}
      else
      sprintf(Echo485,"?%02X",addr7522);
      }
  else if(addr7522==CurAddress+1)  /* AA+1=COM3 		 */
      {
      if(Cmd485[4]=='0')           /* Rts of COM3 inactive       */
	{
	SetRtsInactive3();
	/* if(DEBUG_7522) Print("RTS3=0(%02X)",inp(0x14));*/
	sprintf(Echo485,"!%02X",addr7522);
	}
      else if(Cmd485[4]=='1')      /* Rts of COM3 active LOW     */
	{
	SetRtsActive3();
	/* if(DEBUG_7522) Print("RTS3=1(%02X)",inp(0x14)); */
	sprintf(Echo485,"!%02X",addr7522);
	}
      else
      sprintf(Echo485,"?%02X",addr7522);
      }
  else
      sprintf(Echo485,"?%02X",addr7522);
  EchoType=ECHO2_ECHO;
}

/* --- Read On Board DI ---------------------------------------- */
/* $AAY1: read DI1						 */
/* $AAY2: read DI2						 */
/* $AAY3: read DI3						 */

void ReadOnBoardDi(void) /* valid address: AA			 */
{
  int data;
  if  (addr7522==CurAddress)	   /* AA			 */
      {
      if(Cmd485[4]=='1')           /* Read DI1=INIT* pin         */
	{			   /* DI1=!ReadInitPin()	 */
	sprintf(Echo485,"!%02X%d",addr7522,!ReadInitPin());
	}
      else if(Cmd485[4]=='2')      /* Read DI2                   */
	{
	sprintf(Echo485,"!%02X%d",addr7522,GetDi2()?1:0);
	}
      else if(Cmd485[4]=='3')      /* Read DI3                   */
	{
	sprintf(Echo485,"!%02X%d",addr7522,GetDi3()?1:0);
	}
      else
      sprintf(Echo485,"?%02X",addr7522);
      }
  else
      sprintf(Echo485,"?%02X",addr7522);
  EchoType=ECHO2_ECHO;
}

/* --- Write On Board DO --------------------------------------- */
/* $AAZ10: Turn DO1 OFF, $AAZ11:Turn DO1 ON			 */

void WriteOnBoardDo(void) /* valid address: AA			 */
{
  int data;
  if  (addr7522==CurAddress)	   /* AA			 */
      {
      if(HostWdtModuleStatus)	   /* Host Failure		 */
	 sprintf(Echo485,"!");
      else if(Cmd485[4]=='1')      /* Write DO1                  */
	{
	if (Cmd485[5]=='0')        /* turn DO1 OFF               */
	   {
	   SetDo1High();
	   sprintf(Echo485,"!%02X",addr7522);
	   }
	else if (Cmd485[5]=='1')   /* turn DO1 ON                */
	   {
	   SetDo1Low();
	   sprintf(Echo485,"!%02X",addr7522);
	   }
	else			   /* invalid command		 */
	   sprintf(Echo485,"?%02X",addr7522);
	}
      }
  else
      sprintf(Echo485,"?%02X",addr7522);
  EchoType=ECHO2_ECHO;
}

/* --- synchronoized sampling ---------------------------------- */

void SyncSample(void) /* valid address: all AA			 */
{
SyncData=!ReadInitPin()+GetDi2()+GetDi3(); /* DI1=!ReadInitPin() */
FirstRead=1;
}

/* --- Host is OK ---------------------------------------------- */

void HostOk(void) /* valid address: all AA			 */
{
_asm cli
  HostTimerStart=*timetick;
_asm sti
}

/* --- Set Power On Value of DO -------------------------------- */

void SetPowerOnValue(void) /* valid address: AA 		 */
{
if (!GetDo1()) HostWdtPowerOnValue=1; else HostWdtPowerOnValue=0;
sprintf(Echo485,"!%02X%X",CurAddress,HostWdtPowerOnValue);
EnableEEP();
WriteEEP(7,23,HostWdtPowerOnValue);
ProtectEEP();
}

/* --- Set Safe Value	  of DO -------------------------------- */

void SetSafeValue(void) /* valid address: AA			 */
{
if (!GetDo1()) HostWdtSafeValue=1; else HostWdtSafeValue=0;
sprintf(Echo485,"!%02X%X",CurAddress,HostWdtSafeValue);
EnableEEP();
WriteEEP(7,24,HostWdtSafeValue);
ProtectEEP();
}

/* --- Set all Do ---------------------------------------------- */

void SetAllDo(char);
void SetAllDo(char DoVal) /* valid address: AA			 */
{
if (DoVal&0x01) SetDo1Low(); else SetDo1High();
}

/* ------------------------------------------------------------- */


void ByPassTo232(void)
{

    ToComBufn232(Cmd485+3,Idx485-3); /* send to COM1	  */
    switch(CurModeCrLf232){
      case 0:
	   ToCom232Str("\r");        /* CrLfMode=0 --> CR    */
	   break;
      case 1:
	   ToCom232Str("\r\n");      /* CrLfMode=1 --> CR+LF */
	   break;
      case 2:
	   ToCom232Str("\n");        /* CrLfMode=2 --> LF    */
	   break;
      case 3:
	   ToCom232Str("\n\r");      /* CrLfMode=3 --> LF+CR */
	   break;
    }

}

void ByPassTo232_2(void)
{
    ToComBufn232_2(Cmd485+3,Idx485-3);/* send to COM3	    */
    switch(CurModeCrLf232_2){
      case 0:
	 ToCom232Str_2("\r");       /* CrLfMode=0 --> CR    */
	 break;
      case 1:
	 ToCom232Str_2("\r\n");     /* CrLfMode=1 --> CR+LF */
	 break;
      case 2:
	 ToCom232Str_2("\n");       /* CrLfMode=2 --> LF    */
	 break;
      case 3:
	 ToCom232Str_2("\n\r");     /* CrLfMode=3 --> LF+CR */
	 break;
    }

}


/* ------------------------------------------------------------- */

void ProcessCom485(void)
{
 InitPin=ReadInitPin();  /* 1: Init* connect to GND	      */

/* step 1 : process this command string 		      */

 EchoType=NO_ECHO;

 if((Cmd485[0]=='#')&&(Cmd485[1]=='*')&&(Cmd485[2]=='*')&&(Idx485==3))
  SyncSample();
 else if((Cmd485[0]=='~')&&(Cmd485[1]=='*')&&(Cmd485[2]=='*')&&(Idx485==3))
  HostOk();
 else if(Idx485>=3){
  addr7522=(ascii_to_hex(Cmd485[1])<<4)+ascii_to_hex(Cmd485[2]);
  if(addr7522==CurAddress
    || (addr7522==CurAddress+1)){


/* ----------- command type 1 --> $???? for 7188XC standard command --- */
     if(Cmd485[0]=='$'){
	switch(Cmd485[3]){
	  case 'M': /* $AAM: read module name                           */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X7522",CurAddress);
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case 'F': /* $AAF: read firmware version number               */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02XA1.0",CurAddress);/* A1.0        */
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '6': /* $AA6(ID): Set ID, max. length=50 chars           */
	       if(Idx485>4) SetID();
	       break;
	  case '7': /* $AA7: Read ID                                    */
	       if(Idx485==4) ReadID();
	       break;
	  case 'A': /* $AAA[addr]: Read/Set new address                 */
	       if(Idx485==4) ReadAddress();	   /* read AA		*/
	       else if(Idx485==6) SetAddress();    /* set  AA		*/
	       break;
	  case 'B': /* $AABN[baudrate]: Read/Set new baudrate           */
	       if(Idx485==5) ReadComBaudrate();    /* read baudrate	*/
	       else if(Idx485>5) SetComBaudrate(); /* set		*/
	       break;
	  case 'C': /* $AAC[delimiter]: Read/Set new delimiter          */
	       if(Idx485==4){ /* $AAC: Read Delimiter			*/
		 sprintf(Echo485,"!%02X%c",addr7522,Delimiter);
		 EchoType=ECHO2_ECHO;
	       }
	       else /* $AAC[delimiter]: Set new Delimiter		*/
		    if(Idx485==5 && Cmd485[4]!='$') SetDelimiter();
	       break;
	  case 'D': /* $AADN[data-bit] & $AAD                           */
	       if(Idx485==4) ReadDelimiter();	/* $AAD: read delimiter */
	       else if(Idx485==5) ReadDataBit();/* $AADN: read data-bit */
	       else if(Idx485>5) SetDataBit();	/* $AADN[data-bit]: set */
	       break;
	  case 'K': /* $AAK[chksum]: Read/Set checksum mode             */
	       if(Idx485==4) ReadCheckSumMode();
	       else if(Idx485==5) SetCheckSumMode();
	       break;
	  case 'T': /* $AATN[CrLfMode]: Read/Set new CrLfMode           */
	       if(Idx485==5) ReadCRLF();	/* read CrLfMode	*/
	       else if(Idx485>5) SetCRLF();	/* set CrlFMode 	*/
	       break;
	  case 'P': /* $AAPN[Parity-bit]: Read/Set new parity-bit       */
	       if(Idx485==5) ReadParity();	/* read parity-bit	*/
	       else if(Idx485>5) SetParity();	/* set parity-bit	*/
	       break;
	  case 'O': /* $AAON[stop-bit]: Read/Set new stop-bit           */
	       if(Idx485==5) ReadStopBit();	/* read stop-bit	*/
	       else if(Idx485>5) SetStopBit();	/* set stop-bit 	*/
	       break;
	  case 'W': /* $AAW: Read CTS of COM1 or COM3                   */
	       if(Idx485==4) ReadCts();
	       break;
	  case 'X': /* $AAXN: Set RTS of COM1 or COM3                   */
	       if(Idx485==5) SetRts();
	       break;
	  case 'Y': /* $AAYN: Read onboard DI1/2/3 for N=1/2/3          */
	       if(Idx485==5) ReadOnBoardDi();
	       break;
	  case 'Z': /* $AAZNV: Write onboard DO1/2/3 for N=1/2/3,V=0/1  */
	       if(Idx485==6) WriteOnBoardDo();
	       break;
	  case '4': /* $AA4: read the sync-sample data                  */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X%d%X",CurAddress,FirstRead,SyncData);
		 FirstRead=0;
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '5': /* $AA5: read the reset-status                      */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X%d",CurAddress,ResetStatus);
		 ResetStatus=0;
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '2': /* $AA2: read the configuration saved in EEPROM     */
	       if(Idx485==4) ReadConfiguration();
	       break;
	  case 'R':{
	       bypass_source=0;
	       Idx485=0;
	       Idx232=0;
	       Idx232_2=0;
	       }
	       break;
	}
     }
/* ----------- command type 2 --> bypass command-string to COM1/3/4 --- */
     else if(Cmd485[0]==Delimiter && addr7522==CurAddress){
	     bypass_source=485;
	     ByPassTo232();  /* bypass command-string from COM2 to COM1 */
     }
     else if(Cmd485[0]==Delimiter_2 && addr7522==CurAddress+1){
	     bypass_source=485;
	     ByPassTo232_2();/* bypass command-string from COM2 to COM3 */
     }
/* ----------- command type 3 --> ~???? for dual-watchdog command ----- */
     else if(Cmd485[0]=='~'){
	switch(Cmd485[3]){
	  case '0': /* ~AA0: read module status, 7000 compatible        */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X%d",CurAddress,HostWdtModuleStatus);
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '1': /* ~AA1: reset module status, 7000 compatible       */
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X",CurAddress);
		 HostWdtModuleStatus=0;
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '2': /* ~AA2: read host watchdog status & value          */
		    /* 7000 compatible					*/
	       if(Idx485==4){
		 sprintf(Echo485,"!%02X%d%02X",CurAddress,HostWdtEnable,HostWdtTimer&0xff);
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '3': /* ~AA3ETT: enable host watchdog timer              */
		    /* 7000 compatible (partial)			*/
	       if(Idx485==7){
		 if (Cmd485[4]=='1') HostWdtEnable=1; else HostWdtEnable=0;
		 HostWdtTimer=(ascii_to_hex(Cmd485[5])<<4)+ascii_to_hex(Cmd485[6]);
		 sprintf(Echo485,"!%02X%X%02X",CurAddress,HostWdtEnable,HostWdtTimer);
		 EnableEEP();
		 WriteEEP(7,21,HostWdtEnable);
		 WriteEEP(7,22,HostWdtTimer);
		 ProtectEEP();
		 if (HostWdtEnable)
		    {
		    _asm cli
		    HostTimerStart=*timetick;
		    _asm sti
		    }
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '4': /* ~AA4P/S: read power-on/safe value of D/O         */
		    /* 7000 compatible					*/
	       if(Idx485==5){
		 if (Cmd485[4]=='P') sprintf(Echo485,"!%02X%X",CurAddress,HostWdtPowerOnValue);
		 else if (Cmd485[4]=='S') sprintf(Echo485,"!%02X%X",CurAddress,HostWdtSafeValue);
		 else sprintf(Echo485,"?%02X",CurAddress);
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	  case '5': /* ~AA5P/S: Set  power-on/safe value of D/O         */
		    /* 7000 compatible (partial)			*/
	       if(Idx485==5){
		 if (Cmd485[4]=='P') SetPowerOnValue();
		 else if (Cmd485[4]=='S') SetSafeValue();
		 else sprintf(Echo485,"?%02X",CurAddress);
		 EchoType=ECHO2_ECHO;
	       }
	       break;
	}
     }
/* ----------- command type 4 --> @???? for user defined command ------ */
     else if(Cmd485[0]=='@'){
     }
/* ----------- command type 5 --> #???? for user defined command ------ */
     else if(Cmd485[0]=='#'){
     }
/* ----------- command type 6 --> %???? for user defined command ------ */
     else if(Cmd485[0]=='%'){
     }
  }
 }

/* step 2 : ECHO response string to COM2		      */

  switch(EchoType){
    case NO_ECHO:	  /* 0: NoEcho			      */
	 break;
    case ERROR_ECHO:	  /* 1: Call EchoErrorCmd()	      */
	 EchoErrorCmd();
	 break;
    case OK_ECHO:	  /* 2: Call EchoOkCmd()	      */
	 EchoOkCmd();
	 break;
    case ECHO2_ECHO:	  /* 3: echo string stored in Echo485 */
	 SendCmdToCom485Str(Echo485);
	 if(quit) WaitTransmitOver485();
	 break;
  }

 if(WaitToDo){
    if(WaitToDo==_ChangeCheckSum) { CheckSum=NewCheckSum; }
    else {
       WaitTransmitOver485();
       RestoreCom485();
       InstallCom485(BAUD[Baud485],Data485,Parity485);
    }
    WaitToDo=0;
 }
 Idx485=0;
}

/* --- if comand-format is match then process this command -------- */

void DoCom485(void) /* COM2=RS-485 */
{ int data;
  int Do485=0;

  while(IsCom485()){
    Cmd485[Idx485]=data=ReadCom485();
    if(DEBUG_7522){
       Putchd(data); //
       if(data=='\r') Putchd('\n');
    }
    if(data=='\r'){
       switch(CurModeCrLf485){
	 case 0:		 /* CrLfMode=0=CR	 */
	      Cmd485[Idx485]=0;
	      if(DEBUG_7522) dPrint("[CR]\n");
	      Do485=1;
	      goto End485;
	 case 1: /* CR+LF */	 /* not match		 */
	 case 2: /* LF */	 /* not match		 */
	      Idx485++;
	      break;
	 case 3:		 /* CrLfMode=3=LF+CR	 */
	      if(Cmd485[Idx485-1]=='\n'){
		 Idx485--;
		 Cmd485[Idx485]=0;
		 if(DEBUG_7522) dPrint("[LF+CR]\n");
		 Do485=1;
		 goto End485;
	      }
	      break;
       }
    }
    else if(data=='\n'){
       switch(CurModeCrLf485){
	 case 0: /* CR */	 /* not match		 */
	      Idx485++;
	      break;
	 case 1: /* CR+LF */	 /* CrLfMode=1=CR+LF	 */
	      if(Cmd485[Idx485-1]=='\r'){
		 Idx485--;
		 Cmd485[Idx485]=0;
		 if(DEBUG_7522) dPrint("[CR+LF]\n");
		 Do485=1;
		 goto End485;
	      }
	      break;
	 case 2: /* LF */	 /* CrLfMode=2=LF	 */
	      Cmd485[Idx485]=0;
	      if(DEBUG_7522) dPrint("[LF]\n");
	      Do485=1;
	      goto End485;
	 case 3: /* LF+CR */	 /* not match		 */
	      Idx485++;
	      break;
       }
    }
    else {
       Idx485++;
    }
  }
End485:
  if(Do485){
     if(CheckSum){
       unsigned char sum=0;
       int i;
       for(i=0;i<Idx485-2;i++){
	   sum+=Cmd485[i];
       }
       if(DEBUG_7522) dPrint("[%02X]",sum);
       if( (hex_to_ascii[sum >> 4] == Cmd485[i])
	  && (hex_to_ascii[sum & 0x0F] == Cmd485[i+1]) ) {
	  Idx485-=2;
	  Cmd485[Idx485]=0;
       }
       else {	/* checksum is enable & echeck error */
	  Idx485=0;
	  if(DEBUG_7522) dPrint("(Checksum error!)",sum);
	  return;
       }
     }
     ProcessCom485();	 /* process this command */
  }
}

/* ------------------------------------------------------------- */

void main(int argc,char *argv[])
{ int i;
  unsigned long NowTimeTick;

  if(!Is7188x()){    /* run this program in PC will halt that PC */
     Print("This program must be run under 7188XC/7521/7522/7523.");
     return;
  }

  for(i=1;i<argc;i++) {
      if(argv[i][0]=='/'){
	 switch(argv[i][1]){
	   case 'd': case 'D':
		DEBUG_7522=1;
		/*
		  DEBUG_7522=1 --> go to debug mode, take care as following:
		  note 1: COM1 is used to show debug message
		  note 2: do not call InstallCom1()
		  note 3: and do not echo COM1 message back to COM2
		*/
		break;

	 }
      }
  }

  init_user();
  if(DEBUG_7522) dPrint("Start 7522!\n\r");

  Open7522();
  EnableWDT();
  while(!quit){
    RefreshWDT();
    if(!DEBUG_7522) DoCom232();   /* if receive string from COM1 --> send to COM2 */
    DoCom232_2(); /* if receive string from COM3 --> send to COM2 */

    DoCom485();   /* process command from COM2			  */

    if (HostWdtEnable) {
       _asm cli
       NowTimeTick=*timetick;
       _asm sti
       if (NowTimeTick>=HostTimerStart) i=NowTimeTick-HostTimerStart;
       else i=0xffffffffffffffff-HostTimerStart+NowTimeTick;
       if (i>(HostWdtTimer*100)) {
	  HostWdtModuleStatus=0x04;
	  SetAllDo(HostWdtSafeValue);
	  HostWdtEnable=0;
       }
    }

    if(DEBUG_7522){
      if(IsComd() && ReadComd()=='q') quit=1;
    }
  }
  DisableWDT();
  Close7522();
}


init_user()
{
return 0;
}
