/*****************************************************************************
 *
 * Serial I/O.
 *
 *****************************************************************************
 * FileName:        io.c
 * Dependencies:    
 * Processor:       PIC18F with CAN
 * Compiler:       	C18 02.30.00 or higher
 * Linker:          MPLINK 03.20.01 or higher
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the "Company") is intended and supplied to you, the Company's
 * customer, for use solely and exclusively with products manufactured
 * by the Company. 
 *
 * The software is owned by the Company and/or its supplier, and is 
 * protected under applicable copyright laws. All rights are reserved. 
 * Any use in violation of the foregoing restrictions may subject the 
 * user to criminal sanctions under applicable laws, as well as to 
 * civil liability for the breach of the terms and conditions of this 
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, 
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * This is a simple timer function used within the DeviceNet Stack for
 * demonstration.
 * 
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Ross Fosler			08/13/04	...	
 * 
 *****************************************************************************/


#include	"TYPES.H"			// Standard types
#include	"MEMIO.H"			// Memory movement routines
#include	"RS232_IO.H"		// Serial communications
#include	"SRALLOC.H"			// Dynamic memory allocation



// Flags used by the I/O functions
typedef struct __IOFLAGS
{
	unsigned rx:1;
	unsigned tx:1;
	unsigned err:1;

}IOFLAGS;

// String definition used by the dynamic string buffer
typedef struct __STRING
{
	UCHAR slength;
	UCHAR * pString;
}STRING;

// Rom string definition used by the dynamic string buffer
typedef struct __RSTRING
{
	UCHAR slength;
	RUCHAR * pString;
}RSTRING;



// References for string buffer management
UCHAR 	*pCurrentStr;
UCHAR 	*pLastStr;
UCHAR 	*pTemp;

// Locals to hold the current position and length of the string
UCHAR 	*_pStr;	
UCHAR 	_uStrLen;
UCHAR 	OutFlag;
IOFLAGS	ioflags;
UCHAR 	uBitrate;



// Open an IO channel
unsigned char IOOpen(UCHAR bitrate)
{
	// Store the requested bitrate
	uBitrate = bitrate;

	// Reset the current transmit string pointers
	pCurrentStr = pLastStr = 0;
	ioflags.tx = 0; 
	
	// Setup async communications
	mIOInit(uBitrate);

	// Setup a receive buffer

	return 1;
}

void IOClose(void)
{
	// Clean up any allocated buffer space

}


// Process I/O events that are queued
void IOProcessEvents(void)
{
	// If the output buffer is ready then process any outgoing data
	if (ioflags.tx && mIOIsPutReady())
	{
		mIOPutByte(*_pStr);
		_uStrLen--;

		// If at the end of the current string
		if (_uStrLen == 0)
		{
			// If this is the last string then cleanup
			if (pCurrentStr == pLastStr)
			{
				SRAMfree(pCurrentStr);			// Free used ram
				pCurrentStr = pLastStr = 0;		// null the pointers
				ioflags.tx = 0;					// Indicate nothing to tx
			}
			else
			{
				// Reference the next string
				pTemp = ((STRING*)pCurrentStr)->pString;
				_pStr = pTemp + sizeof(STRING);
				_uStrLen = ((STRING*)pCurrentStr)->slength;

				SRAMfree(pCurrentStr);			// Release used memory

				pCurrentStr = pTemp;			// Set the new current string
			}
		}
		else {_pStr++;}
	}

	// Process incomming events
	if (mIOIsGetReady())
	{


	}

	// Process any error events
	if (mIOIsError())
	{
		mIOInit(uBitrate);
		// Reset communications

	}
}



// Put a string into the output stream
// The string is always a length followed by the string data
UCHAR puts(UCHAR *pStrData)
{ 
	// Find a space for the string
	pTemp = SRAMalloc(*pStrData + sizeof(UCHAR) + sizeof(UCHAR*));

	if (pTemp)
	{
		// If the current string is not valid then make it valid
		if (!pCurrentStr)
		{
			pCurrentStr = pLastStr = pTemp;
			_uStrLen = *pStrData;
			_pStr = (UCHAR *)pCurrentStr + sizeof(UCHAR) + sizeof(UCHAR*);
		}
		// Else link the this string to the last string
		else
		{
			// Copy the ref to the next string to the head of this string
			((STRING*)pLastStr)->pString = (UCHAR *)pTemp;
			((STRING*)pLastStr)->slength = *pStrData;
			pLastStr = pTemp;
		}

		// Now copy the string
		MEMIO_CopySram((pStrData + sizeof(UCHAR)), (unsigned char *)(pTemp + sizeof(STRING)), *pStrData);

		// Indicate ready to send something
		ioflags.tx = 1;
	}
	else return 0;
	return 1;
}


// Put a ROM string into the output stream
// The string is always a length followed by the string data
UCHAR putrs(RUCHAR *pStrData)
{
	// Find a space for the string
	pTemp = SRAMalloc(*pStrData + sizeof(UCHAR) + sizeof(UCHAR*));

	if (pTemp)
	{
		// If the current string is not valid then make it valid
		if (!pCurrentStr)
		{
			pCurrentStr = pLastStr = pTemp;
			_uStrLen = *pStrData;
			_pStr = (UCHAR *)pCurrentStr + sizeof(UCHAR) + sizeof(UCHAR*);
		}
		// Else link the this string to the last string
		else
		{
			// Copy the ref to the next string to the head of this string
			((STRING*)pLastStr)->pString = (UCHAR *)pTemp;
			((STRING*)pLastStr)->slength = *pStrData;
			pLastStr = pTemp;
		}

		// Now copy the string
		MEMIO_CopyRomToRam((pStrData + sizeof(RUCHAR)), (unsigned char *)(pTemp + sizeof(STRING)), *pStrData);

		// Indicate ready to send something
		ioflags.tx = 1;
	}
	else return 0;
	return 1;
}


// Grab a string from the input stream
UCHAR *gets(UCHAR* pStr)
{

}




// Grab a character from the input stream
char getc(void)
{
	if (mIOIsGetReady())
		return mIOGetByte();
	else
		return 0;
}


