Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,11 @@ config ARDUINO_ENTRY
bool "Provide arduino setup and loop entry points"
default y

config ARDUINO_MAX_TONES
int "Maximum number of tones that can be played simultaneously with tone()"
default -1
help
Specify the maximum number of tones that can be played simultaneously with tone().
If set to a negative value, the maximum number will be determined from the
system's digital pin configuration.
endif
115 changes: 88 additions & 27 deletions cores/arduino/zephyrCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <Arduino.h>
#include "zephyrInternal.h"

#include <zephyr/spinlock.h>

static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP(
DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};

Expand Down Expand Up @@ -212,51 +214,97 @@ PinStatus digitalRead(pin_size_t pinNumber) {
return (gpio_pin_get_dt(&arduino_pins[pinNumber]) == 1) ? HIGH : LOW;
}

#ifndef MAX_TONE_PINS
#if CONFIG_ARDUINO_MAX_TONES < 0
#define MAX_TONE_PINS DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)
#else
#define MAX_TONE_PINS CONFIG_ARDUINO_MAX_TONES
#endif

#define TOGGLES_PER_CYCLE 2ULL

static struct pin_timer {
struct k_timer timer;
uint32_t count;
pin_size_t pin;
bool infinity;
uint32_t count{0};
pin_size_t pin{pin_size_t(-1)};
bool infinity{false};
struct k_spinlock lock;
} arduino_pin_timers[MAX_TONE_PINS];

static struct pin_timer* find_pin_timer(pin_size_t pinNumber, bool active_only) {
for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);

if (arduino_pin_timers[i].pin == pinNumber) {
k_spin_unlock(&arduino_pin_timers[i].lock, key);
return &arduino_pin_timers[i];
}

k_spin_unlock(&arduino_pin_timers[i].lock, key);
}

if (active_only) {
return nullptr;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extra newline please

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've overhauled this entire function.

for (size_t i = 0; i < ARRAY_SIZE(arduino_pin_timers); i++) {
k_spinlock_key_t key = k_spin_lock(&arduino_pin_timers[i].lock);

if (arduino_pin_timers[i].pin == pin_size_t(-1)) {
arduino_pin_timers[i].pin = pinNumber;
k_spin_unlock(&arduino_pin_timers[i].lock, key);
return &arduino_pin_timers[i];
}

k_spin_unlock(&arduino_pin_timers[i].lock, key);
}

return nullptr;
}

void tone_expiry_cb(struct k_timer *timer) {
struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer);
const struct gpio_dt_spec *spec = &arduino_pins[pt->pin];
k_spinlock_key_t key = k_spin_lock(&pt->lock);
pin_size_t pin = pt->pin;

