//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>

#include "main.h"

#pragma hdrstop
//---------------------------------------------------------------------------

/* Table of CRC values for high-order byte */
unsigned char auchCRCHi[256]={
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
	0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
	0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
	0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
	0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
	0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
	0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};

/* Table of CRC values for low-order byte */
unsigned char auchCRCLo[256]={
	0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
	0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
	0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
	0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
	0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
	0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
	0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
	0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
	0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
	0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
	0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
	0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
	0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
	0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
	0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
	0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
	0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
	0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
	0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
	0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
	0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
	0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
	0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
	0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
	0x43, 0x83, 0x41, 0x81, 0x80, 0x40};


HANDLE cport=NULL;

unsigned char cmd[256];
unsigned char *pcmd;
unsigned long rxn;

#pragma argsused
int main(int argc, char* argv[])
{
	int baudT[5]={9600,19200,38400,57600,115200};
	int com;
	int c;
	int baud=115200;
	char cname[260];



	Reconect:
	clrscr();

	printf("Enter COM port number: ");
	while(1)
	{
		c=getch();
		if(c>='0' && c<='9') break;
		if(c==27) return(1);
	}
	printf("%d\n",(com=c-'0'));
	sprintf(cname,"COM%d",com);
	if(COMopen(&cport,cname)==1)
	{
		printf("Can't open specified COM%d port!\n",c-'0');
		Sleep(2000);
		goto Reconect;
	}

	printf("Choose baudrate (1=9600,2=19200,3=38400,4=57600,5=115200): ");
	while(1)
	{
		c=getch();
		if(c>='1' && c<='5')
		{
			baud=baudT[c-'1'];
			break;
		}
		if(c==27) return(1);
	}

	printf("%dbd\n",baud);
	printf("COM%d opened at %dbd ...\n",com,baud);

	WriteHelp();

	COMsetBuf(cport,1024,512);
	COMsetFormat(cport,baud,TWOSTOPBITS);
	COMsetTimeouts(cport,20,5,1,100,1);

	while(1)
	{
		c=getch();
		if(c==27) break;
		if(c>='1' && c<='8')
		{
			SendPushButtonEvent(c-'0',0);
			Sleep(20);
			SendPushButtonEvent(0,c-'0');
		}
		if(c=='c') clrscr();
		if(c=='h') WriteHelp();
		if(c=='r')
		{
			COMclose(&cport);
			goto Reconect;
		}
		if(c=='i') GetInfo();
		if(c=='x') ReadXRAM();
		if(c==0)
		{
			c=getch();
			//printf("%d\n",c);
			if(c>=59 && c<=62) SendLEDtoggleCmd(1<<(c-59));
			if(c==63) SendLEDtoggleCmd(0x80);
			if(c==134) SendBacklightCmd(1);
			if(c==133) SendBacklightCmd(0);
		}
	}
	COMclose(&cport);

	printf("\nUser termination ...\n",c);

	return(0);
}
//---------------------------------------------------------------------------





