Skip to content

Commit 55b0c93

Browse files
committed
cores: arduino: Split zephyrCommon.cpp
Split zephyrCommon.cpp into smaller source files. wiring_digital.cpp: - pinMode - digitalWrite - digitalRead wiring_analog.cpp: - analogRead - analogWrite - analogReference - analogReadResolution - analogWriteResolution wiring_pulse.cpp: - pulseIn WInterrupts.cpp: - attachInterrupt - detachInterrupt - interrupts - noInterrupts - digitalPinToInterrupt WMath.cpp: - randomSeed - random Tone.cpp: - tone - noTone Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 2497736 commit 55b0c93

10 files changed

Lines changed: 758 additions & 686 deletions

cores/arduino/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ if(CONFIG_USE_ARDUINO_API_RUST_IMPLEMENTATION)
1919
zephyr_sources(apiCommon.cpp)
2020
endif()
2121

22+
zephyr_sources(wiring_analog.cpp)
23+
zephyr_sources(wiring_digital.cpp)
24+
zephyr_sources(wiring_pulse.cpp)
25+
zephyr_sources(Tone.cpp)
26+
zephyr_sources(WMath.cpp)
27+
zephyr_sources(WInterrupts.cpp)
28+
2229
if(DEFINED CONFIG_ARDUINO_ENTRY)
2330
zephyr_sources(main.cpp)
2431
endif()

