diff --git a/CMakeLists.txt b/CMakeLists.txt index e97dcc4..430e256 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ pico_set_program_name(raspi_keyer "raspi_keyer") pico_set_program_version(raspi_keyer "0.0.1") pico_enable_stdio_uart(raspi_keyer 1) -pico_enable_stdio_usb(raspi_keyer 0) +pico_enable_stdio_usb(raspi_keyer 1) target_compile_options(raspi_keyer PRIVATE -Wall -Wextra -Werror) @@ -52,6 +52,7 @@ target_link_libraries(raspi_keyer hardware_exception hardware_pwm pico_flash + pico_multicore ) pico_add_extra_outputs(raspi_keyer) diff --git a/src/keyer.cpp b/src/keyer.cpp index 3e81201..3efe547 100644 --- a/src/keyer.cpp +++ b/src/keyer.cpp @@ -56,7 +56,7 @@ void Keyer::run() if (left_paddle_pressed() && right_paddle_pressed()) { m_keyNextIambicB = false; - + if (m_previousState == State::Dit) { state = State::Dah; @@ -141,16 +141,56 @@ void Keyer::run() m_pausing_until = make_timeout_time_us(m_elementDuration); m_currentlyPausing = true; } - - if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0) + // Handle the case when the other paddle is pressed during the inter character space + else if (absolute_time_diff_us(timestamp, m_pausing_until) > 0) { - m_currentlyPausing = false; - state = State::Wait; + if (left_paddle_pressed() && m_previousState == State::Dah && m_nextState == State::Wait) + { + printf("--- Pause --- Next state is Dit!\n"); + m_nextState = State::Dit; + + m_keyNextIambicB = right_paddle_pressed() ? true : false; + } + else if (right_paddle_pressed() && m_previousState == State::Dit && m_nextState == State::Wait) + { + printf("--- Pause --- Next state is Dah!\n"); + m_nextState = State::Dah; + + m_keyNextIambicB = left_paddle_pressed() ? true : false; + } + else if (m_previousState == State::Wait) + { + m_nextState = State::Wait; + } + } + else + { + + if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0) + { + m_currentlyPausing = false; + state = m_nextState; + m_nextState = State::Wait; + } } break; - + case State::Abort: + gpio_put(LED_PIN, 0); + m_Sidetone.off(); + m_keyNextIambicB = false; + m_currentlyPausing = false; + m_currentlyKeying = false; + m_previousState = State::Abort; + m_nextState = State::Wait; + state = State::Wait; + break; default: break; } +} + +void Keyer::stop() +{ + state = State::Abort; } \ No newline at end of file diff --git a/src/keyer.h b/src/keyer.h index bc32db9..8732030 100644 --- a/src/keyer.h +++ b/src/keyer.h @@ -15,6 +15,7 @@ public: Dit, Dah, InterCharSpace, + Abort, }; Keyer() = delete; Keyer(uint8_t wpm, Mode mode); @@ -23,10 +24,12 @@ public: void setSpeed(uint8_t wpm); void run(); + void stop(); private: State state{State::Wait}; State m_previousState{State::Wait}; + State m_nextState{State::Wait}; uint8_t m_wpm{18}; Mode m_mode{Mode::IAMBIC_B}; uint64_t m_elementDuration{0}; diff --git a/src/raspi_keyer.cpp b/src/raspi_keyer.cpp index 984a45c..20538f0 100644 --- a/src/raspi_keyer.cpp +++ b/src/raspi_keyer.cpp @@ -1,6 +1,8 @@ #include #include "pico/stdlib.h" +#include "pico/multicore.h" +#include "pico/util/queue.h" #include "settings.h" #include "keyer.h" @@ -13,7 +15,24 @@ 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; +extern const uint BUZZER_PIN = 18; + +// Stuff for communicating between cores +enum class KeyerQueueCommand +{ + Run, + Stop, + Config, + Wait, +}; +struct KeyerQueueData +{ + KeyerQueueCommand cmd; + uint8_t wpm; + Mode mode; +}; + +queue_t keyerQueue; void setup() { @@ -30,23 +49,67 @@ void setup() gpio_set_dir(RIGHT_PADDLE_PIN, GPIO_IN); gpio_pull_up(RIGHT_PADDLE_PIN); - sleep_ms(1000); + //sleep_ms(1000); +} + +/* Let's do all the keying stuff in the second core, so there are no timing problems. */ +void core1_main() +{ + printf("Hello from core1!\n"); + KeyerQueueData data; + queue_remove_blocking(&keyerQueue, &data); + + Keyer keyer(data.wpm, data.mode); + + while (true) + { + queue_try_remove(&keyerQueue, &data); + + switch (data.cmd) + { + case KeyerQueueCommand::Run: + keyer.run(); + break; + case KeyerQueueCommand::Stop: + keyer.stop(); + data.cmd = KeyerQueueCommand::Wait; + break; + case KeyerQueueCommand::Config: + keyer.setSpeed(data.wpm); + keyer.setMode(data.mode); + data.cmd = KeyerQueueCommand::Run; + break; + case KeyerQueueCommand::Wait: + break; + default: + break; + } + } } int main() { - timer_hw->dbgpause = 0; // workaround for problem with debug and sleep_ms + timer_hw->dbgpause = 1; // workaround for problem with debug and sleep_ms // https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639 setup(); - Settings settings{read_settings()}; + printf("Hello from core0!\n"); - Keyer keyer(settings.wpm, settings.mode); + Settings settings{read_settings()}; + settings.wpm = 25; // TODO: remove! + + queue_init(&keyerQueue, sizeof(KeyerQueueData), 2); + multicore_reset_core1(); + multicore_launch_core1(core1_main); + + KeyerQueueData keyerQueueData{KeyerQueueCommand::Run, settings.wpm, settings.mode}; + queue_add_blocking(&keyerQueue, &keyerQueueData); while (true) { - keyer.run(); + // Currently there's nothing to do on core0 + sleep_ms(1000); } return 0;