//---------------------------------------------------------------------------
// otevrit COM port, pro win XP a COM vyssi nez 9 uvadet jmena ve formatu "\\\\.\\COM10"
//---------------------------------------------------------------------------
int COMopen(HANDLE *cporth, char *cportname)
{
	*cporth=CreateFile(cportname,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
	if(*cporth==INVALID_HANDLE_VALUE)
		return(1);
	return(0);
}
//---------------------------------------------------------------------------
// zavrit COM port
//---------------------------------------------------------------------------
void COMclose(HANDLE *cporth)
{
	CloseHandle(*cporth);
	*cporth=NULL;
}
//---------------------------------------------------------------------------
// nastavit velikost RX, TX bufferu
//---------------------------------------------------------------------------
bool COMsetBuf(HANDLE cporth, int inlen, int outlen)
{
	return(SetupComm(cporth,inlen,outlen));
}
//---------------------------------------------------------------------------
// nastavit format ramce (baudrate a pocet stopbitu)
//---------------------------------------------------------------------------
void COMsetFormat(HANDLE cporth, int baud, int stopbit)
{
	DCB dcb;
	GetCommState(cporth,&dcb);
	dcb.fBinary=true;
	dcb.fAbortOnError=false;
	dcb.BaudRate=baud;
	dcb.StopBits=stopbit;
	dcb.Parity=NOPARITY;
	dcb.ByteSize=8;
	SetCommState(cporth,&dcb);
}
//---------------------------------------------------------------------------
// nastavit timeouty (rxtime/txtime v ms)
//---------------------------------------------------------------------------
void COMsetTimeouts(HANDLE cporth, int rxinterval, int rxtime, int rxmult, int txtime, int txmult)
{
	COMMTIMEOUTS timeouts;
	timeouts.ReadIntervalTimeout=rxinterval;
	timeouts.ReadTotalTimeoutMultiplier=rxmult;
	timeouts.ReadTotalTimeoutConstant=rxtime;
	timeouts.WriteTotalTimeoutMultiplier=txmult;
	timeouts.WriteTotalTimeoutConstant=txtime;
	SetCommTimeouts(cporth,&timeouts);
}
//---------------------------------------------------------------------------
// vymazat vstupni buffer
//---------------------------------------------------------------------------
void COMflushInput(HANDLE cporth)
{
	PurgeComm(cporth,PURGE_RXCLEAR);
}
//---------------------------------------------------------------------------
// odeslat byte (vraci pocet zapsanych bytu)
//---------------------------------------------------------------------------
unsigned long COMtxByte(HANDLE cporth, byte byte)
{
	unsigned long written;
	WriteFile(cporth,&byte,1,&written,NULL);
	return(written);
}
//---------------------------------------------------------------------------
// cist byte (vraci pocet prectenych bytu)
//---------------------------------------------------------------------------
unsigned long COMrxByte(HANDLE cporth, byte *byte)
{
	unsigned long read;
	ReadFile(cporth,byte,1,&read,NULL);
	return(read);
}
//---------------------------------------------------------------------------
// odeslat data (vraci pocet skutecne zapsanych bytu)
//---------------------------------------------------------------------------
unsigned long COMtxData(HANDLE cporth, void *data, unsigned long datalen)
{
	unsigned long written;
	WriteFile(cporth,data,datalen,&written,NULL);
	return(written);
}
//---------------------------------------------------------------------------
// cist data (vraci pocet skutecne nactenych bytu)
//---------------------------------------------------------------------------
unsigned long COMrxData(HANDLE cporth, void *data, unsigned long datalen)
{
	unsigned long read;
	ReadFile(cporth,data,datalen,&read,NULL);
	return(read);
}



void WriteHelp(void)
{
	printf("\n");
	printf("---------- Help ----------\n");
	printf("F1,F2,F3 and F4 - toggling LEDs\n");
	printf("F5 - turn off all LEDs\n");
	printf("F11 - turn off backlight\n");
	printf("F12 - turn on backlight\n");
	printf("1,2,3,4,5,6,7,8 - send button press event\n");
	printf("h - help\n");
	printf("c - clear screen\n");
	printf("r - COM reconection\n");
	printf("esc - program terminate\n");
	printf("--------------------------\n\n");
}


void GetInfo(void)
{
	int leds=0;
	unsigned int comevents;
	char str0x00[256];
	char str0x01[256];
	char str0x02[256];
	char str0x03[256];
	char str0x04[256];

	memset((void*)str0x00,'\0',256);
	memset((void*)str0x01,'\0',256);
	memset((void*)str0x02,'\0',256);
	memset((void*)str0x03,'\0',256);
	memset((void*)str0x04,'\0',256);

	printf("\nRetrieving status informations:\n");
  printf("  ");
	GetCommEvents(&comevents);
	printf("  ");
	GetIdent(str0x00,0x00);
	printf("  ");
	GetIdent(str0x01,0x01);
	printf("  ");
	GetIdent(str0x02,0x02);
	printf("  ");
	GetIdent(str0x03,0x03);
	printf("  ");
	GetIdent(str0x04,0x04);
	printf("  ");
	GetLEDstate(&leds);

	printf("\nStatus:\n");
	printf("  Comunication events: %d\n",comevents);
	printf("  --- Identification ---\n");
	printf("    Manufacturer:     %s\n",str0x00);
	printf("    Product code:     %s\n",str0x01);
	printf("    Version:          %s\n",str0x02);
	printf("    Manufacturer URL: %s\n",str0x03);
	printf("    Product name:     %s\n",str0x04);
	printf("  --- LEDs ---\n");
	printf("    Red LED:       %s\n",(leds&0x01)?"ON":"OFF");
	printf("    Yellow LED:    %s\n",(leds&0x02)?"ON":"OFF");
	printf("    Green LED:     %s\n",(leds&0x04)?"ON":"OFF");
	printf("    Blue LED:      %s\n",(leds&0x08)?"ON":"OFF");
	printf("    Backlight LED: %s\n",(leds&0x10)?"ON":"OFF");

}


void ReadXRAM(void)
{
	FILE *fw;
	char data[65536];
	int offset=0;
	int plen;
	int tries=32;
	int	ctr;
	int x,y;

	printf("Reading XRAM: ");
	x=wherex();
	y=wherey();

	while(tries>0 && offset<65535)
	{
		COMflushInput(cport);
		pcmd=cmd;
		*pcmd++=0x55;
		*pcmd++=0x47;
		*pcmd++=mrmXDATA;
		wr16be(&pcmd,offset);
		*pcmd++=plen=((offset+247)>65536)?(65536-offset):247;
		wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
		COMtxData(cport,(void*)cmd,pcmd-cmd);

		memset((void*)cmd,0x00,256);

		ctr=10;
		while(--ctr)
			if((rxn=COMrxByte(cport,cmd))!=0) break;
		rxn+=COMrxData(cport,(void*)(cmd+rxn),255);

		pcmd=cmd+rxn-2;
		if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55 && cmd[1]==0x47 && cmd[2]==mrmXDATA && ((((unsigned int)cmd[3])<<8) + ((unsigned int)cmd[4]))==offset && cmd[5]==plen)
		{
			memcpy((void*)&data[offset],(void*)cmd[6],plen);
			offset+=plen;
			gotoxy(x,y);
			printf("%5dB/65536B\n",offset);
			tries=32;
		}
		tries--;
	}
	if(offset==65536)
	{
		// reading done
		gotoxy(x,y);
		printf("writting data to file \"XRAM.bin\" ...\n",offset);
		fwrite((void*)data,1,65536,fw);
		fflush(fw);
		printf(" done ...\n",offset);
	}
	else
	{
		// reading done
		gotoxy(x,y);
		printf("communication errors ...\n",offset);
	}
}



