/*
 * Code generated from Atmel Start.
 *
 * This file will be overwritten when reconfiguring your Atmel Start project.
 * Please copy examples or other code you want to keep to a separate file
 * to avoid losing it when reconfiguring.
 */

#include "driver_init.h"
#include <peripheral_clk_config.h>
#include <utils.h>
#include <hal_init.h>

#include <hpl_adc_base.h>

/*! The buffer size for USART */
#define EMAPLAY_DEBUG_UART_BUFFER_SIZE 16

/*! The buffer size for USART */
#define EMA_MGMT_UART_BUFFER_SIZE 16

/*! The buffer size for USART */
#define EMA_MODEM_UART_BUFFER_SIZE 16

struct usart_async_descriptor emaPlay_debug_uart;
struct usart_async_descriptor ema_mgmt_uart;
struct usart_async_descriptor ema_modem_uart;
struct timer_descriptor       TIMER_0;

static uint8_t emaPlay_debug_uart_buffer[EMAPLAY_DEBUG_UART_BUFFER_SIZE];
static uint8_t ema_mgmt_uart_buffer[EMA_MGMT_UART_BUFFER_SIZE];
static uint8_t ema_modem_uart_buffer[EMA_MODEM_UART_BUFFER_SIZE];

struct adc_sync_descriptor ADC_0;

struct i2c_m_sync_desc I2C;

void ADC_0_PORT_init(void)
{

	// Disable digital pin circuitry
	gpio_set_pin_direction(photo_an_mon, GPIO_DIRECTION_OFF);

	gpio_set_pin_function(photo_an_mon, PINMUX_PB00B_ADC0_AIN12);

	// Disable digital pin circuitry
	gpio_set_pin_direction(ema_v_an_mon, GPIO_DIRECTION_OFF);

	gpio_set_pin_function(ema_v_an_mon, PINMUX_PB01B_ADC0_AIN13);

	// Disable digital pin circuitry
	gpio_set_pin_direction(vin_an_mon, GPIO_DIRECTION_OFF);

	gpio_set_pin_function(vin_an_mon, PINMUX_PB02B_ADC0_AIN14);

	// Disable digital pin circuitry
	gpio_set_pin_direction(io_app_hdr_an_mon, GPIO_DIRECTION_OFF);

	gpio_set_pin_function(io_app_hdr_an_mon, PINMUX_PB03B_ADC0_AIN15);
}

void ADC_0_CLOCK_init(void)
{
	hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
	hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, CONF_GCLK_ADC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
}

void ADC_0_init(void)
{
	ADC_0_CLOCK_init();
	ADC_0_PORT_init();
	adc_sync_init(&ADC_0, ADC0, (void *)NULL);
}

/**
 * \brief USART Clock initialization function
 *
 * Enables register interface and peripheral clock
 */
void emaPlay_debug_uart_CLOCK_init()
{

	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE, CONF_GCLK_SERCOM0_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_SLOW, CONF_GCLK_SERCOM0_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	hri_mclk_set_APBAMASK_SERCOM0_bit(MCLK);
}

/**
 * \brief USART pinmux initialization function
 *
 * Set each required pin to USART functionality
 */
void emaPlay_debug_uart_PORT_init()
{

	gpio_set_pin_function(PA04, PINMUX_PA04D_SERCOM0_PAD0);

	gpio_set_pin_function(PA05, PINMUX_PA05D_SERCOM0_PAD1);
}

/**
 * \brief USART initialization function
 *
 * Enables USART peripheral, clocks and initializes USART driver
 */
void emaPlay_debug_uart_init(void)
{
	emaPlay_debug_uart_CLOCK_init();
	usart_async_init(
	    &emaPlay_debug_uart, SERCOM0, emaPlay_debug_uart_buffer, EMAPLAY_DEBUG_UART_BUFFER_SIZE, (void *)NULL);
	emaPlay_debug_uart_PORT_init();
}

