#include "UIThread.h" #include "SharedState.h" #include // --- Local State --- static int g_last_clk_state; // --- Forward Declarations --- static void readEncoder(); static void updateDisplay(); void setupUI() { // --- Initialize I2C and Display --- Wire.setSDA(OLED_SDA_PIN); Wire.setSCL(OLED_SCL_PIN); Wire.begin(); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64 Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); display.setTextSize(1); display.println("NoiceSynth Booting..."); display.display(); delay(1000); // --- Initialize Controls --- pinMode(ENCODER_CLK_PIN, INPUT_PULLUP); pinMode(ENCODER_DT_PIN, INPUT_PULLUP); pinMode(ENCODER_SW_PIN, INPUT_PULLUP); g_last_clk_state = digitalRead(ENCODER_CLK_PIN); } void loopUI() { // Read the volume potentiometer (Pico ADC is 12-bit, 0-4095) // We use a bit of filtering by averaging with the old value to reduce noise. float new_volume = analogRead(VOL_POT_PIN) / 4095.0f; g_volume = (g_volume * 0.95) + (new_volume * 0.05); // Read the rotary encoder readEncoder(); // Update the display periodically static uint32_t last_display_update = 0; if (millis() - last_display_update > 100) { // Update 10 times/sec last_display_update = millis(); updateDisplay(); } } static void updateDisplay() { display.clearDisplay(); display.setCursor(0, 0); display.println(F(" NoiceSynth")); display.println(F("--------------------")); if (g_note_on) { display.print(F("Note Freq: ")); display.print(g_note_frequency, 2); display.println(F(" Hz")); } else { display.println(F("Note: Off")); } display.print(F("Volume: ")); display.print(static_cast(g_volume * 100)); display.println(F("%")); display.print(F("Encoder: ")); display.println(g_encoder_value); display.display(); } static void readEncoder() { int new_clk_state = digitalRead(ENCODER_CLK_PIN); // Check for a change on the CLK pin (a "tick" of the encoder) if (new_clk_state != g_last_clk_state && new_clk_state == LOW) { // Read the DT pin to determine direction if (digitalRead(ENCODER_DT_PIN) == LOW) { g_encoder_value++; // Clockwise } else { g_encoder_value--; // Counter-clockwise } } g_last_clk_state = new_clk_state; }