Skip to content

Commit f64d3f7

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 a896076 commit f64d3f7

File tree

8 files changed

+545
-0
lines changed

8 files changed

+545
-0
lines changed

Diff for: cores/arduino/Arduino.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "api/ArduinoAPI.h"
88

99
#include <zephyr/drivers/gpio.h>
10+
#include <zephyr/drivers/adc.h>
1011
#include <zephyr/kernel.h>
1112

1213
#include <variants.h>

Diff for: cores/arduino/zephyrCommon.cpp

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

77
#include <Arduino.h>
88

9+
#define ADC_DT_SPEC(n,p,i) ADC_DT_SPEC_GET_BY_IDX(n, i),
10+
#define ADC_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i),
11+
#define ADC_CH_CFG(n,p,i) arduino_adc[i].channel_cfg,
12+
13+
namespace {
14+
15+
#ifdef CONFIG_ADC
16+
17+
const struct adc_dt_spec arduino_adc[] =
18+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_DT_SPEC) };
19+
20+
/* io-channel-pins node provides a mapping digital pin numbers to adc channels */
21+
const pin_size_t arduino_analog_pins[] =
22+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channel_pins, ADC_PINS) };
23+
24+
struct adc_channel_cfg channel_cfg[ARRAY_SIZE(arduino_analog_pins)] =
25+
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_CH_CFG) };
26+
27+
size_t analog_pin_index(pin_size_t pinNumber) {
28+
for(size_t i=0; i<ARRAY_SIZE(arduino_analog_pins); i++) {
29+
if (arduino_analog_pins[i] == pinNumber) {
30+
return i;
31+
}
32+
}
33+
return (size_t)-1;
34+
}
35+
36+
#endif //CONFIG_ADC
37+
38+
}
39+
940
void yield(void) {
1041
k_yield();
1142
}
@@ -49,3 +80,55 @@ unsigned long micros(void) {
4980

5081
unsigned long millis(void) { return k_uptime_get_32(); }
5182

83+
#ifdef CONFIG_ADC
84+
85+
void analogReference(uint8_t mode)
86+
{
87+
/*
88+
* The Arduino API not clearly defined what means of
89+
* the mode argument of analogReference().
90+
* Treat the value as equivalent to zephyr's adc_reference.
91+
*/
92+
size_t idx;
93+
for (size_t i=0; i<ARRAY_SIZE(channel_cfg); i++) {
94+
channel_cfg[i].reference = static_cast<adc_reference>(mode);
95+
}
96+
}
97+
98+
int analogRead(pin_size_t pinNumber)
99+
{
100+
int err;
101+
int16_t buf;
102+
struct adc_sequence seq = { .buffer = &buf, .buffer_size = sizeof(buf) };
103+
size_t idx = analog_pin_index(pinNumber);
104+
105+
if (idx >= ARRAY_SIZE(arduino_adc) ) {
106+
return -EINVAL;
107+
}
108+
109+
/*
110+
* ADC that is on MCU supported by Zephyr exists
111+
* only 16bit resolution, currently.
112+
*/
113+
if (arduino_adc[idx].resolution > 16) {
114+
return -ENOTSUP;
115+
}
116+
117+
err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg);
118+
if (err < 0) {
119+
return err;
120+
}
121+
122+
seq.channels = BIT(arduino_adc[idx].channel_id);
123+
seq.resolution = arduino_adc[idx].resolution;
124+
seq.oversampling = arduino_adc[idx].oversampling;
125+
126+
err = adc_read(arduino_adc[idx].dev, &seq);
127+
if (err < 0) {
128+
return err;
129+
}
130+
131+
return buf;
132+
}
133+
134+
#endif

Diff for: variants/arduino_mkrzero/arduino_mkrzero.overlay

