Example #1
0
/**
 * \internal
 * \brief Test differential conversion with gain in 12-bit mode using the DAC
 *
 * This test outputs a gain compensated level on DAC output that should result
 * in a value of half maximum positive value on the ADC.
 *
 * These values are then measured using the ADC on the pins that are connected
 * to the DAC channel, and the results are compared and checked to see if they
 * are within the acceptable range of values that passes the test.
 *
 * \param test Current test case.
 */
static void run_differential_12bit_with_gain_conversion_test(
		const struct test_case *test)
{
	// Number of MUX inputs that are to be read
	const uint8_t num_inputs = 2;

	/* Connection between DAC outputs and ADC MUX inputs.
	 * Only the high nibble on PORTA is possible for gain.
	 * input 4, 6 is connected to DACA0
	 * input 5, 7 is connected to DACA1.
	 */
	const uint8_t channel_pos[] = {4, 6};
	const uint8_t channel_neg[] = {5, 7};

	/*
	 * Go through gain level up to 8, since any higher gives too much
	 * propagated error for sensible unit test limits.
	 */
	const uint8_t gain[] = {1, 2, 4, 8};
	uint8_t gain_index;

	uint8_t adc_channel;
	uint8_t mux_index;
	int16_t results[2];
	struct dac_config dac_conf;
	struct adc_config adc_conf;

	// Configure ADC
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
			ADC_REF_BANDGAP);
	adc_set_clock_rate(&adc_conf, 2000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_write_configuration(&ADCA, &adc_conf);

	// Configure DAC
	dac_read_configuration(&DACA, &dac_conf);
	dac_set_conversion_parameters(&dac_conf, DAC_REF_BANDGAP,
			DAC_ADJ_RIGHT);
	dac_set_active_channel(&dac_conf, DAC_CH0 | DAC_CH1, 0);
	dac_set_conversion_trigger(&dac_conf, 0, 0);
	dac_set_conversion_interval(&dac_conf, 10);
	dac_set_refresh_interval(&dac_conf, 20);
	dac_write_configuration(&DACA, &dac_conf);
	dac_enable(&DACA);


	// Set negative output to zero
	dac_wait_for_channel_ready(&DACA, DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MIN);

	for (gain_index = 0; gain_index < sizeof(gain); gain_index++) {
		// Set positive output to half positive range adjusted to gain
		dac_wait_for_channel_ready(&DACA, DAC_CH0);
		dac_set_channel_value(&DACA, DAC_CH0, DAC_MAX /
				(gain[gain_index] * 2));

		/* Read all ADC pins connected to active DAC output.
		 * All channels are converted NUM_SAMPLES times and the
		 * final value used for the assert is an average.
		 */
		for (adc_channel = 0; adc_channel < NUM_CHANNELS;
				adc_channel++) {
			differential_signed_average(&ADCA, 1 << adc_channel,
					channel_pos, channel_neg, num_inputs,
					results, gain[gain_index]);
			for (mux_index = 0; mux_index < num_inputs;
					mux_index++) {
				verify_signed_result(test,
						ADC_SIGNED_12BIT_MAX / 2,
						results[mux_index],
						adc_channel,
						channel_pos[mux_index],
						channel_neg[mux_index],
						ADC_SIGNED_12BIT_MIN,
						ADC_SIGNED_12BIT_MAX,
						gain[gain_index], true);
			}
		}
	}
}
Example #2
0
/**
 * \internal
 * \brief Test single ended conversion in 8-bit mode using the DAC
 *
 * This tests output three different values on the two DAC channels:
 * - 0 (output analog value is greater than 0, as the DAC cannot go that low)
 * - 1/2 * \ref DAC_MAX Half of the maximum value of the DAC
 * - \ref DAC_MAX The maximum value (VREF) of the DAC.
 *
 * These values are then measured using the ADC on the pins that are connected
 * to the DAC channel, using all available ADC channels and the results are
 * compared and checked to see if they are within the acceptable range of
 * values that passes the test.
 *
 * \param test Current test case.
 */
