77#include < Arduino.h>
88#include " zephyrInternal.h"
99
10+ #include < zephyr/spinlock.h>
11+
1012static 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,25 +214,59 @@ 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
221225static 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+ 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+
228259void tone_expiry_cb (struct k_timer *timer) {
229260 struct pin_timer *pt = CONTAINER_OF (timer, struct pin_timer , timer);
230261 const struct gpio_dt_spec *spec = &arduino_pins[pt->pin ];
262+ k_spinlock_key_t key;
231263
232264 if (pt->count == 0 && !pt->infinity ) {
265+ key = k_spin_lock (&pt->lock );
233266 k_timer_stop (timer);
267+ pt->pin = pin_size_t (-1 );
268+ k_spin_unlock (&pt->lock , key);
269+
234270 gpio_pin_set_dt (spec, 0 );
235271 } else {
236272 gpio_pin_toggle_dt (spec);
@@ -241,17 +277,18 @@ void tone_expiry_cb(struct k_timer *timer) {
241277void tone (pin_size_t pinNumber, unsigned int frequency,
242278 unsigned long duration) {
243279 const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
244- struct k_timer *timer;
280+ k_spinlock_key_t key;
281+ struct pin_timer *pt;
245282 k_timeout_t timeout;
246283
247- if (pinNumber >= MAX_TONE_PINS) {
284+ pt = find_pin_timer (pinNumber, false );
285+
286+ if (pt == nullptr ) {
248287 return ;
249288 }
250289
251- timer = &arduino_pin_timers[pinNumber].timer ;
252-
253290 pinMode (pinNumber, OUTPUT);
254- k_timer_stop (&arduino_pin_timers[pinNumber]. timer );
291+ k_timer_stop (&pt-> timer );
255292
256293 if (frequency == 0 ) {
257294 gpio_pin_set_dt (spec, 0 );
@@ -263,20 +300,34 @@ void tone(pin_size_t pinNumber, unsigned int frequency,
263300 timeout.ticks = 1 ;
264301 }
265302
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 );
303+ key = k_spin_lock (&pt->lock );
304+ pt->infinity = (duration == 0 );
305+ pt->count = (uint64_t )duration * frequency * (MSEC_PER_SEC / TOGGLES_PER_CYCLE);
306+ pt->pin = pinNumber;
307+ k_spin_unlock (&pt->lock , key);
308+
309+ k_timer_init (&pt->timer , tone_expiry_cb, NULL );
271310
272311 gpio_pin_set_dt (spec, 0 );
273- k_timer_start (timer, timeout, timeout);
312+ k_timer_start (&pt-> timer , timeout, timeout);
274313}
275314
276315void noTone (pin_size_t pinNumber) {
277316 const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
317+ struct pin_timer *pt;
318+ k_spinlock_key_t key;
319+
320+ pt = find_pin_timer (pinNumber, true );
321+
322+ if (pt == nullptr ) {
323+ return ;
324+ }
325+
326+ key = k_spin_lock (&pt->lock );
327+ k_timer_stop (&pt->timer );
328+ pt->pin = pin_size_t (-1 );
329+ k_spin_unlock (&pt->lock , key);
278330
279- k_timer_stop (&arduino_pin_timers[pinNumber].timer );
280331 gpio_pin_set_dt (spec, 0 );
281332}
282333
0 commit comments