Skip to content

Commit 24fdac1

Browse files
facchinmpillo79
authored andcommitted
analogWrite: implement DAC pins
Co-Authored-by: Martino Facchin <m.facchin@arduino.cc> Co-Authored-by: Luca Burelli <l.burelli@arduino.cc> Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent b9ce5ac commit 24fdac1

3 files changed

Lines changed: 123 additions & 0 deletions

File tree

cores/arduino/Arduino.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <zephyr/drivers/gpio.h>
1313
#include <zephyr/drivers/pwm.h>
1414
#include <zephyr/drivers/adc.h>
15+
#include <zephyr/drivers/dac.h>
1516
#include <zephyr/drivers/i2c.h>
1617

1718
#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0
@@ -105,11 +106,37 @@ enum analogPins {
105106

106107
#endif
107108

109+
#ifdef CONFIG_DAC
110+
111+
#undef DAC0
112+
#undef DAC1
113+
#undef DAC2
114+
#undef DAC3
115+
#define DAC_ENUMS(n, p, i) DAC##i = i,
116+
117+
enum dacPins {
118+
#if DT_PROP_LEN_OR(DT_PATH(zephyr_user), dac_channels, 0) > 0
119+
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), dac_channels, DAC_ENUMS)
120+
#endif
121+
NUM_OF_DACS
122+
};
123+
124+
#endif
125+
108126
void interrupts(void);
109127
void noInterrupts(void);
110128

111129
int digitalPinToInterrupt(pin_size_t pin);
112130

131+
#define digitalPinToPort(x) (x)
132+
#define digitalPinToBitMask(x) (x)
133+
#define portOutputRegister(x) (x)
134+
#define portInputRegister(x) (x)
135+
136+
#if defined(CONFIG_PWM) || defined(CONFIG_DAC)
137+
void analogWriteResolution(int bits);
138+
#endif
139+
113140
#include <variant.h>
114141

115142
#if !defined(LED_BUILTIN) && defined(ZARD_LED_BUILTIN)
@@ -120,4 +147,12 @@ int digitalPinToInterrupt(pin_size_t pin);
120147

121148
#ifdef __cplusplus
122149
#include <zephyrSerial.h>
150+
#include <strings.h>
151+
#include <api/itoa.h>
152+
#include <time_macros.h>
153+
#include <overloads.h>
154+
155+
// Allow namespace-less operations if Arduino.h is included
156+
using namespace arduino;
157+
123158
#endif // __cplusplus

cores/arduino/overloads.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifdef CONFIG_DAC
8+
9+
void analogWrite(enum dacPins pinNumber, int value);
10+
11+
#endif
12+
13+
// In c++ mode, we also provide analogReadResolution and analogWriteResolution getters
14+
int analogReadResolution();
15+
int analogWriteResolution();

cores/arduino/zephyrCommon.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,32 @@ size_t analog_pin_index(pin_size_t pinNumber) {
175175

176176
#endif // CONFIG_ADC
177177

178+
#ifdef CONFIG_DAC
179+
180+
#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dac))
181+
182+
#define DAC_NODE DT_PHANDLE(DT_PATH(zephyr_user), dac)
183+
#define DAC_RESOLUTION DT_PROP(DT_PATH(zephyr_user), dac_resolution)
184+
static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE);
185+
186+
#define DAC_CHANNEL_DEFINE(n, p, i) \
187+
{ \
188+
.channel_id = DT_PROP_BY_IDX(n, p, i), \
189+
.resolution = DAC_RESOLUTION, \
190+
.buffered = true, \
191+
},
192+
193+
#if DT_PROP_LEN_OR(DT_PATH(zephyr_user), dac_channels, 0) > 0
194+
static const struct dac_channel_cfg dac_ch_cfg[] = {
195+
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), dac_channels, DAC_CHANNEL_DEFINE)};
196+
197+
static bool dac_channel_initialized[NUM_OF_DACS];
198+
#endif
199+
200+
#endif
201+
202+
#endif // CONFIG_DAC
203+
178204
static unsigned int irq_key;
179205
static bool interrupts_disabled = false;
180206
} // namespace
@@ -350,6 +376,18 @@ unsigned long millis(void) {
350376
return k_uptime_get_32();
351377
}
352378

379+
#if defined(CONFIG_DAC) || defined(CONFIG_PWM)
380+
static int _analog_write_resolution = 8;
381+
382+
void analogWriteResolution(int bits) {
383+
_analog_write_resolution = bits;
384+
}
385+
386+
int analogWriteResolution() {
387+
return _analog_write_resolution;
388+
}
389+
#endif
390+
353391
#ifdef CONFIG_PWM
354392

355393
static uint32_t map64(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min,
@@ -382,6 +420,41 @@ void analogWrite(pin_size_t pinNumber, int value) {
382420

383421
#endif
384422

423+
#ifdef CONFIG_DAC
424+
void analogWrite(enum dacPins dacName, int value) {
425+
#if DT_PROP_LEN_OR(DT_PATH(zephyr_user), dac_channels, 0) > 0
426+
const int maxInput = BIT(_analog_write_resolution) - 1U;
427+
int ret = 0;
428+
429+
if (dacName >= NUM_OF_DACS) {
430+
return;
431+
}
432+
433+
if (!dac_channel_initialized[dacName]) {
434+
if (!device_is_ready(dac_dev)) {
435+
return;
436+
}
437+
438+
ret = dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]);
439+
if (ret != 0) {
440+
return;
441+
}
442+
dac_channel_initialized[dacName] = true;
443+
}
444+
445+
value = CLAMP(value, 0, maxInput);
446+
447+
const int max_dac_value = BIT(dac_ch_cfg[dacName].resolution) - 1;
448+
const uint32_t output = map(value, 0, maxInput, 0, max_dac_value);
449+
450+
(void)dac_write_value(dac_dev, dac_ch_cfg[dacName].channel_id, output);
451+
#else
452+
ARG_UNUSED(dacName);
453+
ARG_UNUSED(value);
454+
#endif
455+
}
456+
#endif
457+
385458
#ifdef CONFIG_ADC
386459

387460
void analogReference(uint8_t mode) {

0 commit comments

Comments
 (0)