/**
 ******************************************************************************
 *
 * @file        MG32_IEC60730_ADC.c
 *
 * @brief       This file provides firmware functions to manage the following 
 *              functionalities of the ADC peripheral:
 *
 * @par         Project
 *              MG32
 * @version     V1.13
 * @date        2021/01/22
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2016 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. 
 ******************************************************************************
 ******************************************************************************
 */ 



#include "MG32_IEC60730_Common.h"


/**
 *******************************************************************************
 * @brief       
 * @details  
 * @param[in]    
 * @return      
 * @exception      
 * @note        
 *******************************************************************************
 */
IEC60730_Ret IEC60730_ADC(ADC_ResolutionDef ADC_Resol, uint8_t ADC_ChannelSel, uint16_t HThreshold, uint16_t LThreshold)
{
    ADC_InitTypeDef ADC_Base;
    PIN_InitTypeDef PINX_InitStruct;
	uint32_t GPIOPinReg = 0;
 
	// ------------------------------------------------------------------------
	// GPIO initial (Analog input)
    PINX_InitStruct.PINX_Mode				= PINX_Mode_Analog_IO;
    PINX_InitStruct.PINX_PUResistant        = PINX_PUResistant_Disable;
    PINX_InitStruct.PINX_Speed              = PINX_Speed_Low;
    PINX_InitStruct.PINX_OUTDrive           = PINX_OUTDrive_Level0;
    PINX_InitStruct.PINX_FilterDivider      = PINX_FilterDivider_Bypass;
    PINX_InitStruct.PINX_Inverse            = PINX_Inverse_Disable;
    PINX_InitStruct.PINX_Alternate_Function = 0;
	
	switch(ADC_ChannelSel)
	{
	case ADC_ExtAIN0:
		GPIOPinReg = PINA(0)->CR.W;
		GPIO_PinMode_Config(PINA(0),&PINX_InitStruct);
		break;
	case ADC_ExtAIN1:
		GPIOPinReg = PINA(1)->CR.W;
		GPIO_PinMode_Config(PINA(1),&PINX_InitStruct);
		break;
	case ADC_ExtAIN2:
		GPIOPinReg = PINA(2)->CR.W;
		GPIO_PinMode_Config(PINA(2),&PINX_InitStruct);
		break;
	case ADC_ExtAIN3:
		GPIOPinReg = PINA(3)->CR.W;
		GPIO_PinMode_Config(PINA(3),&PINX_InitStruct);
		break;
	case ADC_ExtAIN4:
		GPIOPinReg = PINA(4)->CR.W;
		GPIO_PinMode_Config(PINA(4),&PINX_InitStruct);
		break;
	case ADC_ExtAIN5:
		GPIOPinReg = PINA(5)->CR.W;
		GPIO_PinMode_Config(PINA(5),&PINX_InitStruct);
		break;
	case ADC_ExtAIN6:
		GPIOPinReg = PINA(6)->CR.W;
		GPIO_PinMode_Config(PINA(6),&PINX_InitStruct);
		break;
	case ADC_ExtAIN7:
		GPIOPinReg = PINA(7)->CR.W;
		GPIO_PinMode_Config(PINA(7),&PINX_InitStruct);
		break;
	case ADC_ExtAIN8:
		GPIOPinReg = PINA(8)->CR.W;
		GPIO_PinMode_Config(PINA(8),&PINX_InitStruct);
		break;
	case ADC_ExtAIN9:
		GPIOPinReg = PINA(9)->CR.W;
		GPIO_PinMode_Config(PINA(9),&PINX_InitStruct);
		break;
	case ADC_ExtAIN10:
		GPIOPinReg = PINA(10)->CR.W;
		GPIO_PinMode_Config(PINA(10),&PINX_InitStruct);
		break;
	case ADC_ExtAIN11:
		GPIOPinReg = PINA(11)->CR.W;
		GPIO_PinMode_Config(PINA(11),&PINX_InitStruct);
		break;
	case ADC_ExtAIN12:
		GPIOPinReg = PINA(12)->CR.W;
		GPIO_PinMode_Config(PINA(12),&PINX_InitStruct);
		break;
	case ADC_ExtAIN13:
		GPIOPinReg = PINA(13)->CR.W;
		GPIO_PinMode_Config(PINA(13),&PINX_InitStruct);
		break;
	case ADC_ExtAIN14:
		GPIOPinReg = PINA(14)->CR.W;
		GPIO_PinMode_Config(PINA(14),&PINX_InitStruct);
		break;
	case ADC_ExtAIN15:
		GPIOPinReg = PINA(15)->CR.W;
		GPIO_PinMode_Config(PINA(15),&PINX_InitStruct);
		break;
    case 0x13:
        UnProtectModuleReg(PWprotect);
        PW_VoltageBuffer(ENABLE);
        ProtectModuleReg(PWprotect);
        ADC_SetExtendSampling(ADC0, 255);
        break;
	default:
		break;
	}
	
	// ------------------------------------------------------------------------
    // initial ADC base condition
    ADC_BaseStructure_Init(&ADC_Base);
    {   // modify parameter
        ADC_Base.ADCMainClockSelect = ADC_CKADC;
            ADC_Base.ADC_IntCK_Div = ADC_IntDIV4;   // 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_Resol;
        
        // ADC overwritten data or keep data
        ADC_Base.ADC_DataOverrunEvent = ADC_DataOverWritten;
        
    }
    ADC_Base_Init(ADC0, &ADC_Base);
    
    ADC_Cmd(ADC0, ENABLE);
	
	// ------------------------------------------------------------------------
    // ADCMode (One shot)
    ADC_ConversionMode_Select(ADC0, ADCMode);
    ADC_PGA_Cmd(ADC0, DISABLE);
    ADC_SingleDifferentMode_Select(ADC0, ADC_SingleMode);
    ADC_TriggerSource_Select(ADC0, ADC_START);
    ADC_SetOutputCodeFormat(ADC0, ADC_UnsignedFormat);

	// ------------------------------------------------------------------------
    // window detect initial (MDI)
    ADC_Output_Select(ADC0, ADC_WDI_Event);
    ADC_WindowDetectRange_Select(ADC0, ADC_WINDAll);
    ADC_SetHigherThreshold(ADC0, (int16_t) HThreshold);
    ADC_SetLowerThreshold(ADC0, (int16_t) LThreshold);    
    ADC_WindowDetect_Cmd(ADC0, ENABLE);
	
 	// ------------------------------------------------------------------------
    // ADC calibration
    ADC_ClearFlag(ADC0, 0xFFFFFFFF);
    ADC_StartCalibration(ADC0, ENABLE);
        
	ADC_ClearFlag(ADC0, 0xFFFFFFFF);
			
	// channel select & start ADC conversion
	ADC_ExternalChannel_Select(ADC0, (ADC_ExtChannelDef) ADC_ChannelSel);
	ADC_SoftwareConversion_Cmd(ADC0, ENABLE);        
	while (ADC_GetSingleFlagStatus (ADC0, ADC_E1CNVF) == DRV_UnHappened);
	ADC_ClearFlag(ADC0,ADC_E1CNVF);
	
 	// ------------------------------------------------------------------------
	// restore GPIO configuration
	switch(ADC_ChannelSel)
	{
	case ADC_ExtAIN0:
		PINA(0)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN1:
		PINA(1)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN2:
		PINA(2)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN3:
		PINA(3)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN4:
		PINA(4)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN5:
		PINA(5)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN6:
		PINA(6)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN7:
		PINA(7)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN8:
		PINA(8)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN9:
		PINA(9)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN10:
		PINA(10)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN11:
		PINA(11)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN12:
		PINA(12)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN13:
		PINA(13)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN14:
		PINA(14)->CR.W = GPIOPinReg;
		break;
	case ADC_ExtAIN15:
		PINA(15)->CR.W = GPIOPinReg;
		break;
  case 0x13:
        UnProtectModuleReg(PWprotect);
        PW_VoltageBuffer(DISABLE);
        ProtectModuleReg(PWprotect);
        ADC_SetExtendSampling(ADC0, 0);
        break;
	default:
		break;
	}
	
 	// ------------------------------------------------------------------------
	// check ADC WDIF flag
	if(ADC_GetSingleFlagStatus(ADC0, ADC_WDIF) == DRV_Happened)
	{
		ADC_DeInit(ADC0);
		return IEC60730_TEST_SUCCESS;
	}
	else 
	{
		ADC_DeInit(ADC0);
		return IEC60730_TEST_FAILURE;
	}
                
}

