/*
 * Copyright 2020-2022 Yuntu Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef eADC_DRIVER_H
#define eADC_DRIVER_H

#include <stdint.h>
#include <stdbool.h>
#include "device_registers.h"

/*! 
 * @file eadc_driver.h
 */

/*!
 * @addtogroup eadc_driver
 * @{
 */

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*!
 * @brief Conversion resolution selection
 *
 * Implements : eadc_resolution_t_Class
 */
typedef enum
{
    eADC_RESOLUTION_12BIT = 0x00U,   /*!< 12-bit resolution mode */
    eADC_RESOLUTION_10BIT = 0x01U,   /*!< 10-bit resolution mode */
    eADC_RESOLUTION_8BIT = 0x02U,    /*!<  8-bit resolution mode */
    eADC_RESOLUTION_6BIT = 0x03U     /*!<  6-bit resolution mode */
} eadc_resolution_t;

/*!
 * @brief Result alignment type selection
 *
 * Implements : eadc_align_t_Class
 */
typedef enum
{
    eADC_ALIGN_RIGHT = 0x00U,   /*!< Right alignment. */
    eADC_ALIGN_LEFT = 0x01U,    /*!< Left alignment. */
} eadc_align_t;

/*!
 * @brief Sequence max length configuration
 *
 * Implements : eadc_sequence_length_t_Class
 */
typedef enum
{
    eADC_SEQ0_15_SEQ1_1 = 0x00U,     /*!< Sequence 0 length 15, and sequence 1 length 1 */
    eADC_SEQ0_2_SEQ1_14 = 0x01U,     /*!< Sequence 0 length 2, and sequence 1 length 14 */
    eADC_SEQ0_4_SEQ1_12 = 0x02U,     /*!< Sequence 0 length 4, and sequence 1 length 12 */
    eADC_SEQ0_8_SEQ1_8 = 0x03U,      /*!< Sequence 0 length 8, and sequence 1 length 8 */
} eadc_sequence_length_t;

/*!
 * @brief High priority sequence select configuration
 *
 * Implements : eadc_high_priority_sequence_select_t_Class
 */
typedef enum
{
    eADC_SEQ0_AS_HIGH_PRIORITY_SEQ = 0x00U,   /*!< Sequence 0 for high priority, sequence 1 for low priority */
    eADC_SEQ1_AS_HIGH_PRIORITY_SEQ = 0x01U,   /*!< Sequence 1 for high priority, sequence 0 for low priority */
} eadc_high_priority_sequence_select_t;

/*!
 * @brief Sequence mode selection
 *
 * Implements : eadc_sequence_mode_t_Class
 */
typedef enum
{
    eADC_CONV_HIGH_PRIORITY_LOOP_LOW_PRIORITY_LOOP = 0x00U,       /*!< HIGH_PRIORITY one loop convert per trigger, 
                                                                      LOW_PRIORITY one loop convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_LOOP_LOW_PRIORITY_CONTINUOUS = 0x01U, /*!< HIGH_PRIORITY one loop convert per trigger, 
                                                                      LOW_PRIORITY continuous convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_LOOP_LOW_PRIORITY_STEP = 0x02U,       /*!< HIGH_PRIORITY one loop convert per trigger, 
                                                                      LOW_PRIORITY one channel convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_STEP_LOW_PRIORITY_LOOP = 0x03U,       /*!< HIGH_PRIORITY one channel convert per trigger, 
                                                                      LOW_PRIORITY one loop convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_CONTINUOUS_LOW_PRIORITY_LOOP = 0x04U, /*!< HIGH_PRIORITY continuous convert per trigger, 
                                                                      LOW_PRIORITY one loop convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_STEP_LOW_PRIORITY_STEP = 0x05U,       /*!< HIGH_PRIORITY one channel convert per trigger, 
                                                                      LOW_PRIORITY one channel convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_CONTINUOUS_LOW_PRIORITY_STEP = 0x06U, /*!< HIGH_PRIORITY continuous convert per trigger, 
                                                                      LOW_PRIORITY one channel convert per trigger. */
    eADC_CONV_HIGH_PRIORITY_STEP_LOW_PRIORITY_CONTINUOUS = 0x07U, /*!< HIGH_PRIORITY one channel convert per trigger, 
                                                                      LOW_PRIORITY continuous convert per trigger. */
} eadc_sequence_mode_t;