+97
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,5 +30,99 @@
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+
io-channels = <&adc 0>,
34+
<&adc 10>,
35+
<&adc 11>,
36+
<&adc 4>,
37+
<&adc 5>,
38+
<&adc 6>,
39+
<&adc 7>;
40+
io-channel-pins = <15 16 17 18 19 20 21>;
3041
};
3142
};
43+
44+
&pinctrl {
45+
adc_default: adc_default {
46+
group1 {
47+
pinmux = <PA2B_ADC_AIN0>,
48+
<PB2B_ADC_AIN10>,
49+
<PB3B_ADC_AIN11>,
50+
<PA4B_ADC_AIN4>,
51+
<PA5B_ADC_AIN5>,
52+
<PA6B_ADC_AIN6>,
53+
<PA7B_ADC_AIN7>;
54+
};
55+
};
56+
};
57+
58+
&adc {
59+
status = "okay";
60+
pinctrl-0 = <&adc_default>;
61+
pinctrl-names = "default";
62+
63+
#address-cells = <1>;
64+
#size-cells = <0>;
65+
66+
channel@0 {
67+
reg = <0>;
68+
zephyr,gain = "ADC_GAIN_1";
69+
zephyr,reference = "ADC_REF_INTERNAL";
70+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
71+
zephyr,resolution = <10>;
72+
zephyr,input-positive = <0>;
73+
};
74+
75+
channel@4 {
76+
reg = <4>;
77+
zephyr,gain = "ADC_GAIN_1";
78+
zephyr,reference = "ADC_REF_INTERNAL";
79+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
80+
zephyr,resolution = <10>;
81+
zephyr,input-positive = <4>;
82+
};
83+
84+
channel@5 {
85+
reg = <5>;
86+
zephyr,gain = "ADC_GAIN_1";
87+
zephyr,reference = "ADC_REF_INTERNAL";
88+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
89+
zephyr,resolution = <10>;
90+
zephyr,input-positive = <5>;
91+
};
92+
93+
channel@6 {
94+
reg = <6>;
95+
zephyr,gain = "ADC_GAIN_1";
96+
zephyr,reference = "ADC_REF_INTERNAL";
97+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
98+
zephyr,resolution = <10>;
99+
zephyr,input-positive = <6>;
100+
};
101+
102+
channel@7 {
103+
reg = <7>;
104+
zephyr,gain = "ADC_GAIN_1";
105+
zephyr,reference = "ADC_REF_INTERNAL";
106+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
107+
zephyr,resolution = <10>;
108+
zephyr,input-positive = <7>;
109+
};
110+
111+
channel@10 {
112+
reg = <10>;
113+
zephyr,gain = "ADC_GAIN_1";
114+
zephyr,reference = "ADC_REF_INTERNAL";
115+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
116+
zephyr,resolution = <10>;
117+
zephyr,input-positive = <10>;
118+
};
119+
120+
channel@11 {
121+
reg = <11>;
122+
zephyr,gain = "ADC_GAIN_1";
123+
zephyr,reference = "ADC_REF_INTERNAL";
124+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
125+
zephyr,resolution = <10>;
126+
zephyr,input-positive = <11>;
127+
};
128+
};

Diff for: variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay

+86
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,91 @@
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+
io-channels = <&adc 2>,
26+
<&adc 3>,
27+
<&adc 6>,
28+
<&adc 5>,
29+
<&adc 7>,
30+
<&adc 0>,
31+
<&adc 4>,
32+
<&adc 1>;
33+
io-channel-pins = <14 15 16 17 18 19 20 21>;
34+
};
35+
};
36+
37+
&adc {
38+
#address-cells = <1>;
39+
#size-cells = <0>;
40+
41+
channel@0 {
42+
reg = <0>;
43+
zephyr,gain = "ADC_GAIN_1_6";
44+
zephyr,reference = "ADC_REF_INTERNAL";
45+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
46+
zephyr,input-positive = <NRF_SAADC_AIN0>; /* P0.02 */
47+
zephyr,resolution = <10>;
48+
};
49+
50+
channel@1 {
51+
reg = <1>;
52+
zephyr,gain = "ADC_GAIN_1_6";
53+
zephyr,reference = "ADC_REF_INTERNAL";
54+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
55+
zephyr,input-positive = <NRF_SAADC_AIN1>; /* P0.03 */
56+
zephyr,resolution = <10>;
57+
};
58+
59+
channel@2 {
60+
reg = <2>;
61+
zephyr,gain = "ADC_GAIN_1_6";
62+
zephyr,reference = "ADC_REF_INTERNAL";
63+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
64+
zephyr,input-positive = <NRF_SAADC_AIN2>; /* P0.04 */
65+
zephyr,resolution = <10>;
66+
};
67+
68+
channel@3 {
69+
reg = <3>;
70+
zephyr,gain = "ADC_GAIN_1_6";
71+
zephyr,reference = "ADC_REF_INTERNAL";
72+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
73+
zephyr,input-positive = <NRF_SAADC_AIN3>; /* P0.05 */
74+
zephyr,resolution = <10>;
75+
};
76+
77+
channel@4 {
78+
reg = <4>;
79+
zephyr,gain = "ADC_GAIN_1_6";
80+
zephyr,reference = "ADC_REF_INTERNAL";
81+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
82+
zephyr,input-positive = <NRF_SAADC_AIN4>; /* P0.28 */
83+
zephyr,resolution = <10>;
84+
};
85+
86+
channel@5 {
87+
reg = <5>;
88+
zephyr,gain = "ADC_GAIN_1_6";
89+
zephyr,reference = "ADC_REF_INTERNAL";
90+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
91+
zephyr,input-positive = <NRF_SAADC_AIN5>; /* P0.29 */
92+
zephyr,resolution = <10>;
93+
};
94+
95+
channel@6 {
96+
reg = <6>;
97+
zephyr,gain = "ADC_GAIN_1_6";
98+
zephyr,reference = "ADC_REF_INTERNAL";
99+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
100+
zephyr,input-positive = <NRF_SAADC_AIN6>; /* P0.30 */
101+
zephyr,resolution = <10>;
102+
};
103+
104+
channel@7 {
105+
reg = <7>;
106+
zephyr,gain = "ADC_GAIN_1_6";
107+
zephyr,reference = "ADC_REF_INTERNAL";
108+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
109+
zephyr,input-positive = <NRF_SAADC_AIN7>; /* P0.31 */
110+
zephyr,resolution = <10>;
25111
};
26112
};

