/********************************************************************
* FileName:        UART LCD Messages.c
* Processor:       18F4520
* Compiler:        MPLAB C18 v.3.06 
*
* This file sends a message via the UART when RA4 is pressed and displays
*  received messages on the LCD
* You will be changing it to do a few addition things
*
* Author               Date        Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// <your name>

/** Processor Header Files *****************************************/
#include <p18f4520.h> 
#include "LCD Module.h"
#include <usart.h>
#include <stdio.h>

/** Define Constants Here ******************************************/
#define MAX_RX_MESSAGE_SIZE 32   // Length of the receive buffers
#define MESSAGE_TERMINATOR 	10	 // ASCII character for '\n' new line
#define PRESSED 			0
#define UNPRESSED 			1

/** Local Function Prototypes **************************************/
#pragma config OSC = EC
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config BOREN = OFF
#pragma config XINST = OFF

/** Local Function Prototypes **************************************/
void low_isr(void);
void high_isr(void);
void clearBuffer(char bufferToClear[]);  // Clears the contents of the passed array
void loadNewMessage(void);               // Copies the contents of tempRxBuffer into newRxMessage

/** Declare Interrupt Vector Sections ****************************/
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
   _asm goto high_isr _endasm
}

#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
{
   _asm goto low_isr _endasm
}

/** Declarations *************************************************/
char tempRxBuffer[MAX_RX_MESSAGE_SIZE]; // Temp storage to hold values while receiving message
char newRxMessage[MAX_RX_MESSAGE_SIZE]; // Array to store completed messages
char newMessageAvailable = 0;  			// Flag set within interrupt to alert main of a new message


/*****************************************************************
* Function:        void main(void)
******************************************************************/
#pragma code
void main( void )
{
	char line1[17];
	char line2[17];
	char recentButtonState = PRESSED;  // Needed for finding RA4 edges
	char age = 32;		// TODO: change to your current age
	
	ADCON1 = 0x0F;
	TRISB = 0x00;
	TRISAbits.TRISA4 = 1;
	clearBuffer(tempRxBuffer);

	// Setup LCD
	XLCDInit();
	XLCDClear(); 
	XLCDL1home() ;
	XLCDPutRomString("Ready");	
	
	RCONbits.IPEN = 1;      // Priority mode interrupts
	
	// configure USART for 19200 buad rate
	OpenUSART( USART_TX_INT_OFF &
		USART_RX_INT_ON &
		USART_ASYNCH_MODE &
		USART_EIGHT_BIT &
		USART_BRGH_HIGH,
		12 );
	
	IPR1bits.RCIP = 1;  // Make the UART Rx interrupt a high priority interrupt
	
	INTCONbits.GIEH = 1;
	
	while(1)
	{			
		if( newMessageAvailable )
		{
			sprintf(line1,"%s",newRxMessage);
			newMessageAvailable = 0;

			XLCDClear(); 
			XLCDL1home();
			XLCDPutRamString(line1);		
		}
		
		
		if(PORTAbits.RA4 == PRESSED) 
		{
			if(recentButtonState == UNPRESSED) 
			{
				printf("Dave Fisher is %d years old.\n\r", age);
				age++;
			}
			recentButtonState = PRESSED;
		}
		else 
		{
			recentButtonState = UNPRESSED;
		}
			
	}
}

/*****************************************************************
* Helper Functions
******************************************************************/

/*****************************************************************
* Function:			void clearBuffer(char bufferToClear[])
* Input Variables:	bufferToClear - The buffer to clear
* Output Return:	none
* Overview:			Clears the contents of a buffer
******************************************************************/
void clearBuffer(char bufferToClear[])
{
	char i;
	for(i=0 ; i<MAX_RX_MESSAGE_SIZE ; i++)
		bufferToClear[i] = 0; 
}	

/*****************************************************************
* Function:			void loadNewMessage(void)
* Input Variables:	none
* Output Return:	none
* Overview:			Copies the contents of tempRxBuffer into newRxBuffer
******************************************************************/
void loadNewMessage(void)
{
	char i;
	for(i=0 ; i<MAX_RX_MESSAGE_SIZE ; i++)
		newRxMessage[i] = tempRxBuffer[i];
}	
				
				
/*****************************************************************
* Function:        void high_isr(void)
* Possible sources of interrupt - none
* Overview:
******************************************************************/
#pragma interrupt high_isr
void high_isr(void)
{	
	if (PIR1bits.RCIF)
	{
		static unsigned char txCounter = 0;  // Makes the variable remember the prior state
		char newByte;
		newByte = RCREG;
		PIR1bits.RCIF = 0;  // Clear the interrupt flag
		if(newByte == MESSAGE_TERMINATOR)
		{
			if( newMessageAvailable == 0)
			{
				clearBuffer(newRxMessage);
				loadNewMessage();
				newMessageAvailable = 1;
			}	
			clearBuffer(tempRxBuffer);
			txCounter=0;
		}
		else
		{
			if(txCounter < MAX_RX_MESSAGE_SIZE && newByte > 31 && newByte < 127)
			{
				tempRxBuffer[txCounter] = newByte;
				txCounter++;
			}	
		}	
	}	
}

/******************************************************************
* Function:        void low_isr(void)
* Possible sources of interrupt - none
* Overview:
********************************************************************/
#pragma interruptlow low_isr
void low_isr(void)
{
	// Add code here for the low priority Interrupt Service Routine (ISR)
}