DAC

The phyCORE-RT1170 features a built-in Digital-to-Analog Converter (DAC) with a 12-bit resolution. This allows it to generate analog voltages ranging from 0 V up to the internal reference voltage.

Setting a Value via Shell

Before the DAC can be used, the driver must be initialized. The RT1170 provides only a single DAC channel with a fixed 12-bit resolution. To initialize the channel, use the following command:

uart:~$ dac setup dac 0 12

To produce a specific output voltage, it’s important to understand how the DAC translates digital values to analog voltages. The DAC operates with an internal reference voltage of 1.8 V. With 12-bit resolution, there are 4096 discrete output steps, meaning the digital value must fall within the range 0 to 4095.

You can compute the required DAC value for a desired output voltage using the following formula:

\[\text{value} = 4095 \times \left( \frac{\text{voltage}}{1.8\,\text{V}} \right)\]

Once you’ve calculated the appropriate value, write it to the DAC using:

uart:~$ dac write_value dac 0 <value>

Saw Tooth Example

The dac_sawtooth() function continuously outputs increasing voltage levels to a DAC channel, forming a ramp or “saw tooth” pattern when observed with an oscilloscope.

DAC Device Initialization

The function begins by retrieving the DAC device specified in the devicetree using the DEVICE_DT_GET_OR_NULL() macro. It verifies that the device is ready with device_is_ready(). If the device is not ready, the function logs an error and exits early.

DAC Channel Configuration

To prepare the DAC for use, a struct dac_channel_cfg is initialized and configured with two key parameters: - channel_id is set to the defined DAC channel (in this case, 0). - resolution is set to 12 bits, allowing values from 0 to 4095.

This configuration is passed to dac_channel_setup(), which initializes the DAC channel with the specified settings. If the setup fails, an error is logged and the function exits.

Generating the Saw Tooth Pattern

In an infinite loop, the function writes a value to the DAC using dac_write_value(). The value starts at 0 and increases by a fixed step (DAC_STEPS, set to 100) with each iteration. After each write, the function sleeps for 200 milliseconds using k_sleep(), which introduces a visible time delay between voltage level changes.

When the output value exceeds the maximum possible value (4095 for 12-bit resolution), it wraps around to 0, creating a repeating rising-edge pattern—hence the “saw tooth” shape.

This example demonstrates the typical usage of the Zephyr DAC API: - Initializing the DAC with dac_channel_setup() - Writing output values using dac_write_value() - Monitoring behavior through incremental updates and delays

Source Code

#include <zephyr/kernel.h>
#include <zephyr/drivers/dac.h>
#include <zephyr/sys/printk.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(dac, CONFIG_APP_LOG_LEVEL);

#define SLEEP_TIME_MS			200

/* size of stack area used by each thread */
#define DAC_SAWTOOTH_STACKSIZE		1024
/* scheduling priority used by each thread */
#define DAC_SAWTOOTH_PRIORITY		5

#define DAC_CHANNEL			0
#define DAC_RESOLUTION			12
#define DAC_STEPS			100
#define DAC_MAX_VALUE			4095

/*
 * Get DAC configuration from the devicetree dac node label. This is mandatory.
 */
#define DAC_NODE			DT_NODELABEL(dac)
static const struct device *dac = DEVICE_DT_GET_OR_NULL(DAC_NODE);

void dac_sawtooth(void)
{
	int ret;
	struct dac_channel_cfg cfg = {0};
	uint32_t output_value = 0;

	if (!device_is_ready(dac)) {
		LOG_ERR("%s is not ready", dac->name);
		return;
	}

	cfg.channel_id = DAC_CHANNEL;
	cfg.resolution = DAC_RESOLUTION;
	ret = dac_channel_setup(dac, &cfg);
	if (ret < 0) {
		LOG_ERR("Unable to configure %s", dac->name);
		return;
	}

	while (1) {
		ret = dac_write_value(dac, DAC_CHANNEL, output_value);
		if (ret < 0) {
			LOG_ERR("Failed to write value to %s", dac->name);
			return;
		}

		k_sleep(K_MSEC(SLEEP_TIME_MS));

		output_value += DAC_STEPS;
		if (output_value > DAC_MAX_VALUE)
			output_value = 0;
	}

	return;
}

K_THREAD_DEFINE(dac_sawtooth_tid, DAC_SAWTOOTH_STACKSIZE, dac_sawtooth, NULL, NULL,
		NULL, DAC_SAWTOOTH_PRIORITY, 0, 0);

For more information see the dac_sawtooth.c file.