/**
  ******************************************************************************
 *
 * @file        Sample_MID_ADC_Sum_SetupExample.c
 *
 * @brief       ADC enable sum and window detection function with DMA access.
 *
 * @par         Project
 *              MG32
 * @version     V1.14
 * @date        2021/05/27
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 *
 ******************************************************************************
* @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 ******************************************************************************
 */


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

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static ADC_HandleTypeDef   mADC;
static DMA_HandleTypeDef   mDMA;

// ADC convert data space
static uint32_t ADCDatArray[3];

/* Private function prototypes -----------------------------------------------*/
void Sample_MID_ADC_Sum_SetupExample(void);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/



/**
 *******************************************************************************
 * @brief	    ADC enable sum and window detection function.
 * @details     1.Config ADC base parameter.
 *    \n        2.Enable & Config ADC watchdog function.
 *    \n        3.Enable & Config accumulation function.
 *    \n        4.Enable ADC scan channels.
 *    \n        5.initial DMA.
 *    \n        6.Trigger ADC convert.
 * @return      None
 *******************************************************************************
 */
void Sample_MID_ADC_Sum_SetupExample(void)
{  
    ADC_AnalogWDGConfTypeDef    ADC_WDG;
    ADC_AccumulateConfDef       sSUM;
    ADC_ChannelConfTypeDef      ADCCh;

    // make sure :
    
    //===Set CSC init====
    //MG32_CSC_Init.h(Configuration Wizard)
    //Select CK_HS source = CK_IHRCO
    //Select IHRCO = 12M
    //  Select CK_PLLI Divider = CK_HS/2
    //  Select CK_PLL Multiplication factor = CK_PLLIx16
    //  Select CK_PLLO Divider = CK_PLL/4
    //Select CK_MAIN Source = CK_PLLO
    //Configure PLL->Select APB Prescaler = CK_MAIN/1
    //Configure Peripheral On Mode Clock->ADC = Enable
    //Configure Peripheral On Mode Clock->DMA = Enable
    //Configure Peripheral On Mode Clock->Port A = Enable
	
    //==Set GPIO init 
    //MG32_GPIO_Init.h(Configuration Wizard)->Use GPIOA->PA3,PA9,PA12
    //GPIO port initial is 0xFFFF
    //PA3,PA9,PA12 mode is AIO
    //PA3,PA9,PA12 function GPA3,9,12
    
    // ------------------------------------------------------------------------
    // 1.Config ADC base parameter.  
    // ------------------------------------------------------------------------
    mADC.Instance                   = ADC0;                     // for ADC0
    mADC.Init.ADCConType            = ADC_CONV_SINGLE;          // Single-end type
    mADC.Init.ADCClock              = ADC_CLOCKPROC_DIV16;      // ADC_Clock = ADC_PROC/16 (~50K in 24MHz)
    mADC.Init.Resolution            = ADC_RESOLUTION_12B;       // ADC conversion resolution
    mADC.Init.DataAlign             = ADC_DATAALIGN_RIGHT;      // ADC data is Right-justified
    mADC.Init.ConversionMode        = ADC_SCAN_AUTO;            // Scan continue control to converion 
    mADC.Init.LowPowerAutoWait      = ADC_CONTINUE_NEXT;        // ADC will replace the older conversion data (WAIT_EN for scan/loop mode)
    mADC.Init.TriggerConverionSrc   = ADC_SOFTWARE_START;       // ADC trigger event from software command
    mADC.Init.TriggerConverionEdge  = ADC_TRIGCONVEDGE_NONE;    // ADC convert signal from external trigger event edge select
    mADC.Init.Overrun               = ADC_ACCEPT_OVERRUN;       // It will overrun the conversion data   
    mADC.Init.ExtendSamplingTime    = 0;                        // Extend time of 'Sample & Hold' of ADC conversion state (0 ADC_Clock)
    mADC.Init.PGACmd                = PGA_ENABLE;               // Enable ADC PGA
    mADC.Init.PGAGain               = 0;                        // PGA Gain=x1, ADC Gain is equal : (1+(ADC0_GAIN_PGA*3)/(63+(63-ADC0_GAIN_PGA)*3))
    
    MID_ADC_Init(&mADC);
    
    // ------------------------------------------------------------------------
    // 2.Enable & Config ADC watchdog function.
    // ------------------------------------------------------------------------
    ADC_WDG.WatchdogMode            = ADC_ANALOGWATCHDOG_ALL_REG;           // AWD will apply all ADC conversion data
    ADC_WDG.Channel                 = ADC_CHANNEL_0;
    ADC_WDG.ITMode                  = NULL;                                 // polling mode
    ADC_WDG.HighThreshold           = 1023;                 
    ADC_WDG.LowThreshold            = 10; 
    ADC_WDG.WatchdogDataLimit       = ADC_ANALOGWATCHDOG_CLAMP_THRESHOLD;   // Clamp data when result is ouside
 
    MID_ADC_AnalogWDGConfig(&mADC, &ADC_WDG);
    
    // ------------------------------------------------------------------------
    // 3.Enable & Config accumulation function.
    // ------------------------------------------------------------------------
    sSUM.AccumulationMode           = ADC_ACCUMULATE_DECLARE_SUMCH;
    sSUM.SUM0_Channel               = ADC_SUMx_CHANNEL3;
    sSUM.SUM1_Channel               = ADC_SUMx_CHANNEL9;
    sSUM.SUM2_Channel               = ADC_SUMx_CHANNEL12;
    sSUM.SUM0_Init                  = 0;
    sSUM.SUM1_Init                  = 0;
    sSUM.SUM2_Init                  = 0;
    sSUM.ITMode                     = NULL;
    sSUM.AccumulateNumber           = 3;
    sSUM.SOverrun                   = ADC_SUM_ACCEPT_OVERRUN;
    
    MID_ADC_AccumulateConfig(&mADC, &sSUM);
    
    // ------------------------------------------------------------------------
    // 4.Enable ADC scan channels.
    // ------------------------------------------------------------------------
    ADCCh.Channel                   = ADC_CHANNEL_3;            // select conversion channel mux for ADC_ONESHOT or ADC_REPITIVE_CHANNEL conversion mode
    ADCCh.SequenceChannelMUX        = (ADC_ScanCHANNEL_3 |      // enable channel3/9/12 for ADC_SCAN_MANUAL, ADC_SCAN_AUTO or ADC_LOOP_AUTO conversion mode
                                       ADC_ScanCHANNEL_9 | 
                                       ADC_ScanCHANNEL_12);    
    MID_ADC_ConfigChannel(&mADC, &ADCCh);
    
    // ------------------------------------------------------------------------
    // 5.Initial DMA. (P2M)
    // ------------------------------------------------------------------------
    mDMA.Instance		            = DMA;
    mDMA.DMAChannelIndex            = DMAChannel0;              // only DMA channel0 can support M2M mode  
    mDMA.Init.SrcPeri	            = MID_DMA_ADC0_SAMPLE;      // Source symbol is ADC
    mDMA.Init.DesPeri	            = MID_DMA_MEMORY_WRITE;     // Destination symbol is Memory
    mDMA.Init.BSize 	            = DMA_BSIZE_4BYTE;          // Burst size is 4 byte
    mDMA.Init.MEMMode	            = MID_DMA_MEMORY_NORMAL;    // Normal memory access mode    
    mDMA.Init.LoopMode	            = DMA_LOOP_DISABLE;         // DISABLE Loop mode
    mDMA.Parent                     = &mADC;
    
    MID_DMA_Init(&mDMA);


    // ------------------------------------------------------------------------
    // 6.Trigger ADC convert. (for ADC_SCAN_AUTO mode)
    // ------------------------------------------------------------------------
    mADC.DMA_Handle                 = &mDMA;
    MID_ADC_Start_DMA(&mADC, (uint32_t *) &ADCDatArray, 12);
        
    // check ADC complete ?
    // if (__DRV_ADC_GET_FLAG(&mADC, ADC_FLAG_ESCNV))    
    // { // to do ... }


    // ------------------------------------------------------------------------
    // 6. (or) Trigger ADC convert. (for ADC_ONESHOT mode)
    // ------------------------------------------------------------------------
    // MID_ADC_Start(&mADC);
    
    // poll ADC flag within 10ms
    // MID_ADC_PollForConversion(&mADC, 10);
        
    
}

