#include "stm32f0xx.h"
#include "adc.h"

void adc_init(void)
{
	uint16_t time_out = 1000;

	GPIOA->MODER |= (3 << GPIO_MODER_MODER0_Pos); // PA0 analog input

	ADC1->CFGR2 |= (2 << ADC_CFGR2_CKMODE_Pos); // clock PCLK (32 MHz) / 4 -> 8 MHz
	ADC1->SMPR |= (5 << ADC_SMPR_SMP_Pos); // 55.5 adc clock cycles sampling rate
	ADC1->CHSELR |= (1 << ADC_CHSELR_CHSEL0_Pos); // AN0 input enable

  ADC1->CR |= (1 << ADC_CR_ADCAL_Pos); // adc calibration
  while(ADC1->CR & (1 << ADC_CR_ADCAL_Pos) && time_out--)
    ;

	ADC1->CR |= (1 << ADC_CR_ADEN_Pos); // adc enable
	time_out = 1000;
	while(!(ADC1->ISR & (1 << ADC_ISR_ADRDY_Pos)) && time_out--) // adc ready
	  ;

	ADC1->CR |= (1 << ADC_CR_ADSTART_Pos); // start sequence of conversion(s)
}

uint16_t adc_voltage(void)
{
  uint16_t value;
  uint16_t time_out = 1000;

  while(!(ADC1->ISR & (1 << ADC_ISR_EOS_Pos)) && time_out--) // wait until sequence of conversion(s) is complete
    ;

  value = ADC1->DR;
  ADC1->ISR |= (1 << ADC_ISR_EOS_Pos); // clear the flag
  ADC1->CR |= (1 << ADC_CR_ADSTART_Pos); // start another sequence

  return value * 0.888378906f; // magic number, (100 * Vref * (R1 + R2)) / (4096 * R2)
}
