// OLED Menu Navigation Template for ESP32
// Adapted by S. James Parsons Jr. with ChatGPT refinement
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ---- Menu State ----
int windowVariable = 1; // top-level menu starts at 1 (e.g., Home menu)
// ---- Menus ----
const char* mainMenu[] = {"Polar Angle", "Kinetics", "Settings", "Credits", "QR Code"};
const char* settingsMenu[] = {"Light Intensity", "Temperature Range"};
// ---- Function Prototypes ----
void showMenu(const char* title, const char* items[], int count, int selected);
void handleMenu(int window);
int getCurrentSelection(int value);
void navigateUp();
void navigateDown(int maxItems);
void selectItem();
void goBack();
void setup() {
Serial.begin(115200); // ESP32 default baud rate
// Initialize I2C manually for ESP32 (optional if using default SDA/SCL)
Wire.begin(21, 22); // SDA = GPIO21, SCL = GPIO22 (standard ESP32 I2C pins)
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.cp437(true);
display.display();
}
void loop() {
handleMenu(windowVariable);
// TEMPORARY: Emulate button presses for testing
if (Serial.available()) {
char input = Serial.read();
switch (input) {
case 'u': navigateUp(); break;
case 'd': navigateDown(5); break; // Update maxItems per menu
case 's': selectItem(); break;
case 'b': goBack(); break;
}
}
delay(200);
}
// ---- Menu Rendering ----
void showMenu(const char* title, const char* items[], int count, int selected) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextColor(BLACK, WHITE);
display.println(title);
display.setTextColor(WHITE);
for (int i = 0; i < count; i++) {
display.setCursor(20, 10 + i * 10);
display.println(items[i]);
}
display.setCursor(10, 10 + selected * 10);
display.write(0x3E); // > arrow
display.display();
}
// ---- Menu Handling ----
void handleMenu(int window) {
int root = window;
while (root >= 10) root /= 10;
int selection = getCurrentSelection(window);
switch (root) {
case 1:
showMenu("Home", mainMenu, sizeof(mainMenu) / sizeof(char*), selection);
break;
case 3:
showMenu("Settings", settingsMenu, sizeof(settingsMenu) / sizeof(char*), selection);
break;
case 10:
display.clearDisplay();
display.setCursor(0, 0);
display.println("Polar Angle Tool");
display.display();
break;
// Add more cases for tools/screens as needed
}
}
// ---- Navigation Helpers ----
int getCurrentSelection(int value) {
return value % 10;
}
void navigateUp() {
int sel = getCurrentSelection(windowVariable);
if (sel > 0) windowVariable--;
}
void navigateDown(int maxItems) {
int sel = getCurrentSelection(windowVariable);
if (sel < maxItems - 1) windowVariable++;
}
void selectItem() {
windowVariable *= 10;
}
void goBack() {
windowVariable /= 10;
}