Diff for: variants/arduino_nano_33_ble_sense/arduino_nano_33_ble_sense.overlay

+86
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,91 @@
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+
io-channels = <&adc 2>,
26+
<&adc 3>,
27+
<&adc 6>,
28+
<&adc 5>,
29+
<&adc 7>,
30+
<&adc 0>,
31+
<&adc 4>,
32+
<&adc 1>;
33+
io-channel-pins = <14 15 16 17 18 19 20 21>;
34+
};
35+
};
36+
37+
&adc {
38+
#address-cells = <1>;
39+
#size-cells = <0>;
40+
41+
channel@0 {
42+
reg = <0>;
43+
zephyr,gain = "ADC_GAIN_1_6";
44+
zephyr,reference = "ADC_REF_INTERNAL";
45+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
46+
zephyr,input-positive = <NRF_SAADC_AIN0>; /* P0.02 */
47+
zephyr,resolution = <10>;
48+
};
49+
50+
channel@1 {
51+
reg = <1>;
52+
zephyr,gain = "ADC_GAIN_1_6";
53+
zephyr,reference = "ADC_REF_INTERNAL";
54+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
55+
zephyr,input-positive = <NRF_SAADC_AIN1>; /* P0.03 */
56+
zephyr,resolution = <10>;
57+
};
58+
59+
channel@2 {
60+
reg = <2>;
61+
zephyr,gain = "ADC_GAIN_1_6";
62+
zephyr,reference = "ADC_REF_INTERNAL";
63+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
64+
zephyr,input-positive = <NRF_SAADC_AIN2>; /* P0.04 */
65+
zephyr,resolution = <10>;
66+
};
67+
68+
channel@3 {
69+
reg = <3>;
70+
zephyr,gain = "ADC_GAIN_1_6";
71+
zephyr,reference = "ADC_REF_INTERNAL";
72+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
73+
zephyr,input-positive = <NRF_SAADC_AIN3>; /* P0.05 */
74+
zephyr,resolution = <10>;
75+
};
76+
77+
channel@4 {
78+
reg = <4>;
79+
zephyr,gain = "ADC_GAIN_1_6";
80+
zephyr,reference = "ADC_REF_INTERNAL";
81+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
82+
zephyr,input-positive = <NRF_SAADC_AIN4>; /* P0.28 */
83+
zephyr,resolution = <10>;
84+
};
85+
86+
channel@5 {
87+
reg = <5>;
88+
zephyr,gain = "ADC_GAIN_1_6";
89+
zephyr,reference = "ADC_REF_INTERNAL";
90+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
91+
zephyr,input-positive = <NRF_SAADC_AIN5>; /* P0.29 */
92+
zephyr,resolution = <10>;
93+
};
94+
95+
channel@6 {
96+
reg = <6>;
97+
zephyr,gain = "ADC_GAIN_1_6";
98+
zephyr,reference = "ADC_REF_INTERNAL";
99+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
100+
zephyr,input-positive = <NRF_SAADC_AIN6>; /* P0.30 */
101+
zephyr,resolution = <10>;
102+
};
103+
104+
channel@7 {
105+
reg = <7>;
106+
zephyr,gain = "ADC_GAIN_1_6";
107+
zephyr,reference = "ADC_REF_INTERNAL";
108+
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
109+
zephyr,input-positive = <NRF_SAADC_AIN7>; /* P0.31 */
110+
zephyr,resolution = <10>;
25111
};
26112
};

0 commit comments

Comments
 (0)