cores/arduino/Tone.cpp

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
3+
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
4+
* Copyright (c) 2026 TOKITA Hiroshi
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <Arduino.h>
10+
#include "wiring_private.h"
11+
12+
using namespace zephyr::arduino;
13+
14+
namespace {
15+
16+
#if CONFIG_ARDUINO_MAX_TONES < 0
17+
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
18+
#else
19+
#define MAX_TONE_PINS CONFIG_ARDUINO_MAX_TONES
20+
#endif
21+
22+
#define TOGGLES_PER_CYCLE 2ULL
23+
24+
static struct pin_timer {
25+
struct k_timer timer;
26+
uint32_t count{0};
27+
pin_size_t pin{pin_size_t(-1)};
28+
bool infinity{false};
29+
bool timer_initialized{false};
30+
struct k_spinlock lock{};
31+
} arduino_pin_timers[MAX_TONE_PINS];
32+
33+
K_MUTEX_DEFINE(timer_cfg_lock);
34+
35+
void tone_expiry_cb(struct k_timer *timer);
36+
37+
/* Callers must hold timer_cfg_lock while using this helper. */
38+
static struct pin_timer *find_pin_timer(pin_size_t pinNumber, bool active_only) {
39+
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
40+
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
41+
42+
if (arduino_pin_timers[i].pin == pinNumber) {
43+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
44+
return &arduino_pin_timers[i];
45+
}
46+
47+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
48+
}
49+
50+
if (active_only) {
51+
return nullptr;
52+
}
53+
54+
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
55+
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
56+
57+
if (arduino_pin_timers[i].pin == pin_size_t(-1)) {
58+
arduino_pin_timers[i].pin = pinNumber;
59+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
60+
return &arduino_pin_timers[i];
61+
}
62+
63+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
64+
}
65+
66+
return nullptr;
67+
}
68+
69+
void tone_expiry_cb(struct k_timer *timer) {
70+
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
71+
k_spinlock_key_t key = k_spin_lock(&pt->lock);
72+
pin_size_t pin = pt->pin;
73+
74+
if (pt->count == 0 && !pt->infinity) {
75+
if (pin != pin_size_t(-1)) {
76+
gpio_pin_set_dt(&arduino_pins[pin], 0);
77+
}
78+
79+
k_timer_stop(timer);
80+
pt->count = 0;
81+
pt->infinity = false;
82+
pt->pin = pin_size_t(-1);
83+
} else {
84+
if (pin != pin_size_t(-1)) {
85+
gpio_pin_toggle_dt(&arduino_pins[pin]);
86+
}
87+
pt->count--;
88+
}
89+
90+
k_spin_unlock(&pt->lock, key);
91+
}
92+
93+
} // anonymous namespace
94+
95+
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
96+
RETURN_ON_INVALID_PIN(pinNumber);
97+
98+
k_spinlock_key_t key;
99+
uint64_t toggles_count;
100+
struct pin_timer *pt;
101+
k_timeout_t timeout;
102+
103+
if (k_is_in_isr()) {
104+
return;
105+
}
106+
107+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
108+
109+
pt = find_pin_timer(pinNumber, false);
110+
111+
if (pt == nullptr) {
112+
k_mutex_unlock(&timer_cfg_lock);
113+
return;
114+
}
115+
116+
if (!pt->timer_initialized) {
117+
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
118+
pt->timer_initialized = true;
119+
}
120+
121+
pinMode(pinNumber, OUTPUT);
122+
k_timer_stop(&pt->timer);
123+
124+
toggles_count = ((uint64_t)duration * frequency / (MSEC_PER_SEC / TOGGLES_PER_CYCLE));
125+
if (frequency == 0 || (toggles_count == 0 && duration != 0)) {
126+
key = k_spin_lock(&pt->lock);
127+
pt->count = 0;
128+
pt->infinity = false;
129+
pt->pin = pin_size_t(-1);
130+
k_spin_unlock(&pt->lock, key);
131+
132+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
133+
134+
k_mutex_unlock(&timer_cfg_lock);
135+
return;
136+
}
137+
138+
timeout = K_NSEC(NSEC_PER_SEC / (TOGGLES_PER_CYCLE * frequency));
139+
if (timeout.ticks == 0) {
140+
timeout.ticks = 1;
141+
}
142+
143+
key = k_spin_lock(&pt->lock);
144+
pt->infinity = (duration == 0);
145+
pt->count = min(toggles_count, UINT32_MAX);
146+
pt->pin = pinNumber;
147+
k_spin_unlock(&pt->lock, key);
148+
149+
gpio_pin_set_dt(&arduino_pins[pinNumber], 1);
150+
k_timer_start(&pt->timer, timeout, timeout);
151+
152+
k_mutex_unlock(&timer_cfg_lock);
153+
}
154+
155+
void noTone(pin_size_t pinNumber) {
156+
RETURN_ON_INVALID_PIN(pinNumber);
157+
158+
struct pin_timer *pt;
159+
k_spinlock_key_t key;
160+
161+
if (k_is_in_isr()) {
162+
return;
163+
}
164+
165+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
166+
167+
pt = find_pin_timer(pinNumber, true);
168+
169+
if (pt == nullptr) {
170+
k_mutex_unlock(&timer_cfg_lock);
171+
return;
172+
}
173+
174+
key = k_spin_lock(&pt->lock);
175+
k_timer_stop(&pt->timer);
176+
pt->count = 0;
177+
pt->infinity = false;
178+
pt->pin = pin_size_t(-1);
179+
k_spin_unlock(&pt->lock, key);
180+
181+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
182+
183+
k_mutex_unlock(&timer_cfg_lock);
184+
}

