/** * @file sdrv_acmp.h * @brief SemiDrive Analog Compare (ACMP) driver header file. * * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #ifndef SDRV_ACMP_H_ #define SDRV_ACMP_H_ #include #include #include "sdrv_acmp.h" #include "sdrv_common.h" /* ACMP Chanel Polar */ #define ACMP_CH_POLAR_POS 1U #define ACMP_CH_POLAR_NEG 0U /* Single-End Mode Channel Select */ #define ACMP_SINGLE_CH_SEL(ch, polar, mux) \ (((mux & 0x7u) << 6) | ((polar & 0x1u) << 3) | (ch & 0x7u)) /* Differential Mode Channel Select */ #define ACMP_DIFF_CH_SEL(ch_p, ch_n, mux) \ (((mux & 0x7u) << 6) | ((ch_p & 0x7u) << 3) | (ch_n & 0x7u)) /** * @brief ACMP status error code. */ enum sdrv_acmp_error { SDRV_ACMP_STATUS_INVALID_PARAM = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_ACMP, 1), /* Acmp invalid param. */ SDRV_ACMP_STATUS_WRONG_MODE = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_ACMP, 2), /* Acmp wrong mode. */ }; /* sdrv acmp dev */ struct sdrv_acmp_dev; /* sdrv acmp mode */ typedef enum { ACMP_HT_MODE = 0x0U, /**< Acmp hardware trigger mode */ ACMP_IT_MODE, /**< Acmp internal trigger mode */ } sdrv_acmp_mode_t; /* sdrv acmp csel num */ typedef enum { ACMP_CSEL_0 = 0x0U, /**< Acmp first compare select controller */ ACMP_CSEL_1, /**< Acmp second compare select controller */ ACMP_CSEL_2, /**< Acmp third compare select controller */ ACMP_CSEL_3, /**< Acmp fourth compare select controller */ } sdrv_acmp_csel_t; /* sdrv acmp index num */ typedef enum { ACMP_INDEX_0 = 0x0U, /**< Acmp config select index num, max index is 31 */ ACMP_INDEX_1, ACMP_INDEX_2, ACMP_INDEX_3, ACMP_INDEX_4, ACMP_INDEX_5, ACMP_INDEX_6, ACMP_INDEX_7, ACMP_INDEX_8, ACMP_INDEX_9, ACMP_INDEX_10, ACMP_INDEX_11, ACMP_INDEX_12, ACMP_INDEX_13, ACMP_INDEX_14, ACMP_INDEX_15, ACMP_INDEX_16, ACMP_INDEX_17, ACMP_INDEX_18, ACMP_INDEX_19, ACMP_INDEX_20, ACMP_INDEX_21, ACMP_INDEX_22, ACMP_INDEX_23, ACMP_INDEX_24, ACMP_INDEX_25, ACMP_INDEX_26, ACMP_INDEX_27, ACMP_INDEX_28, ACMP_INDEX_29, ACMP_INDEX_30, ACMP_INDEX_31, } sdrv_acmp_index_t; /* sdrv acmp pol adjust */ typedef enum { ACMP_POL_ADJ_DIRECTLY = 0x0U, /**< Acmp analog output directly */ ACMP_POL_ADJ_INVERT, /**< Acmp invert raw analog output */ } sdrv_acmp_pol_adj_t; /* sdrv acmp select reference voltage source */ typedef enum { ACMP_SEL_REFP1 = 0x0U, /**< Acmp select internal reference voltage REFP1 */ ACMP_SEL_REFP2, /**< Acmp select internal reference voltage REFP2 or extern reference voltage */ } sdrv_acmp_reg_sel_t; /* sdrv acmp sd sel */ typedef enum { ACMP_SEL_SINGLE = 0x0U, /**< Acmp single-ended comparison mode */ ACMP_SEL_DIFF, /**< Acmp differential comparison mode*/ } sdrv_acmp_sd_sel_t; /* sdrv acmp hysteresis window configure */ typedef enum { ACMP_HCFG_NO = 0x0U, /**< Acmp without windows */ ACMP_HCFG_50_mV, /**< Acmp with windows, 50 mV */ ACMP_HCFG_100_mV = 0x3U, /**< Acmp With windows, 100 mV */ } sdrv_acmp_hcfg_t; /* sdrv acmp csel configurations */ typedef struct sdrv_acmp_csel_cfg { sdrv_acmp_csel_t csel_idx; /**< Index of compare select controller */ /* acmp ctrl cfg */ uint8_t amux_setup; /**< Analog mux setup time, preparation time required for a comparison. The first period of (prop_delay + amux_setup) time in a comparison, the comparison result is not reliable. */ uint8_t prop_delay : 5; /**< Propagation delay, in cycles of clock */ uint8_t rbw : 4; /**< Rising edge filter, unit: cycle number of clock, set 0 means bypass filter */ uint8_t fbw : 4; /**< Falling edge filter, unit: cycle number of clock, set 0 means bypass filter */ bool sample_en; /**< The result of analog comparison is sampled by an additional digital clock and then output. sample_en is usually set to 0, when set to 1, mask and sync will not work. */ bool mask_en; /**< If sample_en is not enabled, mask_en refers to converting the above digital sampling clock into an enable signal, which will be output only when the sampling clock is high */ bool pol_adj; /**< Analog output polar adjust */ bool sync_en; /**< Whether the output result is synchronized with the internal clock of acmp */ /* acmp analog cfg */ sdrv_acmp_reg_sel_t refsel; /**< select reference voltage source */ sdrv_acmp_sd_sel_t sdsel; /**< Single-ended or differential comparison mode */ sdrv_acmp_hcfg_t hcfg; /**< Set hysteresis window */ uint8_t dain; /**< Reference voltage adjustment. */ } sdrv_acmp_csel_cfg_t; /* sdrv acmp index configurations */ typedef struct sdrv_acmp_index_cfg { sdrv_acmp_index_t idx; /**< Acmp index num */ uint16_t amsel : 9; /**< Analog mux select */ uint8_t csel : 2; /**< Acmp config select */ bool ie; /**< Acmp interrupt enable */ bool uie; /**< Acmp uncorrect interrupt enable */ } sdrv_acmp_index_cfg_t; /* sdrv acmp callback */ typedef int (*sdrv_acmp_callback)(struct sdrv_acmp_dev *dev, uint32_t state); /* sdrv acmp configurations */ typedef struct sdrv_acmp_config { paddr_t base; /**< Acmp base address */ int irq; /**< Acmp irq number */ sdrv_acmp_mode_t mode; /**< Acmp mode */ sdrv_acmp_csel_cfg_t *csel_cfg; /**< Acmp compare select controller configuration */ uint8_t csel_num; /**< Acmp config csel number */ sdrv_acmp_index_cfg_t *index_cfg; /**< Acmp index configurations */ uint8_t index_num; /**< Acmp config index number */ uint8_t req_n_dly; /**< Acmp req_n delay number */ bool qch_dac_en; /**< Allow acmp analog dac recieve q channel low power requset */ bool qch_cmp_en; /**< Allow acmp analog competitor recieve q channel low power requset */ /* IT MODE */ uint8_t qstart : 5; /**< The head idx number in a scanning sequence in IT mode */ uint8_t qend : 5; /**< The tail idx number in a scanning sequence in IT mode */ uint8_t cur_entry_pt : 5; /**< The start idx number in a scanning sequence in IT mode */ uint16_t timer_compare_val; /**< The total time for a whole comparison. Only used in IT (internal trigger) mode. The time must be more than (prop_delay + amux_setup) */ uint16_t timer_terminal_val; /**< Cycle comparison time, only used in IT (internal trigger) mode. Acmp output once per cycle, the value must be more than (timer_compare_val + prop_delay + amux_setup) */ } sdrv_acmp_config_t; /* define the type of acmp device */ typedef struct sdrv_acmp_dev { paddr_t base; /**< Acmp base address */ int irq; /**< Acmp irq number */ sdrv_acmp_callback callback; /**< Acmp callback function */ void *priv; /**< reserved */ } sdrv_acmp_t; /** * @brief sdrv acmp init * * This function initializes acmp device and attach callback function. * * @param[in] dev sdrv acmp device * @param[in] acmp_cfg sdrv acmp configuration parameters * @param[in] callback sdrv acmp callback function * @return SDRV_STATUS_OK represents success or other error code */ status_t sdrv_acmp_init(sdrv_acmp_t *dev, sdrv_acmp_config_t *acmp_cfg, sdrv_acmp_callback callback); /** * @brief sdrv acmp start * * This function is used to start or stop acmp comparation. * All the parameters are remained when acmp stop, and the previous comparation will restart when acmp start. * * @param[in] dev sdrv acmp dev * @param[in] start sdrv acmp start * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_start(sdrv_acmp_t *dev, bool start); /** * @brief sdrv acmp IT mode trigger start * * This function is used to stop or restart trigger with differnet id numbers in IT mode. * The new comparation will use the same comparation parameters with the former comparation. * If the parameters need to be modified, acmp should be stopped and reinitialized. * * @param[in] dev sdrv acmp device * @param[in] qstart sdrv acmp trigger start id number for loop * @param[in] qend sdrv acmp trigger end id number for loop * @param[in] cur_entry_pt sdrv acmp trigger first access id number * @param[in] trigger_start acmp IT mode trigger start * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_it_trigger_start(sdrv_acmp_t *dev, uint8_t qstart, uint8_t qend, uint8_t cur_entry_pt, bool trigger_start); /** * @brief sdrv acmp IT mode update valid irq state * * This function is used to workaround for multiple trigger if interrupt is required in IT mode. * Occurrence scenario: Only appers in multiple triggers of IT mode, but this is not a problem * if not changing the configuration(index and analog config) at next trigger. * At the end of each trigger, if acmp voltage comparision result is pulled up one clock cycle * before next trigger, the interrupt generated by this trigger will update to the register ID * of the next trigger. Other functions of ACMP are not affected. * * How to use this function: * Call the function at beginning of acmp callback function. * * @param[in] dev sdrv acmp device * @param[in] state sdrv acmp irq state * @param[in] wait_time check irq valid wait time, the period should be longer than terminal time. * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_it_update_valid_irq(sdrv_acmp_t *dev, uint32_t *state, uint32_t wait_time); /** * @brief sdrv acmp power ctrl * * This function sets the sdrv acmp power mode. * The status is default power on after acmp initilization. * If the acmp comparation is finished, the power mode can be set to power down to reduce power consumption. * * @param[in] dev sdrv acmp device * @param[in] down 0 power on (default), 1 power down * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_power_ctrl(sdrv_acmp_t *dev, bool down); /** * @brief sdrv acmp allows analog competitor and dac enter lowpower mode * * This function allows competitor and dac recv q channel low power request. * And than if the lowpower request is received, the competitor and dac will enter * low power mode after req_n_dly clock cycle. * * @param[in] dev sdrv acmp device * @param[in] cmp_en competitor enable or disable * @param[in] dac_en dac enable or disable * @param[in] req_n_dly enter lowpower mode delay number * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_enable_low_power(sdrv_acmp_t *dev, bool cmp_en, bool dac_en, uint8_t req_n_dly); /** * @brief sdrv acmp set callback * * This function is used to set the sdrv acmp callback function separately, after acmp initilization. * * @param[in] dev sdrv acmp device * @param[in] callback acmp callback function * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_set_callback(sdrv_acmp_t *dev, sdrv_acmp_callback callback); /** * @brief sdrv acmp deinit * * This function stops acmp and deletes acmp initilization. * Acmp must be de-initiated before entering lowpower mode. * * @param[in] dev sdrv acmp device * @return SDRV_STATUS_OK represents success */ status_t sdrv_acmp_deinit(sdrv_acmp_t *dev); #endif /* SDRV_ACMP_H_ */