コード例 #1
0
ファイル: unit_test.c プロジェクト: evarty/Microcontroller
/**
 * \internal
 * \brief Test for AC comparison in single shot mode.
 *
 * This test checks the single shot comparison of the AC.
 * 0.5V is applied to the negative input of AC from internal voltage scaler.
 * 0V and 1V from DAC is applied to the positive input and the results
 * are verified.
 *
 * \param test Current test case.
 */
static void run_ac_single_shot_test(const struct test_case *test)
{
	volatile uint32_t state = AC_CHAN_STATUS_UNKNOWN;

	/* Skip test if initialization failed */
	test_assert_true(test, ac_init_success,
			"Skipping test due to failed AC initialization");

	/* Test for positive input < negative input */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ZERO_VOLT);
	delay_ms(1);
	ac_chan_trigger_single_shot(&ac_inst, AC_CHAN_CHANNEL_0);
	while (!ac_chan_is_ready(&ac_inst, AC_CHAN_CHANNEL_0)) {
	}
	state = ac_chan_get_status(&ac_inst, AC_CHAN_CHANNEL_0);
	state = state & AC_CHAN_STATUS_NEG_ABOVE_POS;
	test_assert_true(test, state == AC_CHAN_STATUS_NEG_ABOVE_POS,
			"AC comparison failed: POS < NEG not detected");

	/* Test for negative input < positive input */
	state = AC_CHAN_STATUS_UNKNOWN;
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ONE_VOLT);
	delay_ms(1);
	ac_chan_trigger_single_shot(&ac_inst, AC_CHAN_CHANNEL_0);
	while (!ac_chan_is_ready(&ac_inst, AC_CHAN_CHANNEL_0)) {
	}
	state = ac_chan_get_status(&ac_inst, AC_CHAN_CHANNEL_0);
	state = state & AC_CHAN_STATUS_POS_ABOVE_NEG;
	test_assert_true(test, state == AC_CHAN_STATUS_POS_ABOVE_NEG,
			"AC comparison failed: Interrupt not detected");
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_0);
}
コード例 #2
0
ファイル: unit_test.c プロジェクト: evarty/Microcontroller
/**
 * \internal
 * \brief AC window mode test function
 *
 * This test checks the window functionality of the AC module.
 * Inputs are given in each region of the window (below, inside & above)
 * and corresponding window output states are verified.
 *
 * \param test Current test case.
 */
