/*
 *This is a uart_fifo.c file of the FIFO UART TX ONLY Hardware demo using USCI on the MSP430G2553 microcontroller.
 *Set your baud rate in your terminal to 9600 8N1.
 *When using your TI MSP-430 LaunchPad you will need to cross the TXD and RXD jumpers.
 *
 *This program is free software: you can redistribute it and/or modify
 *it under the terms of the GNU General Public License as published by
 *the Free Software Foundation, either version 3 of the License, or
 *(at your option) any later version.

 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *Parker Dillmann
 *www.longhornengineer.com
*/

#include <msp430g2553.h>
#include "uart_fifo_tx.h"

#define TXD BIT2

#define FIFO_SIZE 128

volatile unsigned char tx_char;			//This char is the most current char to go into the UART

volatile unsigned char tx_fifo[FIFO_SIZE];	//The array for the tx fifo

volatile unsigned int tx_fifo_ptA;			//Theses pointers keep track where the UART and the Main program are in the Fifos
volatile unsigned int tx_fifo_ptB;

volatile unsigned int tx_fifo_full;

/*uart_init
* Sets up the UART interface via USCI
* INPUT: None
* RETURN: None
*/
void uart_init(void)
{
	P1SEL = TXD;					//Setup the I/O
	P1SEL2 = TXD;

	UCA0CTL1 |= UCSSEL_2; 				//SMCLK
										//8,000,000Hz, 9600Baud, UCBRx=52, UCBRSx=0, UCBRFx=1
	UCA0BR0 = 52;                  		//8MHz, OSC16, 9600
	UCA0BR1 = 0;                   	 	//((8MHz/9600)/16) = 52.08333
	UCA0MCTL = 0x10|UCOS16; 			//UCBRFx=1,UCBRSx=0, UCOS16=1
	UCA0CTL1 &= ~UCSWRST; 				//USCI state machine

	tx_fifo_ptA = 0;					//Set the fifo pointers to 0
	tx_fifo_ptB = 0;
	
	tx_fifo_full = 0;

	return;
}

/*uart_putc
* Sends a char to the UART. Will wait if the UART is busy
* INPUT: Char to send
* RETURN: None
*/
void uart_putc(unsigned char c)
{
	tx_char = c;						//Put the char into the tx_char
	tx_fifo[tx_fifo_ptA] = tx_char;		//Put the tx_char into the fifo
	tx_fifo_ptA++;						//Increase the fifo pointer
	if(tx_fifo_ptA == FIFO_SIZE)		//Check to see if the pointer is max size. If so roll it over
	{
		tx_fifo_ptA = 0;
	}
	if(tx_fifo_ptB == tx_fifo_ptA)		//fifo full
	{
		tx_fifo_full = 1;
	}
	else
	{
		tx_fifo_full = 0;
	}
	IE2 |= UCA0TXIE; 					//Enable USCI_A0 TX interrupt
	return;
}

/*uart_puts
* Sends a string to the UART. Will wait if the UART is busy
* INPUT: Pointer to String to send
* RETURN: None
*/
void uart_puts(char *str)				//Sends a String to the UART.
{
     while(*str) uart_putc(*str++);		//Advance though string till end
     return;
}

#pragma vector = USCIAB0TX_VECTOR			//UART TX USCI Interrupt
__interrupt void USCI0TX_ISR(void)
{
	UCA0TXBUF = tx_fifo[tx_fifo_ptB];		//Copy the fifo into the TX buffer
	tx_fifo_ptB++;

	if(tx_fifo_ptB == FIFO_SIZE)			//Roll the fifo pointer over
	{
		tx_fifo_ptB = 0;
	}
    if(tx_fifo_ptB == tx_fifo_ptA)			//Fifo pointers the same no new data to transmit
    {
    	IE2 &= ~UCA0TXIE; 					//Turn off the interrupt to save CPU
    }
}
