11 #define FIFO_INTERRUPT_THRESHOLD (16)
13 #define QM_ADC_CHAN_SEQ_MAX (32)
16 #define QM_ADC_CMD_START_SINGLE (0)
17 #define QM_ADC_CMD_START_CONT (1)
18 #define QM_ADC_CMD_RESET_CAL (2)
19 #define QM_ADC_CMD_START_CAL (3)
20 #define QM_ADC_CMD_LOAD_CAL (4)
21 #define QM_ADC_CMD_STOP_CONT (5)
23 static uint8_t sample_window[QM_ADC_NUM];
27 static uint32_t count[QM_ADC_NUM];
28 static bool dummy_conversion =
false;
31 static void (*mode_callback[QM_ADC_NUM])(
void *data,
int error,
34 static void (*cal_callback[QM_ADC_NUM])(
void *data,
int error,
37 static void *mode_callback_data[QM_ADC_NUM];
38 static void *cal_callback_data[QM_ADC_NUM];
41 static void qm_adc_isr_handler(
const qm_adc_t adc)
43 uint32_t int_status = 0;
44 uint32_t i, samples_to_read;
46 int_status = QM_ADC[adc].adc_intr_status;
49 if (int_status & QM_ADC_INTR_STATUS_FO) {
51 QM_ADC[adc].adc_cmd = QM_ADC_CMD_STOP_CONT;
53 QM_ADC[adc].adc_intr_enable = 0;
55 if (irq_xfer[adc]->callback) {
56 irq_xfer[adc]->
callback(irq_xfer[adc]->callback_data,
63 if (int_status & QM_ADC_INTR_STATUS_CONT_CC) {
65 QM_ADC[adc].adc_intr_status &= QM_ADC_INTR_STATUS_CONT_CC;
68 samples_to_read = QM_ADC[adc].adc_fifo_count;
70 (irq_xfer[adc]->samples_len - count[adc])) {
78 for (i = 0; i < samples_to_read; i++) {
79 irq_xfer[adc]->
samples[count[adc]] =
80 (QM_ADC[adc].adc_sample >>
81 (2 * (3 - resolution[adc])));
87 if (count[adc] == irq_xfer[adc]->samples_len) {
89 QM_ADC[adc].adc_cmd = QM_ADC_CMD_STOP_CONT;
91 QM_ADC[adc].adc_intr_enable = 0;
93 if (irq_xfer[adc]->callback) {
95 irq_xfer[adc]->callback_data, 0,
103 if ((int_status & QM_ADC_INTR_STATUS_CC) && (!dummy_conversion)) {
105 QM_ADC[adc].adc_intr_enable &= ~QM_ADC_INTR_ENABLE_CC;
106 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
109 if (cal_callback[adc]) {
117 if ((int_status & QM_ADC_INTR_STATUS_CC) && (dummy_conversion)) {
119 QM_ADC[adc].adc_sample = QM_ADC_FIFO_CLEAR;
121 QM_ADC[adc].adc_intr_enable &= ~QM_ADC_INTR_ENABLE_CC;
122 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
124 dummy_conversion =
false;
127 if (mode_callback[adc]) {
135 static void qm_adc_pwr_0_isr_handler(
const qm_adc_t adc)
140 QM_ADC[adc].adc_op_mode &= ~QM_ADC_OP_MODE_IE;
144 if ((QM_ADC[adc].adc_op_mode & QM_ADC_OP_MODE_OM_MASK) >=
148 QM_ADC[adc].adc_seq0 = QM_ADC_CAL_SEQ_TABLE_DEFAULT;
150 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
152 dummy_conversion =
true;
155 QM_ADC[adc].adc_cmd = (QM_ADC_CMD_IE | QM_ADC_CMD_START_SINGLE);
158 if (mode_callback[adc]) {
168 qm_adc_isr_handler(QM_ADC_0);
170 QM_ISR_EOI(QM_IRQ_ADC_0_CAL_INT_VECTOR);
176 qm_adc_pwr_0_isr_handler(QM_ADC_0);
178 QM_ISR_EOI(QM_IRQ_ADC_0_PWR_0_VECTOR);
183 uint32_t i, offset = 0;
184 volatile uint32_t *reg_pointer = NULL;
187 for (i = 0; i < xfer->
ch_len; i++) {
189 reg_pointer = &QM_ADC[adc].adc_seq0 + (i / 4);
191 offset = ((i % 4) * 8);
193 *reg_pointer &= ~(1 << (offset + 7));
195 *reg_pointer |= (xfer->
ch[i] << offset);
200 *reg_pointer |= (1 << (offset + 7));
206 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
209 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
211 QM_ADC[adc].adc_cmd = (QM_ADC_CMD_IE | QM_ADC_CMD_START_CAL);
212 while (!(QM_ADC[adc].adc_intr_status & QM_ADC_INTR_STATUS_CC))
215 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
221 void (*callback)(
void *data,
int error,
226 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
229 cal_callback[adc] = callback;
230 cal_callback_data[adc] = callback_data;
233 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
234 QM_ADC[adc].adc_intr_enable |= QM_ADC_INTR_ENABLE_CC;
237 QM_ADC[adc].adc_cmd = (QM_ADC_CMD_IE | QM_ADC_CMD_START_CAL);
244 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
245 QM_CHECK(cal < 0x3F, -EINVAL);
248 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
251 QM_ADC[adc].adc_cmd = ((cal << QM_ADC_CMD_CAL_DATA_OFFSET) |
252 QM_ADC_CMD_IE | QM_ADC_CMD_LOAD_CAL);
253 while (!(QM_ADC[adc].adc_intr_status & QM_ADC_INTR_STATUS_CC))
256 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
263 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
264 QM_CHECK(NULL != cal, -EINVAL);
266 *cal = QM_ADC[adc].adc_calibration;
273 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
277 QM_ADC[adc].adc_op_mode = mode;
278 while ((QM_ADC[adc].adc_op_mode & QM_ADC_OP_MODE_OM_MASK) != mode)
284 QM_ADC[adc].adc_seq0 = QM_ADC_CAL_SEQ_TABLE_DEFAULT;
287 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
289 QM_ADC[adc].adc_cmd = (QM_ADC_CMD_IE | QM_ADC_CMD_START_SINGLE);
290 while (!(QM_ADC[adc].adc_intr_status & QM_ADC_INTR_STATUS_CC))
294 QM_ADC[adc].adc_sample = QM_ADC_FIFO_CLEAR;
296 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
303 void (*callback)(
void *data,
int error,
308 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
312 mode_callback[adc] = callback;
313 mode_callback_data[adc] = callback_data;
318 QM_ADC[adc].adc_intr_enable |= QM_ADC_INTR_ENABLE_CC;
324 QM_ADC[adc].adc_op_mode = (QM_ADC_OP_MODE_IE | mode);
331 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
332 QM_CHECK(NULL != cfg, -EINVAL);
339 sample_window[adc] = cfg->
window;
350 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
351 QM_CHECK(NULL != xfer, -EINVAL);
352 QM_CHECK(NULL != xfer->
ch, -EINVAL);
353 QM_CHECK(NULL != xfer->
samples, -EINVAL);
354 QM_CHECK(xfer->
ch_len > 0, -EINVAL);
355 QM_CHECK(xfer->
ch_len <= QM_ADC_CHAN_SEQ_MAX, -EINVAL);
357 QM_CHECK(xfer->
samples_len <= QM_ADC_FIFO_LEN, -EINVAL);
360 QM_ADC[adc].adc_sample = QM_ADC_FIFO_CLEAR;
363 setup_seq_table(adc, xfer);
366 QM_ADC[adc].adc_cmd =
367 (sample_window[adc] << QM_ADC_CMD_SW_OFFSET |
368 resolution[adc] << QM_ADC_CMD_RESOLUTION_OFFSET |
369 ((xfer->
samples_len - 1) << QM_ADC_CMD_NS_OFFSET) |
370 QM_ADC_CMD_START_SINGLE);
373 while (QM_ADC[adc].adc_fifo_count != xfer->
samples_len)
385 (QM_ADC[adc].adc_sample >> (2 * (3 - resolution[adc])));
393 QM_CHECK(adc < QM_ADC_NUM, -EINVAL);
394 QM_CHECK(NULL != xfer, -EINVAL);
395 QM_CHECK(NULL != xfer->
ch, -EINVAL);
396 QM_CHECK(NULL != xfer->
samples, -EINVAL);
397 QM_CHECK(xfer->
ch_len > 0, -EINVAL);
398 QM_CHECK(xfer->
ch_len <= QM_ADC_CHAN_SEQ_MAX, -EINVAL);
403 QM_ADC[adc].adc_sample = QM_ADC_FIFO_CLEAR;
406 setup_seq_table(adc, xfer);
409 irq_xfer[adc] = xfer;
412 QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC |
413 QM_ADC_INTR_STATUS_FO |
414 QM_ADC_INTR_STATUS_CONT_CC;
416 QM_ADC[adc].adc_intr_enable =
417 QM_ADC_INTR_ENABLE_FO | QM_ADC_INTR_ENABLE_CONT_CC;
423 QM_ADC[adc].adc_cmd =
424 (sample_window[adc] << QM_ADC_CMD_SW_OFFSET |
425 resolution[adc] << QM_ADC_CMD_RESOLUTION_OFFSET |
426 ((FIFO_INTERRUPT_THRESHOLD - 1) << QM_ADC_CMD_NS_OFFSET) |
427 QM_ADC_CMD_IE | QM_ADC_CMD_START_CONT);
void(* callback)(void *data, int error, qm_adc_status_t status, qm_adc_cb_source_t source)
Transfer callback.
qm_adc_mode_t
ADC operating mode type.
qm_adc_channel_t * ch
Channel sequence array (1-32 channels).
qm_adc_resolution_t resolution
12, 10, 8, 6-bit resolution.
int qm_adc_irq_set_mode(const qm_adc_t adc, const qm_adc_mode_t mode, void(*callback)(void *data, int error, qm_adc_status_t status, qm_adc_cb_source_t source), void *callback_data)
Switch operating mode of ADC.
int qm_adc_irq_calibrate(const qm_adc_t adc, void(*callback)(void *data, int error, qm_adc_status_t status, qm_adc_cb_source_t source), void *callback_data)
Calibrate the ADC.
int qm_adc_get_calibration(const qm_adc_t adc, qm_adc_calibration_t *const cal)
Get the current calibration data for an ADC.
qm_adc_t
Number of ADC controllers.
Calibration complete callback.
Mode change complete callback.
qm_adc_cb_source_t
ADC interrupt callback source.
uint8_t ch_len
Number of channels in the above array.
uint32_t samples_len
Length of sample array.
void * callback_data
Callback user data.
int qm_adc_irq_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer)
Asynchronously read values from the ADC.
int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer, qm_adc_status_t *const status)
Synchronously read values from the ADC.
Transfer complete or error callback.
int qm_adc_set_config(const qm_adc_t adc, const qm_adc_config_t *const cfg)
Set ADC configuration.
qm_adc_sample_t * samples
Array to store samples.
int qm_adc_calibrate(const qm_adc_t adc)
Calibrate the ADC.
int qm_adc_set_mode(const qm_adc_t adc, const qm_adc_mode_t mode)
Switch operating mode of ADC.
uint8_t qm_adc_calibration_t
ADC calibration type.
QM_ISR_DECLARE(qm_adc_0_cal_isr)
ISR for ADC 0 convert and calibration interrupt.
int qm_adc_set_calibration(const qm_adc_t adc, const qm_adc_calibration_t cal)
Set ADC calibration data.
qm_adc_resolution_t
ADC resolution type.
uint8_t window
Sample interval in ADC clock cycles, defines the period to wait between the start of each sample and ...
Normal mode, with calibration.
Normal mode, no calibration.