/**
  ******************************************************************************
 *
 * @file        Sample_ADC_GetVrefVoltage.c
 *
 * @brief       Get MCU Vref voltage by sampling VBUF.(Driver level)
 *
 * @par         Project
 *              MG32
 * @version     V1.02
 * @date        2022/04/14
 * @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_DRV.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
uint16_t Sample_ADC_GetVrefVoltage(void);
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External vairables --------------------------------------------------------*/


/**
 *******************************************************************************
 * @brief	    Conversion PA4 analog input voltage to Digital value depend VREF 
 * @details     1.Enable VBUF module + Settling time 
 *    \n        2.Config ADC base parameter
 *    \n        3.Enable ADC + Settling time  
 *    \n        4.Config ADC Mode (one shot mode)
 *    \n        5.Clear all flag
 *    \n        6.Start Calibration 
 *    \n        7.Select internal Channel (VBUF) be converted
 *    \n        8.Trigger Source select and Start conversion
 *    \n        9.until E1CNVF & clear flag
 *    \n        10.Convert to Vref voltage (unit: 10mV)
 * @return      Result of ADC conversion data
 *******************************************************************************
 */
uint16_t Sample_ADC_GetVrefVoltage(void)
{  
	
    ADC_InitTypeDef ADC_Base;
    __IO uint32_t VddVoltage;
    __IO uint16_t CalVal;
    
    
    // make sure :
	
    //===Set CSC init====
    //MG32_CSC_Init.h(Configuration Wizard)
    //Select CK_HS source = CK_IHRCO
    //Select IHRCO = 12M
    //Select CK_MAIN Source = CK_HS
    //Configure PLL->Select APB Prescaler = CK_MAIN/1
    //Configure Peripheral On Mode Clock->ADC = Enable
    //Configure Peripheral On Mode Clock->Port A = Enable 
    
    // User must run 'Systick' routine. (for delay routine)
    // 1. Run 'InitTick(12000000, 0);' (if MCU run in 12MHz)
    // 2. Enable 'Systick' in MG32_IRQ_Handler of 'Manage Run-Time Enviroment'
    // 3. Enable 'IRQ Handler' in MG32_ChipInit_Wizard of 'Manage Run-Time Enviroment'
	
    // ------------------------------------------------------------------------
    // 1.Enable VBUF module  
    UnProtectModuleReg(PWprotect);
    PW_VoltageBuffer(ENABLE);
	ProtectModuleReg(PWprotect);
    
    // VBUF settling time 
    Delay(1);
    
    // ------------------------------------------------------------------------
    // 2.Config ADC base parameter    
    ADC_BaseStructure_Init(&ADC_Base);
    {   // modify parameter
        ADC_Base.ADCMainClockSelect = ADC_CKADC;
            ADC_Base.ADC_IntCK_Div = ADC_IntDIV16;   // for internal clock divider
    
        // ADC data alignment mode (Right or Left)
        ADC_Base.ADC_DataAlign = ADC_RightJustified;
        
        // ADC conversion resolution 8, 10 or 12 bit
        ADC_Base.ADC_ResolutionSel = ADC_12BitData;
        
        // ADC overwritten data or keep data
        ADC_Base.ADC_DataOverrunEvent = ADC_DataOverWritten;
        
    }
    ADC_Base_Init(ADC0, &ADC_Base);
    
    // ------------------------------------------------------------------------
	// 3.Enable ADC 
    ADC_Cmd(ADC0, ENABLE);
    
    // ADC settling time 
    Delay(1);
    
    // ------------------------------------------------------------------------
    // 4.Config ADC Mode
    ADC_ConversionMode_Select(ADC0, ADCMode);   // one-shot
    #if !(defined(MG32_4TH))
    ADC_PGA_Cmd(ADC0, DISABLE);                 // Disable PGA
    #endif
    ADC_SingleDifferentMode_Select(ADC0, ADC_SingleMode);  // Single Mode  
    
    ADC_SetExtendSampling(ADC0, 0);
    
    // ------------------------------------------------------------------------
    // 5.Clear all flag
    ADC_ClearFlag(ADC0, 0xFFFFFFFF);

    // ------------------------------------------------------------------------
    // 6.Start Calibration 
    ADC_StartCalibration(ADC0, ENABLE);
    
    // ------------------------------------------------------------------------
	// 7.Select internal Channel (VBUF)
    ADC_InternalChannel_Select(ADC0, ADC_INT_VBUF);

    // ------------------------------------------------------------------------
	// 8.Trigger Source select and Start conversion
    ADC_TriggerSource_Select(ADC0, ADC_START);
    ADC_SoftwareConversion_Cmd(ADC0, ENABLE);
	
    // ------------------------------------------------------------------------
	// 9.until E1CNVF & clear flag
    while(ADC_GetSingleFlagStatus(ADC0, ADC_E1CNVF) == DRV_UnHappened);
    ADC_ClearFlag(ADC0, ADC_E1CNVF);

    // ------------------------------------------------------------------------
    // 10.Convert Vref Volatge (unit:10mV)
    CalVal = (uint16_t) ADC_GetDAT0Data(ADC0);
    VddVoltage = (uint32_t) (140 * 4096) ;
    VddVoltage = VddVoltage / CalVal ;
    
    return (uint16_t) VddVoltage;

}



