/*
	TERM.C

	This program demonstrates basic functions to let the controller
	interact with a user via a dumb terminal.

	If you wish to use the stdio window in Dynamic C, make sure the macro
	_USE_STDIO is defined to 1. Otherwise, define the macro to 0 and the
	program will use the internal communication port 0 of the Z180 (usually
	connected to RS-232 for most Z-World boards).

	If you use port 0, you need to run a terminal emulation program on the
	PC after setting the controller to run stand-alone.
*/

#define _USE_STDIO	0	//	define macro to be 1 to use debugger
								//	stdio window as terminal, otherwise
								//	define macro to be 0 to use the
								//	z0 UART

#if _USE_STDIO
#define RUNKERNEL 1		//	kernel is needed to run _dioServer
								//	periodically
#use srtk.lib				//	use real time kernel
#use aascdio.lib			//	device driver for the stdio device
#else
#use aascz0.lib			//	device driver for the z0 device
#endif

CHANNEL termChan;		//	declare storage for the terminal
										//	channel
void demoBasic(CHANNEL termChan) {
	//	this function demostrates how to use the basic function of
	//	the AASC library.
	
	auto int remainLen;		//	remaining length to send or receive
	auto char *pRemaining;	//	points to the start of the remaining
	auto int thisRound;		//	how many bytes did we just send/receive?
	auto char localBuf[4];
	static char *prompt =	//	a literal string to send out
		"Input 4 characters\n\r";

	//	send the prompt
	remainLen = strlen(prompt);	//	initialize how many to send
	pRemaining = prompt;				//	initialize where to start
	while (remainLen) {				//	while there is more to send
		thisRound = aascWriteBlk(	//	try to send
			termChan,					//	sent to which channel
			pRemaining,					//	what to send
			remainLen,					//	how many
			0								//	send as many as possible
			);
		remainLen -= thisRound;		//	compute remaining length
		pRemaining += thisRound;	//	compute new starting point
		hitwd();
	}

	//	get the four bytes, no echo
	remainLen = 4;						//	initialize how many to receive
	pRemaining = localBuf;			//	initialize where to receive to
	while (remainLen) {				//	while there is more to receive
		thisRound = aascReadBlk(	//	try to receive
			termChan,					//	read from which channel
			pRemaining,					//	where to read to
			remainLen,					//	how many more to read?
			0								//	read as many as available
			);
		remainLen -= thisRound;		//	compute remaining length
		pRemaining += thisRound;	//	compute new starting point
		hitwd();
	}
	
	//	echo the bytes received
	remainLen = 4;	//	initialize how many to send
	pRemaining = localBuf;			//	initialize where to start
	while (remainLen) {				//	while there is more to send
		thisRound = aascWriteBlk(	//	try to send
			termChan,					//	sent to which channel
			pRemaining,					//	what to send
			remainLen,					//	how many
			0								//	send as many as possible
			);
		remainLen -= thisRound;		//	compute remaining length
		pRemaining += thisRound;	//	compute new starting point
		hitwd();
	}
}

void demoPrintf(CHANNEL termChan) {
	//	this function demonstrates how to use the printf
	//	function in the AASC libraries
	auto int i;
	auto float f;

	aascPrintf(											//	like printf
		termChan,										//	specify where to
		"\n\rThis is a literal string\n\r");	//	and the format string
	f = 0.0;
	for (i = 0; i < 16; ++i) {
		aascPrintf(
			termChan,					//	where to
			"i=%d, f=%f\n\r",			//	format string
			i,								//	argument
			f);							//	argument
		f = f + 0.456;
		hitwd();
	}
}

void demoSelect(CHANNEL termChan) {
	//	this function demonstrates how to use the selectkey
	//	function in the AASC libraries
	auto int i;

	aascPrintf(termChan,"Select from [12345abcde]\n\r");
	do {
		i = aascSelectKey(
			termChan,			//	which channel to read from
			"12345abcde",		//	the characters corresponding to choices
			1);					//	echo or not, 1 to echo.
		hitwd();
		}
	while (i == 0);			//	aascSelectKey returns 0 if nothing is
									//	selected
	aascPrintf(termChan,"Your selection has an index of %d\n\r",i);
}

