#include <samd21g18a.h>
#include "ADC.h"

volatile uint16_t adc_value;

void ADC_init(void)
{
	/* enable peripheral clock */
	PM->APBCMASK.bit.ADC_ = 1;
	
	/* enable generic clock */
	GCLK->CLKCTRL.bit.ID = GCLK_CLKCTRL_ID_ADC_Val;              // configure generic clock for ADC
	GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val;          // source is generic clock generator 0
	GCLK->CLKCTRL.bit.CLKEN = 1;                                 // enable generic clock
	
	/* select GPIO pins alternative function */
	PORT->Group[1].PINCFG[8].bit.PMUXEN = 1;                     // enable alternative function for pin PB08
	PORT->Group[1].PINCFG[3].bit.PMUXEN = 1;                     // enable alternative function for pin PA03 (analog function AREF)
	PORT->Group[1].PMUX[4].bit.PMUXE = MUX_PB08B_ADC_AIN2;       // PB08 alternative function B (ADC in 2)
	
	/* configure peripheral */
	ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV256_Val;   // prescaler 
	ADC->CTRLB.bit.DIFFMODE = 0x00;                              // single-ended mode
	ADC->CTRLB.bit.LEFTADJ = 0x00;                               // right adjusted result
	ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_16BIT_Val;          // conversion resolution is 16 bit (for accumulation)
	ADC->CTRLB.bit.FREERUN = 1;                                  // fee run mode
	ADC->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_16_Val;   // result is the accumulation of 16 samples
	ADC->AVGCTRL.bit.ADJRES = 0x04;                              // result is averaged over 16 samples
	ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val;    // negative input is internal ground
	ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_PIN2_Val;   // positive input on ADC in 2 (pin PB08)

	/* enable result ready interrupt */
	ADC->INTENSET.reg = ADC_INTENSET_RESRDY;
	NVIC_EnableIRQ(ADC_IRQn);

	/* enable peripheral */
	ADC->CTRLA.reg |= ADC_CTRLA_ENABLE;
}

void ADC_deinit(void)
{
	/* disable result ready interrupt */
	ADC->INTENCLR.reg = ADC_INTENCLR_RESRDY;
	NVIC_DisableIRQ(ADC_IRQn);
}

void ADC_Handler(void)
{
	adc_value = (ADC->RESULT.reg);
}



