blob: 122218c36457966401fbe962488bf0f16d73d673 [file] [log] [blame]
/*
* 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 <zephyr/drivers/dac.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
/*
* 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_L073RZ) || \
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)
#define ADC_CHANNEL_ID 1
#define ADC_RESOLUTION 12
#define ADC_GAIN ADC_GAIN_1
#define ADC_REFERENCE ADC_REF_INTERNAL
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
#elif 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
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
#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_BL652_DVK) || \
defined(CONFIG_BOARD_BL653_DVK) || \
defined(CONFIG_BOARD_BL654_DVK) || \
defined(CONFIG_BOARD_BL5340_DVK_CPUAPP)
#include <hal/nrf_saadc.h>
/* 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
};
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_CPUAPP)
.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_equal(ret, 0,
"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_equal(ret, 0,
"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_equal(ret, 0, "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_equal(ret, 0, "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);