/*!
 * @brief Enumeration of input channels assignable to a control channel.
 *
 * Implements : eadc_inputchannel_t_Class
 */
typedef enum
{
    eADC_INPUTCHAN_EXT0 = 0x00U,               /*!< External input channel 0 */
    eADC_INPUTCHAN_EXT1 = 0x01U,               /*!< External input channel 1 */
    eADC_INPUTCHAN_EXT2 = 0x02U,               /*!< External input channel 2 */
    eADC_INPUTCHAN_EXT3 = 0x03U,               /*!< External input channel 3 */
    eADC_INPUTCHAN_EXT4 = 0x04U,               /*!< External input channel 4 */
    eADC_INPUTCHAN_EXT5 = 0x05U,               /*!< External input channel 5 */
    eADC_INPUTCHAN_EXT6 = 0x06U,               /*!< External input channel 6 */
    eADC_INPUTCHAN_EXT7 = 0x07U,               /*!< External input channel 7 */
    eADC_INPUTCHAN_EXT8 = 0x08U,               /*!< External input channel 8 */
    eADC_INPUTCHAN_EXT9 = 0x09U,               /*!< External input channel 9 */
    eADC_INPUTCHAN_EXT10 = 0x0AU,              /*!< External input channel 10 */
    eADC_INPUTCHAN_EXT11 = 0x0BU,              /*!< External input channel 11 */
    eADC_INPUTCHAN_EXT12 = 0x0CU,              /*!< External input channel 12 */
    eADC_INPUTCHAN_EXT13 = 0x0DU,              /*!< External input channel 13 */
    eADC_INPUTCHAN_EXT14 = 0x0EU,              /*!< External input channel 14 */
    eADC_INPUTCHAN_EXT15 = 0x0FU,              /*!< External input channel 15 */
#if (FEATURE_eADC_MAX_NUM_EXT_CHANS > 16)
    eADC_INPUTCHAN_EXT16 = 0x10U,              /*!< External input channel 16 */
    eADC_INPUTCHAN_EXT17 = 0x11U,              /*!< External input channel 17 */
    eADC_INPUTCHAN_EXT18 = 0x12U,              /*!< External input channel 18 */
    eADC_INPUTCHAN_EXT19 = 0x13U,              /*!< External input channel 19 */
    eADC_INPUTCHAN_EXT20 = 0x14U,              /*!< External input channel 20 */
    eADC_INPUTCHAN_EXT21 = 0x15U,              /*!< External input channel 21 */
    eADC_INPUTCHAN_EXT22 = 0x16U,              /*!< External input channel 22 */
    eADC_INPUTCHAN_EXT23 = 0x17U,              /*!< External input channel 23 */
 #endif
#if (FEATURE_eADC_MAX_NUM_EXT_CHANS > 24)
    eADC_INPUTCHAN_EXT24 = 0x18U,              /*!< External input channel 24 */
    eADC_INPUTCHAN_EXT25 = 0x19U,              /*!< External input channel 25 */
    eADC_INPUTCHAN_EXT26 = 0x1AU,              /*!< External input channel 26 */
    eADC_INPUTCHAN_EXT27 = 0x1BU,              /*!< External input channel 27 */
    eADC_INPUTCHAN_EXT28 = 0x1CU,              /*!< External input channel 28 */
    eADC_INPUTCHAN_EXT29 = 0x1DU,              /*!< External input channel 29 */
    eADC_INPUTCHAN_EXT30 = 0x1EU,              /*!< External input channel 30 */
    eADC_INPUTCHAN_EXT31 = 0x1FU,              /*!< External input channel 31 */
#endif
#if (FEATURE_eADC_MAX_NUM_EXT_CHANS > 32)
    eADC_INPUTCHAN_EXT32 = 0x20U,              /*!< External input channel 32 */
    eADC_INPUTCHAN_EXT33 = 0x21U,              /*!< External input channel 33 */
    eADC_INPUTCHAN_EXT34 = 0x22U,              /*!< External input channel 34 */
    eADC_INPUTCHAN_EXT35 = 0x23U,              /*!< External input channel 35 */
    eADC_INPUTCHAN_EXT36 = 0x24U,              /*!< External input channel 36 */
    eADC_INPUTCHAN_EXT37 = 0x25U,              /*!< External input channel 37 */
    eADC_INPUTCHAN_EXT38 = 0x26U,              /*!< External input channel 38 */
    eADC_INPUTCHAN_EXT39 = 0x27U,              /*!< External input channel 39 */
#endif
#if (FEATURE_eADC_MAX_NUM_EXT_CHANS > 40)
    eADC_INPUTCHAN_EXT40 = 0x28U,              /*!< External input channel 40 */
    eADC_INPUTCHAN_EXT41 = 0x29U,              /*!< External input channel 41 */
    eADC_INPUTCHAN_EXT42 = 0x2AU,              /*!< External input channel 42 */
    eADC_INPUTCHAN_EXT43 = 0x2BU,              /*!< External input channel 43 */
    eADC_INPUTCHAN_EXT44 = 0x2CU,              /*!< External input channel 44 */
    eADC_INPUTCHAN_EXT45 = 0x2DU,              /*!< External input channel 45 */
    eADC_INPUTCHAN_EXT46 = 0x2EU,              /*!< External input channel 46 */
    eADC_INPUTCHAN_EXT47 = 0x2FU,              /*!< External input channel 47 */
#endif 
} eadc_inputchannel_t;

