#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Initialize the OLED display using the Adafruit_SSD1306 library.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
// Declare variables for menu navigation.
const int NUM_MENUS = 3;
const int MENU_ITEMS[NUM_MENUS] = {6, 5, 7};
const char *MENU_NAMES[NUM_MENUS] = {"Menu 1", "Menu 2", "Menu 3"};
const char *SUBMENU_NAMES[NUM_MENUS][7] = {
{"Submenu 1-1", "Submenu 1-2", "Submenu 1-3", "Submenu 1-4", "Submenu 1-5", "Submenu 1-6"},
{"Submenu 2-1", "Submenu 2-2", "Submenu 2-3", "Submenu 2-4", "Submenu 2-5"},
{"Submenu 3-1", "Submenu 3-2", "Submenu 3-3", "Submenu 3-4", "Submenu 3-5", "Submenu 3-6", "Submenu 3-7"}};
int currentMenu = 0;
int subMenu = 0;
int parentMenu = 0;
int scrollOffset = 0; // Keep track of the current scroll offset.
int buttonPin = 2; // Connect the button to digital pin D2.
bool lastButtonState = HIGH;
void setup() {
Serial.begin(9600);
Wire.begin();
// Initialize the OLED display.
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
pinMode(buttonPin, INPUT_PULLUP);
// Clear the screen before displaying menu items.
display.clearDisplay();
display.display();
}
void loop() {
bool buttonState = digitalRead(buttonPin);
if (buttonState != lastButtonState) {
lastButtonState = buttonState;
if (buttonState == LOW) {
// Button is pressed, perform the menu action.
performMenuAction();
}
}
// Update the OLED display with the current menu items and scrollbar.
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
// Display parent menu name at the top of the screen.
display.print(MENU_NAMES[parentMenu]);
display.print(" > ");
// Calculate the maximum number of visible submenu items.
int maxVisibleItems = min(MENU_ITEMS[currentMenu], 4);
// Display the submenu items with the current scroll offset.
for (int i = scrollOffset; i < scrollOffset + maxVisibleItems; i++) {
if (i == subMenu) {
display.setTextColor(BLACK, WHITE); // Highlight selected item.
} else {
display.setTextColor(WHITE);
}
display.print(SUBMENU_NAMES[currentMenu][i]);
display.println();
}
// Calculate and display the scrollbar.
int scrollbarHeight = SCREEN_HEIGHT - (maxVisibleItems * 8);
if (scrollbarHeight > 0) {
int scrollbarPosition = map(scrollOffset, 0, MENU_ITEMS[currentMenu] - maxVisibleItems, 0, scrollbarHeight);
display.drawLine(SCREEN_WIDTH - 2, 0, SCREEN_WIDTH - 2, SCREEN_HEIGHT, WHITE);
display.fillRect(SCREEN_WIDTH - 2, scrollbarPosition, 2, maxVisibleItems * 8, WHITE);
}
display.display();
}
void performMenuAction() {
unsigned long buttonPressTime = millis();
delay(50);
bool buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
// Button is still pressed.
while (digitalRead(buttonPin) == LOW) {
// Wait for the button to be released.
}
unsigned long buttonReleaseTime = millis();
unsigned long buttonDuration = buttonReleaseTime - buttonPressTime;
if (buttonDuration < 200) {
// Short press: Scroll down one item.
if (subMenu < MENU_ITEMS[currentMenu] - 1) {
subMenu++;
if (subMenu >= scrollOffset + 4) {
scrollOffset++;
}
}
} else {
// Long press: Go back to parent menu.
if (parentMenu != currentMenu) {
currentMenu = parentMenu;
subMenu = 0;
scrollOffset = 0;
}
}
// If a submenu was selected, enter it and reset the scroll offset.
if (currentMenu < NUM_MENUS - 1 && subMenu < MENU_ITEMS[currentMenu]) {
parentMenu = currentMenu;
currentMenu++;
subMenu = 0;
scrollOffset = 0;
}
}
}