#include <em_device.h>
#include "hardware.h"
#include "i2c.h"

void CMU_setup(void)									// configure clock
{
	CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN +			// enable LFRCO
		CMU_OSCENCMD_LFXODIS + CMU_OSCENCMD_LFRCOEN;
	CMU->LFCLKSEL = CMU_LFCLKSEL_LFA_LFRCO;				// set LFRCO as LFA
	CMU->HFCORECLKEN0 = CMU_HFCORECLKEN0_LE;			// enable HF clock
	CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;			// enable HF clock to GPIO
}

void RTC_setup(void)									// configure RTC
{
	CMU->LFACLKEN0 |= CMU_LFACLKEN0_RTC; 				// enable LFA to RTC
	CMU->LFAPRESC0 = CMU_LFAPRESC0_RTC_DIV16;			// set 1:16 prescaler
	RTC->COMP0 = 0x7FFF;								// 1*16 sec period setup
	RTC->CTRL = RTC_CTRL_COMP0TOP + RTC_CTRL_EN;		// start RTC
	RTC->IEN = RTC_IEN_COMP0;							// enable COMP0 interrupt
	NVIC_ClearPendingIRQ(RTC_IRQn);						// clear pending RTC interrupt
	NVIC_EnableIRQ(RTC_IRQn);							// enable RTC interrupt in NVIC
}

void I2C0_setup(void)
{
	CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_I2C0;			// enable HF clock to I2C
	(GPIO->P[3]).MODEL |= GPIO_P_MODEL_MODE6_WIREDAND + // PD.6/7 = SDA/SCL of I2C0
						  GPIO_P_MODEL_MODE7_WIREDAND;
	I2C0->ROUTE = I2C_ROUTE_LOCATION_LOC1 +				// enable I2C pins at location 1
				  I2C_ROUTE_SDAPEN + I2C_ROUTE_SCLPEN;
	I2C0->CLKDIV = 3;									// set 368 KHz I2C clock (@ PERCLK=14 MHz)
	I2C0->CTRL = I2C_CTRL_EN;							// clear module reset
}

void USART_setup(void)
{
	CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_USART0 + CMU_HFPERCLKEN0_USART1; // enable clock to UART0,1
	USART0->CLKDIV = 0x1A << 6;							// set 115200bd @ 14 MHz PERCLK
	USART0->ROUTE = USART_ROUTE_LOCATION_LOC4 +
		USART_ROUTE_TXPEN + USART_ROUTE_RXPEN;			// enable TX/RX pins at PB.7/8
	(GPIO->P[1]).MODEL |= GPIO_P_MODEL_MODE7_PUSHPULL; 	// configure PB.7 for output
	(GPIO->P[1]).MODEH |= GPIO_P_MODEH_MODE8_INPUT; 	// configure PB.8 for input
	USART0->CMD = USART_CMD_TXEN + USART_CMD_RXEN;		// enable TX, RX

	USART1->CLKDIV = 0x1A << 6;							// set 115200bd @ 14 MHz clock
	USART1->ROUTE = USART_ROUTE_LOCATION_LOC0 +
		USART_ROUTE_TXPEN + USART_ROUTE_RXPEN;			// enable TX/RX pins at PC.0/1
	(GPIO->P[2]).MODEL |= GPIO_P_MODEL_MODE0_PUSHPULL; 	// configure PC.0 for output
	(GPIO->P[2]).MODEL |= GPIO_P_MODEL_MODE1_INPUT; 	// configure PC.1 for input
	USART1->CMD = USART_CMD_TXEN + USART_CMD_RXEN;		// enable TX, RX

	USART0->IEN = USART_IEN_RXDATAV;					// enable RX data valid interrupt
	NVIC_ClearPendingIRQ(USART0_RX_IRQn);				// clear pending USART0 RX interrupt
	NVIC_EnableIRQ(USART0_RX_IRQn);						// enable USART0 RX interrupt in NVIC	
	
	USART1->IEN = USART_IEN_RXDATAV;					// enable RX data valid interrupt
	NVIC_ClearPendingIRQ(USART1_RX_IRQn);				// clear pending USART1 RX interrupt
	NVIC_EnableIRQ(USART1_RX_IRQn);						// enable USART1 RX interrupt in NVIC		
}

void LETIMER_setup(void)
{
	CMU->LFACLKEN0 |= CMU_LFACLKEN0_LETIMER0; 			// enable LFA to LETIMER
	LETIMER0->CTRL = LETIMER_CTRL_COMP0TOP + LETIMER_CTRL_REPMODE_ONESHOT +
					LETIMER_CTRL_DEBUGRUN;				// USERDATA_BASE it for short delays
}

void Delay_ms(uint32_t d)
{
	LETIMER0->COMP0 = d << 5;							// delay value
	LETIMER0->REP0 = 1;									// set 1-shot mode
	LETIMER0->CMD = LETIMER_CMD_START;// + LETIMER_CMD_CLEAR;	// start LETIMER0
	while (!(LETIMER0->IF & LETIMER_IF_REP0)){}
	LETIMER0->IFC = LETIMER_IFC_REP0;
}
