
/* *INDENT-OFF* */
#include <avr\io.h>
#include <avr\pgmspace.h>
#include <avr\interrupt.h>
#include <inttypes.h>
#include "serial_mega.h"

volatile uint8_t gSerialOutBuffer[SERIALOUTSIZE];
volatile uint8_t *gSerialOutStart;
volatile uint8_t *gSerialOutEnd;

/*Interrupt vector declarations*/

/******************************************************************/
/* Function name 	: SIG_UART_DATA								  */
/* 																  */
/* Return value		: None										  */
/*																  */
/* Pre condition  	: UART present on chip						  */
/*																  */
/* Post condition	: data in sent buffer placed in UDR  		  */	
/*					  register so it will be transmitted 		  */
/*																  */
/* Remark			: None										  */
/*		   														  */
/******************************************************************/

SIGNAL (SIG_USART_TRANS)
{
	/*Sent byte if pointers are unequal*/
	if (gSerialOutStart != gSerialOutEnd)
	{
		UDR0 = *gSerialOutStart;
		
		gSerialOutStart++;
	
		/*Check if pointer does not exceed buffer size*/
		if ( gSerialOutStart >= (gSerialOutBuffer + SERIALOUTSIZE))
		{
			gSerialOutStart = gSerialOutBuffer;
		}	
	}
}

/******************************************************************/
/* Function name 	: Serial_Init_19200()						  */
/* 																  */
/* Return value		: None										  */
/*																  */
/* Pre condition  	: UART present on chip						  */
/*																  */
/* Post condition	: UART tried to be set @19200b 8 bit, 		  */	
/* 					  1 start-,1 stopbit						  */
/*																  */
/* Remark			: None										  */
/*		   														  */
/******************************************************************/

void Serial_Init_19200_Baud(void)
{
  	gSerialOutStart = gSerialOutBuffer;					/*Pointer to write buffer*/
  	gSerialOutEnd = gSerialOutBuffer;
  	
    UCSR0A = 0;										/*no U2X, MPCM*/
    UCSR0B = 0;
    UCSR0C = 0;
  	UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);	            /*8 Bit */
  	UBRR0L = BAUDDIVIDER19200; 						/*set baud rate*/
	UBRR0H = 0;

}

/******************************************************************/
/* Function name 	: Serial_Enable_Transmit_Interrupts			  */
/* 																  */
/* Return value		: None										  */
/*																  */
/* Pre condition  	: UART present on chip						  */
/*																  */
/* Post condition	: Tx interrupt set							  */
/*																  */
/* Remark			: Interrupts active after SEI() command!      */
/*		   														  */
/******************************************************************/



void Serial_Enable_Transmit_Interrupts(void)
{
	UCSR0B |= (1<<TXEN0);			/*enable transmit*/
	UCSR0B |= (1<<TXCIE0);			/*Enable int transmit*/
}

/******************************************************************/
/* Function name 	: Serial_Buffer_Sent_Fill()					  */	
/* 																  */
/* Return value		: None										  */
/*																  */
/* Pre condition  	: UART present on chip						  */
/*																  */
/* Post condition	: Copy source into sent buffer				  */
/*																  */
/* Remark			: Source is pointer or constant string.	      */
/*					  Not written data in buffer will be 		  */
/* 					  overwritten if source is too big.			  */	
/*		   														  */
/******************************************************************/

void Serial_Buffer_Sent_Fill_Block(uint8_t *s)
{
	/*If buffer is empty, i.e. pointers equal, set first byte in transmit. 
	  This causes the UDR empty interrupt, so all data is written*/
	  
	if (gSerialOutEnd == gSerialOutStart)
	{
	    /* Now check if nothing is present in transmit buffer */
		if (UCSR0A & (1<<UDRE0))
		{
		   UDR0=*s;     /*First byte in UDR*/
		   s++;		/*Increase source pointer*/
        }
	}
	
	/*Copy source into buffer until end of string*/
	while (*s)
	{
		/*Store data from source into buffer*/
		*gSerialOutEnd = *s;

		/*Increase pointers*/
		s++;
		gSerialOutEnd ++;
			
		/*and check if buffer does not overrun*/
		
		if (gSerialOutEnd >= (gSerialOutBuffer + SERIALOUTSIZE))
		{
			gSerialOutEnd = gSerialOutBuffer;
		}
	}
}		

/******************************************************************/
/* Function name 	: Serial_Buffer_Sent_FillFlash()			  */	
/* 																  */
/* Return value		: None										  */
/*																  */
/* Pre condition  	: UART present on chip						  */
/*																  */
/* Post condition	: Copy source in FLASH into sent buffer		  */
/*																  */
/* Remark			: Source is pointer to string in flash.	      */
/******************************************************************/

void Serial_Buffer_Sent_FillFlash(const char *s)
{
	if (gSerialOutEnd == gSerialOutStart)
	{
		/* Now check if nothing is present in transmit buffer */
		if (UCSR0A & (1<<UDRE0))
		{
           UDR0=pgm_read_byte(s);     /*First byte in UDR*/
		   s++;		/*Increase source pointer*/
	    }
	}

	/*Copy source into buffer until end of string*/
	while (pgm_read_byte(s))
	{
		/*Store data from source into buffer*/
		*gSerialOutEnd = pgm_read_byte(s);

		/*Increase pointers*/
		s++;
		gSerialOutEnd ++;
			
		/*and check if buffer does not overrun*/
		
		if (gSerialOutEnd >= (gSerialOutBuffer + SERIALOUTSIZE))
		{
			gSerialOutEnd = gSerialOutBuffer;
		}
	}
}
/* *INDENT-ON* */