static void run_ac_window_mode_test(const struct test_case *test)
{
	volatile uint32_t state = AC_WIN_STATUS_UNKNOWN;

	/* Skip test if initialization failed */
	test_assert_true(test, ac_init_success,
			"Skipping test due to failed AC initialization");

	/* Test for region-below detection */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ZERO_VOLT);
	delay_ms(1);
	ac_chan_trigger_single_shot(&ac_inst, AC_CHAN_CHANNEL_0);
	while (!ac_win_is_ready(&ac_inst, AC_WIN_CHANNEL_0)) {
	}
	state = ac_win_get_status(&ac_inst, AC_WIN_CHANNEL_0);
	state = state & AC_WIN_STATUS_BELOW;
	test_assert_true(test, state == AC_WIN_STATUS_BELOW,
			"AC window mode: Less than lower limit not detected");
	ac_win_clear_status(&ac_inst, AC_WIN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_1);

	/* Test for region-inside detection */
	state = AC_WIN_STATUS_UNKNOWN;
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT);
	delay_ms(1);
	ac_chan_trigger_single_shot(&ac_inst, AC_CHAN_CHANNEL_0);
	while (!ac_win_is_ready(&ac_inst, AC_WIN_CHANNEL_0)) {
	}
	state = ac_win_get_status(&ac_inst, AC_WIN_CHANNEL_0);
	state = state & AC_WIN_STATUS_INSIDE;
	test_assert_true(test, state == AC_WIN_STATUS_INSIDE,
			"AC window mode: Within limit not detected");
	ac_win_clear_status(&ac_inst, AC_WIN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_1);

	/* Test for region-above detection */
	state = AC_WIN_STATUS_UNKNOWN;
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ONE_VOLT);
	delay_ms(1);
	ac_chan_trigger_single_shot(&ac_inst, AC_CHAN_CHANNEL_0);
	while (!ac_win_is_ready(&ac_inst, AC_WIN_CHANNEL_0)) {
	}
	state = ac_win_get_status(&ac_inst, AC_WIN_CHANNEL_0);
	state = state & AC_WIN_STATUS_ABOVE;
	test_assert_true(test, state == AC_WIN_STATUS_ABOVE,
			"AC window mode: More than upper limit not detected");
	ac_win_clear_status(&ac_inst, AC_WIN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_0);
	ac_chan_clear_status(&ac_inst, AC_CHAN_CHANNEL_1);
}
コード例 #3
0
ファイル: qs_dac_basic.c プロジェクト: Realtime-7/asf
int main(void)
{
	system_init();

//! [setup_init]
	configure_dac();
	configure_dac_channel();
//! [setup_init]

//! [main]
//! [main_output_var]
	uint16_t i = 0;
//! [main_output_var]

//! [main_loop]
	while (1) {
//! [main_loop]
//! [main_write]
		dac_chan_write(&dac_instance, DAC_CHANNEL_0, i);
//! [main_write]

//! [main_inc_val]
		if (++i == 0x3FF) {
			i = 0;
		}
//! [main_inc_val]
	}
//! [main]
}
コード例 #4
0
ファイル: unit_test.c プロジェクト: InSoonPark/asf
/**
 * \internal
 * \brief ADC callback mode test function
 *
 * This test checks the callback functionality of the ADC driver.
 * ADC callback for buffered conversion is enabled.
 * Converted results are verified for expected results.
 *
 * \param test Current test case.
 */
static void run_adc_callback_mode_test(const struct test_case *test)
{
	uint16_t timeout_cycles = 0xFFFF;

	/* Set 0.5V DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT);
	delay_ms(1);
	/* Start ADC read */
	adc_read_buffer_job(&adc_inst, adc_buf, ADC_SAMPLES);

	do {
		timeout_cycles--;
		if (interrupt_flag) {
			break;
		}
	} while (timeout_cycles > 0);

	/* Test for timeout */
	test_assert_true(test, timeout_cycles > 0,
			"Timeout in ADC read");

	/* Test result */
	for (uint8_t i = 0; i < ADC_SAMPLES; i++) {
		test_assert_true(test,
				(adc_buf[i] > (ADC_VAL_DAC_HALF_OUTPUT - ADC_OFFSET)) &&
				(adc_buf[i] < (ADC_VAL_DAC_HALF_OUTPUT + ADC_OFFSET)),
				"Error in ADC conversion for 0.5V at index %d, Result: %d", i, adc_buf[i]);
	}
}
コード例 #5
0
ファイル: dac.c プロジェクト: InSoonPark/asf
/**
 * \brief Write to the DAC.
 *
 * This function converts a specific number of digital data.
 * The conversion should be event-triggered, the data will be written to DATABUF
 * and transferred to the DATA register and converted when a Start Conversion
 * Event is issued.
 * Conversion data must be right or left adjusted according to configuration
 * settings.
 * \note To be event triggered, the enable_start_on_event must be
 * enabled in the configuration.
 *
 * \param[in] module_inst      Pointer to the DAC software device struct
 * \param[in] channel          DAC channel to write to
 * \param[in] buffer             Pointer to the digital data write buffer to be converted
 * \param[in] length             Length of the write buffer
 *
 * \return Status of the operation.
 * \retval STATUS_OK           If the data was written or no data conversion required
 * \retval STATUS_ERR_UNSUPPORTED_DEV  The DAC is not configured as using
 *                                         event trigger
 * \retval STATUS_BUSY      The DAC is busy to convert
 */
enum status_code dac_chan_write_buffer_wait(
		struct dac_module *const module_inst,
		enum dac_channel channel,
		uint16_t *buffer,
		uint32_t length)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Zero length request */
	if (length == 0) {
		/* No data to be converted */
		return STATUS_OK;
	}