void I2C_PORT_init(void)
{

	gpio_set_pin_pull_mode(PA12,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(PA12, PINMUX_PA12C_SERCOM2_PAD0);

	gpio_set_pin_pull_mode(PA13,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(PA13, PINMUX_PA13C_SERCOM2_PAD1);
}

void I2C_CLOCK_init(void)
{
	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK);
}

void I2C_init(void)
{
	I2C_CLOCK_init();
	i2c_m_sync_init(&I2C, SERCOM2);
	I2C_PORT_init();
}

/**
 * \brief USART Clock initialization function
 *
 * Enables register interface and peripheral clock
 */
void ema_mgmt_uart_CLOCK_init()
{

	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	hri_mclk_set_APBBMASK_SERCOM3_bit(MCLK);
}

/**
 * \brief USART pinmux initialization function
 *
 * Set each required pin to USART functionality
 */
void ema_mgmt_uart_PORT_init()
{

	gpio_set_pin_function(PA17, PINMUX_PA17D_SERCOM3_PAD0);

	gpio_set_pin_function(PA16, PINMUX_PA16D_SERCOM3_PAD1);
}

/**
 * \brief USART initialization function
 *
 * Enables USART peripheral, clocks and initializes USART driver
 */
void ema_mgmt_uart_init(void)
{
	ema_mgmt_uart_CLOCK_init();
	usart_async_init(&ema_mgmt_uart, SERCOM3, ema_mgmt_uart_buffer, EMA_MGMT_UART_BUFFER_SIZE, (void *)NULL);
	ema_mgmt_uart_PORT_init();
}

/**
 * \brief USART Clock initialization function
 *
 * Enables register interface and peripheral clock
 */
void ema_modem_uart_CLOCK_init()
{

	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_CORE, CONF_GCLK_SERCOM4_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_SLOW, CONF_GCLK_SERCOM4_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	hri_mclk_set_APBDMASK_SERCOM4_bit(MCLK);
}

/**
 * \brief USART pinmux initialization function
 *
 * Set each required pin to USART functionality
 */
void ema_modem_uart_PORT_init()
{

	gpio_set_pin_function(PB08, PINMUX_PB08D_SERCOM4_PAD0);

	gpio_set_pin_function(PB09, PINMUX_PB09D_SERCOM4_PAD1);
}

/**
 * \brief USART initialization function
 *
 * Enables USART peripheral, clocks and initializes USART driver
 */
void ema_modem_uart_init(void)
{
	ema_modem_uart_CLOCK_init();
	usart_async_init(&ema_modem_uart, SERCOM4, ema_modem_uart_buffer, EMA_MODEM_UART_BUFFER_SIZE, (void *)NULL);
	ema_modem_uart_PORT_init();
}

/**
 * \brief Timer initialization function
 *
 * Enables Timer peripheral, clocks and initializes Timer driver
 */
static void TIMER_0_init(void)
{
	hri_mclk_set_APBCMASK_TC5_bit(MCLK);
	hri_gclk_write_PCHCTRL_reg(GCLK, TC5_GCLK_ID, CONF_GCLK_TC5_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));

	timer_init(&TIMER_0, TC5, _tc_get_timer());
}

void system_init(void)
{
	init_mcu();

	// GPIO on PA06

	// Set pin direction to input
	gpio_set_pin_direction(pa06_user_din0, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(pa06_user_din0,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_UP);

	gpio_set_pin_function(pa06_user_din0, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA07

	// Set pin direction to input
	gpio_set_pin_direction(pa07_user_din1, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(pa07_user_din1,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_UP);

	gpio_set_pin_function(pa07_user_din1, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA09

	gpio_set_pin_level(n_sht30_res,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(n_sht30_res, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(n_sht30_res, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA10

	// Set pin direction to input
	gpio_set_pin_direction(sw0_read, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(sw0_read,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(sw0_read, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA11

	// Set pin direction to input
	gpio_set_pin_direction(sw1_read, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(sw1_read,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(sw1_read, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA18

	// Set pin direction to input
	gpio_set_pin_direction(ema_sts, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(ema_sts,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(ema_sts, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA19

	// Set pin direction to input
	gpio_set_pin_direction(ema_rng, GPIO_DIRECTION_IN);

	gpio_set_pin_pull_mode(ema_rng,
	                       // <y> Pull configuration
	                       // <id> pad_pull_config
	                       // <GPIO_PULL_OFF"> Off
	                       // <GPIO_PULL_UP"> Pull-up
	                       // <GPIO_PULL_DOWN"> Pull-down
	                       GPIO_PULL_OFF);

	gpio_set_pin_function(ema_rng, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PA20

	gpio_set_pin_level(ema_reset,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   false);

	// Set pin direction to output
	gpio_set_pin_direction(ema_reset, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(ema_reset, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB04

	gpio_set_pin_level(n_photosense_en,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(n_photosense_en, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(n_photosense_en, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB05

	gpio_set_pin_level(iovref_dis,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   false);

	// Set pin direction to output
	gpio_set_pin_direction(iovref_dis, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(iovref_dis, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB06

	gpio_set_pin_level(pb06_user_dout0,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   false);

	// Set pin direction to output
	gpio_set_pin_direction(pb06_user_dout0, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(pb06_user_dout0, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB07

	gpio_set_pin_level(pb07_user_dout1,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   false);

	// Set pin direction to output
	gpio_set_pin_direction(pb07_user_dout1, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(pb07_user_dout1, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB10

	gpio_set_pin_level(blu_led0,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(blu_led0, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(blu_led0, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB11

	gpio_set_pin_level(blu_led1,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(blu_led1, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(blu_led1, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB12

	gpio_set_pin_level(blu_led2,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(blu_led2, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(blu_led2, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB13

	gpio_set_pin_level(blu_led3,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(blu_led3, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(blu_led3, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB14

	gpio_set_pin_level(red_led0,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(red_led0, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(red_led0, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB15

	gpio_set_pin_level(red_led1,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(red_led1, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(red_led1, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB16

	gpio_set_pin_level(mod4V_dis,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   true);

	// Set pin direction to output
	gpio_set_pin_direction(mod4V_dis, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(mod4V_dis, GPIO_PIN_FUNCTION_OFF);

	// GPIO on PB17

	gpio_set_pin_level(ema_on_off,
	                   // <y> Initial level
	                   // <id> pad_initial_level
	                   // <false"> Low
	                   // <true"> High
	                   false);

	// Set pin direction to output
	gpio_set_pin_direction(ema_on_off, GPIO_DIRECTION_OUT);

	gpio_set_pin_function(ema_on_off, GPIO_PIN_FUNCTION_OFF);

	ADC_0_init();

	emaPlay_debug_uart_init();

	I2C_init();
	ema_mgmt_uart_init();
	ema_modem_uart_init();

	TIMER_0_init();
}
