int adc_qmsi_init(struct device *dev) { qm_adc_config_t cfg; struct adc_info *info = dev->driver_data; dev->driver_api = &api_funcs; /* Enable the ADC and set the clock divisor */ clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_ADC | CLK_PERIPH_ADC_REGISTER); /* ADC clock divider*/ clk_adc_set_div(CONFIG_ADC_QMSI_CLOCK_RATIO); /* Set up config */ /* Clock cycles between the start of each sample */ cfg.window = CONFIG_ADC_QMSI_SERIAL_DELAY; cfg.resolution = CONFIG_ADC_QMSI_SAMPLE_WIDTH; qm_adc_set_config(QM_ADC_0, &cfg); device_sync_call_init(&info->sync); nano_sem_init(&info->sem); nano_sem_give(&info->sem); info->state = ADC_STATE_IDLE; adc_config_irq(); return 0; }
static int adc_qmsi_read(struct device *dev, struct adc_seq_table *seq_tbl) { int i, ret = 0; qm_adc_xfer_t xfer; qm_adc_config_t cfg; struct adc_info *info = dev->driver_data; if (qm_adc_get_config(QM_ADC_0, &cfg) != QM_RC_OK) { return -ENOTSUP; } for (i = 0; i < seq_tbl->num_entries; i++) { xfer.ch = (qm_adc_channel_t *)&seq_tbl->entries[i].channel_id; /* Just one channel at the time using the Zephyr sequence table */ xfer.ch_len = 1; xfer.samples = (uint32_t *)seq_tbl->entries[i].buffer; /* buffer length (bytes) the number of samples, the QMSI Driver does * not allow more than QM_ADC_FIFO_LEN samples at the time in polling * mode, if that happens, the qm_adc_convert api will return with an * error */ xfer.samples_len = (seq_tbl->entries[i].buffer_length); xfer.complete_callback = NULL; xfer.error_callback = NULL; cfg.window = seq_tbl->entries[i].sampling_delay; adc_lock(info); if (qm_adc_set_config(QM_ADC_0, &cfg) != QM_RC_OK) { ret = -EINVAL; adc_unlock(info); break; } /* Run the conversion, here the function will poll for the samples * The function will constantly read the status register to check if * the number of samples required has been captured */ if (qm_adc_convert(QM_ADC_0, &xfer) != QM_RC_OK) { ret = -EIO; adc_unlock(info); break; } /* Successful Analog to Digital conversion */ adc_unlock(info); } return ret; }
int main(void) { #if (QUARK_D2000) int i; qm_adc_config_t cfg; qm_adc_xfer_t xfer; qm_adc_channel_t channels[] = {QM_ADC_CH_8, QM_ADC_CH_9}; uint32_t samples_polled[NUM_SAMPLES_POLLED] = {0}; uint32_t samples_interrupt[NUM_SAMPLES_INTERRUPT] = {0}; QM_PUTS("\nADC example app start"); /* Enable the ADC and set the clock divisor */ clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_ADC | CLK_PERIPH_ADC_REGISTER); clk_adc_set_div(100); /* ADC clock is 320KHz @ 32MHz */ /* Set up pinmux */ qm_pmux_select(QM_PIN_ID_8, QM_PMUX_FN_1); qm_pmux_select(QM_PIN_ID_9, QM_PMUX_FN_1); qm_pmux_input_en(QM_PIN_ID_8, true); qm_pmux_input_en(QM_PIN_ID_9, true); /* Set the mode and calibrate */ qm_adc_set_mode(QM_ADC_0, QM_ADC_MODE_NORM_CAL); qm_adc_calibrate(QM_ADC_0); /* Set up config */ cfg.window = 20; /* Clock cycles between the start of each sample */ cfg.resolution = QM_ADC_RES_12_BITS; qm_adc_set_config(QM_ADC_0, &cfg); /******************************* * ADC polled mode example ******************************/ QM_PUTS("ADC polled mode"); /* Set up xfer */ xfer.ch = channels; xfer.ch_len = NUM_CHANNELS; xfer.samples = samples_polled; xfer.samples_len = NUM_SAMPLES_POLLED; /* Run the conversion */ if (qm_adc_convert(QM_ADC_0, &xfer)) { QM_PUTS("ERROR: qm_adc_convert failed"); return 1; } /* Print the values of the samples */ for (i = 0; i < NUM_SAMPLES_POLLED; i++) { QM_PRINTF("%d:%x ", i, (unsigned int)samples_polled[i]); } /******************************* * ADC interrupt mode example ******************************/ QM_PUTS("\nADC interrupt mode"); qm_irq_request(QM_IRQ_ADC_0, qm_adc_0_isr); /* Set up xfer */ xfer.ch = channels; xfer.ch_len = NUM_CHANNELS; xfer.samples = samples_interrupt; xfer.samples_len = NUM_SAMPLES_INTERRUPT; xfer.complete_callback = complete_callback; xfer.error_callback = error_callback; if (qm_adc_irq_convert(QM_ADC_0, &xfer)) { QM_PUTS("ERROR: qm_adc_irq_convert failed"); return 1; } /* Wait for the callback */ while (false == complete) ; for (i = 0; i < NUM_SAMPLES_INTERRUPT; i++) { QM_PRINTF("%d:%x ", i, (unsigned int)samples_interrupt[i]); } QM_PUTS("\nADC example app complete"); #endif /* QUARK_D2000 */ return 0; }
static int adc_qmsi_read(struct device *dev, struct adc_seq_table *seq_tbl) { int i, ret = 0; qm_adc_xfer_t xfer; qm_adc_config_t cfg; struct adc_info *info = dev->driver_data; if (qm_adc_get_config(QM_ADC_0, &cfg) != QM_RC_OK) { return -ENOTSUP; } for (i = 0; i < seq_tbl->num_entries; i++) { xfer.ch = (qm_adc_channel_t *)&seq_tbl->entries[i].channel_id; /* Just one channel at the time using the Zephyr sequence table */ xfer.ch_len = 1; xfer.samples = (uint32_t *)seq_tbl->entries[i].buffer; xfer.samples_len = (seq_tbl->entries[i].buffer_length) >> 2; xfer.complete_callback = complete_callback; xfer.error_callback = error_callback; cfg.window = seq_tbl->entries[i].sampling_delay; adc_lock(info); if (qm_adc_set_config(QM_ADC_0, &cfg) != QM_RC_OK) { ret = -EINVAL; adc_unlock(info); break; } /* ADC info used by the callbacks */ adc_context = info; /* This is the interrupt driven API, will generate and interrupt and * call the complete_callback function once the samples have been * obtained */ if (qm_adc_irq_convert(QM_ADC_0, &xfer) != QM_RC_OK) { adc_context = NULL; ret = -EIO; adc_unlock(info); break; } /* Wait for the interrupt to finish */ device_sync_call_wait(&info->sync); if (info->state == ADC_STATE_ERROR) { ret = -EIO; adc_unlock(info); break; } adc_context = NULL; /* Successful Analog to Digital conversion */ adc_unlock(info); } return ret; }