Skip to content

Commit e6f489f

Browse files
committed
zephyrCommon: Implement analogRead()/analogReference()
The 'io-channels' node under the 'zephyr,user' defines available ADC channels. The 'io-channel-pins' defines the mapping of ADC channels to pin numbers. API looks up the 'io-channel-pins' when querying the ADC channel by digital pin number. So it should be in the same order as 'io-channels' node. For original Arduino API compatibility, adc resolution should configure as 10-bit. ADC that is on MCU supported by Zephyr exists only 16-bit resolution currently. So it supports resolutions up to 16-bit. Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent 37f6176 commit e6f489f

File tree

8 files changed

+578
-33
lines changed

8 files changed

+578
-33
lines changed

Diff for: cores/arduino/Arduino.h

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <zephyr/drivers/gpio.h>
1010
#include <zephyr/drivers/pwm.h>
11+
#include <zephyr/drivers/adc.h>
1112
#include <zephyr/kernel.h>
1213

1314
#include <variants.h>

Diff for: cores/arduino/zephyrCommon.cpp

+83-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
#include <Arduino.h>
88

9-
#define PWM_DT_SPEC(n,p,i) PWM_DT_SPEC_GET_BY_IDX(n, i),
10-
#define PWM_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i),
11-
129
namespace {
1310

1411
#ifdef CONFIG_PWM
1512

13+
#define PWM_DT_SPEC(n,p,i) PWM_DT_SPEC_GET_BY_IDX(n, i),
14+
#define PWM_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i),
15+
1616
const struct pwm_dt_spec arduino_pwm[] =
1717
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) };
1818

@@ -31,6 +31,33 @@ size_t pwm_pin_index(pin_size_t pinNumber) {
3131

3232
#endif //CONFIG_PWM
3333

34+
#ifdef CONFIG_ADC
35+
36+
#define ADC_DT_SPEC(n,p,i) ADC_DT_SPEC_GET_BY_IDX(n, i),
37+
#define ADC_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i),
38+
#define ADC_CH_CFG(n,p,i) arduino_adc[i].channel_cfg,
39+
40+
const struct adc_dt_spec arduino_adc[] =
41+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_DT_SPEC) };
42+
43+
/* io-channel-pins node provides a mapping digital pin numbers to adc channels */
44+
const pin_size_t arduino_analog_pins[] =
45+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channel_pins, ADC_PINS) };
46+
47+
struct adc_channel_cfg channel_cfg[ARRAY_SIZE(arduino_analog_pins)] =
48+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_CH_CFG) };
49+
50+
size_t analog_pin_index(pin_size_t pinNumber) {
51+
for(size_t i=0; i<ARRAY_SIZE(arduino_analog_pins); i++) {
52+
if (arduino_analog_pins[i] == pinNumber) {
53+
return i;
54+
}
55+
}
56+
return (size_t)-1;
57+
}
58+
59+
#endif //CONFIG_ADC
60+
3461
}
3562

3663
void yield(void) {
@@ -101,3 +128,56 @@ void analogWrite(pin_size_t pinNumber, int value)
101128
}
102129

103130
#endif
131+
132+
#ifdef CONFIG_ADC
133+
134+
void analogReference(uint8_t mode)
135+
{
136+
/*
137+
* The Arduino API not clearly defined what means of
138+
* the mode argument of analogReference().
139+
* Treat the value as equivalent to zephyr's adc_reference.
140+
*/
141+
size_t idx;
142+
for (size_t i=0; i<ARRAY_SIZE(channel_cfg); i++) {
143+
channel_cfg[i].reference = static_cast<adc_reference>(mode);
144+
}
145+
}
146+
147+
int analogRead(pin_size_t pinNumber)
148+
{
149+
int err;
150+
int16_t buf;
151+
struct adc_sequence seq = { .buffer = &buf, .buffer_size = sizeof(buf) };
152+
size_t idx = analog_pin_index(pinNumber);
153+
154+
if (idx >= ARRAY_SIZE(arduino_adc) ) {
155+
return -EINVAL;
156+
}
157+
158+
/*
159+
* ADC that is on MCU supported by Zephyr exists
160+
* only 16bit resolution, currently.
161+
*/
162+
if (arduino_adc[idx].resolution > 16) {
163+
return -ENOTSUP;
164+
}
165+
166+
err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg);
167+
if (err < 0) {
168+
return err;
169+
}
170+
171+
seq.channels = BIT(arduino_adc[idx].channel_id);
172+
seq.resolution = arduino_adc[idx].resolution;
173+
seq.oversampling = arduino_adc[idx].oversampling;
174+
175+
err = adc_read(arduino_adc[idx].dev, &seq);
176+
if (err < 0) {
177+
return err;
178+
}
179+
180+
return buf;
181+
}
182+
183+
#endif