#if DAC_CALLBACK_MODE == true
	/* Check if busy */
	if (module_inst->job_status[channel] == STATUS_BUSY) {
		return STATUS_BUSY;
	}
#endif

	/* Only support event triggered conversion */
	if (module_inst->start_on_event[channel] == false) {
		return STATUS_ERR_UNSUPPORTED_DEV;
	}

	/* Blocks while buffer is being transferred */
	while (length--) {
		/* Convert one data */
		dac_chan_write(module_inst, channel, buffer[length]);

		/* Wait until Transmit is complete or timeout */
		for (uint32_t i = 0; i <= DAC_TIMEOUT; i++) {
			if(channel == DAC_CHANNEL_0) {
				if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY0) {
					break;
				} else if (i == DAC_TIMEOUT) {
					return STATUS_ERR_TIMEOUT;
				}
			} else if(channel == DAC_CHANNEL_1) {
				if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY1) {
					break;
				} else if (i == DAC_TIMEOUT) {
					return STATUS_ERR_TIMEOUT;
				}
			}
		}
	}

	return STATUS_OK;
}
コード例 #6
0
ファイル: analogout_api.c プロジェクト: AlessandroA/mbed
void analogout_write_u16(dac_t *obj, uint16_t value)
{
    MBED_ASSERT(obj);
    uint16_t count_val;
    count_val = (uint16_t)((value * (float)MAX_VAL_10BIT) / 0xFFFF);  /*Normalization to the value 0xFFFF*/
    dac_chan_write(&dac_instance, DAC_CHANNEL_0, count_val);

}
コード例 #7
0
ファイル: analogout_api.c プロジェクト: toyowata/mbed
void analogout_write_u16(dac_t *obj, uint16_t value)
{
    MBED_ASSERT(obj);
    uint16_t count_val;
    count_val = (uint16_t)((value * (float)MAX_VAL_12BIT) / 0xFFFF);  /*Normalization to the value 0xFFFF*/
    dac_chan_write(&(obj->dac_instance), obj->channel, count_val);

}
コード例 #8
0
ファイル: main.c プロジェクト: evarty/Microcontroller
/* Timer 0 interrupt handler */
void TC0_Handler(void)
{
	TC0->COUNT16.INTFLAG.bit.MC0 = 1;
#if WAVE_MODE==SINE_WAVE
	dac_chan_write(&dac_inst, 0, sine_wave_buf[arr_index++]);
	if (arr_index == 360) {
		arr_index = 0;
	}
#elif WAVE_MODE==SAW_TOOTH_WAVE
	dac_chan_write(&dac_inst, 0, sawtooth_wave_buf[arr_index++]);
	if (arr_index == 256) {
		arr_index = 0;
	}
#elif WAVE_MODE==TRIANGLE_WAVE
	dac_chan_write(&dac_inst, 0, triangle_wave_buf[arr_index++]);
	if (arr_index == 256) {
		arr_index = 0;
	}
#endif
}
コード例 #9
0
ファイル: unit_test.c プロジェクト: evarty/Microcontroller
/**
 * \internal
 * \brief AC callback mode test function
 *
 * This test changes the positive input from 0V to 1V to detect the
 * rising edge and again from 1V to 0V to detect the falling edge.
 *
 * \param test Current test case.
 */
