/* * Copyright (c) 2020 Libre Solar Technologies GmbH * * SPDX-License-Identifier: Apache-2.0 */ /* * @addtogroup test_dac_loopback * @{ * @defgroup t_dac_basic_loopback test_dac_loopback * @brief TestPurpose: read back DAC driver output with ADC * @} */ #include #include #include #include /* * We need to define an ADC channel to read back the output generated by the * ADC. The two pins need to be connected with a jumper in order to pass the * test in actual hardware. * * ADC and DAC need to use the same reference voltage, as the test sampling * point is at half of the full scale voltage. */ #if defined(CONFIG_BOARD_NUCLEO_L152RE) || \ defined(CONFIG_BOARD_STM32F3_DISCO) || \ defined(CONFIG_BOARD_STM32L562E_DK) || \ defined(CONFIG_BOARD_NUCLEO_L552ZE_Q) || \ defined(CONFIG_BOARD_NUCLEO_WL55JC) || \ defined(CONFIG_BOARD_RONOTH_LODEV) /* * DAC output on PA4 (Arduino A2 pin of Nucleo board) * ADC input read from PA1 (Arduino A1 pin of Nucleo board) */ #define DAC_DEVICE_NODE DT_NODELABEL(dac1) #define DAC_CHANNEL_ID 1 #define DAC_RESOLUTION 12 #define ADC_DEVICE_NODE DT_NODELABEL(adc1) #if defined(CONFIG_BOARD_STM32L562E_DK) #define ADC_CHANNEL_ID 13 #else #define ADC_CHANNEL_ID 1 #endif /* CONFIG_BOARD_STM32L562E_DK */ #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_INTERNAL /* The STM32L562E_DK does not accept ADC_ACQ_TIME_DEFAULT (=0) but the MAX one */ #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_MAX #elif defined(CONFIG_BOARD_NUCLEO_L073RZ) || \ defined(CONFIG_BOARD_NUCLEO_F207ZG) || \ defined(CONFIG_BOARD_NUCLEO_F429ZI) || \ defined(CONFIG_BOARD_NUCLEO_F746ZG) || \ defined(CONFIG_BOARD_NUCLEO_G071RB) /* * DAC output on PA4 * ADC input read from PA0 */ #define DAC_DEVICE_NODE DT_NODELABEL(dac1) #define DAC_CHANNEL_ID 1 #define DAC_RESOLUTION 12 #define ADC_DEVICE_NODE DT_NODELABEL(adc1) #define ADC_CHANNEL_ID 0 #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_INTERNAL /* The NUCLEO_G071RB does not accept ADC_ACQ_TIME_DEFAULT (=0) but the MAX one */ #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_MAX #elif defined(CONFIG_BOARD_TWR_KE18F) /* * DAC0 output is internally available on ADC0_SE23 when test output * is enabled. */ #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 #define ADC_DEVICE_NODE DT_NODELABEL(adc0) #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_INTERNAL #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 23 #elif defined(CONFIG_BOARD_FRDM_K64F) /* DAC0 output is internally available on ADC0_SE23 */ #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 #define ADC_DEVICE_NODE DT_NODELABEL(adc0) #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_INTERNAL #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 23 #elif defined(CONFIG_BOARD_FRDM_K22F) /* DAC0 output is internally available on ADC0_SE23 */ #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 #define ADC_DEVICE_NODE DT_NODELABEL(adc0) #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_INTERNAL #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 23 #elif defined(CONFIG_BOARD_LPCXPRESSO55S36) /* DAC0 output is internally available on ADC0_SE4 */ #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 #define ADC_DEVICE_NODE DT_NODELABEL(adc0) #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1 #define ADC_REFERENCE ADC_REF_EXTERNAL0 #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 0 #define ADC_1ST_CHANNEL_INPUT 4 #elif defined(CONFIG_BOARD_BL652_DVK) || \ defined(CONFIG_BOARD_BL653_DVK) || \ defined(CONFIG_BOARD_BL654_DVK) || \ defined(CONFIG_BOARD_BL5340_DVK) #include /* DAC output from MCP4725 pin 1 * On BL65x ADC_1 input is read from pin SIO_3 * On BL5340 ADC_1 input is read from pin SIO_5 * Note external DAC MCP4725 is not populated on BL652_DVK, BL653_DVK and * BL654_DVK at factory */ #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 #define ADC_DEVICE_NODE DT_NODELABEL(adc) #define ADC_RESOLUTION 12 #define ADC_GAIN ADC_GAIN_1_4 #define ADC_REFERENCE ADC_REF_VDD_1_4 #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT #define ADC_CHANNEL_ID 1 #define ADC_1ST_CHANNEL_INPUT NRF_SAADC_INPUT_AIN1 #else #error "Unsupported board." #endif static const struct dac_channel_cfg dac_ch_cfg = { .channel_id = DAC_CHANNEL_ID, .resolution = DAC_RESOLUTION, .buffered = true }; static const struct adc_channel_cfg adc_ch_cfg = { .gain = ADC_GAIN, .reference = ADC_REFERENCE, .acquisition_time = ADC_ACQUISITION_TIME, .channel_id = ADC_CHANNEL_ID, #if defined(CONFIG_BOARD_BL652_DVK) || \ defined(CONFIG_BOARD_BL653_DVK) || \ defined(CONFIG_BOARD_BL654_DVK) || \ defined(CONFIG_BOARD_BL5340_DVK) || \ defined(CONFIG_BOARD_LPCXPRESSO55S36) .input_positive = ADC_1ST_CHANNEL_INPUT, #endif }; static const struct device *init_dac(void) { int ret; const struct device *const dac_dev = DEVICE_DT_GET(DAC_DEVICE_NODE); zassert_true(device_is_ready(dac_dev), "DAC device is not ready"); ret = dac_channel_setup(dac_dev, &dac_ch_cfg); zassert_ok(ret, "Setting up of the first channel failed with code %d", ret); return dac_dev; } /* ADC necessary to read back the value from DAC */ static const struct device *init_adc(void) { int ret; const struct device *const adc_dev = DEVICE_DT_GET(ADC_DEVICE_NODE); zassert_true(device_is_ready(adc_dev), "ADC device is not ready"); ret = adc_channel_setup(adc_dev, &adc_ch_cfg); zassert_ok(ret, "Setting up of the ADC channel failed with code %d", ret); return adc_dev; } /* * test_dac_loopback */ static int test_task_loopback(void) { int ret; const struct device *dac_dev = init_dac(); const struct device *adc_dev = init_adc(); if (!dac_dev || !adc_dev) { return TC_FAIL; } /* write a value of half the full scale resolution */ ret = dac_write_value(dac_dev, DAC_CHANNEL_ID, (1U << DAC_RESOLUTION) / 2); zassert_ok(ret, "dac_write_value() failed with code %d", ret); /* wait to let DAC output settle */ k_sleep(K_MSEC(10)); static int16_t m_sample_buffer[1]; static const struct adc_sequence sequence = { .channels = BIT(ADC_CHANNEL_ID), .buffer = m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), .resolution = ADC_RESOLUTION, }; ret = adc_read(adc_dev, &sequence); zassert_ok(ret, "adc_read() failed with code %d", ret); zassert_within(m_sample_buffer[0], (1U << ADC_RESOLUTION) / 2, 32, "Value %d read from ADC does not match expected range.", m_sample_buffer[0]); return TC_PASS; } ZTEST(dac_loopback, test_dac_loopback) { zassert_true(test_task_loopback() == TC_PASS); } ZTEST_SUITE(dac_loopback, NULL, NULL, NULL, NULL, NULL);