static void run_single_ended_8bit_conversion_test(
		const struct test_case *test)
{
	// Number of MUX inputs that are to be read
	const uint8_t num_inputs = 4;

	/* Connection between DAC outputs and ADC MUX inputs
	 * input 0, 2, 4, 6 is connected to DACA0
	 * input 1, 3, 5, 7 is connected to DACA1.
	 */
	const uint8_t channelgroup[2][4] = {{0, 2, 4, 6}, {1, 3, 5, 7}};

	uint8_t dac_channel;
	uint8_t adc_channel;
	uint8_t mux_index;
	uint16_t results[4];
	struct dac_config dac_conf;
	struct adc_config adc_conf;

	// Configure ADC
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_8,
			ADC_REF_BANDGAP);
	adc_set_clock_rate(&adc_conf, 2000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_write_configuration(&ADCA, &adc_conf);

	// Configure DAC
	dac_read_configuration(&DACA, &dac_conf);
	dac_set_conversion_parameters(&dac_conf, DAC_REF_BANDGAP, DAC_ADJ_RIGHT);
	dac_set_active_channel(&dac_conf, DAC_CH0 | DAC_CH1, 0);
	dac_set_conversion_trigger(&dac_conf, 0, 0);
	dac_set_conversion_interval(&dac_conf, 10);
	dac_set_refresh_interval(&dac_conf, 20);

	dac_write_configuration(&DACA, &dac_conf);
	dac_enable(&DACA);

	// Set outputs as zero
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MIN);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MIN);

	for(dac_channel = 0; dac_channel < 2; dac_channel++) {
		/* Read all ADC pins connected to active DAC output.
		 * All channels are converted NUM_SAMPLES times and the
		 * final value used for the assert is an average.
		 */
		for (adc_channel = 0; adc_channel < NUM_CHANNELS;
				adc_channel++) {
			single_ended_unsigned_average(&ADCA, 1 << adc_channel,
					(uint8_t *)&channelgroup[dac_channel],
					num_inputs, results);
			for (mux_index = 0; mux_index < num_inputs;
					mux_index++) {
				verify_unsigned_result(test,
						ADC_ZERO,
						results[mux_index],
						dac_channel,
						adc_channel,
						channelgroup[dac_channel]
						[mux_index],
						ADC_UNSIGNED_8BIT_MAX, false);
			}
		}
	}

	// Set outputs as 1/2 * MAX_VALUE
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MAX / 2);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MAX / 2);

	for(dac_channel = 0; dac_channel < 2; dac_channel++) {
		/* Read all ADC pins connected to active DAC output.
		 * All channels are converted NUM_SAMPLES times and the
		 * final value used for the assert is an average.
		 */
		for (adc_channel = 0; adc_channel < NUM_CHANNELS;
				adc_channel++) {
			single_ended_unsigned_average(&ADCA, 1 << adc_channel,
					(uint8_t *)&channelgroup[dac_channel],
					num_inputs, results);
			for (mux_index = 0; mux_index < num_inputs;
					mux_index++) {
				verify_unsigned_result(test,
						ADC_UNSIGNED_8BIT_MAX / 2,
						results[mux_index],
						dac_channel,
						adc_channel,
						channelgroup[dac_channel]
						[mux_index],
						ADC_UNSIGNED_8BIT_MAX, false);
			}
		}
	}

	// Set outputs as MAX_VALUE
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MAX);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MAX);

	for(dac_channel = 0; dac_channel < 2; dac_channel++) {
		/* Read all ADC pins connected to active DAC output.
		 * All channels are converted NUM_SAMPLES times and the
		 * final value used for the assert is an average.
		 */
		for (adc_channel = 0; adc_channel < NUM_CHANNELS;
				adc_channel++) {
			single_ended_unsigned_average(&ADCA, 1 << adc_channel,
					(uint8_t *)&channelgroup[dac_channel],
					num_inputs, results);
			for (mux_index = 0; mux_index < num_inputs;
					mux_index++) {
				verify_unsigned_result(test,
						ADC_UNSIGNED_8BIT_MAX,
						results[mux_index],
						dac_channel,
						adc_channel,
						channelgroup[dac_channel]
						[mux_index],
						ADC_UNSIGNED_8BIT_MAX, false);
			}
		}
	}
}
Example #3
0
/**
 * \internal
 * \brief Test differential conversion in 12-bit mode using the DAC
 *
 * This tests output three different values on the two DAC channels:
 * - 1/2 * \ref DAC_MAX on both outputs to get a differential zero
 * - \ref DAC_MAX on positive and \ref DAC_MIN on negative to get max positive
 * result
 * - \ref DAC_MIN on positive and \ref DAC_MAX on negative to get max negative
 * result
 *
 * These values are then measured using the ADC on the pins that are connected
 * to the DAC channel, and the results are compared and checked to see if they
 * are within the acceptable range of values that passes the test.
 *
 * \param test Current test case.
 */
