// DisplayHandler.cpp #include "pico/stdlib.h" #include "DisplayHandler.h" #include "globals.h" #include #include #include "hardware/i2c.h" #include "pico-ssd1306/ssd1306.h" #include "pico-ssd1306/shapeRenderer/ShapeRenderer.h" #include "pico-ssd1306/textRenderer/TextRenderer.h" pico_ssd1306::SSD1306* display = nullptr; extern void update_BPM(bool up); DisplayHandler::DisplayHandler(Gate* outputs[]) { this->outputs = outputs; currentScreen = 0; currentOut = -1; updateScreen = 1; cursorPosition = 0; mainMaxCursorPosition = 8; outMaxCursorPosition = std::size(out_pages) - 1; cursorClick = 0; } void DisplayHandler::setup() { i2c_init(i2c1, 400 * 1000); gpio_set_function(SCREEN_SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(SCREEN_SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(SCREEN_SDA_PIN); gpio_pull_up(SCREEN_SCL_PIN); display = new pico_ssd1306::SSD1306(i2c1, 0x3C, pico_ssd1306::Size::W128xH64); display->setOrientation(0); } void DisplayHandler::moveCursor(bool dir) { if (onOutScreen) { if (cursorClick == 0) { if (dir == 1) { cursorPosition++; currentScreen++; } else { cursorPosition--; currentScreen--; } if (cursorPosition > outMaxCursorPosition) { cursorPosition = 0; currentScreen = 0; } if (cursorPosition < 0) { cursorPosition = outMaxCursorPosition; currentScreen = outMaxCursorPosition; } } else { // click = 1 if (currentScreen == 1) { // mod screen outputs[currentOut]->editing = 1; if (dir == 1) { outputs[currentOut]->modifierSelectionIndex++; } else { outputs[currentOut]->modifierSelectionIndex--; } if (outputs[currentOut]->modifierSelectionIndex < 0) { outputs[currentOut]->modifierSelectionIndex = 0; } if (outputs[currentOut]->modifierSelectionIndex > std::size(MOD_TYPES) - 1) { outputs[currentOut]->modifierSelectionIndex = std::size(MOD_TYPES) - 1; } } else if (currentScreen == 2) { // width control outputs[currentOut]->editing = 1; if (dir == 1) { outputs[currentOut]->width++; } else { outputs[currentOut]->width--; } if (outputs[currentOut]->width > 100) { outputs[currentOut]->width = 100; } if (outputs[currentOut]->width < 1) { outputs[currentOut]->width = 1; } outputs[currentOut]->setWidth(outputs[currentOut]->width); } else if (currentScreen == 3) { outputs[currentOut]->editing = 1; if (dir == 1) { outputs[currentOut]->p++; } else { outputs[currentOut]->p--; } if (outputs[currentOut]->p > 100) { outputs[currentOut]->p = 100; } if (outputs[currentOut]->p < 0) { outputs[currentOut]->p = 0; } } } } else { if (cursorPosition == 0 && cursorClick == 1) { // Engage BPM on Main Screen update_BPM(dir); } else { if (dir == 1) { cursorPosition++; } else { cursorPosition--; } if (cursorPosition > mainMaxCursorPosition) { cursorPosition = 0; } if (cursorPosition < 0) { cursorPosition = mainMaxCursorPosition; } } } updateScreen = 1; } void DisplayHandler::handleClick() { cursorClick ^= true; if (onOutScreen) { if (currentScreen == 0) { // exit screen cursorPosition = currentOut + 1; currentOut = -1; currentScreen = 0; onOutScreen = 0; cursorClick = false; } if (currentScreen == 1 && outputs[currentOut]->editing == 1) { outputs[currentOut]->setDiv(outputs[currentOut]->modifierSelectionIndex); outputs[currentOut]->editing = 0; cursorClick = false; } } else { if (currentScreen == 0) { // on main screen if (cursorPosition == 0) { // Change BPM } else if (cursorPosition > 0 && cursorPosition < 9) { // go to out screen currentOut = cursorPosition - 1; cursorPosition = 1; currentScreen = 1; onOutScreen = 1; cursorClick = 0; } } } updateScreen = 1; } void DisplayHandler::render() { if (updateScreen) { display->clear(); if (currentScreen == 0 && currentOut == -1) { // main screen renderMainPage(); } else if (currentOut != -1) { renderOutPage(); } display->sendBuffer(); updateScreen = 0; } } void DisplayHandler::renderMainPage() { std::string bpm_string = "BPM: " + std::to_string(BPM); if (cursorPosition == 0) { if (cursorClick == 1) { pico_ssd1306::fillRect(display, 0, 0, 100, 18); pico_ssd1306::drawText(display, font_12x16, bpm_string.c_str(), 1, 2, pico_ssd1306::WriteMode::SUBTRACT); } else { pico_ssd1306::drawRect(display, 0, 0, 100, 18, pico_ssd1306::WriteMode::ADD); pico_ssd1306::drawText(display, font_12x16, bpm_string.c_str(), 1, 2); } } else { pico_ssd1306::drawText(display, font_12x16, bpm_string.c_str(), 1, 2); } uint8_t cursor_x = 2; uint8_t cursor_y = 25; for (uint8_t i = 1; i < 9; i++) { if (i == 5) { cursor_x = 2; cursor_y += 20; } if (cursorPosition == i) { pico_ssd1306::drawRect(display, cursor_x - 2, cursor_y - 4, cursor_x + 14, cursor_y + 16, pico_ssd1306::WriteMode::ADD); } pico_ssd1306::drawText(display, font_12x16, std::to_string(i).c_str(), cursor_x, cursor_y); cursor_x += 30; } } void DisplayHandler::renderOutPage() { uint8_t visualOut = currentOut + 1; std::string title = std::to_string(visualOut) + "| " + out_pages[currentScreen]; pico_ssd1306::drawText(display, font_12x16, title.c_str(), 1, 2); std::string param_string; if (currentScreen == 0) { // exit screen param_string = "<--"; } else if (currentScreen == 1) { // modifier screen uint8_t modifier_selection_index = outputs[currentOut]->modifierSelectionIndex; param_string = MODIFIER_STRINGS[modifier_selection_index]; } else if (currentScreen == 2) { // Width screen param_string = std::to_string(outputs[currentOut]->width) + "%"; } else if (currentScreen == 3) { // Probability screen param_string = std::to_string(outputs[currentOut]->p) + "%"; } if (cursorClick) { pico_ssd1306::fillRect(display, 1, 42, 50, 60); pico_ssd1306::drawText(display, font_12x16, param_string.c_str(), 1, 45, pico_ssd1306::WriteMode::SUBTRACT); } else { pico_ssd1306::drawText(display, font_12x16, param_string.c_str(), 1, 45); } }