static void run_ac_callback_mode_test(const struct test_case *test)
{
	uint16_t timeout_cycles = 100;

	/* Skip test if initialization failed */
	test_assert_true(test, ac_init_success,
			"Skipping test due to failed AC initialization");

	/* Set input to 0V */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ZERO_VOLT);
	/* Wait for AC output */
	delay_ms(1);
	/* Test for rising edge detection */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ONE_VOLT);
	/* Wait for AC output */
	delay_ms(1);
	do {
		timeout_cycles--;
		if (interrupt_flag) {
			break;
		}
	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles,
			"Error: Timeout in rising edge detection");

	/* Test for falling edge detection */
	timeout_cycles = 100;
	interrupt_flag = false;
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ZERO_VOLT);
	delay_ms(1);
	do {
		timeout_cycles--;
		if (interrupt_flag) {
			break;
		}
	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles,
			"Error: Timeout in falling edge detection");
}
コード例 #10
0
ファイル: unit_test.c プロジェクト: InSoonPark/asf
/**
 * \internal
 * \brief Setup Function: ADC window mode test.
 *
 * This function initializes the ADC in window mode.
 * Upper and lower threshold values are provided.
 * It also registers & enables callback for window detection.
 *
 * \param test Current test case.
 */
static void setup_adc_window_mode_test(const struct test_case *test)
{
	enum status_code status = STATUS_ERR_IO;

	interrupt_flag = false;

	/* Set 0.5V DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT);
	delay_ms(1);

	/* Skip test if ADC initialization failed */
	test_assert_true(test, adc_init_success,
			"Skipping test due to failed initialization");

	/* Disable ADC before initialization */
	adc_disable(&adc_inst);
	struct adc_config config;
	adc_get_config_defaults(&config);
	config.positive_input = ADC_POSITIVE_INPUT_PIN2;
	config.negative_input = ADC_NEGATIVE_INPUT_GND;
#if (SAML21)
	config.reference      = ADC_REFERENCE_INTREF;
	config.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16;
#else
	config.reference      = ADC_REFERENCE_INT1V;
#endif
	config.clock_source   = GCLK_GENERATOR_3;
#if !(SAML21)
	config.gain_factor    = ADC_GAIN_FACTOR_1X;
#endif
	config.resolution     = ADC_RESOLUTION_12BIT;
	config.freerunning    = true;
	config.window.window_mode = ADC_WINDOW_MODE_BETWEEN_INVERTED;
	config.window.window_lower_value = (ADC_VAL_DAC_HALF_OUTPUT - ADC_OFFSET);
	config.window.window_upper_value = (ADC_VAL_DAC_HALF_OUTPUT + ADC_OFFSET);

	/* Re-initialize & enable ADC */
	status = adc_init(&adc_inst, ADC, &config);
	test_assert_true(test, status == STATUS_OK,
			"ADC initialization failed");
	status = adc_enable(&adc_inst);
	test_assert_true(test, status == STATUS_OK,
			"ADC enabling failed");

	/* Register and enable window mode callback */
	adc_register_callback(&adc_inst, adc_user_callback,
			ADC_CALLBACK_WINDOW);
	adc_enable_callback(&adc_inst, ADC_CALLBACK_WINDOW);

	/* Start ADC conversion */
	adc_start_conversion(&adc_inst);
}
コード例 #11
0
ファイル: analogout_api.c プロジェクト: AlessandroA/mbed
void analogout_write(dac_t *obj, float value)
{
    MBED_ASSERT(obj);
    uint16_t count_val = 0;
    if (value < 0.0f) {
        count_val = 0;
    } else if (value > 1.0f) {
        count_val = MAX_VAL_10BIT;
    } else {
        count_val = (uint16_t)(value * (float)MAX_VAL_10BIT);
    }
    dac_chan_write(&dac_instance, DAC_CHANNEL_0, count_val);

}
コード例 #12
0
ファイル: analogout_api.c プロジェクト: toyowata/mbed
void analogout_write(dac_t *obj, float value)
{
    MBED_ASSERT(obj);
    uint16_t count_val = 0;
    if (value < 0.0f) {
        count_val = 0;
    } else if (value > 1.0f) {
        count_val = MAX_VAL_12BIT;
    } else {
        count_val = (uint16_t)(value * (float)MAX_VAL_12BIT);
    }
    dac_chan_write(&(obj->dac_instance), obj->channel, count_val);

}
コード例 #13
0
ファイル: unit_test.c プロジェクト: InSoonPark/asf
/**
 * \internal
 * \brief ADC window mode test function
 *
 * This test gives an input voltage outside the window and checks
 * whether the callback is triggered or not.
 *
 * \param test Current test case.
 */