/*!
 * @brief Enumeration of overflow mode select.
 *
 * Implements : eadc_overflow_select_t_Class
 */
typedef enum
{
    eADC_OVERFLOW_COVER_DATA = 0x00U,    /*!< Cover current channel data when overflow */
    eADC_OVERFLOW_KEEP_DATA = 0x01U,     /*!< Keep current channel data when overflow */
} eadc_overflow_select_t;

/*!
 * @brief Enumeration of sample time select.
 *
 * Implements : eadc_sample_time_select_t_Class
 */
typedef enum
{
    eADC_CHANNEL_SELECT_SMP0 = 0x00U,    /*!< eADC channel select SMP0 as sample time */
    eADC_CHANNEL_SELECT_SMP1 = 0x01U,    /*!< eADC channel select SMP1 as sample time */
} eadc_sample_time_select_t;

/*!
 * @brief Enumeration of sample average select.
 *
 * Implements : eadc_sample_average_t_Class
 */
typedef enum
{
    eADC_RESULT_NO_AVERAGE = 0x00U,      /*!< No sample averaging */
    eADC_RESULT_WITH_2_AVERAGE = 0x01U,  /*!< The results of the 2 conversions are averaged */
    eADC_RESULT_WITH_4_AVERAGE = 0x02U,  /*!< The results of the 4 conversions are averaged */
    eADC_RESULT_WITH_8_AVERAGE = 0x03U,  /*!< The results of the 8 conversions are averaged */
    eADC_RESULT_WITH_16_AVERAGE = 0x04U, /*!< The results of the 16 conversions are averaged */
    eADC_RESULT_WITH_32_AVERAGE = 0x05U, /*!< The results of the 32 conversions are averaged */
} eadc_sample_average_t;

/*!
 * @brief Defines the channel configuration
 *
 * This structure is used to configure the input channel feature for eADC.
 *
 * Implements : eadc_inputchannel_config_t_Class
 */
typedef struct
{
    eadc_inputchannel_t channel;             /*!< eADC input channel */
    eadc_sample_time_select_t sampleSelect;  /*!< Sample time select, SMP0 or SMP1 */
    eadc_overflow_select_t overflowMode;     /*!< eADC overflow mode select */
} eadc_inputchannel_config_t;

