diff --git a/CMakeLists.txt b/CMakeLists.txt index bd176ac..8e28f11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ include_directories(include) add_executable(clock src/main.cpp + src/Output.cpp src/Gate.cpp src/DisplayHandler.cpp src/EncoderHandler.cpp diff --git a/include/DisplayHandler.h b/include/DisplayHandler.h index 491f7e7..78f3296 100644 --- a/include/DisplayHandler.h +++ b/include/DisplayHandler.h @@ -13,7 +13,7 @@ class DisplayHandler { char buffer[32]; uint8_t currentScreen; std::string screens[7]; - std::array out_pages = {"Exit", "Mod", "Width", "Prob"}; + std::array out_pages = {"Exit", "Mod", "Width", "Prob", "Mute"}; bool onOutScreen = 0; void renderMainPage(); void renderOutPage(); diff --git a/include/Gate.h b/include/Gate.h index 58814af..2cd4b2d 100644 --- a/include/Gate.h +++ b/include/Gate.h @@ -3,29 +3,28 @@ #define Gate_h #include +#include "Output.h" -class Gate { +class Gate : public Output { private: - bool state; uint32_t dur; uint32_t len; uint32_t lastTriggerTick = 0xFFFFFFFF; public: Gate(uint8_t pin); - uint8_t pin; - uint8_t editing; + int8_t modifierSelectionIndex; uint8_t divideMode; uint16_t modifier; uint16_t tickInterval; - bool isEnabled; uint8_t width; uint8_t p; - void turnOn(); - void turnOff(); + void turnOn() override; + void turnOff() override; + void setLen(uint32_t currentPeriod); void setDiv(uint8_t modifier_selection_index); void setWidth(uint16_t newWidth); diff --git a/include/Output.h b/include/Output.h new file mode 100644 index 0000000..daea529 --- /dev/null +++ b/include/Output.h @@ -0,0 +1,23 @@ +// Output.h +#ifndef Output_h +#define Output_h + +#include + + +class Output { + private: + + public: + Output(uint8_t pin); + bool state; + uint8_t pin; + uint8_t editing; + bool isEnabled; + + virtual ~Output() {}; + virtual void turnOn(); + virtual void turnOff(); +}; + +#endif diff --git a/include/globals.h b/include/globals.h index 8470f43..4343ba6 100644 --- a/include/globals.h +++ b/include/globals.h @@ -28,6 +28,7 @@ static constexpr uint8_t ENCODER_DT_PIN = 21; static constexpr uint8_t ENCODER_SW_PIN = 22; // TIME BASED +extern volatile bool PLAY; extern volatile uint8_t BPM; static constexpr uint32_t MINUTE_US = 60000000; static constexpr uint8_t PPQN = 96; diff --git a/src/DisplayHandler.cpp b/src/DisplayHandler.cpp index bbd6ed0..b61e72a 100644 --- a/src/DisplayHandler.cpp +++ b/src/DisplayHandler.cpp @@ -21,7 +21,7 @@ DisplayHandler::DisplayHandler(Gate* outputs[]) { currentOut = -1; updateScreen = 1; cursorPosition = 0; - mainMaxCursorPosition = 8; + mainMaxCursorPosition = 10; outMaxCursorPosition = std::size(out_pages) - 1; cursorClick = 0; } @@ -96,7 +96,7 @@ void DisplayHandler::moveCursor(bool dir) { outputs[currentOut]->setWidth(outputs[currentOut]->width); - } else if (currentScreen == 3) { + } else if (currentScreen == 3) { // PROBABILITY outputs[currentOut]->editing = 1; if (dir == 1) { @@ -112,6 +112,11 @@ void DisplayHandler::moveCursor(bool dir) { if (outputs[currentOut]->p < 0) { outputs[currentOut]->p = 0; } + } else if (currentScreen == 4) { // MUTE + + outputs[currentOut]->editing = 1; + outputs[currentOut]->isEnabled ^= true; + } } @@ -167,6 +172,8 @@ void DisplayHandler::handleClick() { currentScreen = 1; onOutScreen = 1; cursorClick = 0; + } else if (cursorPosition == 9) { // PLAY/PAUSE BUTTON + PLAY ^= true; } } @@ -226,8 +233,23 @@ void DisplayHandler::renderMainPage() { } pico_ssd1306::drawText(display, font_12x16, std::to_string(i).c_str(), cursor_x, cursor_y); cursor_x += 30; - } + + + if (cursorPosition == 9) { // PLAY BUTTON + pico_ssd1306::fillRect(display, 120, 8, 130, 18, pico_ssd1306::WriteMode::ADD); + pico_ssd1306::drawText(display, font_8x8, PLAY ? ">" : "#", 120, 10, pico_ssd1306::WriteMode::SUBTRACT); + } else { + pico_ssd1306::drawText(display, font_8x8, PLAY ? ">" : "#", 120, 10); + } + + if (cursorPosition == 10) { // OPTIONS BUTTON + pico_ssd1306::fillRect(display, 120, 28, 130, 38, pico_ssd1306::WriteMode::ADD); + pico_ssd1306::drawText(display, font_8x8, "*", 120, 30, pico_ssd1306::WriteMode::SUBTRACT); + } else { + pico_ssd1306::drawText(display, font_8x8, "*", 120, 30); + } + } @@ -250,6 +272,8 @@ void DisplayHandler::renderOutPage() { } else if (currentScreen == 3) { // Probability screen param_string = std::to_string(outputs[currentOut]->p) + "%"; + } else if (currentScreen == 4) { // Mute Screen + param_string = outputs[currentOut]->isEnabled ? "ON" : "OFF"; } if (cursorClick) { diff --git a/src/Gate.cpp b/src/Gate.cpp index d494c62..4dba464 100644 --- a/src/Gate.cpp +++ b/src/Gate.cpp @@ -4,13 +4,13 @@ #include -Gate::Gate(uint8_t pin) { +Gate::Gate(uint8_t pin) : Output(pin){ this->pin = pin; state = 0; editing = 0; - modifierSelectionIndex = 3; + modifierSelectionIndex = 8; divideMode = 0; // 1 divison | 0 multiplication modifier = 0; // divide mode modifier (4x, /32, etc) diff --git a/src/Output.cpp b/src/Output.cpp new file mode 100644 index 0000000..eb335cb --- /dev/null +++ b/src/Output.cpp @@ -0,0 +1,10 @@ +#include "Output.h" + +Output::Output(uint8_t pin) { + this->pin = pin; + state = 0; + isEnabled = false; +} + +void Output::turnOn() {} +void Output::turnOff() {} diff --git a/src/main.cpp b/src/main.cpp index daf883a..c155442 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,7 @@ // Time based operations struct repeating_timer bpm_timer = {0}; volatile uint8_t BPM = 60; -volatile uint8_t PLAY = 1; +volatile bool PLAY = true; volatile uint32_t period_us = 0; volatile uint32_t MASTER_TICK; @@ -122,8 +122,18 @@ int main() { update_period(); + bool lastPlayState = false; + while (true) { encoder_handler.update(); - handle_outs(); + if (PLAY) { + handle_outs(); + } else { + for (Gate* g: outputs) { + g->turnOff(); + } + } + + lastPlayState = PLAY; } }