/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

#ifndef _ADC_DRV_H_
#define _ADC_DRV_H_

/*! \brief Contains public interface to various functions related
 *         to the driver of ADC (Analog-to-digital conversion)
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include <stdint.h>
#include <stdbool.h>
#include "../CVM012x_features.h"

/*! \addtogroup adc_drv
 *  @{
 */

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/
#define ADCDRV_CHANNEL_NUM (24)

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

#if FEATURE_ADC_SWTRG_ON == 1
/*! \brief ADC type of conversion trigger selection
 */
typedef enum
{
    ADCDRV_SW_TRIGGER = 0x0U, /*!< Conversion trigger select software trigger.*/
    ADCDRV_HW_TRIGGER = 0x1U, /*!< Conversion trigger select hardware trigger.*/
} AdcDrv_TrgMode;
#endif

/*! \brief ADC type of ADC arbitration
 * decide the priority of general ADC and touch request
 */
typedef enum
{
    ADCDRV_ARBTYPE_GENERAL_PRIORITY = 0x0U, /*!< General ADC request has the priority to use ADC_CTRL.*/
    ADCDRV_ARBTYPE_TOUCH_PRIORITY   = 0x1U, /*!< Touch request has the priority to use ADC_CTRL.*/
} AdcDrv_ArbType;

/*! \brief ADC type of hardware average times selection
 */
typedef enum
{
    ADCDRV_AVERAGE_4  = 0x0U, /*!< Hardware average of 4 samples.*/
    ADCDRV_AVERAGE_8  = 0x1U, /*!< Hardware average of 8 samples.*/
    ADCDRV_AVERAGE_16 = 0x2U, /*!< Hardware average of 16 samples.*/
    ADCDRV_AVERAGE_32 = 0x3U, /*!< Hardware average of 32 samples.*/
} AdcDrv_AverageMode;

/*! \brief ADC type of self-test channel selection
 */
typedef enum
{
    ADCDRV_SELF_TEST_VALUE_AVSS              = 0x0U, /*!< ADC self-test channel select AVSS.*/
    ADCDRV_SELF_TEST_VALUE_ONE_EIGHTH_AVSS   = 0x1U, /*!< ADC self-test channel select 1/8*VREF.*/
    ADCDRV_SELF_TEST_VALUE_HALF_AVSS         = 0x2U, /*!< ADC self-test channel select 1/2*VREF.*/
    ADCDRV_SELF_TEST_VALUE_SEVEN_EIGHTH_AVSS = 0x3U, /*!< ADC self-test channel select 7/8*VREF.*/

} AdcDrv_SelfTestValue;

/*! \brief ADC type of resolution selection
 */
typedef enum
{
    ADCDRV_CONVERSION_8BIT    = 0x0U, /*!< Selects the ADC resolution to 8-bit conversion.*/
    ADCDRV_CONVERSION_10BIT   = 0x2U, /*!< Selects the ADC resolution to 10-bit conversion.*/
} AdcDrv_ConversionMode;

/*! \brief ADC type of compare mode
 */
typedef enum
{
    ADCDRV_CMPMODE_NO_COMPARE                 = 0x0U, /*!< ADC disable compare function.*/
    ADCDRV_CMPMODE_LESSTHAN                   = 0x1U, /*!< Automatic compare with interrupt for less-than.*/
    ADCDRV_CMPMODE_GREATER_OR_EQUTHAN         = 0x2U, /*!< Automatic compare with interrupt for greater-than or equal-to.*/
    ADCDRV_CMPMODE_OUTSIDE_EXCLUDE_BOUNDARIES = 0x3U, /*!< Automatic compare with interrupt for out-of-range(Does not contain boundaries).*/
    ADCDRV_CMPMODE_INSIDE_EXCLUDE_BOUNDARIES  = 0x4U, /*!< Automatic compare with interrupt for within range(Does not contain boundaries).*/
    ADCDRV_CMPMODE_INSIDE_INCLUDE_BOUNDARIES  = 0x5U, /*!< Automatic compare with interrupt for within range(Contain boundaries).*/
    ADCDRV_CMPMODE_OUTSIDE_INCLUDE_BOUNDARIES = 0x6U, /*!< Automatic compare with interrupt for out-of-range range(Contain boundaries).*/
} AdcDrv_CmpMode;

/*! \brief ADC type of input channel selection.
 */
