/*
	This is a pseudo code demonstrate simple uart bi-directional protocol
	some of the functions are not defined, but by name explins there job
*/




// timeout definitions
QUIET_TIMEOUT 
KEEP_ALIVE_TIMEOUT 
TX_RETRY_TIMEOUT 
RX_SESSION_TIMEOUT

TX_MAX_RETRY_COUNT 


//event definitions
RX_ISSUE
MESSAGE_RECEIVED
TX_COMMAND
TX_ENDED
KEEP_ALIVE_TIMEOUT_EXPIRED

//bitmap definitions
TX_READY
RX_SESSION
CMD_IN_QUEUE


//whenever activity occures in rx pin, switch it to uart rx
pinIoCallback()
{
	setRxAsUartPin();
	EventPost(RX_ACTIVITY);
}


//called by application
putCommandInQueue(cmd)
{
	QueuePut(cmd);
	bitmapSet(CMD_IN_QUEUE);
	EventPost(TX_COMMAND)
}


uartTaskFcn(void)
{
	timeout = KEEP_ALIVE_TIMEOUT;
	while(1)
	{
		event = EventPend(FOREVER);

		if(event == RX_ISSUE)
		{
			bitmapSet(RX_SESSION);
			uartRead(1);
			rxSessionTimerStart(RX_SESSION_TIMEOUT);
		}
		
		if(event == MESSAGE_RECEIVED)
		{
			rxSessionTimerStop();
			if( checkIfMessageIsAck(rxBuff) )
			{
				//if first message in queue is acknowledge by the received message,
				//extract it from queue
				QueueExtract(cmd);
				
				if(QueueIsEmpty)
				{
					//mark that there are no more commands
					bitmapClear(CMD_IN_QUEUE);
				}

			}
			else
			{
				//upload recieved message to app
				putRecievedMsgInApp(rxBuff);
			}
		
		}
		if(event == TX_COMMAND)
		{
			//command handle and send mechanism
			handleCommandAndSend();
		}	
		if(event == TX_ENDED)
		{
			txState = TX_READY;
			bitmapClear(TX_BUSY)
		}
		
		if(event == KEEP_ALIVE_TIMEOUT_EXPIRED)
		{
			SendKeepAliveMessage();
		}
		//check if there is no uart activity
		if( bitmapNotContains(TX_BUSY) && bitmapNotContain(RX_SESSION) )
		{
			//if there are more command in queue, notify task
			if( bitmapContains(CMD_IN_QUEUE) )
			{
				EventPost(TX_COMMAND);
			}
			else
			{
				closeUart();
				setRxAsGpioPin();
				KeepAliveTimerStart(KEEP_ALIVE_TIMEOUT);
			}
		}
		
		
		
	}
	
}


handleCommandAndSend()
{
//check if tx is ready to sent
	if(txState == TX_READY)
	{
		//stop tx timer
		TxTimerStop();
		//take (not extract) first waiting message
		QueuePeek(cmd);
		
		
		if(retryCnt < TX_MAX_RETRY_COUNT)
		{
			txState = TX_BUSY;
			WriteCmdBytesInBuffer(cmd,txBuffer);
			uartWrite(txBuffer);
			//open timer, and wait for ack
			TxTimerStart(TX_RETRY_TIMEOUT );
			KeepAliveTimerStop();
			
			//ready to recive ack
			bitmapSet(RX_SESSION);
			//initiate read
			uartRead(1);
			rxSessionTimerStart(RX_SESSION_TIMEOUT);
			
		}
		else
		{
			retryCnt =0;
			//no more retries, throw message away
			QueueExtract(cmd);
			
			if(QueueIsEmpty)
			{
				//mark that there are no more commands
				bitmapClear(CMD_IN_QUEUE);
			}
		}
		
	}
	
}

uartReadCallback(byte)
{
	//prasing message, according to application protocol
	//if succed, notify task
	if(PARSE_OK == parse(byte,rxBuffer) )
	{
		EventPost(MESSAGE_RECEIVED);
	}
	//initiate next read
	uartRead(1);	
}


uartWriteCallback()
{
	EventPost(TX_ENDED);
}

TxTimerExpired()
{
	EventPost(TX_COMMAND);
}

KeepAliveTimerExpired()
{
	EventPost(KEEP_ALIVE_TIMEOUT_EXPIRED);
}