/*!
 * @brief Defines the channel sequence conversion configuration
 *
 * This structure is used to configure the high or low priority sequence conversion
 * feature for the eADC
 *
 * Implements : eadc_sequence_t_Class
 */
typedef struct
{
    eadc_inputchannel_config_t channels[eADC_CHSEL_COUNT];  /*!< Sequence of channels */
    uint8_t totalChannels;                                 /*!< Total channels count sequence */
    bool sequenceIntEnable;                                /*!< Sequence end interrupt enable */
    bool dmaEnable;                                        /*!< Sequence DMA enable */
} eadc_sequence_t;

/*!
 * @brief Defines the sequence conversion configuration
 *
 * This structure is used to configure the sequence conversion
 * feature for the eADC
 *
 * Implements : eadc_sequence_config_t_Class
 */
typedef struct
{
    eadc_high_priority_sequence_select_t highSelect; /*!< Select SEQ0 or SEQ1 as high priority sequence */
    eadc_sequence_length_t seqLengthMax;             /*!< Determine sequence max length */
    eadc_sequence_mode_t sequenceMode;               /*!< Sequence mode of conversion */
    eadc_sequence_t highPrioSequence;                /*!< High priority sequence for eADC conversion */
    bool swTriggerEnable;                           /*!< Software trigger low priority sequence enable */
    eadc_sequence_t lowPrioSequence;                 /*!< Low priority sequence for eADC conversion */
} eadc_sequence_config_t;

typedef uint8_t eadc_clk_divide_t;

/*!
 * @brief AWG effective type selection
 *
 * Implements : eadc_awg_effective_mode_t_Class
 */
typedef enum
{
    eADC_AWG_EFFECTIVE_OUTSIDE = 0x00U,   /*!< Effective outside. */
    eADC_AWG_EFFECTIVE_INSIDE = 0x01U     /*!< Effective inside. */
} eadc_awg_effective_mode_t;

/*!
 * @brief Defines the hardware compare configuration
 *
 * This structure is used to configure the hardware compare
 * feature for the eADC
 *
 * Implements : eadc_compare_config_t_Class
 */
typedef struct
{
    uint8_t comWdchIndex;                   /*!< The index of watch dog configuration */
    bool compareEnable;                     /*!< Enable the compare feature */
    bool compareAllChannelEnable;           /*!< Enable all channel compare */
    eadc_inputchannel_t compChalSel;         /*!< Compare channel when AWDG on a single channel */
    uint16_t compHigh;                      /*!< First Compare Value */
    uint16_t compLow;                       /*!< Second Compare Value */
    eadc_awg_effective_mode_t effectiveMode; /*!< Watch Dog Effective Mode Selection */
} eadc_compare_config_t;

/*!
 * @brief Defines the converter configuration
 *
 * This structure is used to configure the eADC converter
 *
 * Implements : eadc_converter_config_t_Class
 */
