Skip to content

Commit 600a596

Browse files
committed
zephyrCommon: Make configurable the max number of tones
Allows you to change the maximum number of notes that can be played with `tone()`. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent d148f91 commit 600a596

File tree

2 files changed

+129
-27
lines changed

2 files changed

+129
-27
lines changed

Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ config ARDUINO_ENTRY
3030
bool "Provide arduino setup and loop entry points"
3131
default y
3232

33+
config ARDUINO_MAX_TONES
34+
int "Maximum number of tones that can be played simultaneously with tone()"
35+
default -1
36+
help
37+
Specify the maximum number of tones that can be played simultaneously with tone().
38+
If set to a negative value, the maximum number will be determined from the
39+
system's digital pin configuration.
40+
3341
endif
3442

3543
if USB_DEVICE_STACK_NEXT

cores/arduino/zephyrCommon.cpp

Lines changed: 121 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include <Arduino.h>
88
#include "zephyrInternal.h"
99

10+
#include <zephyr/kernel.h>
11+
#include <zephyr/spinlock.h>
12+
1013
static const struct gpio_dt_spec arduino_pins[] = {
1114
DT_FOREACH_PROP_ELEM_SEP(
1215
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
@@ -230,53 +233,120 @@ PinStatus digitalRead(pin_size_t pinNumber) {
230233
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
231234
}
232235

233-
#ifndef MAX_TONE_PINS
236+
#if CONFIG_ARDUINO_MAX_TONES < 0
234237
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
238+
#else
239+
#define MAX_TONE_PINS CONFIG_ARDUINO_MAX_TONES
235240
#endif
236241

237242
#define TOGGLES_PER_CYCLE 2ULL
238243

239244
static struct pin_timer {
240245
struct k_timer timer;
241-
uint32_t count;
242-
pin_size_t pin;
243-
bool infinity;
246+
uint32_t count{0};
247+
pin_size_t pin{pin_size_t(-1)};
248+
bool infinity{false};
249+
bool timer_initialized{false};
250+
struct k_spinlock lock;
244251
} arduino_pin_timers[MAX_TONE_PINS];
245252

253+
K_MUTEX_DEFINE(timer_cfg_lock);
254+
255+
void tone_expiry_cb(struct k_timer *timer);
256+
257+
static struct pin_timer *find_pin_timer(pin_size_t pinNumber, bool active_only) {
258+
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
259+
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
260+
261+
if (arduino_pin_timers[i].pin == pinNumber) {
262+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
263+
return &arduino_pin_timers[i];
264+
}
265+
266+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
267+
}
268+
269+
if (active_only) {
270+
return nullptr;
271+
}
272+
273+
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
274+
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
275+
276+
if (arduino_pin_timers[i].pin == pin_size_t(-1)) {
277+
arduino_pin_timers[i].pin = pinNumber;
278+
279+
if (!arduino_pin_timers[i].timer_initialized) {
280+
k_timer_init(&arduino_pin_timers[i].timer, tone_expiry_cb, NULL);
281+
arduino_pin_timers[i].timer_initialized = true;
282+
}
283+
284+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
285+
return &arduino_pin_timers[i];
286+
}
287+
288+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
289+
}
290+
291+
return nullptr;
292+
}
293+
246294
void tone_expiry_cb(struct k_timer *timer) {
247295
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
248-
const struct gpio_dt_spec *spec = &arduino_pins[pt->pin];
296+
k_spinlock_key_t key = k_spin_lock(&pt->lock);
297+
pin_size_t pin = pt->pin;
249298

250299
if (pt->count == 0 && !pt->infinity) {
300+
if (pin != pin_size_t(-1)) {
301+
gpio_pin_set_dt(&arduino_pins[pin], 0);
302+
}
303+
251304
k_timer_stop(timer);
252-
gpio_pin_set_dt(spec, 0);
305+
pt->count = 0;
306+
pt->infinity = false;
307+
pt->pin = pin_size_t(-1);
253308
} else {
254-
gpio_pin_toggle_dt(spec);
309+
if (pin != pin_size_t(-1)) {
310+
gpio_pin_toggle_dt(&arduino_pins[pin]);
311+
}
312+
255313
pt->count--;
256314
}
257-
}
258315

259-
void tone_timeout_cb(struct k_timer *timer) {
260-
pin_size_t pinNumber = (pin_size_t)(uintptr_t)k_timer_user_data_get(timer);
261-
noTone(pinNumber);
316+
k_spin_unlock(&pt->lock, key);
262317
}
263318

264319
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
265-
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
266-
struct k_timer *timer;
320+
k_spinlock_key_t key;
321+
struct pin_timer *pt;
267322
k_timeout_t timeout;
268323

269-
if (pinNumber >= MAX_TONE_PINS) {
324+
if (k_is_in_isr()) {
270325
return;
271326
}
272327

273-
timer = &arduino_pin_timers[pinNumber].timer;
328+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
329+
330+
pt = find_pin_timer(pinNumber, false);
331+
332+
if (pt == nullptr) {
333+
k_mutex_unlock(&timer_cfg_lock);
334+
return;
335+
}
274336

275337
pinMode(pinNumber, OUTPUT);
276-
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
338+
k_timer_stop(&pt->timer);
277339

278340
if (frequency == 0) {
279-
gpio_pin_set_dt(spec, 0);
341+
key = k_spin_lock(&pt->lock);
342+
pt->count = 0;
343+
pt->infinity = false;
344+
pt->pin = pin_size_t(-1);
345+
k_spin_unlock(&pt->lock, key);
346+
347+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
348+
349+
k_mutex_unlock(&timer_cfg_lock);
280350
return;
281351
}
282352

@@ -285,21 +355,45 @@ void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration)
285355
timeout.ticks = 1;
286356
}
287357

288-
arduino_pin_timers[pinNumber].infinity = (duration == 0);
289-
arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency *
290-
(MSEC_PER_SEC / TOGGLES_PER_CYCLE);
291-
arduino_pin_timers[pinNumber].pin = pinNumber;
292-
k_timer_init(timer, tone_expiry_cb, NULL);
358+
key = k_spin_lock(&pt->lock);
359+
pt->infinity = (duration == 0);
360+
pt->count = min((uint64_t)duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC, UINT32_MAX);
361+
pt->pin = pinNumber;
362+
k_spin_unlock(&pt->lock, key);
363+
364+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
365+
k_timer_start(&pt->timer, timeout, timeout);
293366

294-
gpio_pin_set_dt(spec, 0);
295-
k_timer_start(timer, timeout, timeout);
367+
k_mutex_unlock(&timer_cfg_lock);
296368
}
297369

298370
void noTone(pin_size_t pinNumber) {
299-
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
371+
struct pin_timer *pt;
372+
k_spinlock_key_t key;
373+
374+
if (k_is_in_isr()) {
375+
return;
376+
}
377+
378+
k_mutex_lock(&timer_cfg_lock, K_FOREVER);
379+
380+
pt = find_pin_timer(pinNumber, true);
381+
382+
if (pt == nullptr) {
383+
k_mutex_unlock(&timer_cfg_lock);
384+
return;
385+
}
386+
387+
key = k_spin_lock(&pt->lock);
388+
k_timer_stop(&pt->timer);
389+
pt->count = 0;
390+
pt->infinity = false;
391+
pt->pin = pin_size_t(-1);
392+
k_spin_unlock(&pt->lock, key);
393+
394+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
300395

301-
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
302-
gpio_pin_set_dt(spec, 0);
396+
k_mutex_unlock(&timer_cfg_lock);
303397
}
304398

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

0 commit comments

Comments
 (0)