typedef enum
{
    ADCDRV_PCH_TK_ADC00            = 0x0U,  /*!< TK_ADC00.*/
    ADCDRV_PCH_TK_ADC01            = 0x1U,  /*!< TK_ADC01.*/
    ADCDRV_PCH_TK_ADC02            = 0x2U,  /*!< TK_ADC02.*/
    ADCDRV_PCH_TK_ADC03            = 0x3U,  /*!< TK_ADC03.*/
    ADCDRV_PCH_TK_ADC04            = 0x4U,  /*!< TK_ADC04.*/
    ADCDRV_PCH_TK_ADC05            = 0x5U,  /*!< TK_ADC05.*/
    ADCDRV_PCH_TK_ADC06            = 0x6U,  /*!< TK_ADC06.*/
    ADCDRV_PCH_TK_ADC07            = 0x7U,  /*!< TK_ADC07.*/
    ADCDRV_PCH_TK_ADC08            = 0x8U,  /*!< TK_ADC08.*/
    ADCDRV_PCH_TK_ADC09            = 0x9U,  /*!< TK_ADC09.*/
    ADCDRV_PCH_TK_ADC10            = 0xAU,  /*!< TK_ADC10.*/
    ADCDRV_PCH_TK_ADC11            = 0xBU,  /*!< TK_ADC11.*/
    ADCDRV_PCH_TK_ADC12            = 0xCU,  /*!< TK_ADC12.*/
    ADCDRV_PCH_TK_ADC13            = 0xDU,  /*!< TK_ADC13.*/
    ADCDRV_PCH_TK_ADC14            = 0xEU,  /*!< TK_ADC14.*/
    ADCDRV_PCH_TK_ADC15            = 0xFU,  /*!< TK_ADC15.*/
    ADCDRV_PCH_TK_ADC16            = 0x10U, /*!< TK_ADC16.*/
    ADCDRV_PCH_TK_ADC17            = 0x11U, /*!< TK_ADC17.*/
    ADCDRV_PCH_TK_ADC18            = 0x12U, /*!< TK_ADC18.*/
    ADCDRV_PCH_TK_ADC19            = 0x13U, /*!< TK_ADC19.*/
    ADCDRV_PCH_TK_ADC20            = 0x14U, /*!< TK_ADC20.*/
    ADCDRV_PCH_TK_ADC21            = 0x15U, /*!< TK_ADC21.*/
    ADCDRV_PCH_TK_ADC22            = 0x16U, /*!< TK_ADC22.*/
    ADCDRV_PCH_TK_ADC23            = 0x17U, /*!< TK_ADC23.*/
    ADCDRV_PCH_TK_ADC24            = 0x18U, /*!< TK_ADC24.*/
    ADCDRV_PCH_TK_ADC25            = 0x19U, /*!< TK_ADC25.*/
    ADCDRV_PCH_TK_ADC26            = 0x1AU, /*!< TK_ADC26.*/
    ADCDRV_PCH_TK_ADC27            = 0x1BU, /*!< TK_ADC27.*/
    ADCDRV_PCH_TK_ADC28            = 0x1CU, /*!< TK_ADC28.*/
    ADCDRV_PCH_TK_ADC29            = 0x1DU, /*!< TK_ADC29.*/
    ADCDRV_PCH_BANDGAP_VOLTAGE     = 0x1EU, /*!< inner Bandgap voltage.*/
    ADCDRV_PCH_SELF_TEST_VOLTAGE   = 0x20U, /*!< inner self test voltage.*/
    ADCDRV_PCH_CLOSE               = 0X3F,  /*!< close*/
} AdcDrv_PchType;

/*! \brief ADC type of continuous conversion mode selection.
 */
typedef enum
{
    ADCDRV_ONESHOT     = 0x0U, /*!< One conversion will be performed (or one set of conversions, if AVGE is set) after a conversion is initiated.*/
    ADCDRV_CONTINUOUS  = 0x1U, /*!< Continuous conversions will be performed (or continuous sets of conversions, if AVGE is set) after a conversion is initiated.*/
} AdcDrv_ContinuousMode;

/*! \brief ADC type of hardware trigger source selection.
 */
typedef enum
{
    ADCDRV_HW_TRGSRC_PDB    = 0x0U, /*!< Select PDB output for trigger source.*/
    ADCDRV_HW_TRGSRC_TRGMUX = 0x1U, /*!< Select TRGMUX output output for trigger source.*/
} AdcDrv_HwTrgSrc;

/*! \brief ADC type of software pretrigger source selection.
 */
typedef enum
{
    ADCDRV_SWPRETRG_PRETRIGGER_0 = 0x4U, /*!< Select PRETRIGGER_0 for software pretrigger sources.*/
    ADCDRV_SWPRETRG_PRETRIGGER_1 = 0x5U, /*!< Select PRETRIGGER_1 for software pretrigger sources.*/
    ADCDRV_SWPRETRG_PRETRIGGER_2 = 0x6U, /*!< Select PRETRIGGER_2 for software pretrigger sources.*/
    ADCDRV_SWPRETRG_PRETRIGGER_3 = 0x7U, /*!< Select PRETRIGGER_3 for software pretrigger sources.*/
} ADCDRV_SwPretrgSrc;

