From 5e500086f0471b50270664ec2eb51b14f79cab11 Mon Sep 17 00:00:00 2001 From: Dominic DiTaranto Date: Fri, 13 Mar 2026 19:15:21 -0400 Subject: [PATCH] fix BPM, fix gates not closing, add experimental clk in --- include/DisplayHandler.h | 1 + include/globals.h | 4 ++ src/DisplayHandler.cpp | 16 ++++-- src/Gate.cpp | 4 ++ src/main.cpp | 107 ++++++++++++++++++++++++++++----------- 5 files changed, 99 insertions(+), 33 deletions(-) diff --git a/include/DisplayHandler.h b/include/DisplayHandler.h index 57beb5d..a3a83e1 100644 --- a/include/DisplayHandler.h +++ b/include/DisplayHandler.h @@ -38,6 +38,7 @@ class DisplayHandler { bool onOutScreen = false; bool onMainScreen = true; bool onSettingsScreen = false; + bool engageBPM = false; std::array settings = { "Save", diff --git a/include/globals.h b/include/globals.h index 5e85ee9..b11ecd3 100644 --- a/include/globals.h +++ b/include/globals.h @@ -18,6 +18,7 @@ static constexpr uint8_t OUT_6_PIN = 10; static constexpr uint8_t OUT_7_PIN = 12; static constexpr uint8_t OUT_8_PIN = 14; +static constexpr uint8_t IN_CLK_PIN = 16; static constexpr uint8_t IN_RUN_PIN = 17; static constexpr uint8_t SCREEN_SCL_PIN = 18; @@ -44,6 +45,9 @@ extern volatile bool RUN; extern volatile uint8_t EXTPPQNIdx; #define PPQN_OPTS_LEN 5 extern const uint16_t PPQNOPTS[PPQN_OPTS_LEN]; +extern volatile uint64_t last_clk_us; +extern volatile uint64_t last_valid_clk_us; +extern volatile bool EXTERNAL_CLOCK; enum WaveShape { SQUARE, TRIANGLE, SAW, RAMP, EXP, HALFSINE, REXP, LOG, SINE, BOUNCE, SIGMO, WOBBLE, STEPDW, STEPUP, SH, SHAPE_COUNT}; diff --git a/src/DisplayHandler.cpp b/src/DisplayHandler.cpp index 85b30b0..be1bdf4 100644 --- a/src/DisplayHandler.cpp +++ b/src/DisplayHandler.cpp @@ -258,22 +258,32 @@ void DisplayHandler::handleClickOnOutputScreen() { void DisplayHandler::handleClickOnMainScreen() { - if (cursorPosition > 0 && cursorPosition < 9) { // GO TO OUTPUT + if (cursorPosition == 0) { + if (engageBPM) { + cursorClick = 0; + engageBPM = false; + } else { + engageBPM = true; + cursorClick = 1; + } + } if (cursorPosition > 0 && cursorPosition < 9) { // GO TO OUTPUT currentOut = cursorPosition - 1; cursorPosition = 1; currentScreen = 1; onOutScreen = true; onMainScreen = false; - onSettingsScreen = false;; + onSettingsScreen = false; + cursorClick = 0; } else if (cursorPosition == 9) { // PLAY/PAUSE BUTTON PLAY ^= true; + cursorClick = 0; } else if (cursorPosition == 10) { // GLOBAL SETTINGS cursorPosition = 0; onSettingsScreen = true; onMainScreen = false; onOutScreen = false; + cursorClick = 0; } - cursorClick = 0; } diff --git a/src/Gate.cpp b/src/Gate.cpp index e8e7478..2a1bdcf 100644 --- a/src/Gate.cpp +++ b/src/Gate.cpp @@ -293,6 +293,10 @@ void Gate::update() { if (elapsedUs >= pulseDurationUs) { state = 0; + if (width < 100) { + scheduledTick = 0xFFFFFFFF; + lastTriggerTick = 0xFFFFFFFF; + } if (!sticky) writeAnalog(0); return; diff --git a/src/main.cpp b/src/main.cpp index 5e5198e..4b3dc06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include "DisplayHandler.h" @@ -26,6 +28,9 @@ volatile uint32_t MASTER_TICK; volatile bool RUN = false; const uint16_t PPQNOPTS[] = {1, 2, 4, 24, 48}; volatile uint8_t EXTPPQNIdx = 0; +volatile uint64_t last_clk_us = 0; +volatile uint64_t last_valid_clk_us; +volatile bool EXTERNAL_CLOCK = false; ModMatrix matrix; @@ -75,6 +80,12 @@ void update_BPM(bool up) { for (auto g : outputs) { g->setWidth(g->width); } + + if (!EXTERNAL_CLOCK) { + init_timer(period_us); + } else { + cancel_repeating_timer(&bpm_timer); + } } void core1_entry() { @@ -93,10 +104,10 @@ void full_save() { outputs[i]->pack(globalSettings.configs[i]); } - globalSettings.bpm = BPM; - globalSettings.play = PLAY; - globalSettings.run = RUN; - globalSettings.ppqnidx = EXTPPQNIdx; + globalSettings.bpm = BPM; + globalSettings.play = PLAY; + globalSettings.run = RUN; + globalSettings.ppqnidx = EXTPPQNIdx; memcpy(globalSettings.slots, matrix.slots, sizeof(ModSlot) * 16); @@ -130,20 +141,49 @@ void handle_outs() { } void gpio_callback(uint gpio, uint32_t events) { + // CLK LOGIC + if (gpio == IN_CLK_PIN && (events & GPIO_IRQ_EDGE_RISE)) { + uint64_t now = to_us_since_boot(get_absolute_time()); - if (gpio == IN_RUN_PIN) { - if (RUN) { - if (events & GPIO_IRQ_EDGE_RISE) { - PLAY = true; - } else if (events & GPIO_IRQ_EDGE_FALL) { - PLAY = false; - } - } - } + if (now - last_valid_clk_us < 5000) { + return; + } + last_valid_clk_us = now; + + uint16_t incomingPPQN; + if (last_clk_us > 0) { + uint64_t diff = now - last_clk_us; + incomingPPQN = PPQNOPTS[EXTPPQNIdx]; + float calculatedBPM = 60000000.0f / (float)(diff * incomingPPQN); + + if (calculatedBPM >= 30 && calculatedBPM <= 255) { + if (fabsf((float)BPM - calculatedBPM) > 0.5f) { + BPM = (uint8_t)(calculatedBPM + 0.5f); + + update_period(); + for (auto g : outputs) { + g->setWidth(g->width); + } + } + } + } + MASTER_TICK += (PPQN / incomingPPQN); + last_clk_us = now; + } + + if (gpio == IN_RUN_PIN) { + if (RUN) { + if (events & GPIO_IRQ_EDGE_RISE) { + PLAY = true; + } else if (events & GPIO_IRQ_EDGE_FALL) { + PLAY = false; + } + } + } if (gpio == ENCODER_SW_PIN) { - uint64_t now = to_us_since_boot(get_absolute_time()); - static uint64_t last_sw_time = 0; + uint64_t now = to_us_since_boot(get_absolute_time()); + static uint64_t last_sw_time = 0; if (now - last_sw_time > 200000) { // 200ms debounce display_handler.handleClick(); last_sw_time = now; @@ -152,15 +192,22 @@ void gpio_callback(uint gpio, uint32_t events) { } void setup_ins() { - // SETUP RUN - gpio_init(IN_RUN_PIN); - gpio_set_dir(IN_RUN_PIN, GPIO_IN); - gpio_pull_down(IN_RUN_PIN); - gpio_set_irq_enabled_with_callback(IN_RUN_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback); + // SETUP RUN + gpio_init(IN_RUN_PIN); + gpio_set_dir(IN_RUN_PIN, GPIO_IN); + gpio_pull_down(IN_RUN_PIN); + gpio_set_irq_enabled_with_callback(IN_RUN_PIN, + GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, + true, &gpio_callback); - // SETUP CLOCK + // SETUP CLOCK + gpio_init(IN_CLK_PIN); + gpio_set_dir(IN_CLK_PIN, GPIO_IN); + gpio_pull_down(IN_CLK_PIN); + // Add to existing callback + gpio_set_irq_enabled(IN_CLK_PIN, GPIO_IRQ_EDGE_RISE, true); - // SETUP CV INS + // SETUP CV INS } int main() { @@ -179,10 +226,10 @@ int main() { matrix.slots[i] = globalSettings.slots[i]; } - BPM = globalSettings.bpm; - PLAY = globalSettings.play; - RUN = globalSettings.run; - EXTPPQNIdx = globalSettings.ppqnidx; + BPM = globalSettings.bpm; + PLAY = globalSettings.play; + RUN = globalSettings.run; + EXTPPQNIdx = globalSettings.ppqnidx; } for (int i = 0; i < 8; i++) { @@ -197,11 +244,11 @@ int main() { bool lastPlayState = false; - setup_ins(); + setup_ins(); - if (RUN) { - PLAY = false; - } + if (RUN) { + PLAY = false; + } while (true) { encoder_handler.update();