// ***********************************************************************
// main - HEADER
// ***********************************************************************

#ifndef MAIN_H_
#define MAIN_H_

// direct acces of multi-byte variables
#define _BYTEX(val, x)                          (*((uint8_t*)&val+x))

// direct copy of U8 variable to selected position of multi-byte variables
#define _MOVE_TO_BYTE0(dest,src)                (*((uint8_t*)&dest) = src)
#define _MOVE_TO_BYTE1(dest,src)                (*((uint8_t*)&dest+1) = *&src)

// ______________________ C o n s t a n t s___________________ //

// EEPROM adresses
#define EEPROM_ID			(uint8_t*)0x00
#define EEPROM_BROADCAST_ID (uint8_t*)0x01
#define EEPROM_VOL_BAL		(uint16_t*)0x02

// ______________________ C o n s t a n t s___________________ //

#define VOLTAGE_SAMPLE_TTL	250		// 1 s

#define BAL_VOL_MIN			3000
#define BAL_VOL_MAX			5500

#define BALANCE_N_CYCLES	4

// ADC Channel
#define ADC_VOL_CH			3
#define ADC_TEMP_CH			0x1E

// ADC Voltage Calculation
#define ADC_MUL_FORMAT		16
#define ACD_MUL				40039

// AVG Calculation
#define AVG_INC_FORMAT		11
#define AVG_FORMAT			8
#define AVG_ONE				256      // 1 >> 8
#define AVG_COEF			250      // 0.976 >> 8

// ADC Temp Calculation
#define ADC_TEMP_FORMAT		8
#define ADC_SAMPLES			8
#define ADC_SAMPLES_FORMAT	3		// 2^3 = 8 = ADC_SAMPLES

typedef enum t_Vrefs
{
	VREF_2V50, VREF_1V10, VREF_ENUM_COUNT
} t_Vrefs;

typedef enum t_voltage
{
	VOLTAGE_AVG_SAMPLE, VOLTAGE_AVG, VOLTAGE_BALANCE, VOLTAGE_ACTUAL, VOLTAGE_ENUM_COUNT
} t_voltage;

typedef enum t_tasks
{
	TASK_NONE = -1, TASK_ADC_TRIG_VOL, TASK_BAL_CTRL_ADC_TRIG_TEMP, TASK_MEAS_TEMP
} t_tasks;

// ______________________ C o n t r o l_______________________ //

#define SLEEP()				asm("SLEEP")

// ADC
#define ADC_START(ch)		ADC0_MUXPOS = ch, \
							ADC0_COMMAND = ADC_STCONV_bm
							
#define ADC_RESULT			ADC0_RES

// Clock Timer
#define CLK_TIM_OVF_CLR()	TCA0_SINGLE_INTFLAGS |= TCA_SINGLE_OVF_bm

// PWM Timer
#define PWM_TIM_ON()		TCD0_CTRLA |= TCD_ENABLE_bm
#define PWM_TIM_OFF()		TCD0_CTRLE |= TCD_DISEOC_bm

#define PWM_A_SET(val)		TCD0_CMPASET = val
#define PWM_B_SET(val)		TCD0_CMPBSET = 0xFF - val
#define PWM_SYNC()			TCD0_CTRLE |= (TCD_SYNCEOC_bm)

// _________________________ I N I T _________________________ //

// System Clock 10 MHz
#define CLK_INIT()			CCP = CCP_IOREG_gc, \
							CLKCTRL_MCLKCTRLB = (CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm)
							
// Sleep Mode Idle
#define SLEEP_INIT()		SLPCTRL_CTRLA = (SLPCTRL_SMODE_IDLE_gc | SLPCTRL_SEN_bm)

// USART on alternate pins
#define PORTMUX_INIT()		PORTMUX_CTRLB = PORTMUX_USART0_ALTERNATE_gc

// Watchdog
#define WDT_INIT()			CCP = CCP_IOREG_gc, \
							WDT_CTRLA = WDT_PERIOD_32CLK_gc

//________ A D C ________ //

// Vref = 2.5V
#define VREF_2V5_INIT()		VREF_CTRLA = VREF_ADC0REFSEL_2V5_gc
#define VREF_1V1_INIT()		VREF_CTRLA = VREF_ADC0REFSEL_1V1_gc

// Variable delay between samples
// Clock = SYSCLK / 128
// 4 cycles sample length
// 8 samples per run
// Single conversion mode
// Interrupt on result ready
#define ACD_INIT()			ADC0_CTRLD = ( ADC_ASDV_ASVON_gc | ADC_INITDLY_DLY16_gc ), \
							ADC0_SAMPCTRL = 4, \
							ADC0_CTRLC = ADC_PRESC_DIV128_gc, \
							ADC0_CTRLB = ADC_SAMPNUM_ACC8_gc, \
							ADC0_CTRLA = ADC_ENABLE_bm, \
							ADC0_INTCTRL = ADC_RESRDY_bm

// IO init
#define PORTA_INIT()		PORTA_DIR = (PIN1_bm | PIN6_bm | PIN7_bm);

//______ T I M E R S ______ //

// Dual Slope Mode
// Resolution 8-bit
// Period = 10 MHz / 2*(0xFE+1) = 19.6 kHz
#define PWM_TIM_INIT()		TCD0_CMPBCLR = 0xFE, \
							TCD0_CTRLC = (TCD_CMPDSEL_PWMA_gc | TCD_CMPCSEL_PWMB_gc), \
							TCD0_CTRLB = (TCD_WGMODE_DS_gc), \
							TCD0_CTRLA = (TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc | TCD_SYNCPRES_DIV1_gc), \
							CPU_CCP = CCP_IOREG_gc, \
							TCD0_FAULTCTRL = (TCD_CMPAEN_bm | TCD_CMPBEN_bm)
							
// Period = 1 / (10 MHz / 16 / 6250) = 10 ms
// Overflow interrupt
// Do not change the clock prescaler! Clock source for USART timeout.
#define CLK_TIM_INIT()		TCA0_SINGLE_PER = 6250, \
							TCA0_SINGLE_CTRLA = (TCA_SINGLE_CLKSEL_DIV16_gc | TCA_SINGLE_ENABLE_bm), \
							TCA0_SINGLE_INTCTRL = (TCA_SINGLE_OVF_bm)
							
#endif /* MAIN_H_ */