/* Board */ #include "clock_config.h" #include "pin_mux.h" /* SDK drivers */ #include "fsl_adc.h" #include "fsl_clock.h" #include "fsl_power.h" /* App */ #include "app_adc.h" #define APP_ADC_CHANNEL_COUNT (1U) #define APP_ADC_SEQUENCE (0U) #define APP_ADC_REG_OFFSET_CTRL (0x00U) #define APP_ADC_REG_OFFSET_STAT (0x01U) #define APP_ADC_REG_OFFSET_CH (0x02U) #define APP_ADC_CTRL_CHN_Pos (0U) #define APP_ADC_CTRL_CHN_Msk (((1 << APP_ADC_CHANNEL_COUNT) - 1) << APP_ADC_CTRL_CHN_Pos) #define APP_ADC_CTRL_CONV_Pos (15U) #define APP_ADC_CTRL_CONV_Msk (1U << APP_ADC_CTRL_CONV_Pos) #define APP_ADC_STAT_DONE_Pos (0U) #define APP_ADC_STAT_DONE_Msk (1U << APP_ADC_STAT_DONE_Pos) static const uint8_t s_app_adc_channel_id_table[APP_ADC_CHANNEL_COUNT] = { 2U, // VDDIO channel }; static inline uint16_t app_adc_read_reg_ctrl(void); static inline uint16_t app_adc_read_reg_stat(void); static inline uint16_t app_adc_read_reg_ch(uint8_t ch); static inline void app_adc_write_reg_ctrl(uint16_t data); static inline void app_adc_write_reg_stat(uint16_t data); void app_adc_init(void) { POWER_DisablePD(kPDRUNCFG_PD_ADC0); CLOCK_Select(kADC_Clk_From_Fro); CLOCK_SetClkDivider(kCLOCK_DivAdcClk, 5); CLOCK_EnableClock(kCLOCK_Adc); RESET_PeripheralReset(kADC_RST_N_SHIFT_RSTn); ADC->CTRL = ADC_CTRL_LPWRMODE(1) | (1U << 8U); // Async mode, LP mode enabled /* Continuous mode, interrupt after sequence is completed */ ADC->SEQ_CTRL[APP_ADC_SEQUENCE] = ADC_SEQ_CTRL_MODE(1); ADC->INTEN |= ADC_INTEN_SEQA_INTEN(1); } uint16_t app_adc_module_reg_read(uint8_t addr) { uint16_t ret = 0x5555; switch (addr) { case APP_ADC_REG_OFFSET_CTRL: ret = app_adc_read_reg_ctrl(); break; case APP_ADC_REG_OFFSET_STAT: ret = app_adc_read_reg_stat(); break; default: if ((addr >= APP_ADC_REG_OFFSET_CH) && addr < (APP_ADC_REG_OFFSET_CH + APP_ADC_CHANNEL_COUNT)) { ret = app_adc_read_reg_ch(addr - APP_ADC_REG_OFFSET_CH); } break; } return ret; } void app_adc_module_reg_write(uint8_t addr, uint16_t data) { switch (addr) { case APP_ADC_REG_OFFSET_CTRL: app_adc_write_reg_ctrl(data); break; case APP_ADC_REG_OFFSET_STAT: app_adc_write_reg_stat(data); break; default: break; } } static inline uint16_t app_adc_read_reg_ctrl(void) { uint16_t ret = 0x0000U; for (uint8_t i = 0; i < APP_ADC_CHANNEL_COUNT; i++) { if (ADC->SEQ_CTRL[APP_ADC_SEQUENCE] & (1U << s_app_adc_channel_id_table[i])) { ret |= (1U << i); } } if (ADC->SEQ_CTRL[APP_ADC_SEQUENCE] & ADC_SEQ_CTRL_SEQ_ENA(1)) { ret |= APP_ADC_CTRL_CONV_Msk; } return ret; } static inline uint16_t app_adc_read_reg_stat(void) { uint16_t ret = 0x0000U; if (ADC->FLAGS & ADC_FLAGS_SEQA_INT(1)) { ret |= APP_ADC_STAT_DONE_Msk; } return ret; } static inline uint16_t app_adc_read_reg_ch(uint8_t ch) { uint32_t dat = ADC->DAT[s_app_adc_channel_id_table[ch]]; return ((dat & ADC_DAT_RESULT_MASK) >> ADC_DAT_RESULT_SHIFT); } static inline void app_adc_write_reg_ctrl(uint16_t data) { /* Channel configuration can only be changed when ADC is disabled */ if ((ADC->SEQ_CTRL[APP_ADC_SEQUENCE] & ADC_SEQ_CTRL_SEQ_ENA(1)) == 0) { for (uint8_t i = 0; i < APP_ADC_CHANNEL_COUNT; i++) { if (data & (1U << i)) { ADC->SEQ_CTRL[APP_ADC_SEQUENCE] |= (1U << s_app_adc_channel_id_table[i]); } } } if (data & APP_ADC_CTRL_CONV_Msk) { ADC->SEQ_CTRL[APP_ADC_SEQUENCE] |= ADC_SEQ_CTRL_SEQ_ENA(1) | ADC_SEQ_CTRL_BURST(1); } else { ADC->SEQ_CTRL[APP_ADC_SEQUENCE] &= ~(ADC_SEQ_CTRL_SEQ_ENA(1) | ADC_SEQ_CTRL_BURST(1)); } } static inline void app_adc_write_reg_stat(uint16_t data) { if (data & APP_ADC_STAT_DONE_Msk) { /* W1C DONE Msk */ if (ADC->FLAGS & ADC_FLAGS_SEQA_INT(1)) { /* Read GDATn register to clear INT flag. */ (void)ADC->SEQ_GDAT[APP_ADC_SEQUENCE]; } } }