Skip to content

Commit 766dd5b

Browse files
committed
zephyrCommon: Improved tone implementation
Improved to align more closely with the standard Arduino implementation. - Eliminated the end timer and used counting to determine the end. - Improved to handle infinity correctly. - Added a guard to prevent the timeout value from reaching 0. - Set the GPIO value to 0 when the timer starts. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 87421b4 commit 766dd5b

File tree

1 file changed

+46
-17
lines changed

1 file changed

+46
-17
lines changed

cores/arduino/zephyrCommon.cpp

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,32 @@ PinStatus digitalRead(pin_size_t pinNumber) {
230230
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
231231
}
232232

233-
struct k_timer arduino_pin_timers[ARRAY_SIZE(arduino_pins)];
234-
struct k_timer arduino_pin_timers_timeout[ARRAY_SIZE(arduino_pins)];
233+
#ifndef MAX_TONE_PINS
234+
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
235+
#endif
236+
237+
#define TOGGLES_PER_CYCLE 2ULL
238+
239+
static struct pin_timer {
240+
struct k_timer timer;
241+
uint32_t count;
242+
pin_size_t pin;
243+
bool infinity;
244+
} arduino_pin_timers[MAX_TONE_PINS];
235245

236246
void tone_expiry_cb(struct k_timer *timer) {
237-
const struct gpio_dt_spec *spec = (gpio_dt_spec *)k_timer_user_data_get(timer);
238-
gpio_pin_toggle_dt(spec);
247+
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
248+
const struct gpio_dt_spec *spec = &arduino_pins[pt->pin];
249+
250+
if (pt->count == 0) {
251+
k_timer_stop(timer);
252+
gpio_pin_set_dt(spec, 0);
253+
} else {
254+
gpio_pin_toggle_dt(spec);
255+
if (!pt->infinity) {
256+
pt->count--;
257+
}
258+
}
239259
}
240260

241261
void tone_timeout_cb(struct k_timer *timer) {
@@ -244,35 +264,44 @@ void tone_timeout_cb(struct k_timer *timer) {
244264
}
245265

246266
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
247-
struct k_timer *timer = &arduino_pin_timers[pinNumber];
248267
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
268+
struct k_timer *timer;
249269
k_timeout_t timeout;
250270

271+
if (pinNumber >= MAX_TONE_PINS) {
272+
return;
273+
}
274+
275+
timer = &arduino_pin_timers[pinNumber].timer;
276+
251277
pinMode(pinNumber, OUTPUT);
278+
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
252279

253280
if (frequency == 0) {
254281
gpio_pin_set_dt(spec, 0);
255282
return;
256283
}
257284

258-
timeout = K_NSEC(NSEC_PER_SEC / (2 * frequency));
285+
timeout = K_NSEC(NSEC_PER_SEC / (TOGGLES_PER_CYCLE * frequency));
286+
if (timeout.ticks == 0) {
287+
timeout.ticks = 1;
288+
}
259289

290+
arduino_pin_timers[pinNumber].infinity = (duration == 0);
291+
arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency *
292+
(MSEC_PER_SEC / TOGGLES_PER_CYCLE);
293+
arduino_pin_timers[pinNumber].pin = pinNumber;
260294
k_timer_init(timer, tone_expiry_cb, NULL);
261-
k_timer_user_data_set(timer, (void *)spec);
262-
gpio_pin_set_dt(spec, 1);
263-
k_timer_start(timer, timeout, timeout);
264295

265-
if (duration > 0) {
266-
timer = &arduino_pin_timers_timeout[pinNumber];
267-
k_timer_init(timer, tone_timeout_cb, NULL);
268-
k_timer_user_data_set(timer, (void *)(uintptr_t)pinNumber);
269-
k_timer_start(timer, K_MSEC(duration), K_NO_WAIT);
270-
}
296+
gpio_pin_set_dt(spec, 0);
297+
k_timer_start(timer, timeout, timeout);
271298
}
272299

273300
void noTone(pin_size_t pinNumber) {
274-
k_timer_stop(&arduino_pin_timers[pinNumber]);
275-
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
301+
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
302+
303+
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
304+
gpio_pin_set_dt(spec, 0);
276305
}
277306

278307
__attribute__((always_inline)) void delay(unsigned long ms) {

0 commit comments

Comments
 (0)