static void run_differential_12bit_conversion_test(
		const struct test_case *test)
{
	// Number of MUX inputs that are to be read
	const uint8_t num_inputs = 4;

	/* Connection between DAC outputs and ADC MUX inputs
	 * input 0, 2, 4, 6 is connected to DACA0
	 * input 1, 3, 5, 7 is connected to DACA1.
	 */
	const uint8_t channel_pos[] = {0, 2, 4, 6};
	const uint8_t channel_neg[] = {1, 3, 5, 7};

	uint8_t adc_channel;
	uint8_t mux_index;
	int16_t results[4];
	struct dac_config dac_conf;
	struct adc_config adc_conf;

	// Configure ADC
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
			ADC_REF_BANDGAP);
	adc_set_clock_rate(&adc_conf, 2000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_write_configuration(&ADCA, &adc_conf);

	// Configure DAC
	dac_read_configuration(&DACA, &dac_conf);
	dac_set_conversion_parameters(&dac_conf, DAC_REF_BANDGAP,
			DAC_ADJ_RIGHT);
	dac_set_active_channel(&dac_conf, DAC_CH0 | DAC_CH1, 0);
	dac_set_conversion_trigger(&dac_conf, 0, 0);
	dac_set_conversion_interval(&dac_conf, 10);
	dac_set_refresh_interval(&dac_conf, 20);
	dac_write_configuration(&DACA, &dac_conf);
	dac_enable(&DACA);


	// Set outputs to same (1/2 * MAX_VALUE) to get zero
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MAX / 2);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MAX / 2);

	/* Read all ADC pins connected to active DAC output.
	 * All channels are converted NUM_SAMPLES times and the
	 * final value used for the assert is an average.
	 */
	for (adc_channel = 0; adc_channel < NUM_CHANNELS; adc_channel++) {
		differential_signed_average(&ADCA, 1 << adc_channel,
				channel_pos, channel_neg, num_inputs, results,
				1);
		for (mux_index = 0; mux_index < num_inputs; mux_index++) {
			verify_signed_result(test, ADC_ZERO,
					results[mux_index], adc_channel,
					channel_pos[mux_index],
					channel_neg[mux_index],
					ADC_SIGNED_12BIT_MIN,
					ADC_SIGNED_12BIT_MAX, 1, true);
		}
	}

	// Set output to max positive range for positive result
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MAX);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MIN);

	/* Read all ADC pins connected to active DAC output.
	 * All channels are converted NUM_SAMPLES times and the
	 * final value used for the assert is an average.
	 */
	for (adc_channel = 0; adc_channel < NUM_CHANNELS; adc_channel++) {
		differential_signed_average(&ADCA, 1 << adc_channel,
				channel_pos, channel_neg, num_inputs, results,
				1);
		for (mux_index = 0; mux_index < num_inputs; mux_index++) {
			verify_signed_result(test, ADC_SIGNED_12BIT_MAX,
					results[mux_index], adc_channel,
					channel_pos[mux_index],
					channel_neg[mux_index],
					ADC_SIGNED_12BIT_MIN,
					ADC_SIGNED_12BIT_MAX, 1, true);
		}
	}

	// Set output to max negative range for negative result
	dac_wait_for_channel_ready(&DACA, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&DACA, DAC_CH0, DAC_MIN);
	dac_set_channel_value(&DACA, DAC_CH1, DAC_MAX);

	/* Read all ADC pins connected to active DAC output.
	 * All channels are converted NUM_SAMPLES times and the
	 * final value used for the assert is an average.
	 */
	for (adc_channel = 0; adc_channel < NUM_CHANNELS; adc_channel++) {
		differential_signed_average(&ADCA, 1 << adc_channel,
				channel_pos, channel_neg, num_inputs, results,
				1);
		for (mux_index = 0; mux_index < num_inputs; mux_index++) {
			verify_signed_result(test, ADC_SIGNED_12BIT_MIN,
					results[mux_index], adc_channel,
					channel_pos[mux_index],
					channel_neg[mux_index],
					ADC_SIGNED_12BIT_MIN,
					ADC_SIGNED_12BIT_MAX, 1, true);
		}
	}
}
Example #4
0
int main(void)
{
	struct dac_config conf;

	board_init();
	sysclk_init();

	// Initialize the dac configuration.
	dac_read_configuration(&OUTPUT_DAC, &conf);

	/* Create configuration:
	 * - AVCC as reference, right adjusted channel value
	 * - both DAC channels active, no internal output
	 * - manually triggered conversions on both channels
	 * - 2 us conversion intervals
	 * - 10 us refresh intervals
	 */
	dac_set_conversion_parameters(&conf, DAC_REF_AVCC, DAC_ADJ_RIGHT);
	dac_set_active_channel(&conf, DAC_CH0 | DAC_CH1, 0);
	dac_set_conversion_trigger(&conf, 0, 0);
#if XMEGA_DAC_VERSION_1
	dac_set_conversion_interval(&conf, 10);
	dac_set_refresh_interval(&conf, 20);
#endif
	dac_write_configuration(&OUTPUT_DAC, &conf);
	dac_enable(&OUTPUT_DAC);

	dac_wait_for_channel_ready(&OUTPUT_DAC, DAC_CH0 | DAC_CH1);
	dac_set_channel_value(&OUTPUT_DAC, DAC_CH0, 0);
	dac_set_channel_value(&OUTPUT_DAC, DAC_CH1, 0);
	dac_wait_for_channel_ready(&OUTPUT_DAC, DAC_CH0 | DAC_CH1);

#if !XMEGA_E
	// Configure timer/counter to generate events at conversion rate.
	sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0);
	TCC0.PER = (sysclk_get_per_hz() / RATE_OF_CONVERSION) - 1;

	// Configure event channel 0 to generate events upon T/C overflow.
	sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
	EVSYS.CH0MUX = EVSYS_CHMUX_TCC0_OVF_gc;

	// Start the timer/counter.
	TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
#else
	// Configure timer/counter to generate events at conversion rate.
	sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC4);
	TCC4.PER = (sysclk_get_per_hz() / RATE_OF_CONVERSION) - 1;

	// Configure event channel 0 to generate events upon T/C overflow.
	sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
	EVSYS.CH0MUX = EVSYS_CHMUX_TCC4_OVF_gc;

	// Start the timer/counter.
	TCC4.CTRLA = TC45_CLKSEL_DIV1_gc;
	
#endif
	/* Write samples to the DAC channel every time it is ready.
	 * Conversions are triggered by the timer/counter.
	 */
	do {
		/* Wait for channels to get ready for new values, then set the
		 * value of one to 10% and the other to 90% of maximum.
		 */
		wait_for_timer();
		dac_set_channel_value(&OUTPUT_DAC, DAC_CH0, 410);
		dac_set_channel_value(&OUTPUT_DAC, DAC_CH1, 3686);

		wait_for_timer();
		dac_set_channel_value(&OUTPUT_DAC, DAC_CH0, 3686);
		dac_set_channel_value(&OUTPUT_DAC, DAC_CH1, 410);
	} while (1);
}