From 83e05701fe508b1d9bb0ab663dd0a695f3fb825d Mon Sep 17 00:00:00 2001 From: Ali Mosallaei Date: Fri, 27 Sep 2024 14:26:13 -0400 Subject: [PATCH] [HAL] Add tones support for the RPi Pico (#1239) * Add tones support for RPi Pico * Add dependencies to CMakeLists * Address review --- examples/NonArduino/Pico/CMakeLists.txt | 4 +- examples/NonArduino/Pico/PicoHal.h | 61 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/examples/NonArduino/Pico/CMakeLists.txt b/examples/NonArduino/Pico/CMakeLists.txt index e58520ff..c86122fb 100644 --- a/examples/NonArduino/Pico/CMakeLists.txt +++ b/examples/NonArduino/Pico/CMakeLists.txt @@ -23,11 +23,11 @@ add_executable(${PROJECT_NAME} ) # Pull in common dependencies -target_link_libraries(${PROJECT_NAME} pico_stdlib hardware_spi hardware_gpio hardware_timer RadioLib) +target_link_libraries(${PROJECT_NAME} pico_stdlib hardware_spi hardware_gpio hardware_timer pico_multicore hardware_pwm RadioLib) pico_enable_stdio_usb(${PROJECT_NAME} 1) pico_enable_stdio_uart(${PROJECT_NAME} 0) # Create map/bin/hex file etc. -pico_add_extra_outputs(${PROJECT_NAME}) \ No newline at end of file +pico_add_extra_outputs(${PROJECT_NAME}) diff --git a/examples/NonArduino/Pico/PicoHal.h b/examples/NonArduino/Pico/PicoHal.h index d0184257..ec4d12e3 100644 --- a/examples/NonArduino/Pico/PicoHal.h +++ b/examples/NonArduino/Pico/PicoHal.h @@ -8,6 +8,45 @@ #include #include "hardware/spi.h" #include "hardware/timer.h" +#include "hardware/pwm.h" +#include "hardware/clocks.h" +#include "pico/multicore.h" + +uint32_t toneLoopPin; +unsigned int toneLoopFrequency; +unsigned long toneLoopDuration; + +// pre-calculated pulse-widths for 1200 and 2200Hz +// we do this to save calculation time (see https://github.com/khoih-prog/RP2040_PWM/issues/6) +#define SLEEP_1200 416.666 +#define SLEEP_2200 227.272 + +// === NOTE === +// The tone(...) implementation uses the second core on the RPi Pico. This is to diminish as much +// jitter in the output tones as possible. + +void toneLoop(){ + gpio_set_dir(toneLoopPin, GPIO_OUT); + + uint32_t sleep_dur; + if (toneLoopFrequency == 1200) { + sleep_dur = SLEEP_1200; + } else if (toneLoopFrequency == 2200) { + sleep_dur = SLEEP_2200; + } else { + sleep_dur = 500000 / toneLoopFrequency; + } + + + // tone bitbang + while(1){ + gpio_put(toneLoopPin, 1); + sleep_us(sleep_dur); + gpio_put(toneLoopPin, 0); + sleep_us(sleep_dur); + tight_loop_contents(); + } +} // create a new Raspberry Pi Pico hardware abstraction // layer using the Pico SDK @@ -21,8 +60,7 @@ public: _spiSpeed(spiSpeed), _misoPin(misoPin), _mosiPin(mosiPin), - _sckPin(sckPin) { - } + _sckPin(sckPin){} void init() override { stdio_init_all(); @@ -110,6 +148,19 @@ public: return (this->micros() - start); } + void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) override { + // tones on the Pico are generated using bitbanging. This process is offloaded to the Pico's second core + multicore_reset_core1(); + toneLoopPin = pin; + toneLoopFrequency = frequency; + toneLoopDuration = duration; + multicore_launch_core1(toneLoop); + } + + void noTone(uint32_t pin) override { + multicore_reset_core1(); + } + void spiBegin() { spi_init(_spiChannel, _spiSpeed); spi_set_format(_spiChannel, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); @@ -125,6 +176,10 @@ public: spi_write_read_blocking(_spiChannel, out, in, len); } + void yield() override { + tight_loop_contents(); + } + void spiEndTransaction() {} void spiEnd() { @@ -140,4 +195,4 @@ private: uint32_t _sckPin; }; -#endif \ No newline at end of file +#endif