static void run_adc_window_mode_test(const struct test_case *test)
{
	uint16_t timeout_cycles = 0xFFFF;

	/* Set 1V DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ONE_VOLT);
	delay_ms(1);

	do {
		timeout_cycles--;
		if (interrupt_flag) {
			break;
		}
	} while (timeout_cycles > 0);
	test_assert_true(test, timeout_cycles > 0,
			"Timeout in window detection");
}
コード例 #14
0
ファイル: unit_test.c プロジェクト: InSoonPark/asf
/**
 * \internal
 * \brief ADC average mode test function
 *
 * This test performs the ADC averaging by starting a conversion.
 * 0.5V is applied as input from DAC.
 * Converted result is verified for expected results.
 *
 * \param test Current test case.
 */
static void run_adc_average_mode_test(const struct test_case *test)
{
	uint16_t adc_result = 0;

	/* Set 0.5V DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT);
	delay_ms(1);

	/* Start an ADC conversion */
	adc_start_conversion(&adc_inst);
	while (adc_read(&adc_inst, &adc_result) != STATUS_OK) {
	}

	/* Test result */
	test_assert_true(test,
			(adc_result > (ADC_VAL_DAC_HALF_OUTPUT - ADC_OFFSET)) &&
			(adc_result < (ADC_VAL_DAC_HALF_OUTPUT + ADC_OFFSET)),
			"Error in ADC average mode conversion at 0.5V input");
}
コード例 #15
0
/**
 * \brief Configures the DAC in event triggered mode.
 *
 * Configures the DAC to use the module's default configuration, with output
 * channel mode configured for event triggered conversions.
 *
 * \param dev_inst  Pointer to the DAC module software instance to initialize
 */
static void configure_dac(struct dac_module *dac_module)
{
    struct dac_config config;
    struct dac_chan_config channel_config;

    /* Get the DAC default configuration */
    dac_get_config_defaults(&config);

    /* Switch to GCLK generator 0 */
    config.clock_source = GCLK_GENERATOR_0;

    dac_init(dac_module, DAC, &config);

    /* Get the default DAC channel config */
    dac_chan_get_config_defaults(&channel_config);

    /* Set the channel configuration, and enable it */
    dac_chan_set_config(dac_module, DAC_CHANNEL_0, &channel_config);
    dac_chan_enable(dac_module, DAC_CHANNEL_0);

    /* Enable event triggered conversions */
    struct dac_events events = { .on_event_start_conversion = true };
    dac_enable_events(dac_module, &events);

    dac_enable(dac_module);
}

/**
 * \brief Configures the TC to generate output events at the sample frequency.
 *
 * Configures the TC in Frequency Generation mode, with an event output once
 * each time the audio sample frequency period expires.
 *
 * \param dev_inst  Pointer to the TC module software instance to initialize
 */
static void configure_tc(struct tc_module *tc_module)
{
    struct tc_config config;
    tc_get_config_defaults(&config);

    config.clock_source    = GCLK_GENERATOR_0;
    config.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;

    tc_init(tc_module, TC3, &config);

    /* Enable periodic event output generation */
    struct tc_events events = { .generate_event_on_overflow = true };
    tc_enable_events(tc_module, &events);

    /* Set the timer top value to alter the overflow frequency */
    tc_set_top_value(tc_module,
                     system_gclk_gen_get_hz(GCLK_GENERATOR_0) / sample_rate);


    tc_enable(tc_module);
}

/**
 * \brief Configures the event system to link the sample timer to the DAC.
 *
 * Configures the event system, linking the TC module used for the audio sample
 * rate timing to the DAC, so that a new conversion is triggered each time the
 * DAC receives an event from the timer.
 */
static void configure_events(struct events_resource *event)
{
    struct events_config config;

    events_get_config_defaults(&config);

    config.generator    = EVSYS_ID_GEN_TC3_OVF;
    config.path         = EVENTS_PATH_ASYNCHRONOUS;

    events_allocate(event, &config);
    events_attach_user(event, EVSYS_ID_USER_DAC_START);
}

/**
 * \brief Main application routine
 */
int main(void)
{
    struct dac_module dac_module;
    struct tc_module tc_module;
    struct events_resource event;

    /* Initialize all the system clocks, pm, gclk... */
    system_init();

    /* Enable the internal bandgap to use as reference to the DAC */
    system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);

    /* Module configuration */
    configure_tc(&tc_module);
    configure_dac(&dac_module);
    configure_events(&event);

    /* Start the sample trigger timer */
    tc_start_counter(&tc_module);

    while (true) {
        while (port_pin_get_input_level(SW0_PIN) == SW0_INACTIVE) {
            /* Wait for the button to be pressed */
        }

        port_pin_toggle_output_level(LED0_PIN);

        for (uint32_t i = 0; i < number_of_samples; i++) {
            dac_chan_write(&dac_module, DAC_CHANNEL_0, wav_samples[i]);

            while (!(DAC->INTFLAG.reg & DAC_INTFLAG_EMPTY)) {
                /* Wait for data buffer to be empty */
            }

        }

        while (port_pin_get_input_level(SW0_PIN) == SW0_ACTIVE) {
            /* Wait for the button to be depressed */
        }
    }
}
コード例 #16
0
ファイル: unit_test.c プロジェクト: InSoonPark/asf
/**
 * \internal
 * \brief Test for ADC conversion in polled mode.
 *
 * This test checks the polled mode functionality of the ADC.
 * 0.5V and 1V inputs are applied to the ADC via DAC and the ADC
 * outputs are verified for expected results.
 *
 * \param test Current test case.
 */
