MPyATE_Firmware/src/app_adc.c

146 lines
4.1 KiB
C

/* 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];
}
}
}