typedef struct
{
    eadc_clk_divide_t clockDivider;           /*!< Divider of the input clock for the eADC */
    uint8_t startTime;                       /*!< eADC startup time in AD Clocks */
    uint8_t sampleTime0;                     /*!< Sample time 0 in AD Clocks */
    uint8_t sampleTime1;                     /*!< Sample time 1 in AD Clocks */
    eadc_sample_average_t sampleAverage;      /*!< eADC sampling average select */
    uint8_t switchChannelCnt;                /*!< eADC switch channel counter */

    bool convIntEnable;                      /*!< Conversion end interrupt enable */
    bool ovrunIntEnable;                     /*!< Overrun interrupt enable */
    bool sampIntEnable;                      /*!< Sample end interrupt enable */
    bool readyIntEnable;                     /*!< Ready interrupt enable */
    bool lowerTriggerErrorEnable;            /*!< Low priority trigger error interrupt enable */
    bool normalErrorEnable;                  /*!< Normal error interrupt enabled */

    bool autoOffEnable;                      /*!< Auto-off mode */
    bool lowPowerEnable;                     /*!< Keep working in low power enable */
    bool overrideGenDMAReq;                  /*!< Generate DMA request when override event */        
    eadc_align_t align;                       /*!< eADC alignment */
    eadc_resolution_t resolution;             /*!< eADC resolution (8,10,12 bit) */

    eadc_sequence_config_t seqConfig;         /*!< eADC Sequence configuration */

    uint8_t eadcCompareCnt;                   /*!< The count of eADC hardware compare configuration */
    bool compIntEnable;                      /*!< Watch Dog Interrupt Enable */
    eadc_compare_config_t* compareConfig;     /*!< eADC hardware compare configuration */
} eadc_converter_config_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined (__cplusplus)
extern "C" {
#endif

/*!
 * @name Converter
 */
/*! @{*/


/*!
 * @brief Configures the converter with the given configuration structure
 *
 * This function configures the eADC converter with the options
 * provided in the provided structure.
 *
 * @param[in] instance instance number
 * @param[in] config the configuration structure
 */
void eADC_DRV_ConfigConverter(const uint32_t instance,
                              const eadc_converter_config_t *const config);

/*!
 * @brief Start the converter
 *
 * This function start eADC conversion if and in software trigger mode or 
 * set eADC waiting for external trigger
 *
 * @param[in] instance instance number
 * @param[in] swTrigEnable check if need start software trigger
 */
void eADC_DRV_Start(const uint32_t instance, bool swTrigEnable);

/*!
 * @brief Stop the converter
 *
 * This function stop eADC conversion.
 *
 * @param[in] instance instance number
 */
void eADC_DRV_Stop(const uint32_t instance);

/*!
 * @brief Configures the Hardware Compare feature with the given configuration
 * structure
 *
 * This functions sets the configuration for the Hardware
 * Compare feature using the configuration structure.
 *
 * @param[in] instance instance number
 * @param[in] config pointer to the configuration structure
 * @param[in] count The count of eADC hardware compare configuration
 */
void eADC_DRV_ConfigHwCompareGroup(const uint32_t instance,
                                  eadc_compare_config_t *const config, 
                                  uint8_t count);

/*!
 * @brief Configures the sequence convert feature with the given configuration
 * structure
 *
 * This functions sets the configuration for the sequence
 * convert feature using the configuration structure.
 *
 * @param[in] instance instance number
 * @param[in] config the configuration structure
 */
void eADC_DRV_ConfigSequence(const uint32_t instance,
                             const eadc_sequence_config_t *const config);

/*!
 * @brief Gets the result from result FIFO
 *
 * This function returns the conversion result from FIFO
 *
 * @param[in] instance instance number
 * @return the result raw value
 */
uint16_t eADC_DRV_ReadFIFO(const uint32_t instance, uint8_t index);

/*!
 * @brief Gets End of High Priority Sequence Conversion Flag state
 *
 * This function returns the state of the EOSEQ Flag
 * This flag is set by hardware at the end of conversion of a sequence 
 * or the condition generated by the Hardware
 * Compare feature is evaluated to true.
 *
 * @param[in] instance instance number
 * @return the HEOSEQ Flag state
 */
bool eADC_DRV_GetEndOfHighSequenceFlag(const uint32_t instance);

/*!
 * @brief Gets End of Low Priority Sequence Conversion Flag state
 *
 * This function returns the state of the EOSEQ Flag
 * This flag is set by hardware at the end of conversion of a sequence 
 * or the condition generated by the Hardware
 * Compare feature is evaluated to true.
 *
 * @param[in] instance instance number
 * @return the LEOSEQ Flag state
 */
bool eADC_DRV_GetEndOfLowSequenceFlag(const uint32_t instance);

/*!
 * @brief Clear High Priority end of sequence flag
 *
 * This function is used to clear EOSEQ flag.
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearHighEoseqFlagCmd(const uint32_t instance);

/*!
 * @brief Clear Low Priority end of sequence flag
 *
 * This function is used to clear EOSEQ flag.
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearLowEoseqFlagCmd(const uint32_t instance);

/*!
 * @brief Get eADC ready flag
 *
 * This function is used to get ready flag.
 *
 * @param[in] instance instance number
 * @return the Ready Flag state 
 */
bool eADC_DRV_GetReadyFlag(const uint32_t instance);

/*!
 * @brief Clear eADC ready flag
 *
 * This function is used to clear ready flag.
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearReadyFlag(const uint32_t instance);

/*!
 * @brief Get eADC end of sample flag
 *
 * This function is used to get end of sample flag.
 *
 * @param[in] instance instance number
 * @return the End of Sample Flag state 
 */
bool eADC_DRV_GetEndOfSampleFlag(const uint32_t instance);

/*!
 * @brief Clear end of sample flag
 *
 * This function is used to clear end of sample flag
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearEndOfSampleFlag(const uint32_t instance);

/*!
 * @brief Get eADC end of convert flag
 *
 * This function is used to get end of convert flag.
 *
 * @param[in] instance instance number
 * @return the End of Convert Flag state 
 */
bool eADC_DRV_GetEndOfConvertFlag(const uint32_t instance);

/*!
 * @brief Clear end of convert flag
 *
 * This function is used to clear end of convert flag
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearEndOfConvertFlag(const uint32_t instance);

/*!
 * @brief Get eADC normal error flag
 *
 * This function is used to get normal error flag.
 *
 * @param[in] instance instance number
 * @return the Normal Error Flag state 
 */
bool eADC_DRV_GetNormalErrorFlag(const uint32_t instance);

/*!
 * @brief Clear normal error flag
 *
 * This function is used to clear normal error flag
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearNormalErrorFlag(const uint32_t instance);

/*!
 * @brief Get eADC low priority trigger missing flag.
 *
 * This function is used to get low priority trigger missing flag.
 *
 * @param[in] instance instance number
 * @return the Low Priority Trigger Missing state 
 */
bool eADC_DRV_GetLowPrioTriggerErrorFlag(const uint32_t instance);

/*!
 * @brief Clear low priority trigger missing flag.
 *
 * This function is used to clear low priority trigger missing flag.
 *
 * @param[in] instance instance number
 */
void eADC_DRV_ClearLowPrioTriggerErrorFlag(const uint32_t instance);

/*!
 * @brief Get eADC overrun flag.
 *
 * This function is used to get overrun flag.
 *
 * @param[in] instance instance number
 * @param[in] channelIndex channel index 0 ~ 16
 * @return the Overrun state 
 */
bool eADC_DRV_GetChannelOverrunFlag(const uint32_t instance, uint8_t channelIndex);

/*!
 * @brief Clear overrun flag.
 *
 * This function is used to clear overrun flag.
 *
 * @param[in] instance instance number
 * @param[in] channelIndex channel index 0 ~ 16
 */
void eADC_DRV_ClearChannelOverrunFlag(const uint32_t instance, uint8_t channelIndex);

/*!
 * @brief Get eADC analogy watch dog flag.
 *
 * This function is used to get analogy watch dog flag.
 *
 * @param[in] instance instance number
 * @param[in] wdgChannel awdg channel number
 * @return the AWDG state 
 */
bool eADC_DRV_GetWatchDogFlag(const uint32_t instance, uint8_t wdgChannel);

/*!
 * @brief Clear analogy watch dog flag.
 *
 * This function is used to clear analogy watch dog flag.
 *
 * @param[in] instance instance number
 * @param[in] wdgChannel awdg channel number
 */
void eADC_DRV_ClearWatchDogFlag(const uint32_t instance, uint8_t wdgChannel);

#if defined (__cplusplus)
}
#endif

/*! @}*/

#endif /* eADC_DRIVER_H */
/*******************************************************************************
 * EOF
 ******************************************************************************/
