out screens
This commit is contained in:
parent
90915b89f6
commit
6532b218fe
9 changed files with 453 additions and 138 deletions
|
|
@ -17,6 +17,8 @@ include_directories(include)
|
||||||
add_executable(clock
|
add_executable(clock
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/Gate.cpp
|
src/Gate.cpp
|
||||||
|
src/DisplayHandler.cpp
|
||||||
|
src/EncoderHandler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable USB output (useful for later printf debugging)
|
# Enable USB output (useful for later printf debugging)
|
||||||
|
|
|
||||||
37
include/DisplayHandler.h
Normal file
37
include/DisplayHandler.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
// DisplayHandler.h
|
||||||
|
#ifndef DisplayHandler_h
|
||||||
|
#define DisplayHandler_h
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <array>
|
||||||
|
#include "Gate.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayHandler {
|
||||||
|
private:
|
||||||
|
char buffer[32];
|
||||||
|
uint8_t currentScreen;
|
||||||
|
std::string screens[7];
|
||||||
|
std::array<std::string, 4> out_pages = {"Exit", "Mod", "Width", "Prob"};
|
||||||
|
bool onOutScreen = 0;
|
||||||
|
void renderMainPage();
|
||||||
|
void renderOutPage();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
DisplayHandler(Gate* outputs[]);
|
||||||
|
Gate** outputs;
|
||||||
|
bool updateScreen;
|
||||||
|
int8_t cursorPosition;
|
||||||
|
uint8_t mainMaxCursorPosition;
|
||||||
|
uint8_t outMaxCursorPosition;
|
||||||
|
int8_t currentOut;
|
||||||
|
bool cursorClick;
|
||||||
|
void setup();
|
||||||
|
void render();
|
||||||
|
void handleClick();
|
||||||
|
void moveCursor(bool dir = 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
28
include/EncoderHandler.h
Normal file
28
include/EncoderHandler.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// EncoderHandler.h
|
||||||
|
#ifndef EncoderHandler_h
|
||||||
|
#define EncoderHandler_h
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include "pico/multicore.h"
|
||||||
|
#include "DisplayHandler.h"
|
||||||
|
|
||||||
|
|
||||||
|
class EncoderHandler {
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
EncoderHandler(DisplayHandler* display_handler);
|
||||||
|
|
||||||
|
DisplayHandler* display_handler;
|
||||||
|
uint8_t encoder_pos;
|
||||||
|
bool button_pressed;
|
||||||
|
uint16_t clk_last_state;
|
||||||
|
|
||||||
|
void setup();
|
||||||
|
static void gpio_callback(uint gpio, uint32_t events);
|
||||||
|
void moveCursor(bool dir = 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -12,21 +12,22 @@ class Gate {
|
||||||
int16_t cycle;
|
int16_t cycle;
|
||||||
uint32_t dur;
|
uint32_t dur;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t width;
|
|
||||||
uint8_t divideMode;
|
|
||||||
uint16_t div;
|
uint16_t div;
|
||||||
uint16_t modifier;
|
|
||||||
std::string divString;
|
|
||||||
uint8_t p;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Gate(uint8_t pin);
|
Gate(uint8_t pin);
|
||||||
uint8_t pin;
|
uint8_t pin;
|
||||||
|
uint8_t editing;
|
||||||
|
int8_t modifierSelectionIndex;
|
||||||
|
uint8_t divideMode;
|
||||||
|
uint16_t modifier;
|
||||||
|
uint8_t width;
|
||||||
|
uint8_t p;
|
||||||
|
|
||||||
void turnOn();
|
void turnOn();
|
||||||
void turnOff();
|
void turnOff();
|
||||||
void setLen(uint32_t currentPeriod);
|
void setLen(uint32_t currentPeriod);
|
||||||
void setDiv(uint16_t newDiv, uint8_t divide = 1);
|
void setDiv(uint8_t modifier_selection_index);
|
||||||
void setWidth(uint16_t newWidth);
|
void setWidth(uint16_t newWidth);
|
||||||
void setP(uint16_t prob);
|
void setP(uint16_t prob);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
static constexpr uint8_t OUT_1_PIN = 0;
|
static constexpr uint8_t OUT_1_PIN = 0;
|
||||||
static constexpr uint8_t OUT_2_PIN = 2;
|
static constexpr uint8_t OUT_2_PIN = 2;
|
||||||
|
|
@ -25,6 +27,15 @@ extern volatile uint8_t BPM;
|
||||||
static constexpr uint32_t MINUTE_US = 60000000;
|
static constexpr uint32_t MINUTE_US = 60000000;
|
||||||
static constexpr uint8_t PPQN = 96;
|
static constexpr uint8_t PPQN = 96;
|
||||||
|
|
||||||
|
static uint32_t MASTER_TICK = 0;
|
||||||
|
|
||||||
|
// Modifiers in UI order
|
||||||
|
static std::array<uint8_t, 10> MODIFIERS = {8, 4, 2, 0, 1, 2, 3, 4, 8, 16};
|
||||||
|
// Modifier type; 0 = multiplicaton, 1 = division; matched with MODIFIERS
|
||||||
|
static std::array<uint8_t, 10> MOD_TYPES = {0, 0, 0, 0, 1, 1, 1, 1, 1, 1};
|
||||||
|
// Modifier string
|
||||||
|
static std::array<std::string, 10> MODIFIER_STRINGS = {"x8", "x4", "x2", "x0", "/1", "/2", "/3", "/4", "/8", "/16"};
|
||||||
|
|
||||||
inline uint32_t millis() {
|
inline uint32_t millis() {
|
||||||
return to_ms_since_boot(get_absolute_time());
|
return to_ms_since_boot(get_absolute_time());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
229
src/DisplayHandler.cpp
Normal file
229
src/DisplayHandler.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
//TODO:
|
||||||
|
// the pulses are not even... they occur independently of eachother.
|
||||||
|
|
||||||
|
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 (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;
|
||||||
|
currentOut = -1;
|
||||||
|
currentScreen = 0;
|
||||||
|
onOutScreen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentScreen == 1 && outputs[currentOut]->editing == 1) {
|
||||||
|
outputs[currentOut]->setDiv(outputs[currentOut]->modifierSelectionIndex);
|
||||||
|
cursorClick = 0;
|
||||||
|
outputs[currentOut]->editing = 0;
|
||||||
|
}
|
||||||
|
} 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() {
|
||||||
|
std::string title = std::to_string(currentOut) + "| " + 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
71
src/EncoderHandler.cpp
Normal file
71
src/EncoderHandler.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
// EncoderHandler.cpp
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "EncoderHandler.h"
|
||||||
|
#include "DisplayHandler.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
static EncoderHandler* self = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
EncoderHandler::EncoderHandler(DisplayHandler* display_handler) {
|
||||||
|
this->display_handler = display_handler;
|
||||||
|
self = this;
|
||||||
|
encoder_pos = 0;
|
||||||
|
button_pressed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EncoderHandler::gpio_callback(uint gpio, uint32_t events) {
|
||||||
|
static uint64_t last_sw_time = 0;
|
||||||
|
static uint64_t last_rotate_time = 0;
|
||||||
|
uint64_t now = to_us_since_boot(get_absolute_time());
|
||||||
|
|
||||||
|
if (gpio == ENCODER_SW_PIN) { // handle button press
|
||||||
|
if (now - last_sw_time > 200000) {
|
||||||
|
self->display_handler->handleClick();
|
||||||
|
last_sw_time = now;
|
||||||
|
}
|
||||||
|
} else if (gpio == ENCODER_CLK_PIN) { // handle encoder turn
|
||||||
|
|
||||||
|
if (now - last_rotate_time < 5000) return;
|
||||||
|
|
||||||
|
if (events & GPIO_IRQ_EDGE_FALL) {
|
||||||
|
if (gpio_get(ENCODER_CLK_PIN) == 0) {
|
||||||
|
|
||||||
|
uint16_t dt_state = gpio_get(ENCODER_DT_PIN);
|
||||||
|
|
||||||
|
if (dt_state) {
|
||||||
|
self->display_handler->moveCursor();
|
||||||
|
} else {
|
||||||
|
self->display_handler->moveCursor(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_rotate_time = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EncoderHandler::setup() {
|
||||||
|
gpio_init(ENCODER_SW_PIN);
|
||||||
|
gpio_set_dir(ENCODER_SW_PIN, GPIO_IN);
|
||||||
|
gpio_pull_up(ENCODER_SW_PIN);
|
||||||
|
|
||||||
|
gpio_init(ENCODER_CLK_PIN);
|
||||||
|
gpio_set_dir(ENCODER_CLK_PIN, GPIO_IN);
|
||||||
|
gpio_pull_up(ENCODER_CLK_PIN);
|
||||||
|
|
||||||
|
gpio_init(ENCODER_DT_PIN);
|
||||||
|
gpio_set_dir(ENCODER_DT_PIN, GPIO_IN);
|
||||||
|
gpio_pull_up(ENCODER_DT_PIN);
|
||||||
|
|
||||||
|
clk_last_state = gpio_get(ENCODER_CLK_PIN);
|
||||||
|
|
||||||
|
gpio_set_irq_enabled_with_callback(20, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &EncoderHandler::gpio_callback);
|
||||||
|
gpio_set_irq_enabled(21, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
|
||||||
|
gpio_set_irq_enabled(22, GPIO_IRQ_EDGE_FALL, true);
|
||||||
|
}
|
||||||
27
src/Gate.cpp
27
src/Gate.cpp
|
|
@ -9,11 +9,12 @@ Gate::Gate(uint8_t pin) {
|
||||||
this->pin = pin;
|
this->pin = pin;
|
||||||
state = 0;
|
state = 0;
|
||||||
|
|
||||||
divideMode = 1; // 1 divison | 0 multiplication
|
modifierSelectionIndex = 3;
|
||||||
modifier = 1; // divide mode modifier (4x, /32, etc)
|
editing = 0;
|
||||||
div = 1; // cycles needed before a pulse based on divide mode and modifier
|
divideMode = 0; // 1 divison | 0 multiplication
|
||||||
|
modifier = 0; // divide mode modifier (4x, /32, etc)
|
||||||
|
div = 0; // cycles needed before a pulse based on divide mode and modifier
|
||||||
cycle = 0; // how many cycles have passed since last pulse
|
cycle = 0; // how many cycles have passed since last pulse
|
||||||
divString = ""; // string for screen .. probably does not belong here
|
|
||||||
|
|
||||||
dur = 0; // how long pulse is on
|
dur = 0; // how long pulse is on
|
||||||
width = 50; // pulse width
|
width = 50; // pulse width
|
||||||
|
|
@ -30,16 +31,24 @@ void Gate::setLen(uint32_t currentPeriod) {
|
||||||
len = (uint32_t)((double)currentPeriod * (width / 100.0) / 1000.0);
|
len = (uint32_t)((double)currentPeriod * (width / 100.0) / 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gate::setDiv(uint16_t modifier, uint8_t divide) {
|
void Gate::setDiv(uint8_t modifier_selecton_index) {
|
||||||
if (divide == 1) {
|
printf("HOW ABOUT HERE\n");
|
||||||
|
|
||||||
|
uint8_t modifier = MODIFIERS[modifier_selecton_index];
|
||||||
|
uint8_t mod_type = MOD_TYPES[modifier_selecton_index];
|
||||||
|
if (mod_type == 1) {
|
||||||
div = PPQN * modifier;
|
div = PPQN * modifier;
|
||||||
divString = "/" + std::to_string(modifier);
|
|
||||||
} else {
|
} else {
|
||||||
div = PPQN / modifier;
|
div = PPQN / modifier;
|
||||||
divString = "x" + std::to_string(modifier);
|
|
||||||
}
|
}
|
||||||
divideMode = divide;
|
divideMode = mod_type;
|
||||||
this->modifier = modifier;
|
this->modifier = modifier;
|
||||||
|
|
||||||
|
if (this->modifier == 0) {
|
||||||
|
turnOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
setWidth(this->width);
|
||||||
};
|
};
|
||||||
|
|
||||||
void Gate::setWidth(uint16_t newWidth) {
|
void Gate::setWidth(uint16_t newWidth) {
|
||||||
|
|
|
||||||
173
src/main.cpp
173
src/main.cpp
|
|
@ -1,17 +1,15 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "hardware/i2c.h"
|
|
||||||
#include "hardware/structs/rosc.h"
|
#include "hardware/structs/rosc.h"
|
||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pico/time.h"
|
#include "pico/time.h"
|
||||||
|
|
||||||
#include "pico-ssd1306/ssd1306.h"
|
|
||||||
#include "pico-ssd1306/textRenderer/TextRenderer.h"
|
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "Gate.h"
|
#include "Gate.h"
|
||||||
|
#include "DisplayHandler.h"
|
||||||
|
#include "EncoderHandler.h"
|
||||||
|
|
||||||
struct repeating_timer bpm_timer = {0};
|
struct repeating_timer bpm_timer = {0};
|
||||||
|
|
||||||
|
|
@ -30,17 +28,16 @@ Gate out6(OUT_6_PIN);
|
||||||
Gate out7(OUT_7_PIN);
|
Gate out7(OUT_7_PIN);
|
||||||
Gate out8(OUT_8_PIN);
|
Gate out8(OUT_8_PIN);
|
||||||
|
|
||||||
volatile bool updateScreen = 1;
|
static Gate* outputs[] = {&out1, &out2, &out3, &out4, &out5, &out6, &out7, &out8};
|
||||||
pico_ssd1306::SSD1306* display = nullptr;
|
|
||||||
|
|
||||||
volatile uint8_t encoder_pos = 0;
|
static DisplayHandler display_handler(outputs);
|
||||||
volatile bool button_pressed = 0;
|
static EncoderHandler encoder_handler(&display_handler);
|
||||||
volatile uint16_t clk_last_state;
|
|
||||||
|
|
||||||
|
|
||||||
bool timer_callback(struct repeating_timer *t) {
|
bool timer_callback(struct repeating_timer *t) {
|
||||||
if (PLAY == 1) {
|
if (PLAY == 1) {
|
||||||
beatToggle = true;
|
beatToggle = true;
|
||||||
|
MASTER_TICK += 1;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -69,117 +66,67 @@ void update_BPM(bool up) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void gpio_callback(uint gpio, uint32_t events) {
|
|
||||||
if (gpio == ENCODER_SW_PIN) { // handle button press
|
|
||||||
|
|
||||||
} else if (gpio == ENCODER_CLK_PIN || gpio == ENCODER_DT_PIN) { // handle encoder turn
|
|
||||||
uint16_t clk_state = gpio_get(ENCODER_CLK_PIN);
|
|
||||||
uint16_t dt_state = gpio_get(ENCODER_DT_PIN);
|
|
||||||
|
|
||||||
if (clk_state != clk_last_state && clk_state == 1)
|
|
||||||
if (dt_state != clk_state) {
|
|
||||||
encoder_pos++; // Clockwise
|
|
||||||
update_BPM(1);
|
|
||||||
} else {
|
|
||||||
encoder_pos--; // Counter-clockwise
|
|
||||||
update_BPM(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateScreen = 1;
|
|
||||||
|
|
||||||
clk_last_state = clk_state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setup_encoder() {
|
|
||||||
gpio_init(ENCODER_SW_PIN);
|
|
||||||
gpio_set_dir(ENCODER_SW_PIN, GPIO_IN);
|
|
||||||
gpio_pull_up(ENCODER_SW_PIN);
|
|
||||||
|
|
||||||
gpio_init(ENCODER_CLK_PIN);
|
|
||||||
gpio_set_dir(ENCODER_CLK_PIN, GPIO_IN);
|
|
||||||
gpio_pull_up(ENCODER_CLK_PIN);
|
|
||||||
|
|
||||||
gpio_init(ENCODER_DT_PIN);
|
|
||||||
gpio_set_dir(ENCODER_DT_PIN, GPIO_IN);
|
|
||||||
gpio_pull_up(ENCODER_DT_PIN);
|
|
||||||
|
|
||||||
clk_last_state = gpio_get(ENCODER_CLK_PIN);
|
|
||||||
|
|
||||||
gpio_set_irq_enabled_with_callback(20, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
|
|
||||||
gpio_set_irq_enabled(21, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
|
|
||||||
gpio_set_irq_enabled(22, GPIO_IRQ_EDGE_FALL, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setup_screen() {
|
|
||||||
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 core1_entry() {
|
void core1_entry() {
|
||||||
multicore_fifo_pop_blocking();
|
multicore_fifo_pop_blocking();
|
||||||
|
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (updateScreen) {
|
display_handler.render();
|
||||||
display->clear();
|
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "BPM: %u", BPM);
|
|
||||||
pico_ssd1306::drawText(display, font_12x16, buffer, 0, 0);
|
|
||||||
|
|
||||||
display->sendBuffer();
|
|
||||||
|
|
||||||
updateScreen = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setup_outs() {
|
void setup_outs() {
|
||||||
Gate* my_outputs[] = {&out1, &out2, &out3, &out4, &out5, &out6, &out7, &out8};
|
|
||||||
|
|
||||||
for (auto g : my_outputs) {
|
for (auto g : outputs) {
|
||||||
gpio_init(g->pin);
|
gpio_init(g->pin);
|
||||||
gpio_set_dir(g->pin, GPIO_OUT);
|
gpio_set_dir(g->pin, GPIO_OUT);
|
||||||
g->setLen(period_us);
|
g->setLen(period_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
// manual setup
|
// manual setup
|
||||||
out1.setDiv(8, 0);
|
out1.setDiv(1);
|
||||||
out1.setWidth(50);
|
// out1.setWidth(50);
|
||||||
|
//
|
||||||
|
// out2.setDiv(4, 0);
|
||||||
|
// out2.setWidth(50);
|
||||||
|
//
|
||||||
|
// out3.setDiv(2, 0);
|
||||||
|
// out3.setWidth(50);
|
||||||
|
//
|
||||||
|
// out4.setDiv(1);
|
||||||
|
// out4.setWidth(50);
|
||||||
|
//
|
||||||
|
// out5.setDiv(2);
|
||||||
|
// out5.setWidth(50);
|
||||||
|
//
|
||||||
|
// out6.setDiv(4);
|
||||||
|
// out6.setWidth(50);
|
||||||
|
//
|
||||||
|
// out7.setDiv(8);
|
||||||
|
// out7.setWidth(50);
|
||||||
|
//
|
||||||
|
// out8.setDiv(16);
|
||||||
|
// out8.setWidth(50);
|
||||||
|
}
|
||||||
|
|
||||||
out2.setDiv(4, 0);
|
|
||||||
out2.setWidth(50);
|
|
||||||
|
|
||||||
out3.setDiv(2, 0);
|
void handle_outs() {
|
||||||
out3.setWidth(50);
|
if (beatToggle) {
|
||||||
|
for (Gate* g: outputs) {
|
||||||
|
if (g->modifier != 0) {
|
||||||
|
g->turnOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out4.setDiv(1);
|
beatToggle = false;
|
||||||
out4.setWidth(50);
|
}
|
||||||
|
for (Gate* g: outputs) {
|
||||||
out5.setDiv(2);
|
if (g->modifier != 0) {
|
||||||
out5.setWidth(50);
|
g->turnOff();
|
||||||
|
}
|
||||||
out6.setDiv(4);
|
}
|
||||||
out6.setWidth(50);
|
|
||||||
|
|
||||||
out7.setDiv(8);
|
|
||||||
out7.setWidth(50);
|
|
||||||
|
|
||||||
out8.setDiv(16);
|
|
||||||
out8.setWidth(50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -187,37 +134,17 @@ int main() {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
srand(rosc_hw->randombit);
|
srand(rosc_hw->randombit);
|
||||||
|
|
||||||
setup_screen();
|
display_handler.setup();
|
||||||
multicore_launch_core1(core1_entry);
|
multicore_launch_core1(core1_entry);
|
||||||
multicore_fifo_push_blocking(1);
|
multicore_fifo_push_blocking(1);
|
||||||
|
|
||||||
setup_encoder();
|
encoder_handler.setup();
|
||||||
|
|
||||||
setup_outs();
|
setup_outs();
|
||||||
|
|
||||||
update_period();
|
update_period();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (beatToggle) {
|
handle_outs();
|
||||||
out1.turnOn();
|
|
||||||
out2.turnOn();
|
|
||||||
out3.turnOn();
|
|
||||||
out4.turnOn();
|
|
||||||
out5.turnOn();
|
|
||||||
out6.turnOn();
|
|
||||||
out7.turnOn();
|
|
||||||
out8.turnOn();
|
|
||||||
|
|
||||||
beatToggle = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out1.turnOff();
|
|
||||||
out2.turnOff();
|
|
||||||
out3.turnOff();
|
|
||||||
out4.turnOff();
|
|
||||||
out5.turnOff();
|
|
||||||
out6.turnOff();
|
|
||||||
out7.turnOff();
|
|
||||||
out8.turnOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue