/**
  ******************************************************************************
  * @file    VAPC-meter/lib/adc.c
  * @author  "Vladimir N. Shilov" <shilow@ukr.net>
  * @version V1
  * @date    24-March-2016
  * @brief   This file contains the ADC functions.
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "adc.h"

/** @addtogroup ADC
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t ADC_Buffer[ADC_BUFFER_SIZE] = {0, 0, 0};

uint16_t VoltageFastBuffer[FAST_BUFFER_SIZE];
uint16_t CurrentFastBuffer[FAST_BUFFER_SIZE];
uint16_t RefVoltFastBuffer[FAST_BUFFER_SIZE];

/* Private constants ---------------------------------------------------------*/
__near __no_init const unsigned char Factory_VREFINT @ 0x4910;

/* Private function prototypes -----------------------------------------------*/
static void ADC_Config(void);
static void DMA_Config(void);
static void TIM2_Config(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initialize and start ADC
  * @param  None
  * @retval None
  */
void Init_ADC(void)
{
    /* ADC configuration */
    ADC_Config();

    /* DMA configuration */
    DMA_Config();

    /* TIM2 configuration */
    TIM2_Config();
}

/**
  * @brief  Configure ADC peripheral
  * @param  None
  * @retval None
  */
static void ADC_Config(void)
{
    /* Enable ADC1 clock */
    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);

    /* Initialize and configure ADC1 */
    ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_1);
    ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_384Cycles);
    ADC_SamplingTimeConfig(ADC1, ADC_Group_FastChannels, ADC_SamplingTime_384Cycles);

    /* Enable ADC1 */
    ADC_Cmd(ADC1, ENABLE);

    /* Enable ADC1 Voltage meter channel */
    ADC_ChannelCmd(ADC1, VOLTAGE_CHANNEL, ENABLE);
    ADC_SchmittTriggerConfig(ADC1, VOLTAGE_CHANNEL, DISABLE);

    /* Enable ADC1 Current meter channel */
    ADC_ChannelCmd(ADC1, CURRENT_CHANNEL, ENABLE);
    ADC_SchmittTriggerConfig(ADC1, CURRENT_CHANNEL, DISABLE);

    /* ADC Voltage Reference */
    ADC_VrefintCmd(ENABLE);
    /* Enable ADC1 Vrefint Channel */
    ADC_ChannelCmd(ADC1, ADC_Channel_Vrefint, ENABLE);

    /* Enable ADC1 DMA requests*/
    ADC_DMACmd(ADC1, ENABLE);

    /* Start ADC1 Conversion using TIM1 TRGO*/
    ADC_ExternalTrigConfig(ADC1, ADC_ExtEventSelection_Trigger3, ADC_ExtTRGSensitivity_Rising);
}

/**
  * @brief  Configure DMA peripheral
  * @param  None
  * @retval None
  */
static void DMA_Config(void)
{
    /* Enable DMA1 clock */
    CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);

    /* Connect ADC to DMA channel 0 */
    SYSCFG_REMAPDMAChannelConfig(REMAP_DMA1Channel_ADC1ToChannel0);

    DMA_Init(DMA1_Channel0, ADC_BUFFER_ADDRESS,
           ADC1_DR_ADDRESS,
           ADC_BUFFER_SIZE,
           DMA_DIR_PeripheralToMemory,
           DMA_Mode_Circular,
           DMA_MemoryIncMode_Inc,
           DMA_Priority_High,
           DMA_MemoryDataSize_HalfWord);

    /* DMA Channel0 enable */
    DMA_Cmd(DMA1_Channel0, ENABLE);

    /* Enable DMA1 channel0 Transfer complete interrupt */
    DMA_ITConfig(DMA1_Channel0, DMA_ITx_TC, ENABLE);

    /* DMA enable */
    DMA_GlobalCmd(ENABLE);
}

/**
  * @brief  Configure TIM2 peripheral
  * @param  None
  * @retval None
  */
static void TIM2_Config(void)
{
    /* Enable TIM2 clock */
    CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);

    /* Initializes the TIM2 Time Base Unit */
    TIM2_TimeBaseInit(TIM_PRESCALER, TIM2_CounterMode_Up, TIM_PERIOD);

    /* Selects the TIM2 Update Request Interrupt source */
    TIM2_UpdateRequestConfig(TIM2_UpdateSource_Regular);

    /* Master Mode selection: Update event */
    TIM2_SelectOutputTrigger(TIM2_TRGOSource_Update);

    /* Enable TIM2 */
    TIM2_Cmd(ENABLE);
}


/**
  * @}
  */

/************************ (C) Vladimir N. Shilov *****END OF FILE****/
