Skip to content

Commit 5c09229

Browse files
committed
cores: arduino: Split zephyrCommon.cpp
Split zephyrCommon.cpp into small cpp files. wirinig_digital.cpp: - pinMode - digitalWrite - digitalRead wirinig_analog.cpp: - analogRead - analogWrite - analogReference - analogReadResolution - analogWriteResolution wirinig_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 911a80b commit 5c09229

10 files changed

Lines changed: 745 additions & 662 deletions

cores/arduino/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ zephyr_sources(zephyrCommon.cpp)
99
zephyr_sources(USB.cpp)
1010
zephyr_sources(itoa.cpp)
1111

12+
zephyr_sources(wiring_analog.cpp)
13+
zephyr_sources(wiring_digital.cpp)
14+
zephyr_sources(wiring_pulse.cpp)
15+
zephyr_sources(Tone.cpp)
16+
zephyr_sources(WMath.cpp)
17+
zephyr_sources(WInterrupts.cpp)
18+
1219
if(DEFINED CONFIG_ARDUINO_ENTRY)
1320
zephyr_sources(main.cpp)
1421
zephyr_sources(threads.cpp)

cores/arduino/Tone.cpp

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

cores/arduino/WInterrupts.cpp

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

cores/arduino/WMath.cpp

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

0 commit comments

Comments
 (0)