/*! \brief ADC type of hardware pretrigger source selection.
 */
typedef enum
{
    ADCDRV_PRETRG_PDB_PRETRIGGER      = 0x0U, /*!< Select PDB pretrigger for ADC pretrigger sources.*/
    ADCDRV_PRETRG_TRGMUX_PRETRIGGER   = 0x1U, /*!< Select TRGMUX pretrigger for ADC pretrigger sources.*/
    ADCDRV_PRETRG_SOFTWARE_PRETRIGGER = 0x2U, /*!< Select SOFTWARE pretrigger for ADC pretrigger sources.*/
    ADCDRV_PRETRG_NO_HW_PRETRIGGER    = 0x3U, /*!< Select no hardware trigger for ADC pretrigger sources.*/
} ADCDRV_PretrgSrc;

/*! \brief Definition of configuration of ADC trigger/pretrigger.
 */
typedef struct _AdcDrv_TrgSrcCfgType_
{
#if FEATURE_ADC_SWTRG_ON == 1
    AdcDrv_TrgMode     trgSrc;      /*!< Conversion trigger select*/
#endif
    AdcDrv_HwTrgSrc    hwTrgSrc;    /*!< Selects hardware trigger source for ADC.*/
    ADCDRV_SwPretrgSrc swPretrgSrc; /*!< Selects software pretrigger sources for ADC*/
    ADCDRV_PretrgSrc   pretrgSrc;   /*!< Selects pretrigger sources for ADC*/
} AdcDrv_TrgSrcCfgType;

/*! \brief Definition of configuration of ADC channel
 */
typedef struct _AdcDrv_ChnCfgType_
{
    AdcDrv_PchType pCh;       /*!< ADC Pchannel selection.*/
    bool           intEnable; /*!< Interrupt enable.*/
} AdcDrv_ChnCfgType;

/*! \brief Definition of configuration of ADC compare function
 */
typedef struct _AdcDrv_CmpCfgType_
{
    uint16_t       lowerLim; /*!< Lower limiting value in ADC compare function.*/
    uint16_t       upperLim; /*!< Upper limiting value in ADC compare function.*/
    AdcDrv_CmpMode cmpMode;  /*!< Select compare mode.*/
} AdcDrv_CmpCfgType;

/*! \brief Definition of configuration of ADC driver
 */
typedef struct _AdcDrv_ConfigType_
{
    AdcDrv_ConversionMode conversionMode;             /*!< Conversion mode select.*/
    uint8_t               sampleLen;                  /*!< ADC sampling time.*/
    uint8_t               firstSampleLen;             /*!< First sample delay time.*/
    uint8_t               pwrOnLen;                   /*!< Power on sample delay time.*/
    bool                  dmaEn;                      /*!< DMA enable.*/
    AdcDrv_CmpCfgType     cmpCfg;                     /*!< Compare function configuration*/
    AdcDrv_ContinuousMode continuousMode;             /*!< Switch continuous conversion enable*/
    AdcDrv_AverageMode    avgSamplesSel;              /*!< Hardware average select*/
    bool                  avgEnable;                  /*!< Switch hardware average enable*/
    AdcDrv_ArbType        arbType;                    /*!< Decide the priority of general ADC and touch request*/
    AdcDrv_ChnCfgType     chnCfg[ADCDRV_CHANNEL_NUM]; /*!< ADC channel configuration*/
    AdcDrv_TrgSrcCfgType  trgSrcCfg;                  /*!< ADC trigger source configuration*/
} AdcDrv_ConfigType;

/* Forward declaration of ADC register */
struct _AdcRegType_;

/* Forward declaration of SIm register */
struct _Scg0RegType_;

/*! \brief The definition of ADC driver class
 */
typedef struct _AdcDrvType_
{
    struct _AdcRegType_  *adcReg;
    struct _Scg0RegType_ *scg0Reg;
} AdcDrvType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/

/*! \brief Initializes the ADC driver module
 *
 * This function initializes ADC driver by setting the register
 * instance to it.
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] pdbReg : pointer to ADC register instance
 * \param[in] scg0Reg : pointer to SIM register instance
 * \param[in] initParams : pointer to ADC initialization parameters
 */
extern void AdcDrv_Init(AdcDrvType *obj, struct _AdcRegType_ *adcReg, struct _Scg0RegType_ *scg0Reg);

/*! \brief Get default configures the ADC module for configuration structure
 *
 * This function gets default configures the ADC module for user configuration structure
 *
 * \param[out] userConfig : pointer to configuration structure
 */
extern void AdcDrv_GetDefaultConfig(AdcDrv_ConfigType *userConfig);

/*! \brief Configures the ADC module from a user configuration structure
 *
 * This function configures the ADC module from a user configuration structure
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] userConfig : pointer to configuration structure
 */