unsigned short CRC16(unsigned char *puchMsg, unsigned short usDataLen)
{
	unsigned char uchCRCHi=0xFF;	/* high CRC byte initialized */
	unsigned char uchCRCLo=0xFF;	/* low CRC byte initialized  */
	unsigned char uIndex;				/* will index into CRC lookup*/

	while(usDataLen--)		/* pass through message buffer */
	{
		uIndex = uchCRCHi ^ *puchMsg++;	/* calculate the CRC */
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
		uchCRCLo = auchCRCLo[uIndex];
	}

	return((uchCRCHi<<8)|uchCRCLo);
}

unsigned short rd16be(unsigned char **str)
{
	unsigned short res=((unsigned short)(**str)<<8)&0xFF00;
	(*str)++;
	res+=(unsigned short)(**str);
	(*str)++;
	return(res);
}

void wr16be(unsigned char **str, unsigned int data)
{
	**str=(data>>8)&0x00FF;
	(*str)++;
	**str=(data)&0x00FF;
	(*str)++;
}



int SendPushButtonEvent(int btndown, int btnup)
{
	unsigned char btnmap[9]={0,0x80,0x40,0x20,0x10,0x02,0x01,0x04,0x08};

	if(btnup!=0)
		printf("CMD send btnup event: ");
	else
		printf("CMD send btndown event: ");

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x46;
	wr16be(&pcmd,0x0000);
	*pcmd++=0;
	wr16be(&pcmd,MODBUS_ADDR_BTNEVENT);
	*pcmd++=2;
	*pcmd++=btnmap[btndown];
	*pcmd++=btnmap[btnup];
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	rxn=COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x46)
		{
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x46|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ...\n"); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}
	printf("\n");
	return(1);
}



