#include <adc.h>
#include <string.h>

int16_t Calibrattion_Val = 0;
ADC_DATA g_adcData;

//ADC对应GPIO初始化配置以及ADC初始化配置
void ADC_all_Init(void)
{
    ADC_InitTypeDef  ADC_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOA, ENABLE);
    RCC_PB2PeriphClockCmd(RCC_PB2Periph_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div2);

//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; //PA1~7对应ADC通道1~7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; //PA1~7对应ADC通道1~7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    ADC_DeInit(ADC1);
    Calibrattion_Val = Get_CalibrationValue(ADC1);
    printf("Calibrattion_Val : %d\n", Calibrattion_Val);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_Cmd(ADC1, ENABLE);

    ADC_FIFO_Cmd(ADC1, ENABLE);
    ADC_BufferCmd(ADC1, DISABLE); //disable buffer

    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));

    RCC_ADCCLKConfig(RCC_HCLK_ADC);
    ADC_DutyDelayCmd(ADC1,ENABLE);
    ADC_Sample_ModeConfig(ADC1,ADC_Sample_Over_1M_Mode);
}






void DMA1_Channel1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

/*
 * 初始化ADC的DMA
 *
 *
 */
void DMA_Tx_Init(u32 memadr, u16 bufsize)
{
    DMA_InitTypeDef DMA_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_HBPeriphClockCmd(RCC_HBPeriph_DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->RDATAR;              //ADC1地址
    DMA_InitStructure.DMA_MemoryBaseAddr = memadr;                              //内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          //方向(从外设到内存)
    DMA_InitStructure.DMA_BufferSize = bufsize;                                 //传输内容的大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            //外设地址固定
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     //内存地址递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据单位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         //内存数据单位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                             //DMA模式：循环传输
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                     //优先级：高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                //禁止内存到内存的传输
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                             //使能传输完成中断

    //初始化TIM NVIC，设置中断优先级分组
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;    //
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //设置抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;          //设置响应优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能通道中断
    NVIC_Init(&NVIC_InitStructure); //初始化NVIC

    DMA_Cmd(DMA1_Channel1,ENABLE);

}

void TIM1_Init1(u16 arr,u16 psc)
{
//    /* 初始化PA8为模拟通道输入引脚 */
//    GPIO_InitTypeDef GPIO_InitStructure={0};
//    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOA, ENABLE);
////    RCC_APB2PeriphClockCmd(RCC_PB2Periph_AFIO, ENABLE);    //打开管脚复用AFIO时钟
////    GPIO_PinRemapConfig(GPIO_FullRemap_TIM1, ENABLE);
//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
//    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//    GPIO_Init( GPIOA, &GPIO_InitStructure );

    TIM_OCInitTypeDef TIM_OCInitStructure={0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};

    RCC_PB2PeriphClockCmd(RCC_PB2Periph_TIM1, ENABLE);

//    TIM_TimeBaseInitStructure.TIM_Period = 30000 - 1;
//    TIM_TimeBaseInitStructure.TIM_Prescaler = 48000 - 1;
    TIM_TimeBaseInitStructure.TIM_Period = arr - 1;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc - 1;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 10;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);

    TIM_CtrlPWMOutputs(TIM1, ENABLE);
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
    TIM_ARRPreloadConfig(TIM1, ENABLE);
    TIM_Cmd(TIM1, ENABLE);
}

#define CHG_CURR        ADC_Channel_1
#define PV_VOLT_OUT     ADC_Channel_2
#define DSG_CURR        ADC_Channel_3
#define PV_VOLT_IN      ADC_Channel_4
#define SYS_VOLT_IN     ADC_Channel_5
#define MOSFET_Temper   ADC_Channel_6
#define PV2_VOLT_IN     ADC_Channel_7

/*
 * 通过定时器和DMA完成adc的采集
 * 定时器采用定时器1的cc1完成ADC的外部触发 PA8 --> TIM1_CH1
 * ADC通过DMA的通道1完成数据的传输
 *
 * */
volatile uint16_t ADC_ConvertedValue[3];           //ADC采样的数据
void ADC_TIM_DMA_Init(void)
{
    ADC_InitTypeDef  ADC_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOA, ENABLE);
    RCC_PB2PeriphClockCmd(RCC_PB2Periph_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div2);

//    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; //PA1~7对应ADC通道1~7
//    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; //PA1~7对应ADC通道1~7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    ADC_DeInit(ADC1);
    Calibrattion_Val=Get_CalibrationValue(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
//    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_InitStructure.ADC_NbrOfChannel = 3;
    ADC_Init(ADC1, &ADC_InitStructure);

    //使能ADC、DMA
    ADC_DMACmd(ADC1,ENABLE);
    ADC_Cmd(ADC1, ENABLE);

//    ADC_InjectedSequencerLengthConfig(ADC1, 1);
//    ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_CyclesMode5);
//    ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);

    ADC_FIFO_Cmd(ADC1, ENABLE);
    ADC_BufferCmd(ADC1, DISABLE); //disable buffer
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));