void getAStr(CHANNEL termChan, char *inStr, int strSize) {
	//	this function really gets the string, called by a few other
	//	functions
	auto int strLen;			//	number of chars already read in
	
	strLen = 0;		//	nothing is in the string yet
	do {
		strLen = aascGets(	//	returns -1 when done, otherwise
									//	returns the current size of string already
									//	read in
			termChan,			//	where to read from
			inStr,				//	where to read to
			strSize,				//	maximum of characters to read in
			strLen,				//	how many is already read?
			1);					//	echo, use 0 if you do not want to echo
		hitwd();
	} while (strLen != -1);	//	
}

void demoGetStr(CHANNEL termChan) {
	//	this function demonstrates how to use the gets
	//	function in the AASC libraries
	auto char inStr[256];
	
	aascPrintf(termChan,"Input a string, terminate with <CR>\n\r");
	getAStr(termChan, inStr, sizeof(inStr)-1);
	aascPrintf(termChan,"This is what you entered: %s\n\r",inStr);
}

void demoGetInt(CHANNEL termChan) {
	//	this function demonstrates how to use the atoi
	//	function to interpret an integer
	auto char inStr[256];
	auto int intValue;

	do {		//	repeat until a valid number is entered
		aascPrintf(termChan,"Input an integer\n\r");		//	prompt
		getAStr(termChan, inStr, sizeof(inStr)-1);		//	get the input
		intValue = atoi(inStr);									//	attempt to convert
		if (_xtoxErr) {			//	was there an error during translation?
			//	if so, print error message
			aascPrintf(termChan, "Input is not a valid integer\n\r");
		} else {
			//	otherwise, print the value of the integer
			aascPrintf(termChan, "Input is interpreted as %d\n\r",intValue);
		}
	} while (_xtoxErr);
}

void demoGetFloat(CHANNEL termChan) {
	//	this function demonstrates how to use the atoi
	//	function to interpret an integer
	auto char inStr[256];
	auto float floatValue;

	do {		//	repeat until a valid floating point number is entered
		aascPrintf(termChan,"Input a floating point number\n\r");	//	prompt
		getAStr(termChan, inStr, sizeof(inStr)-1);		//	get the input
		floatValue = atof(inStr);								//	attempt to convert
		if (_xtoxErr) {			//	was there an error during translation?
			//	if so, print error message
			aascPrintf(termChan, "Input is not a valid floating point number\n\r");
		} else {
			//	otherwise, print the value of the integer
			aascPrintf(termChan, "Input is interpreted as %f\n\r",floatValue);
		}
	} while (_xtoxErr);
}

#if _USE_STDIO

#funcchain _srtk_hightask _dioServer

#endif

void main() {
	static char InBuf[256];
	static char OutBuf[256];
#if _USE_STDIO						//	use STDIO window for debugging
	VdInit();						//	need the timer interrupt
	termChan = aascOpen(			//	open a channel
		DEV_STDIO,					//	using the debugger stdio window
		0,								//	C/RTS is not applicable
		0,
		NULL);						//	not used
	init_srtkernel();				//	use the kernel to refresh stdio
#else
	_GLOBAL_INIT();				//	initialize all data
	termChan = aascOpen(			//	open a channel
		DEV_Z0,						//	using the Z0 device
		0,								//	do not use C/RTS flow control
		ASCI_PARAM_1200*8+		//	1200*8=9600bps
		ASCI_PARAM_8N1,			//	8 Data No parity and 1 stop
		NULL);						//	not used
#endif
	aascSetReadBuf(termChan,InBuf,sizeof(InBuf));		//	set up input buffer
	aascSetWriteBuf(termChan,OutBuf,sizeof(OutBuf));	//	set up output buffer
	while (1) {						//	demonstrate stuff indefinitely
		demoBasic(termChan);
		demoPrintf(termChan);
		demoSelect(termChan);
		demoGetStr(termChan);
		demoGetInt(termChan);
		demoGetFloat(termChan);
	}
}