cores/arduino/WInterrupts.cpp

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
3+
* Copyright (c) 2022 TOKITA Hiroshi
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <Arduino.h>
9+
#include "wiring_private.h"
10+
11+
using namespace zephyr::arduino;
12+
13+
namespace {
14+
15+
/*
16+
* GPIO callback implementation
17+
*/
18+
19+
struct arduino_callback {
20+
voidFuncPtr handler;
21+
bool enabled;
22+
};
23+
24+
struct gpio_port_callback {
25+
struct gpio_callback callback;
26+
struct arduino_callback handlers[max_ngpios];
27+
gpio_port_pins_t pins;
28+
const struct device *dev;
29+
} port_callback[port_num] = {};
30+
31+
unsigned int irq_key;
32+
bool interrupts_disabled = false;
33+
34+
struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) {
35+
for (size_t i = 0; i < ARRAY_SIZE(port_callback); i++) {
36+
if (port_callback[i].dev == dev) {
37+
return &port_callback[i];
38+
}
39+
if (port_callback[i].dev == nullptr) {
40+
port_callback[i].dev = dev;
41+
return &port_callback[i];
42+
}
43+
}
44+
45+
return nullptr;
46+
}
47+
48+
void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) {
49+
RETURN_ON_INVALID_PIN(pinNumber);
50+
51+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
52+
53+
if (pcb) {
54+
pcb->handlers[arduino_pins[pinNumber].pin].handler = func;
55+
}
56+
}
57+
58+
void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) {
59+
(void)port; // unused
60+
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;
61+
62+
for (uint32_t i = 0; i < max_ngpios; i++) {
63+
if (pins & BIT(i) && pcb->handlers[i].enabled) {
64+
pcb->handlers[i].handler();
65+
}
66+
}
67+
}
68+
69+
void enableInterrupt(pin_size_t pinNumber) {
70+
RETURN_ON_INVALID_PIN(pinNumber);
71+
72+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
73+
74+
if (pcb) {
75+
pcb->handlers[arduino_pins[pinNumber].pin].enabled = true;
76+
}
77+
}
78+
79+
void disableInterrupt(pin_size_t pinNumber) {
80+
RETURN_ON_INVALID_PIN(pinNumber);
81+
82+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
83+
84+
if (pcb) {
85+
pcb->handlers[arduino_pins[pinNumber].pin].enabled = false;
86+
}
87+
}
88+
89+
} // anonymous namespace
90+
91+
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) {
92+
RETURN_ON_INVALID_PIN(pinNumber);
93+
94+
struct gpio_port_callback *pcb;
95+
gpio_flags_t intmode = 0;
96+
97+
if (!callback) {
98+
return;
99+
}
100+
101+
if (pinStatus == LOW) {
102+
intmode |= GPIO_INT_LEVEL_LOW;
103+
} else if (pinStatus == HIGH) {
104+
intmode |= GPIO_INT_LEVEL_HIGH;
105+
} else if (pinStatus == CHANGE) {
106+
intmode |= GPIO_INT_EDGE_BOTH;
107+
} else if (pinStatus == FALLING) {
108+
intmode |= GPIO_INT_EDGE_FALLING;
109+
} else if (pinStatus == RISING) {
110+
intmode |= GPIO_INT_EDGE_RISING;
111+
} else {
112+
return;
113+
}
114+
115+
pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
116+
__ASSERT(pcb != nullptr, "gpio_port_callback not found");
117+
118+
pcb->pins |= BIT(arduino_pins[pinNumber].pin);
119+
setInterruptHandler(pinNumber, callback);
120+
enableInterrupt(pinNumber);
121+
122+
gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin,
123+
intmode);
124+
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
125+
gpio_add_callback(arduino_pins[pinNumber].port, &pcb->callback);
126+
}
127+
128+
void detachInterrupt(pin_size_t pinNumber) {
129+
RETURN_ON_INVALID_PIN(pinNumber);
130+
131+
setInterruptHandler(pinNumber, nullptr);
132+
disableInterrupt(pinNumber);
133+
}
134+
135+
void interrupts(void) {
136+
if (interrupts_disabled) {
137+
irq_unlock(irq_key);
138+
interrupts_disabled = false;
139+
}
140+
}
141+
142+
void noInterrupts(void) {
143+
if (!interrupts_disabled) {
144+
irq_key = irq_lock();
145+
interrupts_disabled = true;
146+
}
147+
}
148+
149+
int digitalPinToInterrupt(pin_size_t pinNumber) {
150+
RETURN_ON_INVALID_PIN(pinNumber, -1);
151+
152+
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
153+
154+
return (pcb) ? pinNumber : -1;
155+
}

cores/arduino/WMath.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
3+
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
4+
* Copyright (c) 2026 TOKITA Hiroshi
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <Arduino.h>
10+
11+
#ifndef CONFIG_MINIMAL_LIBC_RAND
12+
13+
#include <stdlib.h>
14+
15+
void randomSeed(unsigned long seed) {
16+
srand(seed);
17+
}
18+
19+
long random(long min, long max) {
20+
return rand() % (max - min) + min;
21+
}
22+
23+
long random(long max) {
24+
return rand() % max;
25+
}
26+
27+
#endif

0 commit comments

Comments
 (0)