//    ADC_RegularChannelConfig(ADC1, CHG_CURR,        1, ADC_SampleTime_CyclesMode5);
//    ADC_RegularChannelConfig(ADC1, PV_VOLT_OUT,     2, ADC_SampleTime_CyclesMode5);
//    ADC_RegularChannelConfig(ADC1, DSG_CURR,        3, ADC_SampleTime_CyclesMode5);
//    ADC_RegularChannelConfig(ADC1, PV_VOLT_IN,      4, ADC_SampleTime_CyclesMode5);
//    ADC_RegularChannelConfig(ADC1, SYS_VOLT_IN,     5, ADC_SampleTime_CyclesMode5);
//    ADC_RegularChannelConfig(ADC1, MOSFET_Temper,   6, ADC_SampleTime_CyclesMode5);

    ADC_RegularChannelConfig(ADC1, CHG_CURR,        1, ADC_SampleTime_CyclesMode5);
    ADC_RegularChannelConfig(ADC1, PV_VOLT_OUT,     2, ADC_SampleTime_CyclesMode5);
    ADC_RegularChannelConfig(ADC1, DSG_CURR,        3, ADC_SampleTime_CyclesMode5);

//    /* 设置定时器输出的周期为1S */
//    TIM1_Init1(1000, 48000);
    /* 设置定时器输出的周期为30mS */
    TIM1_Init1(30, 48000);
    /* 设置定时器输出的周期为100uS */
//    TIM1_Init1(300, 48);
    DMA_Tx_Init((u32)&ADC_ConvertedValue, 3);



//    ADC_DeInit(ADC1);
//    Calibrattion_Val = Get_CalibrationValue(ADC1);
//    printf("Calibrattion_Val : %d\n", Calibrattion_Val);
//    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
//    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
//    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
//    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//    ADC_InitStructure.ADC_NbrOfChannel = 1;
//    ADC_Init(ADC1, &ADC_InitStructure);
//
//    ADC_Cmd(ADC1, ENABLE);
//
//    ADC_FIFO_Cmd(ADC1, ENABLE);
//    ADC_BufferCmd(ADC1, DISABLE); //disable buffer
//
//    ADC_ResetCalibration(ADC1);
//    while(ADC_GetResetCalibrationStatus(ADC1));
//    ADC_StartCalibration(ADC1);
//    while(ADC_GetCalibrationStatus(ADC1));
//
//    RCC_ADCCLKConfig(RCC_HCLK_ADC);
//    ADC_DutyDelayCmd(ADC1,ENABLE);
//    ADC_Sample_ModeConfig(ADC1,ADC_Sample_Over_1M_Mode);

}

/**
  * @brief  将采集的adc进行校准
  * @param  val 采集的adc数据
  * @retval     校准后的adc数据
  */
uint16_t Get_ConversionVal1(int16_t val)
{
    if((val + Calibrattion_Val) < 0 || val == 0)
        return 0;
    if((Calibrattion_Val + val) > 4095 || val == 4095)
        return 4095;
    return (val + Calibrattion_Val);
}

void DMA1_Channel1_IRQHandler(void)
{
//    printf("\r\nEnter DMA interrupt\r\n");
    if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
    {
        DMA_ClearITPendingBit(DMA1_IT_TC1);
        //中断处理代码
//        g_adcData.CHG_CURR_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[0]);
//        g_adcData.PV_VOLT_OUT_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[1]);
//        g_adcData.DSG_CURR_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[2]);
//        g_adcData.PV_VOLT_IN_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[3]);
//        g_adcData.SYS_VOLT_IN_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[4]);
//        g_adcData.MOSFET_Temper_array[g_adcData.num] = Get_ConversionVal1(ADC_ConvertedValue[5]);
//        g_adcData.num++;


//        g_adcData.CHG_CURR_array[g_adcData.num]     = ADC_ConvertedValue[0];
//        g_adcData.DSG_CURR_array[g_adcData.num]     = ADC_ConvertedValue[1];
//        g_adcData.PV_VOLT_OUT_array[g_adcData.num]  = ADC_ConvertedValue[2];
//        g_adcData.num++;

//        g_adcData.num++;

//        g_adcData.total_CHG_CURR += Get_ConversionVal1(ADC_ConvertedValue[0]);

        printf("%d\n", ADC_ConvertedValue[0]);
        printf("%d\n", ADC_ConvertedValue[1]);
        printf("%d\r\n", ADC_ConvertedValue[2]);
//        printf("%d\n", ADC_ConvertedValue[3]);
//        printf("%d\n", ADC_ConvertedValue[4]);
//        printf("%d\r\n", ADC_ConvertedValue[5]);

//        g_adcData.total_PV_VOLT_OUT += Get_ConversionVal1(ADC_ConvertedValue[1]);
//        g_adcData.total_DSG_CURR += Get_ConversionVal1(ADC_ConvertedValue[2]);
//        g_adcData.total_PV1_VOLT_IN += Get_ConversionVal1(ADC_ConvertedValue[3]);
//        g_adcData.total_PV_VOLT_IN1 += Get_ConversionVal1(ADC_ConvertedValue[4]);
//        g_adcData.total_MOSFET_Temper += Get_ConversionVal1(ADC_ConvertedValue[5]);

//        printf("\r\n The current ADCH1 value = %d \r\n", ADC_ConvertedValue[0]);
//        printf("\r\n The current ADCH2 value = %d \r\n", ADC_ConvertedValue[1]);
//        printf("\r\n The current ADCH3 value = %d \r\n", ADC_ConvertedValue[2]);
//        printf("\r\n The current ADCH4 value = %d \r\n", ADC_ConvertedValue[3]);
//        printf("\r\n The current ADCH5 value = %d \r\n", ADC_ConvertedValue[4]);
//        printf("\r\n The current ADCH5 value = %d \r\n", ADC_ConvertedValue[5]);
//        ADC_ConvertedValue[0] = 0;
//        ADC_ConvertedValue[1] = 0;
//        ADC_ConvertedValue[2] = 0;
//        ADC_ConvertedValue[3] = 0;
//        ADC_ConvertedValue[4] = 0;
//        ADC_ConvertedValue[5] = 0;
    }
}