extern void AdcDrv_Configure(AdcDrvType *obj, const AdcDrv_ConfigType *userConfig);

/*! \brief Get configures of the ADC module
 *
 * This function get configures of the ADC module
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[out] currentConfig : pointer to configuration structure
 */
extern void AdcDrv_GetConfig(AdcDrvType *obj, AdcDrv_ConfigType *currentConfig);

/*! \brief ADC clear lock trigger
 *
 * This function for ADC clear lock trigger
 *
 * \param[in] obj : pointer to ADC driver instance
 */
extern void AdcDrv_ClrLockTrg(AdcDrvType *obj);

/*! \brief Get ADC data result
 *
 * This function for get ADC data result
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] chn  : channel number
 * \return ADC data result.
 */
extern uint16_t AdcDrv_GetRn(AdcDrvType *obj, uint8_t chn);

/*! \brief Get ADC conversion complete flag
 *
 * This function for get ADC conversion complete flag.
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] chn  : channel number
 * \return ADC data result.
 */
extern bool AdcDrv_GetCocon(AdcDrvType *obj, uint8_t chn);

/*! \brief Disable ADC
 *
 * This function for disable ADC
 *
 * \param[in] obj : pointer to ADC driver instance
 */
extern void AdcDrv_DisableAdc(AdcDrvType *obj);

/*! \brief Enable ADC
 *
 * This function for enable ADC
 *
 * \param[in] obj : pointer to ADC driver instance
 */
extern void AdcDrv_EnableAdc(AdcDrvType *obj);

/*! \brief Abort ADC channel n
 *
 * This function for abort ADC channel n
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] chn  : channel number
 */
extern void AdcDrv_AbortChn(AdcDrvType *obj, uint8_t chn);

/*! \brief Selects one of the input channels.
 *
 * This function for selects one of the input channels.
 *
 * \param[in] obj   : pointer to ADC driver instance
 * \param[in] chn   : channel number
 * \param[in] state : input channel selection.
 */
extern void AdcDrv_ConfigurePchn(AdcDrvType *obj, uint8_t chn, AdcDrv_PchType state);

/*! \brief Get error in Multiplexed Trigger Request.
 *
 * This function for getting error in Multiplexed Trigger Request.
 *
 * \param[in] obj : pointer to ADC driver instance
 * \return ADC error in Multiplexed Trigger Request.
 * -bit0 : corresponds to trigger request 0
 * -bit1 : corresponds to trigger request 1
 * -bit2 : corresponds to trigger request 2
 * -bit3 : corresponds to trigger request 3
 * each bit as follows
 * 0b: No error has occurred
 * 1b: An error has occurred
 */
extern uint8_t AdcDrv_GetTrgErr(AdcDrvType *obj);

/*! \brief Clean all error in Multiplexed Trigger Request.
 *
 * This function for cleaning all error in Multiplexed Trigger Request.
 *
 * \param[in] obj : pointer to ADC driver instance
 */
extern void AdcDrv_ClrTrgErr(AdcDrvType *obj);

/*! \brief Get trigger Status.
 *
 * This function for getting trigger Status.
 *
 * \param[in] obj : pointer to ADC driver instance
 * \return ADC error in Multiplexed Trigger Request.
 * -bit0 : corresponds to trigger request 0
 * -bit1 : corresponds to trigger request 1
 * -bit2 : corresponds to trigger request 2
 * -bit3 : corresponds to trigger request 3
 * each bit as follows
 * 0b: No trigger request has been latched
 * 1b:  A trigger request has been latched
 */
extern uint8_t AdcDrv_GetTrgSt(AdcDrvType *obj);

/*! \brief Get Trigger Process Number.
 *
 * This function for getting trigger Process Number.
 *
 * \param[in] obj : pointer to ADC driver instance
 * \return trigger process number.
 * 00b: corresponds to trigger request 0
 * 01b: corresponds to trigger request 1
 * 10b: corresponds to trigger request 2
 * 11b: corresponds to trigger request 3
 */
extern uint8_t AdcDrv_GetTrgPrNum(AdcDrvType *obj);

/*! \brief Set the priority of general ADC and touch request
 *
 * This function for setting the priority of general ADC and touch request
 *
 * \param[in] obj : pointer to ADC driver instance
 * \param[in] arbType : priority of general ADC and touch request
 */
extern void AdcDrv_SetArb(AdcDrvType *obj,const AdcDrv_ArbType arbType);

#if FEATURE_ADC_SWTRG_ON == 1
/*! \brief ADC software trigger
 *
 * This function for ADC clear lock trigger
 *
 * \param[in] obj : pointer to ADC driver instance
 */
extern void AdcDrv_SwTrg(AdcDrvType *obj);
#endif

#ifdef __cplusplus
}
#endif /* extern "C" */

/*! @}*/

#endif /* _ADC_DRV_H_ */
