#include "drv_adc.h"
#include "drv_clk.h"
#include "drv_dma.h"
#include "kit_data.h"
#include "kit_debug.h"

#define CR1_SCAN_Set                ((uint32_t)0x00000100)
#define CR2_DMA_Set                 ((uint32_t)0x00000100)
#define CR2_RSTCAL_Set              ((uint32_t)0x00000008)
#define CR2_CAL_Set                 ((uint32_t)0x00000004)
#define CR2_SWSTART_Set             ((uint32_t)0x00500000)
#define CR2_CONT_Set                ((uint32_t)0x00000002)
#define CR2_ADON_Set                ((uint32_t)0x00000001)
#define CFGR_ADCPRE_Reset_Mask      ((uint32_t)0xFFFF3FFF)
#define RCC_PCLK2_Div8              ((uint32_t)0x0000C000)
#define SMPR_SMP_Set                ((uint32_t)0x00000007)
#define SQR_SQ_Set                  ((uint32_t)0x0000001F)
#define ADC_ExternalTrigConv_None   ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */


typedef struct
{
    DmaStream  dma_stream;
    DmaChannel dma_channel;

    ADC_TypeDef* reg;
}STM32AdcProp;
STM32AdcProp stm32_adc_prop[kAdcDev_End] = 
{
    {kDma2Stream_0, kDmaChannel_0, ADC1},
    {kDma2Stream_3, kDmaChannel_1, ADC2},
    {kDma2Stream_0, kDmaChannel_2, ADC3},
};

typedef struct
{
    uint16_t arr_len;
    uint16_t sample_cnt;
    uint16_t *dma_buf;   
}AdcItem;

AdcItem adc1_item;

uint8_t drv_adc_init(AdcDev dev, const AdcArray *adc_arr, uint16_t len, uint16_t* dma_buf, uint8_t sample_cnt)
{
    uint8_t tmp1_8u, tmp2_8u;
    uint32_t i;
    __IO uint32_t *sqr[3];
    __IO uint32_t *smpr[2];
    ADC_TypeDef *reg;
    if(dev < kAdcDev_End)
    {
        adc1_item.arr_len = len;
        adc1_item.dma_buf = dma_buf;
        adc1_item.sample_cnt = sample_cnt;
        reg = stm32_adc_prop[dev].reg;
        //dma init
        drv_dma_init(stm32_adc_prop[dev].dma_stream, stm32_adc_prop[dev].dma_channel, DMA_CFG_DATA_DIR_P2M | DMA_CFG_CYCLE_EXE | DMA_CFG_DATA_M_I|DMA_CFG_DATA_P_N|DMA_CFG_DATA_LEN_2B, (uint32_t)&reg->DR);
        drv_dma_set_buf(stm32_adc_prop[dev].dma_stream, (uint8_t*)dma_buf, len * sample_cnt);
        
        RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN << dev); //开启时钟
        //设置ADC通道的转换顺序和采样时间
        sqr[0] = &reg->SQR3;
        sqr[1] = &reg->SQR2;
        sqr[2] = &reg->SQR1;
        smpr[0] = &reg->SMPR2;
        smpr[1] = &reg->SMPR1;
        for(i = 0; i < len ; i++)
        {
            tmp1_8u = adc_arr[i].channel / 10;
            tmp2_8u = adc_arr[i].channel % 10 * 3;

            *smpr[tmp1_8u] &= ~(SMPR_SMP_Set << tmp2_8u);
            *smpr[tmp1_8u] |= (adc_arr[i].cycle << tmp2_8u);
            
            tmp1_8u = i / 6;
            tmp2_8u = i % 6 * 5;
            
            *sqr[tmp1_8u] &= ~(SQR_SQ_Set << tmp2_8u);
            *sqr[tmp1_8u] |= (adc_arr[i].channel << tmp2_8u);
        }
        //设置规则通道数目
        reg->SQR1 &= ~KIT_CREAT_BITS(20, 23);
        reg->SQR1 |= (uint32_t)(len - 1 ) << 20;
        
        KIT_CLR_BIT(reg->SR, 5);
        //设置ADC频率
        reg->CR1 |= ADC_CR1_SCAN;
        ADC->CCR |= 0x30000; //PCLK2 8分频
        //calibration
        
        reg->CR2 |= ADC_CR2_ADON | ADC_CR2_CONT | ADC_CR2_DDS | ADC_CR2_DMA;   

        reg->CR2 |= ADC_CR2_SWSTART;
    }

    return true;
}

bool drv_adc_is_overflow(AdcDev dev)
{
    return ((stm32_adc_prop[dev].reg->SR & 0x20) != 0);
}

uint16_t drv_adc_get_data(uint8_t idx)
{
    uint16_t res = 0;
    
    KIT_ASSERT_PARAM(idx < adc1_item.arr_len);
    if(idx < adc1_item.arr_len)
    {
        res = kit_get_dma_avg_filter_min_max(adc1_item.dma_buf, adc1_item.arr_len, idx, adc1_item.sample_cnt);
    }
    return res;
}