#use eziolp31.lib
#use vdriver.lib
#use aascz0.lib
#use aascz1.lib

CHANNEL z0Chan, z1Chan;
unsigned int nextDelay;

#define REV_NO 3400

#define FLUSHCHAR '|'
#define PACKETSIZE 16
#define TERMINATOR 13
#define BUFSIZE 64
#define port_LED 0x40a0

void processMess(char *pMess) {
	auto char *pCurrent;
	auto unsigned int portNumber;
	auto int portValue;
	auto char charToSend;
	auto int i;
	auto unsigned long int timeMark;
	
	if (nextDelay) {
		timeMark = MS_TIMER;
		while (MS_TIMER - timeMark < nextDelay) hitwd();
	}
	switch(*pMess++) {
		case 'I':
			portNumber=(unsigned int)strtol(pMess,&pCurrent,16);
			portValue = inport(portNumber);
			charToSend=(portValue >> 4);
			charToSend+=(charToSend > 9) ? ('A'-10) : '0';
			if (nextDelay) {
				timeMark = MS_TIMER;
				while (MS_TIMER - timeMark < nextDelay) hitwd();
			}
			while (!aascWriteChar(z0Chan, charToSend)) hitwd();
			charToSend=(portValue & 0xf);
			charToSend += (charToSend > 9) ? ('A'-10) : '0';
			while (!aascWriteChar(z0Chan, charToSend)) hitwd();
			while (!aascWriteChar(z0Chan, 13)) hitwd();
			break;
			nextDelay = 0;
		case 'i':
			portNumber=(unsigned int)strtol(pMess,&pCurrent,16);
			portValue = _eioBrdAI(portNumber);
			if (nextDelay) {
				timeMark = MS_TIMER;
				while (MS_TIMER - timeMark < nextDelay) hitwd();
			}
			for (i = 4; i; --i) {
				charToSend = 0xf & ((portValue & 0xf000) >> 12);
				charToSend+=(charToSend > 9) ? ('A'-10) : '0';
				portValue <<= 4;
				while (!aascWriteChar(z0Chan, charToSend)) hitwd();
			}
			while (!aascWriteChar(z0Chan, 13)) hitwd();
			nextDelay = 0;
			break;
		case 'O':
			portNumber=(unsigned int)strtol(pMess,&pCurrent,16);
			if (*pCurrent == ',') {
				++pCurrent;
				portValue = (char)strtol(pCurrent, &pCurrent, 16);
				outport(portNumber, portValue);
				while (!aascWriteChar(z0Chan,13)) hitwd();
			}
			nextDelay = 0;
			break;
		case 'D':
			nextDelay=(unsigned int)strtol(pMess,&pCurrent,16);
			break;
		default:
			break;
	}
}

void passMess(char *pMess, unsigned length) {
	--(*pMess);
	while (!aascWriteBlk(z1Chan, pMess, length, 1)) hitwd();
}

void testTask() {
	auto int packetSize;
	auto char packet[PACKETSIZE];
	auto char *pCurrent;
	
	if (packetSize=aascScanTerm(z0Chan,TERMINATOR)) {
		//	we have received a complete packet
		outport(port_LED,1);
		aascReadBlk(z0Chan,packet,packetSize,1);
		pCurrent = packet;
		if (isdigit(*pCurrent)) {
			//	daisy chain number
			if (*pCurrent == '0') {
				//	this message is for me
				processMess(pCurrent+1);
				packet[packetSize-1] = '\0';	//	replace terminator with null
			} else {
				//	this message should be passed on
				passMess(pCurrent, packetSize);
			}
		} else {
			//	non-digit, something's wrong
			if (*pCurrent == FLUSHCHAR) {
				aascFlush(z0Chan);
				aascFlush(z1Chan);
			}
		}
		outport(port_LED,0);
	}
	
	if (packetSize = aascScanTerm(z1Chan,TERMINATOR)) {
		//	we have something to pass back
		aascReadBlk(z1Chan,packet,packetSize,1);
		while (!aascWriteBlk(z0Chan,packet,packetSize,1)) hitwd;
	}
}

main() {
	static char inBuf[2][BUFSIZE],outBuf[2][BUFSIZE];
	unsigned long timeMark;
	struct tm t;
	int sec;

	outport(0x40a4,1);		//	DIO as input, avoid fighting
	outport(port_LED,0);
	
	VdInit();
	eioBrdInit(0);
	
	//	initialize the serial channels
	
	z0Chan = aascOpen(DEV_Z0,0,ASCI_PARAM_8N1 | (ASCI_PARAM_1200*16), NULL);
	z1Chan = aascOpen(DEV_Z1,0,ASCI_PARAM_8N1 | (ASCI_PARAM_1200*16), NULL);
	aascSetWriteBuf(z0Chan,outBuf[0],sizeof(outBuf[0]));
	aascSetWriteBuf(z1Chan,outBuf[1],sizeof(outBuf[1]));
	aascSetReadBuf(z0Chan,inBuf[0],sizeof(inBuf[0]));
	aascSetReadBuf(z1Chan,inBuf[1],sizeof(inBuf[1]));
	aascTxSwitch(z0Chan,1);
	aascTxSwitch(z1Chan,1);
	aascRxSwitch(z0Chan,1);
	aascRxSwitch(z1Chan,1);

	outport(0x4084,1);
	outport(0x4083,1);
	outport(0x4082,1);
	nextDelay = 0;
	while (1) {
		testTask();
	}
}