Skip to content

Commit 981dbb8

Browse files
committed
zephyrCommon: Improved tone implemetation
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 <[email protected]>
1 parent 211d5dc commit 981dbb8

File tree

1 file changed

+42
-21
lines changed

1 file changed

+42
-21
lines changed

cores/arduino/zephyrCommon.cpp

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -212,49 +212,70 @@ PinStatus digitalRead(pin_size_t pinNumber) {
212212
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
213213
}
214214

215-
struct k_timer arduino_pin_timers[ARRAY_SIZE(arduino_pins)];
216-
struct k_timer arduino_pin_timers_timeout[ARRAY_SIZE(arduino_pins)];
215+
#ifndef MAX_TONE_PINS
216+
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
217+
#endif
218+
219+
struct pin_timer {
220+
struct k_timer timer;
221+
pin_size_t pin;
222+
uint32_t count;
223+
} arduino_pin_timers[MAX_TONE_PINS];
217224

218225
void tone_expiry_cb(struct k_timer *timer) {
219-
const struct gpio_dt_spec *spec = (gpio_dt_spec*)k_timer_user_data_get(timer);
220-
gpio_pin_toggle_dt(spec);
221-
}
226+
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
227+
const struct gpio_dt_spec *spec = &arduino_pins[pt->pin];
222228

223-
void tone_timeout_cb(struct k_timer *timer) {
224-
pin_size_t pinNumber = (pin_size_t)(uintptr_t)k_timer_user_data_get(timer);
225-
noTone(pinNumber);
229+
if (pt->count == 0) {
230+
k_timer_stop(timer);
231+
gpio_pin_set_dt(spec, 0);
232+
} else {
233+
gpio_pin_toggle_dt(spec);
234+
if (pt->count != UINT32_MAX) {
235+
pt->count--;
236+
}
237+
}
226238
}
227239

228-
void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) {
229-
struct k_timer *timer = &arduino_pin_timers[pinNumber];
240+
void tone(pin_size_t pinNumber, unsigned int frequency,
241+
unsigned long duration) {
230242
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
243+
struct k_timer *timer = &arduino_pin_timers[pinNumber].timer;
231244
k_timeout_t timeout;
245+
uint32_t count;
232246

233247
pinMode(pinNumber, OUTPUT);
248+
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
234249

235250
if (frequency == 0) {
236251
gpio_pin_set_dt(spec, 0);
237252
return;
238253
}
239254

255+
if (duration == 0) {
256+
count = UINT32_MAX;
257+
} else {
258+
count = ((uint64_t)duration * (uint64_t)frequency) / 500ULL;
259+
}
260+
240261
timeout = K_NSEC(NSEC_PER_SEC / (2 * frequency));
262+
if (timeout.ticks == 0) {
263+
timeout.ticks = 1;
264+
}
241265

266+
arduino_pin_timers[pinNumber].count = count;
267+
arduino_pin_timers[pinNumber].pin = pinNumber;
242268
k_timer_init(timer, tone_expiry_cb, NULL);
243-
k_timer_user_data_set(timer, (void*)spec);
244-
gpio_pin_set_dt(spec, 1);
245-
k_timer_start(timer, timeout, timeout);
246269

247-
if(duration > 0) {
248-
timer = &arduino_pin_timers_timeout[pinNumber];
249-
k_timer_init(timer, tone_timeout_cb, NULL);
250-
k_timer_user_data_set(timer, (void*)(uintptr_t)pinNumber);
251-
k_timer_start(timer, K_MSEC(duration), K_NO_WAIT);
252-
}
270+
gpio_pin_set_dt(spec, 0);
271+
k_timer_start(timer, timeout, timeout);
253272
}
254273

255274
void noTone(pin_size_t pinNumber) {
256-
k_timer_stop(&arduino_pin_timers[pinNumber]);
257-
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
275+
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
276+
277+
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
278+
gpio_pin_set_dt(spec, 0);
258279
}
259280

260281
void delay(unsigned long ms) { k_sleep(K_MSEC(ms)); }

0 commit comments

Comments
 (0)