Diff for: variants/arduino_mkrzero/arduino_mkrzero.overlay

+109-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6+
7+
#include <zephyr/dt-bindings/adc/adc.h>
8+
69
/ {
710
zephyr,user {
811
d0_gpios = <&arduino_mkr_header 0 0>;
@@ -27,27 +30,121 @@
2730
d19_gpios = <&arduino_mkr_header 19 0>; /* D19 / A5 / I2C-SCL */
2831
d20_gpios = <&arduino_mkr_header 20 0>;
2932
d21_gpios = <&arduino_mkr_header 21 0>;
33+
3034
pwms = <&tcc0 2 255>,
3135
<&tcc0 3 255>;
3236
pwm-pins = <2 3>;
37+
38+
io-channels = <&adc 0>,
39+
<&adc 10>,
40+
<&adc 11>,
41+
<&adc 4>,
42+
<&adc 5>,
43+
<&adc 6>,
44+
<&adc 7>;
45+
io-channel-pins = <15 16 17 18 19 20 21>;
3346
};
3447
};
3548

3649
&pinctrl {
37-
pwm_default: pwm_default {
38-
group1 {
39-
pinmux = <PA10F_TCC0_WO2>,
40-
<PA11F_TCC0_WO3>;
41-
};
42-
};
50+
pwm_default: pwm_default {
51+
group1 {
52+
pinmux = <PA10F_TCC0_WO2>,
53+
<PA11F_TCC0_WO3>;
54+
};
55+
};
56+
57+
adc_default: adc_default {
58+
group1 {
59+
pinmux = <PA2B_ADC_AIN0>,
60+
<PB2B_ADC_AIN10>,
61+
<PB3B_ADC_AIN11>,
62+
<PA4B_ADC_AIN4>,
63+
<PA5B_ADC_AIN5>,
64+
<PA6B_ADC_AIN6>,
65+
<PA7B_ADC_AIN7>;
66+
};
67+
};
4368
};
4469

4570
&tcc0 {
46-
status = "okay";
47-
compatible = "atmel,sam0-tcc-pwm";
48-
prescaler = <2>;
49-
#pwm-cells = <2>;
71+
status = "okay";
72+
compatible = "atmel,sam0-tcc-pwm";
73+
prescaler = <2>;
74+
#pwm-cells = <2>;
75+
76+
pinctrl-0 = <&pwm_default>;
77+
pinctrl-names = "default";
78+
};
79+
80+
&adc {
81+
status = "okay";
82+
pinctrl-0 = <&adc_default>;
83+
pinctrl-names = "default";
84+
85+
#address-cells = <1>;
86+
#size-cells = <0>;
87+
88+
channel@0 {
89+
reg = <0>;
90+
zephyr,gain = "ADC_GAIN_1";
91+
zephyr,reference = "ADC_REF_INTERNAL";
92+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
93+
zephyr,resolution = <10>;
94+
zephyr,input-positive = <0>;
95+
};
96+
97+
channel@4 {
98+
reg = <4>;
99+
zephyr,gain = "ADC_GAIN_1";
100+
zephyr,reference = "ADC_REF_INTERNAL";
101+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
102+
zephyr,resolution = <10>;
103+
zephyr,input-positive = <4>;
104+
};
105+
106+
channel@5 {
107+
reg = <5>;
108+
zephyr,gain = "ADC_GAIN_1";
109+
zephyr,reference = "ADC_REF_INTERNAL";
110+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
111+
zephyr,resolution = <10>;
112+
zephyr,input-positive = <5>;
113+
};
114+
115+
channel@6 {
116+
reg = <6>;
117+
zephyr,gain = "ADC_GAIN_1";
118+
zephyr,reference = "ADC_REF_INTERNAL";
119+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
120+
zephyr,resolution = <10>;
121+
zephyr,input-positive = <6>;
122+
};
123+
124+
channel@7 {
125+
reg = <7>;
126+
zephyr,gain = "ADC_GAIN_1";
127+
zephyr,reference = "ADC_REF_INTERNAL";
128+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
129+
zephyr,resolution = <10>;
130+
zephyr,input-positive = <7>;
131+
};
50132

51-
pinctrl-0 = <&pwm_default>;
52-
pinctrl-names = "default";
133+
channel@10 {
134+
reg = <10>;
135+
zephyr,gain = "ADC_GAIN_1";
136+
zephyr,reference = "ADC_REF_INTERNAL";
137+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
138+
zephyr,resolution = <10>;
139+
zephyr,input-positive = <10>;
140+
};
141+
142+
channel@11 {
143+
reg = <11>;
144+
zephyr,gain = "ADC_GAIN_1";
145+
zephyr,reference = "ADC_REF_INTERNAL";
146+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
147+
zephyr,resolution = <10>;
148+
zephyr,input-positive = <11>;
149+
};
53150
};

