#include "uart.h"
#include "uart_registers.h"

const uint32_t	UART_ClockFrequency				= 25000000;

// UART Line Status Register Bit Definitions
const uint32_t	ReceiveDataReady  				= (1 << 0);
const uint32_t	ReceiveOverrunError  			= (1 << 1);
const uint32_t	ParityError  					= (1 << 2);
const uint32_t	FramingError  					= (1 << 3);
const uint32_t	BreakInterrupt  				= (1 << 4);
const uint32_t	TransmitHoldingRegisterEmpty	= (1 << 5);
const uint32_t	TransmitBufferRegisterEmpty  	= (1 << 6);
const uint32_t	ReceiverErrorOccurred  			= (1 << 7);

// UART Line Control Register Bit Definitions
const uint32_t	FiveBitCharacters				= (0 << 0);
const uint32_t  SixBitCharacters				= (1 << 0);
const uint32_t  SevenBitCharacters				= (2 << 0);
const uint32_t  EightBitCharacters				= (3 << 0);
const uint32_t  OneStopBit						= (0 << 2);
const uint32_t	TwoStopBits  					= (1 << 2);  
const uint32_t   ParityDisable                   = (0 << 3);
const uint32_t	ParityEnable  					= (1 << 3);
const uint32_t  OddParity						= (0 << 4);
const uint32_t	EvenParity	  					= (1 << 4);
const uint32_t	StickParityBit					= (1 << 5);
const uint32_t	SetBreakCondition			 	= (1 << 6);

void PolledUart::SetBaudRate(uint32_t baudRate)
{
	regWrite(UART::BD, (TicksPerSecond / baudRate));
}

void PolledUart::Initialize(void)
{
	SetBaudRate(38400);
	regWrite(UART::LCR, (EightBitCharacters | OneStopBit | ParityDisable));
}

void PolledUart::RawPutCharacter(const char character)
{
	uint32_t c = character;
	for (uint32_t i = 0; i < 0x100000; i++) {
		if (regRead(UART::LSR) & TransmitHoldingRegisterEmpty)
			break;
	}
	regWrite(UART::TX, c);
}

void PolledUart::PutCharacter(const char character)
{
	RawPutCharacter(character);
	if (character == '\n')
		RawPutCharacter('\r');
}

void PolledUart::PutString(const char *string)
{
	char c;
	while ((c = *string++) != 0)
		PutCharacter(c);
}

bool PolledUart::CharacterAvailable(void)
{
	return ((regRead(UART::LSR) & ReceiveDataReady) ? true : false);
}

uint32_t PolledUart::GetCharacter(void)
{
	while ((regRead(UART::LSR) & ReceiveDataReady) == 0)
		;
	return regRead(UART::RX);
}
