diff --git a/CMakeLists.txt b/CMakeLists.txt index b2268e0..5ac276c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ target_include_directories(pico_keyer PRIVATE target_link_libraries(pico_keyer hardware_flash hardware_exception + hardware_pwm pico_flash ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 510430c..b1dd5de 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,4 +2,5 @@ target_sources(pico_keyer PRIVATE pico_keyer.cpp settings.cpp keyer.cpp + sidetone.cpp ) \ No newline at end of file diff --git a/src/keyer.cpp b/src/keyer.cpp index a804134..4a28f0e 100644 --- a/src/keyer.cpp +++ b/src/keyer.cpp @@ -3,11 +3,15 @@ #include "pico/stdlib.h" #include "keyer.h" +#include "sidetone.h" extern const uint LED_PIN; extern const uint LEFT_PADDLE_PIN; extern const uint RIGHT_PADDLE_PIN; + +const uint SIDETONE_FREQ = 622; + bool left_paddle_pressed() { if (!gpio_get(LEFT_PADDLE_PIN)) @@ -68,6 +72,7 @@ void Keyer::run() m_currentlyKeying = true; m_keying_until = make_timeout_time_us(m_elementDuration); gpio_put(LED_PIN, 1); + m_Sidetone.on(SIDETONE_FREQ); m_lastSymbolWas = Symbol::Dit; } else @@ -76,6 +81,7 @@ void Keyer::run() { m_currentlyKeying = false; gpio_put(LED_PIN, 0); + m_Sidetone.off(); m_previousState = State::Dit; state = State::InterCharSpace; } @@ -87,6 +93,7 @@ void Keyer::run() m_currentlyKeying = true; m_keying_until = make_timeout_time_us(m_elementDuration * 3); gpio_put(LED_PIN, 1); + m_Sidetone.on(SIDETONE_FREQ); m_lastSymbolWas = Symbol::Dah; } else @@ -95,6 +102,7 @@ void Keyer::run() { m_currentlyKeying = false; gpio_put(LED_PIN, 0); + m_Sidetone.off(); m_previousState = State::Dah; state = State::InterCharSpace; } diff --git a/src/keyer.h b/src/keyer.h index a3a2203..bb1e05f 100644 --- a/src/keyer.h +++ b/src/keyer.h @@ -1,6 +1,10 @@ #ifndef KEYER_H #define KEYER_H +#include "sidetone.h" + +extern const uint BUZZER_PIN; + class Keyer final { public: @@ -31,6 +35,7 @@ private: absolute_time_t m_keying_until{0}; absolute_time_t m_pausing_until{0}; Symbol m_lastSymbolWas{Symbol::Dit}; + Sidetone m_Sidetone{BUZZER_PIN}; }; #endif \ No newline at end of file diff --git a/src/pico_keyer.cpp b/src/pico_keyer.cpp index c11cb22..fe4b359 100644 --- a/src/pico_keyer.cpp +++ b/src/pico_keyer.cpp @@ -14,6 +14,7 @@ namespace extern const uint LED_PIN = PICO_DEFAULT_LED_PIN; extern const uint LEFT_PADDLE_PIN = 14; extern const uint RIGHT_PADDLE_PIN = 15; +extern const uint BUZZER_PIN = 13; void setup() { @@ -29,6 +30,7 @@ void setup() gpio_init(RIGHT_PADDLE_PIN); gpio_set_dir(RIGHT_PADDLE_PIN, GPIO_IN); gpio_pull_up(RIGHT_PADDLE_PIN); + sleep_ms(1000); } @@ -45,7 +47,7 @@ int main() // printf("Element duration (u_sec): %" PRIu64 "\n", element_duration_us(settings.wpm)); printf("\n"); - Keyer keyer(15); + Keyer keyer(25); while (true) { diff --git a/src/sidetone.cpp b/src/sidetone.cpp new file mode 100644 index 0000000..81c15b0 --- /dev/null +++ b/src/sidetone.cpp @@ -0,0 +1,29 @@ +#include "pico/stdlib.h" +#include "hardware/pwm.h" + +#include "sidetone.h" + +Sidetone::Sidetone(uint gpio) : m_gpio(gpio) +{ + gpio_set_function(gpio, GPIO_FUNC_PWM); + uint slice_num = pwm_gpio_to_slice_num(gpio); + pwm_config config = pwm_get_default_config(); + pwm_init(slice_num, &config, true); +} + +void Sidetone::on(uint freq) +{ + // Calculate and cofigure new clock divider according to the frequency + // This formula is assuming we are running at 125MHz. + // TODO: Make this work for any frequency + float clkdiv = (1.f / freq) * 2000.f; + uint slice_num = pwm_gpio_to_slice_num(m_gpio); + pwm_set_clkdiv(slice_num, clkdiv); + // Configure duty to 50% ((2**16)-1)/2) to generate a square wave + pwm_set_gpio_level(m_gpio, 32768U); +} + +void Sidetone::off() +{ + pwm_set_gpio_level(m_gpio, 0); +} \ No newline at end of file diff --git a/src/sidetone.h b/src/sidetone.h new file mode 100644 index 0000000..00b288f --- /dev/null +++ b/src/sidetone.h @@ -0,0 +1,16 @@ +#ifndef SIDETONE_H +#define SIDETONE_H + +class Sidetone +{ +public: + Sidetone(uint gpio); + void on(uint freq); + void off(); + +private: + Sidetone(){}; + uint m_gpio{0}; +}; + +#endif \ No newline at end of file