Commit 5c9e414a authored by Martin Jäger's avatar Martin Jäger Committed by Carles Cufi
Browse files

tests: drivers: dac: Add loopback test with ADC



The loopback test reads back the DAC output with the ADC and checks
that it is in a narrow range.

Signed-off-by: default avatarMartin Jäger <martin@libre.solar>
parent de04d33d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
project(dac_loopback)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
+4 −0
Original line number Diff line number Diff line
CONFIG_ZTEST=y

CONFIG_DAC=y
CONFIG_ADC=y
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 Libre Solar Technologies GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @addtogroup t_driver_dac
 * @{
 * @defgroup t_dac_loopback test_dac_loopback
 * @}
 */

#include <zephyr.h>
#include <ztest.h>

extern void test_dac_loopback(void);

void test_main(void)
{
	ztest_test_suite(dac_loopback_test,
			 ztest_unit_test(test_dac_loopback));
	ztest_run_test_suite(dac_loopback_test);
}
+135 −0
Original line number Diff line number Diff line
/*
 * 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 <drivers/dac.h>
#include <drivers/adc.h>
#include <zephyr.h>
#include <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)

/*
 * DAC output on PA4 (Arduino A2 pin of Nucleo board)
 * ADC input read from PA1 (Arduino A1 pin of Nucleo board)
 */

#define DAC_DEVICE_NAME		DT_LABEL(DT_ALIAS(dac1))
#define DAC_CHANNEL_ID		1
#define DAC_RESOLUTION		12

#define ADC_DEVICE_NAME		DT_LABEL(DT_ALIAS(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

#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,
};

static struct device *init_dac(void)
{
	int ret;
	struct device *dac_dev = device_get_binding(DAC_DEVICE_NAME);

	zassert_not_null(dac_dev, "Cannot get DAC device");

	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 struct device *init_adc(void)
{
	int ret;
	struct device *adc_dev = device_get_binding(ADC_DEVICE_NAME);

	zassert_not_null(adc_dev, "Cannot get ADC device");

	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;

	struct device *dac_dev = init_dac();
	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 s16_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;
}

void test_dac_loopback(void)
{
	zassert_true(test_task_loopback() == TC_PASS, NULL);
}
+6 −0
Original line number Diff line number Diff line
common:
  tags: dac drivers userspace
tests:
  drivers.dac:
    platform_whitelist: nucleo_l073rz
    depends_on: dac