Diff for: variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay

+88
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
d19_gpios = <&arduino_nano_header 19 0>; /* D19 / A5 / I2C-SCL */
2323
d20_gpios = <&arduino_nano_header 20 0>;
2424
d21_gpios = <&arduino_nano_header 21 0>;
25+
2526
pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>,
2627
<&pwm1 2 255 PWM_POLARITY_NORMAL>,
2728
<&pwm1 3 255 PWM_POLARITY_NORMAL>,
@@ -30,6 +31,93 @@
3031
<&pwm2 2 255 PWM_POLARITY_NORMAL>,
3132
<&pwm2 3 255 PWM_POLARITY_NORMAL>;
3233
pwm-pins = <3 5 6 13 9 10 11>;
34+
35+
io-channels = <&adc 2>,
36+
<&adc 3>,
37+
<&adc 6>,
38+
<&adc 5>,
39+
<&adc 7>,
40+
<&adc 0>,
41+
<&adc 4>,
42+
<&adc 1>;
43+
io-channel-pins = <14 15 16 17 18 19 20 21>;
44+
};
45+
};
46+
47+
&adc {
48+
#address-cells = <1>;
49+
#size-cells = <0>;
50+
51+
channel@0 {
52+
reg = <0>;
53+
zephyr,gain = "ADC_GAIN_1_6";
54+
zephyr,reference = "ADC_REF_INTERNAL";
55+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
56+
zephyr,input-positive = <NRF_SAADC_AIN0>; /* P0.02 */
57+
zephyr,resolution = <10>;
58+
};
59+
60+
channel@1 {
61+
reg = <1>;
62+
zephyr,gain = "ADC_GAIN_1_6";
63+
zephyr,reference = "ADC_REF_INTERNAL";
64+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
65+
zephyr,input-positive = <NRF_SAADC_AIN1>; /* P0.03 */
66+
zephyr,resolution = <10>;
67+
};
68+
69+
channel@2 {
70+
reg = <2>;
71+
zephyr,gain = "ADC_GAIN_1_6";
72+
zephyr,reference = "ADC_REF_INTERNAL";
73+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
74+
zephyr,input-positive = <NRF_SAADC_AIN2>; /* P0.04 */
75+
zephyr,resolution = <10>;
76+
};
77+
78+
channel@3 {
79+
reg = <3>;
80+
zephyr,gain = "ADC_GAIN_1_6";
81+
zephyr,reference = "ADC_REF_INTERNAL";
82+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
83+
zephyr,input-positive = <NRF_SAADC_AIN3>; /* P0.05 */
84+
zephyr,resolution = <10>;
85+
};
86+
87+
channel@4 {
88+
reg = <4>;
89+
zephyr,gain = "ADC_GAIN_1_6";
90+
zephyr,reference = "ADC_REF_INTERNAL";
91+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
92+
zephyr,input-positive = <NRF_SAADC_AIN4>; /* P0.28 */
93+
zephyr,resolution = <10>;
94+
};
95+
96+
channel@5 {
97+
reg = <5>;
98+
zephyr,gain = "ADC_GAIN_1_6";
99+
zephyr,reference = "ADC_REF_INTERNAL";
100+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
101+
zephyr,input-positive = <NRF_SAADC_AIN5>; /* P0.29 */
102+
zephyr,resolution = <10>;
103+
};
104+
105+
channel@6 {
106+
reg = <6>;
107+
zephyr,gain = "ADC_GAIN_1_6";
108+
zephyr,reference = "ADC_REF_INTERNAL";
109+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
110+
zephyr,input-positive = <NRF_SAADC_AIN6>; /* P0.30 */
111+
zephyr,resolution = <10>;
112+
};
113+
114+
channel@7 {
115+
reg = <7>;
116+
zephyr,gain = "ADC_GAIN_1_6";
117+
zephyr,reference = "ADC_REF_INTERNAL";
118+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
119+
zephyr,input-positive = <NRF_SAADC_AIN7>; /* P0.31 */
120+
zephyr,resolution = <10>;
33121
};
34122
};
35123

0 commit comments

Comments
 (0)