master_clock/src/DisplayHandler.cpp

354 lines
8.7 KiB
C++

// DisplayHandler.cpp
#include "pico/stdlib.h"
#include "DisplayHandler.h"
#include "globals.h"
#include <string>
#include <cstdlib>
#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 = 10;
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) { // shape control
int currentShape = (int)outputs[currentOut]->shape;
if (dir == 1) {
currentShape++;
} else {
currentShape--;
}
if (currentShape >= SHAPE_COUNT) {
currentShape = 0;
}
if (currentShape < 0) {
currentShape = SHAPE_COUNT - 1;
}
outputs[currentOut]->shape = (WaveShape)currentShape;
outputs[currentOut]->writeAnalog(0);
} else if (currentScreen == 3) { // level control
outputs[currentOut]->editing = 1;
if (dir == 1) {
outputs[currentOut]->level++;
} else {
outputs[currentOut]->level--;
}
if (outputs[currentOut]->level > 100) {
outputs[currentOut]->level = 100;
}
if (outputs[currentOut]->level < 1) {
outputs[currentOut]->level = 1;
}
} else if (currentScreen == 4) { // 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 == 5) { // SWING
outputs[currentOut]->editing = 1;
if (dir == 1) {
outputs[currentOut]->swing++;
} else {
outputs[currentOut]->swing--;
}
if (outputs[currentOut]->swing > 100) {
outputs[currentOut]->swing = 100;
}
if (outputs[currentOut]->swing < 50) {
outputs[currentOut]->swing = 50;
}
} else if (currentScreen == 6) { // PROBABILITY
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 (currentScreen == 7) { // STICKY
outputs[currentOut]->sticky ^= true;
} else if (currentScreen == 8) { // MUTE
outputs[currentOut]->editing = 1;
outputs[currentOut]->isEnabled ^= true;
}
}
} 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;
} else if (cursorPosition == 9) { // PLAY/PAUSE BUTTON
PLAY ^= true;
}
}
}
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;
}
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);
}
}
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) { // shape screen
param_string = waveShapeToString(outputs[currentOut]->shape);
} else if (currentScreen == 3) { // level screen
param_string = std::to_string(outputs[currentOut]->level) + "%";
} else if (currentScreen == 4) { // Width screen
param_string = std::to_string(outputs[currentOut]->width) + "%";
} else if (currentScreen == 5) { // Swing screen
param_string = std::to_string(outputs[currentOut]->swing) + "%";
} else if (currentScreen == 6) { // Probability screen
param_string = std::to_string(outputs[currentOut]->p) + "%";
} else if (currentScreen == 7) { // STICKY Screen
param_string = outputs[currentOut]->sticky ? "ON" : "OFF";
} else if (currentScreen == 8) { // Mute Screen
param_string = outputs[currentOut]->isEnabled ? "ON" : "OFF";
}
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);
}
}