Skip to content

Commit 24e41a6

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 535a7e4 commit 24e41a6

File tree

2 files changed

+85
-24
lines changed

2 files changed

+85
-24
lines changed

Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,11 @@ config ARDUINO_ENTRY
3434
bool "Provide arduino setup and loop entry points"
3535
default y
3636

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

cores/arduino/zephyrCommon.cpp

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

10+
#include <zephyr/spinlock.h>
11+
1012
static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP(
1113
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
1214

@@ -212,49 +214,88 @@ PinStatus digitalRead(pin_size_t pinNumber) {
212214
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
213215
}
214216

215-
#ifndef MAX_TONE_PINS
217+
#if CONFIG_ARDUINO_MAX_TONES < 0
216218
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
219+
#else
220+
#define MAX_TONE_PINS CONFIG_ARDUINO_MAX_TONES
217221
#endif
218222

219223
#define TOGGLES_PER_CYCLE 2ULL
220224

221225
static struct pin_timer {
222226
struct k_timer timer;
223-
uint32_t count;
224-
pin_size_t pin;
225-
bool infinity;
227+
uint32_t count{0};
228+
pin_size_t pin{pin_size_t(-1)};
229+
bool infinity{false};
230+
struct k_spinlock lock;
226231
} arduino_pin_timers[MAX_TONE_PINS];
227232

233+
static struct pin_timer* find_pin_timer(pin_size_t pinNumber, bool active_only) {
234+
size_t unusedIndex = size_t(-1);
235+
236+
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
237+
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);
238+
pin_size_t pin = arduino_pin_timers[i].pin;
239+
240+
k_spin_unlock(&arduino_pin_timers[i].lock, key);
241+
242+
243+
if (pin == pin_size_t(-1)) {
244+
unusedIndex = i;
245+
}
246+
247+
if (pin == pinNumber) {
248+
return &arduino_pin_timers[i];
249+
}
250+
}
251+
252+
if (unusedIndex != size_t(-1) && !active_only) {
253+
return &arduino_pin_timers[unusedIndex];
254+
}
255+
256+
return nullptr;
257+
}
258+
228259
void tone_expiry_cb(struct k_timer *timer) {
229260
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
230-
const struct gpio_dt_spec *spec = &arduino_pins[pt->pin];
261+
k_spinlock_key_t key = k_spin_lock(&pt->lock);
262+
pin_size_t pin = pt->pin;
231263

232264
if (pt->count == 0 && !pt->infinity) {
265+
if (pin >= 0) {
266+
gpio_pin_set_dt(&arduino_pins[pin], 0);
267+
}
268+
233269
k_timer_stop(timer);
234-
gpio_pin_set_dt(spec, 0);
270+
pt->pin = pin_size_t(-1);
235271
} else {
236-
gpio_pin_toggle_dt(spec);
272+
if (pin >= 0) {
273+
gpio_pin_toggle_dt(&arduino_pins[pin]);
274+
}
275+
237276
pt->count--;
238277
}
278+
279+
k_spin_unlock(&pt->lock, key);
239280
}
240281

241282
void tone(pin_size_t pinNumber, unsigned int frequency,
242283
unsigned long duration) {
243-
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
244-
struct k_timer *timer;
284+
k_spinlock_key_t key;
285+
struct pin_timer *pt;
245286
k_timeout_t timeout;
246287

247-
if (pinNumber >= MAX_TONE_PINS) {
288+
pt = find_pin_timer(pinNumber, false);
289+
290+
if (pt == nullptr) {
248291
return;
249292
}
250293

251-
timer = &arduino_pin_timers[pinNumber].timer;
252-
253294
pinMode(pinNumber, OUTPUT);
254-
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
295+
k_timer_stop(&pt->timer);
255296

256297
if (frequency == 0) {
257-
gpio_pin_set_dt(spec, 0);
298+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
258299
return;
259300
}
260301

@@ -263,21 +304,34 @@ void tone(pin_size_t pinNumber, unsigned int frequency,
263304
timeout.ticks = 1;
264305
}
265306

266-
arduino_pin_timers[pinNumber].infinity = (duration == 0);
267-
arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency *
268-
(MSEC_PER_SEC / TOGGLES_PER_CYCLE);
269-
arduino_pin_timers[pinNumber].pin = pinNumber;
270-
k_timer_init(timer, tone_expiry_cb, NULL);
307+
key = k_spin_lock(&pt->lock);
308+
pt->infinity = (duration == 0);
309+
pt->count = (uint64_t)duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC;
310+
pt->pin = pinNumber;
311+
k_spin_unlock(&pt->lock, key);
271312

272-
gpio_pin_set_dt(spec, 0);
273-
k_timer_start(timer, timeout, timeout);
313+
k_timer_init(&pt->timer, tone_expiry_cb, NULL);
314+
315+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
316+
k_timer_start(&pt->timer, timeout, timeout);
274317
}
275318

276319
void noTone(pin_size_t pinNumber) {
277-
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
320+
struct pin_timer *pt;
321+
k_spinlock_key_t key;
322+
323+
pt = find_pin_timer(pinNumber, true);
324+
325+
if (pt == nullptr) {
326+
return;
327+
}
328+
329+
key = k_spin_lock(&pt->lock);
330+
k_timer_stop(&pt->timer);
331+
pt->pin = pin_size_t(-1);
332+
k_spin_unlock(&pt->lock, key);
278333

279-
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
280-
gpio_pin_set_dt(spec, 0);
334+
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
281335
}
282336

283337
void delay(unsigned long ms) {

0 commit comments

Comments
 (0)