#include <Wire.h> // For I2C communication with the OLED
#include <Adafruit_GFX.h> // Core graphics library for the OLED
#include <Adafruit_SSD1306.h> // OLED display driver for SSD1306 displays
#include <RotaryEncoder.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define PIN_IN1 2
#define PIN_IN2 3
#define ENCODER_BUTTON_PIN 4
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);
int lastEncoderPos = -1;
int encoderPos = 0;
bool buttonPressed = false;
#define TEXT_HEIGHT 10
int menuSize = 0; // Number of items in the current menu
int currentMenuLevel = 0; // 0 = main menu, 1 = sub-menu, 2 = sub-sub-menu
int currentSelection = 0; // Current selection in the current menu
bool optionSelected = false; // Flag to determine if an option is selected
const char** currentMenu; // Pointer to the current menu array
const char* mainMenu[] = {"Lightning Options", "Cloud Options", "Return"};
const char* lightningOptions[] = {"Active", "Length", "Speed", "Brightness", "Return"};
const char* cloudOptions[] = {"Brightness", "Always-On", "Return"};
const char* settingsOptions[] = {"Save Settings", "Load Settings", "Return"};
const char* onOffOptions[] = {"On", "Off"};
const int lengthMinMax[] = {1, 24};
const int speedMinMax[] = {10, 500};
const int brightnessMinMax[] = {1, 255};
void setup() {
// Initialize the OLED display
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
oled.clearDisplay();
oled.setTextSize(1); // Set text size (1 = small, 2 = medium, etc.)
oled.setTextColor(WHITE);
oled.setCursor(0, 0);
oled.display();
pinMode(ENCODER_BUTTON_PIN, INPUT_PULLUP);
currentMenu = mainMenu;
menuSize = sizeof(mainMenu) / sizeof(mainMenu[0]);
displayMenu(currentMenu, menuSize);
Serial.begin(115200);
}
void loop() {
handleEncoder();
handleButtonPress();
}
void displayMenu(const char** menu, int menuSize) {
oled.clearDisplay();
// Loop through the menu options
for (int i = 0; i < menuSize; i++) {
oled.setTextColor(i == currentSelection ? BLACK : WHITE, i == currentSelection ? WHITE : BLACK);
oled.setCursor(0, i * TEXT_HEIGHT);
oled.print(menu[i]);
}
oled.display();
}
void handleEncoder() {
// Read the encoder position (assuming encoderPos is updated by interrupt or polling)
if (encoderPos != lastEncoderPos) {
currentSelection = (encoderPos > lastEncoderPos) ? currentSelection + 1 : currentSelection - 1;
currentSelection = (currentSelection >= menuSize) ? 0 : (currentSelection < 0) ? menuSize - 1 : currentSelection;
displayMenu(currentMenu, menuSize);
lastEncoderPos = encoderPos;
}
}
void handleButtonPress() {
if (buttonPressed) { // Assuming buttonPressed is updated when the encoder button is pressed
if (currentMenuLevel == 0) {
// Enter sub-menu
if (currentSelection == 0) {
currentMenu = lightningOptions;
menuSize = sizeof(lightningOptions) / sizeof(lightningOptions[0]);
} else if (currentSelection == 1) {
currentMenu = cloudOptions;
menuSize = sizeof(cloudOptions) / sizeof(cloudOptions[0]);
} else if (currentSelection == 2) {
currentMenu = settingsOptions;
menuSize = sizeof(settingsOptions) / sizeof(settingsOptions[0]);
} else {
// Return or Save Settings action (handle separately)
}
currentMenuLevel++;
} else if (currentMenuLevel == 1) {
// Handle sub-options or return logic
if (currentSelection == menuSize - 1) {
// "Return" selected, go back to the main menu
currentMenu = mainMenu;
menuSize = sizeof(mainMenu) / sizeof(mainMenu[0]);
currentMenuLevel--;
} else {
// Handle other options like Min/Max, On/Off, etc.
// Meta code for modifying values:
// modifyValue(currentSelection); // Implement separately
}
}
// Additional levels can be handled similarly
// Update the display to reflect the new menu
displayMenu(currentMenu, menuSize);
}
}