Skip to content
Draft
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 cores/arduino/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ zephyr_sources(zephyrCommon.cpp)
zephyr_sources(USB.cpp)
zephyr_sources(itoa.cpp)

zephyr_sources(wiring_analog.cpp)
zephyr_sources(wiring_digital.cpp)
zephyr_sources(wiring_pulse.cpp)
zephyr_sources(Tone.cpp)
zephyr_sources(WMath.cpp)
zephyr_sources(WInterrupts.cpp)

if(DEFINED CONFIG_ARDUINO_ENTRY)
zephyr_sources(main.cpp)
zephyr_sources(threads.cpp)
Expand Down
60 changes: 60 additions & 0 deletions cores/arduino/Tone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

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

using namespace zephyr::arduino;

namespace {

struct k_timer arduino_pin_timers[ARRAY_SIZE(arduino_pins)];
struct k_timer arduino_pin_timers_timeout[ARRAY_SIZE(arduino_pins)];

void tone_expiry_cb(struct k_timer *timer) {
const struct gpio_dt_spec *spec = (gpio_dt_spec *)k_timer_user_data_get(timer);
gpio_pin_toggle_dt(spec);
}

void tone_timeout_cb(struct k_timer *timer) {
pin_size_t pinNumber = (pin_size_t)(uintptr_t)k_timer_user_data_get(timer);
noTone(pinNumber);
}

} // anonymous namespace

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

pinMode(pinNumber, OUTPUT);

if (frequency == 0) {
gpio_pin_set_dt(spec, 0);
return;
}

timeout = K_NSEC(NSEC_PER_SEC / (2 * frequency));

k_timer_init(timer, tone_expiry_cb, NULL);
k_timer_user_data_set(timer, (void *)spec);
gpio_pin_set_dt(spec, 1);
k_timer_start(timer, timeout, timeout);

if (duration > 0) {
timer = &arduino_pin_timers_timeout[pinNumber];
k_timer_init(timer, tone_timeout_cb, NULL);
k_timer_user_data_set(timer, (void *)(uintptr_t)pinNumber);
k_timer_start(timer, K_MSEC(duration), K_NO_WAIT);
}
}

void noTone(pin_size_t pinNumber) {
k_timer_stop(&arduino_pin_timers[pinNumber]);
gpio_pin_set_dt(&arduino_pins[pinNumber], 0);
}
142 changes: 142 additions & 0 deletions cores/arduino/WInterrupts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2022 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

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

using namespace zephyr::arduino;

namespace {

/*
* GPIO callback implementation
*/

struct arduino_callback {
voidFuncPtr handler;
bool enabled;
};

struct gpio_port_callback {
struct gpio_callback callback;
struct arduino_callback handlers[max_ngpios];
gpio_port_pins_t pins;
const struct device *dev;
} port_callback[port_num] = {0};

unsigned int irq_key;
bool interrupts_disabled = false;

struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) {
for (size_t i = 0; i < ARRAY_SIZE(port_callback); i++) {
if (port_callback[i].dev == dev) {
return &port_callback[i];
}
if (port_callback[i].dev == nullptr) {
port_callback[i].dev = dev;
return &port_callback[i];
}
}

return nullptr;
}

void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[arduino_pins[pinNumber].pin].handler = func;
}
}

void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) {
(void)port; // unused
struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb;

for (uint32_t i = 0; i < max_ngpios; i++) {
if (pins & BIT(i) && pcb->handlers[i].enabled) {
pcb->handlers[i].handler();
}
}
}

void enableInterrupt(pin_size_t pinNumber) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[arduino_pins[pinNumber].pin].enabled = true;
}
}

void disableInterrupt(pin_size_t pinNumber) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);

if (pcb) {
pcb->handlers[arduino_pins[pinNumber].pin].enabled = false;
}
}

} // anonymous namespace

void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) {
struct gpio_port_callback *pcb;
gpio_flags_t intmode = 0;

if (!callback) {
return;
}

if (pinStatus == LOW) {
intmode |= GPIO_INT_LEVEL_LOW;
} else if (pinStatus == HIGH) {
intmode |= GPIO_INT_LEVEL_HIGH;
} else if (pinStatus == CHANGE) {
intmode |= GPIO_INT_EDGE_BOTH;
} else if (pinStatus == FALLING) {
intmode |= GPIO_INT_EDGE_FALLING;
} else if (pinStatus == RISING) {
intmode |= GPIO_INT_EDGE_RISING;
} else {
return;
}

pcb = find_gpio_port_callback(arduino_pins[pinNumber].port);
__ASSERT(pcb != nullptr, "gpio_port_callback not found");

pcb->pins |= BIT(arduino_pins[pinNumber].pin);
setInterruptHandler(pinNumber, callback);
enableInterrupt(pinNumber);

gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin,
intmode);
gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins);
gpio_add_callback(arduino_pins[pinNumber].port, &pcb->callback);
}

void detachInterrupt(pin_size_t pinNumber) {
setInterruptHandler(pinNumber, nullptr);
disableInterrupt(pinNumber);
}

void interrupts(void) {
if (interrupts_disabled) {
irq_unlock(irq_key);
interrupts_disabled = false;
}
}

void noInterrupts(void) {
if (!interrupts_disabled) {
irq_key = irq_lock();
interrupts_disabled = true;
}
}

int digitalPinToInterrupt(pin_size_t pin) {
struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port);

return (pcb) ? pin : -1;
}
26 changes: 26 additions & 0 deletions cores/arduino/WMath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2024 Ayush Singh <ayush@beagleboard.org>
* Copyright (c) 2026 TOKITA Hiroshi
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <Arduino.h>

#ifndef CONFIG_MINIMAL_LIBC_RAND

#include <stdlib.h>

void randomSeed(unsigned long seed) {
srand(seed);
}

long random(long min, long max) {
return rand() % (max - min) + min;
}

long random(long max) {
return rand() % max;
}

#endif
Loading
Loading