if (pt->count == 0 && !pt->infinity) {
if (pin != pin_size_t(-1)) {
gpio_pin_set_dt(&arduino_pins[pin], 0);
}

if (pt->count == 0) {
k_timer_stop(timer);
gpio_pin_set_dt(spec, 0);
pt->pin = pin_size_t(-1);
} else {
gpio_pin_toggle_dt(spec);
if (!pt->infinity) {
pt->count--;
if (pin != pin_size_t(-1)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these changes inside add tone_doremi sample? Can be very misleading, please split into another commit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops!
It was misoperation, Fixed. Thank you for catching.

gpio_pin_toggle_dt(&arduino_pins[pin]);
}

pt->count--;
}

k_spin_unlock(&pt->lock, key);
}

void tone(pin_size_t pinNumber, unsigned int frequency,
unsigned long duration) {
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
struct k_timer *timer;
k_spinlock_key_t key;
struct pin_timer *pt;
k_timeout_t timeout;

if (pinNumber >= MAX_TONE_PINS) {
pt = find_pin_timer(pinNumber, false);

if (pt == nullptr) {
return;
}

timer = &arduino_pin_timers[pinNumber].timer;

pinMode(pinNumber, OUTPUT);
k_timer_stop(&arduino_pin_timers[pinNumber].timer);
k_timer_stop(&pt->timer);

if (frequency == 0) {
gpio_pin_set_dt(spec, 0);
key = k_spin_lock(&pt->lock);
pt->pin = pin_size_t(-1);
k_spin_unlock(&pt->lock, key);

gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
return;
}

Expand All @@ -265,21 +313,34 @@ void tone(pin_size_t pinNumber, unsigned int frequency,
timeout.ticks = 1;
}

arduino_pin_timers[pinNumber].infinity = (duration == 0);
arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency *
(MSEC_PER_SEC / TOGGLES_PER_CYCLE);
arduino_pin_timers[pinNumber].pin = pinNumber;
k_timer_init(timer, tone_expiry_cb, NULL);
key = k_spin_lock(&pt->lock);
pt->infinity = (duration == 0);
pt->count = min((uint64_t)duration * frequency * TOGGLES_PER_CYCLE / MSEC_PER_SEC, UINT32_MAX);
pt->pin = pinNumber;
k_spin_unlock(&pt->lock, key);

gpio_pin_set_dt(spec, 0);
k_timer_start(timer, timeout, timeout);
k_timer_init(&pt->timer, tone_expiry_cb, NULL);

gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
k_timer_start(&pt->timer, timeout, timeout);
}

void noTone(pin_size_t pinNumber) {
const struct gpio_dt_spec *spec = &arduino_pins[pinNumber];
struct pin_timer *pt;
k_spinlock_key_t key;

pt = find_pin_timer(pinNumber, true);

if (pt == nullptr) {
return;
}

key = k_spin_lock(&pt->lock);
k_timer_stop(&pt->timer);
pt->pin = pin_size_t(-1);
k_spin_unlock(&pt->lock, key);

k_timer_stop(&arduino_pin_timers[pinNumber].timer);
gpio_pin_set_dt(spec, 0);
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
}

void delay(unsigned long ms) {
Expand Down
29 changes: 29 additions & 0 deletions samples/tone_doremi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

# get value of NORMALIZED_BOARD_TARGET early
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS yaml boards)

if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${NORMALIZED_BOARD_TARGET}_${BOARD_REVISION})
set(variant_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${NORMALIZED_BOARD_TARGET}_${BOARD_REVISION})
elseif (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${NORMALIZED_BOARD_TARGET})
set(variant_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${NORMALIZED_BOARD_TARGET})
elseif (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${BOARD})
set(variant_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../variants/${BOARD})
endif()

if (EXISTS ${variant_dir}/${NORMALIZED_BOARD_TARGET}_${BOARD_REVISION}.overlay)
set(DTC_OVERLAY_FILE ${variant_dir}/${NORMALIZED_BOARD_TARGET}_${BOARD_REVISION}.overlay)
elseif (EXISTS ${variant_dir}/${NORMALIZED_BOARD_TARGET}.overlay)
set(DTC_OVERLAY_FILE ${variant_dir}/${NORMALIZED_BOARD_TARGET}.overlay)
elseif (EXISTS ${variant_dir}/${BOARD}.overlay)
set(DTC_OVERLAY_FILE ${variant_dir}/${BOARD}.overlay)
endif()

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(tone_doremi)

target_sources(app PRIVATE src/app.cpp)

zephyr_compile_options(-Wno-unused-variable -Wno-comment)
21 changes: 21 additions & 0 deletions samples/tone_doremi/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.. _tone_doremi:

Tone DoReMi
###########

Overview
********

Use tone to play the scale.
Play Do, Re, Mi on D4 pin, then Fa, So, La on D5 pin.

Building and Running
********************

Build and flash tone_doremi sample as follows,

.. code-block:: sh
$> west build -p -b arduino_nano_33_ble samples/tone_doremi/
$> west flash --bossac=/home/$USER/.arduino15/packages/arduino/tools/bossac/1.9.1-arduino2/bossac
2 changes: 2 additions & 0 deletions samples/tone_doremi/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_ARDUINO_API=y
CONFIG_ARDUINO_MAX_TONES=2
44 changes: 44 additions & 0 deletions samples/tone_doremi/src/app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2026 TOKITA Hiroshi
*/

#include <Arduino.h>
#include "zephyrSerial.h"

#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440

void setup() {
Serial.begin(115200);
}

void loop() {
Serial.println("Do@D4");
tone(D4, NOTE_C4, 1000);
delay(2000);
Serial.println("Re@D4");
tone(D4, NOTE_D4, 1000);
delay(2000);
Serial.println("Mi@D4 - Infinity");
tone(D4, NOTE_E4, 0);
delay(2000);
Serial.println("Fa@D5");
tone(D5, NOTE_F4, 1000);
delay(2000);
Serial.println("So@D5");
tone(D5, NOTE_G4, 1000);
delay(2000);
Serial.println("La@D5 - Infinity");
tone(D5, NOTE_A4, 0);

while(true) {
delay(1000);
}
}

Loading