/**************************************************************************//**
 * @file     eadc.c
 * @version  V0.10
 * @brief    M253 series EADC driver source file
 *
 * SPDX-License-Identifier: Apache-2.0
 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

#include "NuMicro.h"

/** @addtogroup Standard_Driver Standard Driver
  @{
*/

/** @addtogroup EADC_Driver EADC Driver
  @{
*/
int32_t g_EADC_i32ErrCode = 0;       /*!< EADC global error code */

/** @addtogroup EADC_EXPORTED_FUNCTIONS EADC Exported Functions
  @{
*/

/**
  * @brief This function make EADC_module be ready to convert.
  * @param[in] eadc The pointer of the specified EADC module.
  * @param[in] u32InputMode Decides the input mode. M253 don't support this feature.
  *                       - \ref NULL      :Always NULL.
  * @details This function is used to set analog input mode and enable A/D Converter.
  *         Before starting A/D conversion function, ADCEN bit (EADC_CTL[0]) should be set to 1.
  * @note   This function sets g_EADC_i32ErrCode to EADC_TIMEOUT_ERR if PWRCTL_READY(EADC_PWRCTL[0]) is not set to 1
  */
void EADC_Open(EADC_T *eadc, uint32_t u32InputMode)
{
    (void)u32InputMode;
    uint32_t u32Delay = SystemCoreClock; /* 1 second */

    g_EADC_i32ErrCode = 0;

    eadc->CTL |= EADC_CTL_ADCEN_Msk;

    /* Wait for EADC start up completely and ready for conversion */
    while ((eadc->PWRCTL & EADC_PWRCTL_READY_Msk) == 0)
    {
        if (--u32Delay == 0)
        {
            g_EADC_i32ErrCode = EADC_TIMEOUT_ERR;
            break;
        }
    }

}


/**
  * @brief Disable EADC_module.
  * @param[in] eadc The pointer of the specified EADC module.
  * @details Clear ADCEN bit (EADC_CTL[0]) to disable A/D converter analog circuit power consumption.
  */
void EADC_Close(EADC_T *eadc)
{
    eadc->CTL &= (~EADC_CTL_ADCEN_Msk);
}


/**
  * @brief Configure the sample control logic module.
  * @param[in] eadc The pointer of the specified EADC module.
  * @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 3.
  * @param[in] u32TriggerSrc Decides the trigger source. Valid values are:
  *                            - \ref EADC_SOFTWARE_TRIGGER              : Disable trigger
  *                            - \ref EADC_FALLING_EDGE_TRIGGER          : STADC pin falling edge trigger
  *                            - \ref EADC_RISING_EDGE_TRIGGER           : STADC pin rising edge trigger
  *                            - \ref EADC_FALLING_RISING_EDGE_TRIGGER   : STADC pin both falling and rising edge trigger
  *                            - \ref EADC_ADINT0_TRIGGER                : EADC ADINT0 interrupt EOC pulse trigger
  *                            - \ref EADC_ADINT1_TRIGGER                : EADC ADINT1 interrupt EOC pulse trigger
  *                            - \ref EADC_TIMER0_TRIGGER                : Timer0 overflow pulse trigger
  *                            - \ref EADC_TIMER1_TRIGGER                : Timer1 overflow pulse trigger
  *                            - \ref EADC_TIMER2_TRIGGER                : Timer2 overflow pulse trigger
  *                            - \ref EADC_TIMER3_TRIGGER                : Timer3 overflow pulse trigger
  *                            - \ref EADC_BPWM0TG_TRIGGER               : BPWM0TG trigger
  *                            - \ref EADC_BPWM1TG_TRIGGER               : BPWM1TG trigger
  * @param[in] u32Channel Specifies the sample module channel, valid value are from 0 to 7, 12 to 15.
  * @details Each of EADC control logic modules 0~3 which is configurable for EADC converter channel EADC_CH0~7, 12~15 and trigger source.
  *          Sample module 16~17 is fixed for EADC channel 16, 17 input sources as band-gap voltage, temperature sensor.
  */
void EADC_ConfigSampleModule(EADC_T *eadc, \
                             uint32_t u32ModuleNum, \
                             uint32_t u32TriggerSrc, \
                             uint32_t u32Channel)
{
    ((eadc->SCTL[u32ModuleNum])) &= (~(EADC_SCTL_EXTFEN_Msk | EADC_SCTL_EXTREN_Msk | EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk));
    ((eadc->SCTL[u32ModuleNum])) |= (u32TriggerSrc | u32Channel);
}


/**
  * @brief Set trigger delay time.
  * @param[in] eadc The pointer of the specified EADC module.
  * @param[in] u32ModuleNum Decides the sample module number, valid values are from 0 to 3.
  * @param[in] u32TriggerDelayTime Decides the trigger delay time, valid range are between 0~255.
  * @param[in] u32DelayClockDivider Decides the trigger delay clock divider. Valid values are:
  *                                 - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_1    : Trigger delay clock frequency is EADC_CLK/1
  *                                 - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_2    : Trigger delay clock frequency is EADC_CLK/2
  *                                 - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_4    : Trigger delay clock frequency is EADC_CLK/4
  *                                 - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_16   : Trigger delay clock frequency is EADC_CLK/16
  * @details User can configure the trigger delay time by setting TRGDLYCNT (EADC_SCTLn[15:8], n=0~15) and TRGDLYDIV (EADC_SCTLn[7:6], n=0~3).
  *         Trigger delay time = (u32TriggerDelayTime) x Trigger delay clock period.
  */
void EADC_SetTriggerDelayTime(EADC_T *eadc, \
                              uint32_t u32ModuleNum, \
                              uint32_t u32TriggerDelayTime, \
                              uint32_t u32DelayClockDivider)
{
    ((eadc->SCTL[u32ModuleNum])) &= (~(EADC_SCTL_TRGDLYDIV_Msk | EADC_SCTL_TRGDLYCNT_Msk));
    ((eadc->SCTL[u32ModuleNum])) |= ((u32TriggerDelayTime << EADC_SCTL_TRGDLYCNT_Pos) | u32DelayClockDivider);
}


/**
  * @brief Set EADC extend sample time.
  * @param[in] eadc The pointer of the specified EADC module.
  * @param[in] u32ModuleNum Decides the sample module number, valid values are from 0 to 3, 16, 17.
  * @param[in] u32ExtendSampleTime Decides the extend sampling time, the range is from 0~255 EADC clock. Valid value are from 0 to 255.
  * @details When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough
  *         if the analog channel has heavy loading to cause fully charge time is longer.
  *         User can extend A/D sampling time after trigger source is coming to get enough sampling time.
  */
void EADC_SetExtendSampleTime(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime)
{
    if (u32ModuleNum < 16)
    {
        ((eadc->SCTL[u32ModuleNum])) &= (~EADC_SCTL_EXTSMPT_Msk);
        ((eadc->SCTL[u32ModuleNum])) |= (u32ExtendSampleTime << EADC_SCTL_EXTSMPT_Pos);
    }
    else
    {
        ((eadc->SCTL0[u32ModuleNum - 16])) &= (~EADC_SCTL0_EXTSMPT_Msk);
        ((eadc->SCTL0[u32ModuleNum - 16])) |= (u32ExtendSampleTime << EADC_SCTL0_EXTSMPT_Pos);
    }
}

/** @} end of group EADC_EXPORTED_FUNCTIONS */

/** @} end of group EADC_Driver */

/** @} end of group Standard_Driver */
