#include "usart.h"
#include "rcc.h"
#include "usart_6.h"
#include "usart_6_registers.h"

void USART_6::Configure(uint32_t baudRate)
{
	RCC&    	clockController(*new RCC);
	uint32_t	SYS_Clock;
	uint32_t	AHB_Clock;
	uint32_t	APB1_Clock;
	uint32_t	APB2_Clock;
	uint32_t	divider;
	uint32_t	fraction;

	// USART_6 is an APB 2 peripheral
	clockController.GetClocks(SYS_Clock, AHB_Clock, APB1_Clock, APB2_Clock);
	if (_overSampleByEight == true) {
		divider = (25 * APB2_Clock) / (2 * baudRate);
	} else {
		divider = (25 * APB2_Clock) / (4 * baudRate);
	}
	uint32_t integer = divider / 100;
	USART_6_REGS::Integer::write(integer);
	fraction = divider - (100 * integer);
	if (_overSampleByEight == true) {
		fraction = (((fraction *  8) + 50) / 100);
	} else {
		fraction = (((fraction * 16) + 50) / 100);
	}
	USART_6_REGS::Fraction::write(fraction);
}

void USART_6::Reset(void)
{
	RCC&    rcc(*new RCC);
	rcc.EnableClocks(USART6_EN, ASSERT);
	rcc.ResetPeripherals(USART6_RST, ASSERT);
	rcc.ResetPeripherals(USART6_RST, NEGATE);
	rcc.EnableClocks(USART6_EN, NEGATE);
}

void USART_6::Enable(void)
{
	RCC&    rcc(*new RCC);
	rcc.EnableClocks(USART6_EN, ASSERT);
	USART_6_REGS::UE::write(1);
}

void USART_6::Disable(void)
{
	RCC&    rcc(*new RCC);
	rcc.EnableClocks(USART6_EN, NEGATE);
	USART_6_REGS::UE::write(0);
}

void USART_6::Send(char ch)
{
	while (USART_6_REGS::TXE::read() == 0) ;
	USART_6_REGS::Data::write(ch);
}

void USART_6::Send(const char* string)
{
	int i = 0;
	// loop through until reach string's zero terminator
	while (string[i] != 0) {
		Send(string[i]); // print each character
		i++;
	}
}