int SendLEDtoggleCmd(int mask)
{
	if(mask==0x80)
		printf("CMD turn off LEDs: ");
	else
		printf("CMD toggle LED: ");

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x46;
	wr16be(&pcmd,0x0000);
	*pcmd++=0;
	wr16be(&pcmd,MODBUS_ADDR_LEDTOGGLE);
	*pcmd++=1;
	*pcmd++=mask;
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	//printf("Respond bytes: %d\n",rxn);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x46)
		{
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x46|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ..."); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}
	printf("\n");
	return(1);
}


int SendBacklightCmd(int state)
{
	if(state==1)
		printf("CMD turn on baclight: ");
	else
		printf("CMD turn off baclight: ");

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x46;
	wr16be(&pcmd,0x0000);
	*pcmd++=0;
	wr16be(&pcmd,MODBUS_ADDR_BACKLIGHT);
	*pcmd++=1;
	*pcmd++=state;
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	//printf("Respond bytes: %d\n",rxn);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x46)
		{
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x46|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ..."); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}
	printf("\n");
	return(1);
}


int GetLEDstate(int *leds)
{
	printf("Reading LEDs status: ");

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x46;
	wr16be(&pcmd,MODBUS_ADDR_LEDS);
	*pcmd++=1;
	wr16be(&pcmd,0x0000);
	*pcmd++=0;
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	//printf("Respond bytes: %d\n",rxn);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x46)
		{
			*leds=cmd[3];
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x46|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ..."); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}

	printf("\n");
	return(1);
}


int GetIdent(char *str, int id)
{
	printf("Reading identification ID 0x%02X: ",id);

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x2B;
	*pcmd++=0x0E;
	*pcmd++=0x01;
	*pcmd++=id;
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	//printf("Respond bytes: %d\n",rxn);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x2B)
		{
			memcpy((void*)str,&cmd[10],cmd[9]);
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x2B|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ..."); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}

	printf("\n");
	return(1);
}



int GetCommEvents(unsigned int *count)
{
	printf("Reading communication events count: ");

	COMflushInput(cport);
	pcmd=cmd;
	*pcmd++=0x55;
	*pcmd++=0x0B;
	wr16be(&pcmd,CRC16(cmd,pcmd-cmd));
	COMtxData(cport,(void*)cmd,pcmd-cmd);

	rxn=COMrxData(cport,(void*)cmd,256);
	//printf("Respond bytes: %d\n",rxn);
	pcmd=cmd+rxn-2;
	if(rxn>3 && CRC16(cmd,rxn-2)==rd16be(&pcmd) && cmd[0]==0x55)
	{
		if(cmd[1]==0x0B)
		{
			pcmd=&cmd[4];
			*count=rd16be(&pcmd);
			printf("done ...\n");
			return(0);
		}
		else if(cmd[1]==0x0B|0x80)
		{
			printf("error 0x%02X ",cmd[2]);
			switch(cmd[2])
			{
				case 0x01: printf("- unknown command ..."); break;
				case 0x02: printf("- address out of range ..."); break;
				case 0x03: printf("- invalid data ..."); break;
				case 0x04: printf("- fatal error occurs during command execution ..."); break;
				default: printf("- general error ..."); break;
			}
		}
	}

	printf("\n");
	return(1);
}