static void run_adc_polled_mode_test(const struct test_case *test)
{
	uint16_t adc_result = 0;

	/* Skip test if ADC initialization failed */
	test_assert_true(test, adc_init_success,
			"Skipping test due to failed initialization");

	/* Set 0.5V on DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT);
	delay_ms(1);

	/* Start an ADC conversion */
	adc_start_conversion(&adc_inst);
	while (adc_read(&adc_inst, &adc_result) != STATUS_OK) {
	}

	/* Test result */
	test_assert_true(test,
			(adc_result > (ADC_VAL_DAC_HALF_OUTPUT - ADC_OFFSET)) &&
			(adc_result < (ADC_VAL_DAC_HALF_OUTPUT + ADC_OFFSET)),
			"Error in ADC conversion at 0.5V input (Expected: ~%d, Result: %d)", ADC_VAL_DAC_HALF_OUTPUT, adc_result);

	adc_flush(&adc_inst);

	/* Set 1V on DAC output */
	dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_ONE_VOLT);
	delay_ms(1);

	/* Start an ADC conversion */
	adc_start_conversion(&adc_inst);
	while (adc_read(&adc_inst, &adc_result) != STATUS_OK) {
	}

	/* Test result */
	test_assert_true(test,
			adc_result > (ADC_VAL_DAC_FULL_OUTPUT - ADC_OFFSET),
			"Error in ADC conversion at 1V input (Expected: ~%d, Result: %d)", ADC_VAL_DAC_FULL_OUTPUT, adc_result);

	uint16_t adc_prev_result = 0;

	/* Ensure ADC gives linearly increasing conversions for linearly increasing inputs */
	for (uint16_t i = 0; i < DAC_VAL_ONE_VOLT; i++) {
		adc_flush(&adc_inst);

		/* Write the next highest DAC output voltage */
		dac_chan_write(&dac_inst, DAC_CHANNEL_0, i);
		delay_ms(1);

		/* Start an ADC conversion */
		adc_start_conversion(&adc_inst);
		while (adc_read(&adc_inst, &adc_result) != STATUS_OK) {
		}

		/* Test result */
		test_assert_true(test,
				(adc_result + ADC_OFFSET) >= adc_prev_result,
				"Error in ADC conversion at a variable input (Expected: >=%d, Result: %d)", adc_prev_result, adc_result);

		adc_prev_result = adc_result;
	}
}