Example #1
0
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;
}
Example #2
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;
}
Example #3
0
File: main.c Project: CurieBSP/qmsi
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;
}
Example #4
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;
}