#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Define button pins
#define BUTTON_ENTER 3 // Enter button
#define BUTTON_BACK 5 // Back button
#define BUTTON_UP 6 // Up button
#define BUTTON_DOWN 7 // Down button
// Menu states
enum State
{
HOME,
PLAYER_MENU,
PLAYER_OPTIONS,
PLAY_INPUT,
RECORDER_MENU,
SAVE_RECORDING,
CONFIRM_SAVE,
CONFIRM_DELETE,
};
// Menu items
const char *homeMenu[] = {"Player", "Recorder"};
const char *confirm[] = {"Yes/Confirm", "No/Cancel"};
const char *recordings[] = {"Recording 1", "Recording 2", "Recording 3", "Recording 4", "Recording 5"};
const char *playerOptions[] = {"Play Loop", "Play Input", "Stop"};
const char *selectFastInput[] = {"Digital 01", "Digital 10", "Digital 11"};
const char *recorderMenu[] = {"Start/Stop", "Save Recording", "Restore Default"};
// Variables
State currentState = HOME; // Initial state
State previousState = HOME; // Previous state
int menuIndex = 0; // Track selected item
int topVisibleIndex = 0; // Track the top visible item for scrolling
int currentRecording;
int recordingInput01;
int recordingInput10;
int recordingInput11;
boolean readInput = false; // When a digital input is assigned it will also check if there is a signal to play the wanted recording.
unsigned long lastButtonPressTime = 0;
const unsigned long debounceDelay = 200;
// Methods
void handleMenu();
void updateDisplay();
void digitalInput();
void printTestInfo();
int getItemCount();
void updateCurrentRecording();
void drawMenuItems(const char *menuItems[], int itemCount);
void setup()
{
Serial.begin(9600);
delay(100); // time to power on
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
pinMode(BUTTON_ENTER, INPUT_PULLUP);
pinMode(BUTTON_BACK, INPUT_PULLUP);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
display.clearDisplay();
display.display();
}
void loop()
{
handleMenu();
updateDisplay();
digitalInput();
}
void handleMenu()
{
unsigned long currentTime = millis();
// Menu item
if (!digitalRead(BUTTON_UP) && (currentTime - lastButtonPressTime > debounceDelay))
{
lastButtonPressTime = currentTime;
while(!digitalRead(BUTTON_UP));
if (menuIndex > 0)
menuIndex--;
if (menuIndex < topVisibleIndex)
topVisibleIndex = menuIndex;
}
if (!digitalRead(BUTTON_DOWN) && (currentTime - lastButtonPressTime > debounceDelay))
{
lastButtonPressTime = currentTime;
while(!digitalRead(BUTTON_DOWN));
int itemCount = getItemCount();
if (menuIndex < itemCount - 1)
menuIndex++;
if (menuIndex >= topVisibleIndex + 5)
topVisibleIndex = menuIndex - 3;
}
// Menu state
if (!digitalRead(BUTTON_ENTER) && (currentTime - lastButtonPressTime > debounceDelay))
{
lastButtonPressTime = currentTime;
while(!digitalRead(BUTTON_ENTER));
previousState = currentState; // We save the previous state before changing the variable of the current one.
switch (previousState)
{
case HOME:
if (menuIndex == 0)
{
currentState = PLAYER_MENU;
}
else if (menuIndex == 1)
{
currentState = RECORDER_MENU;
}
menuIndex = 0;
break;
// Player ----------------------------------------------------------------------------------------
case PLAYER_MENU:
currentState = PLAYER_OPTIONS;
updateCurrentRecording();
menuIndex = 0;
break;
case PLAYER_OPTIONS:
if (menuIndex == 0)
{
// playLoop();
Serial.print("Play Loop Recording ");
Serial.println(currentRecording + 1);
currentState = PLAYER_OPTIONS;
}
else if (menuIndex == 1)
{
currentState = PLAY_INPUT;
}
else if (menuIndex == 2)
{
// stopPlay();
Serial.print("Stop play Recording ");
Serial.println(currentRecording + 1);
currentState = PLAYER_OPTIONS;
}
menuIndex = 0;
break;
case PLAY_INPUT:
currentState = PLAY_INPUT;
if (menuIndex == 0)
{
readInput = true;
recordingInput01 = currentRecording;
Serial.print("Digital input 01 Recording nr ");
Serial.println(currentRecording + 1);
}
else if (menuIndex == 1)
{
readInput = true;
recordingInput10 = currentRecording;
Serial.print("Digital input 10 Recording nr ");
Serial.println(currentRecording + 1);
}
else if (menuIndex == 2)
{
readInput = true;
recordingInput11 = currentRecording;
Serial.print("Digital input 11 Recording nr ");
Serial.println(currentRecording + 1);
}
menuIndex = 0;
break;
// Recorder -------------------------------------------------------------------------------------------
case RECORDER_MENU:
if (menuIndex == 0)
{
currentState = RECORDER_MENU;
Serial.println("Start/Stop");
// startStop();
}
else if (menuIndex == 1)
{
currentState = SAVE_RECORDING;
}
else if (menuIndex == 2)
{
currentState = CONFIRM_DELETE;
}
menuIndex = 0;
break;
case SAVE_RECORDING:
currentState = CONFIRM_SAVE;
updateCurrentRecording();
menuIndex = 0;
break;
case CONFIRM_SAVE:
if (menuIndex == 0)
{
currentState = RECORDER_MENU;
Serial.print("Confirm Save Recording ");
Serial.println(currentRecording + 1);
// saveRecording();
}
else if (menuIndex == 1)
{
currentState = RECORDER_MENU;
}
menuIndex = 0;
break;
case CONFIRM_DELETE:
if (menuIndex == 0)
{
currentState = RECORDER_MENU;
Serial.println("Confirmed Delete All");
// deleteAll();
}
else if (menuIndex == 1)
{
currentState = RECORDER_MENU;
}
menuIndex = 0;
break;
default:
break;
}
}
if (!digitalRead(BUTTON_BACK) && (currentTime - lastButtonPressTime > debounceDelay))
{
lastButtonPressTime = currentTime;
while(!digitalRead(BUTTON_BACK));
switch (currentState) // To make sure the user is able to return to all the states before the current one.
{
case HOME:
previousState = HOME;
break;
// player
case PLAYER_MENU:
previousState = HOME;
break;
case PLAYER_OPTIONS:
previousState = PLAYER_MENU;
break;
case PLAY_INPUT:
previousState = PLAYER_OPTIONS;
break;
// Recorder
case RECORDER_MENU:
previousState = HOME;
break;
case SAVE_RECORDING:
previousState = RECORDER_MENU;
break;
case CONFIRM_SAVE:
previousState = SAVE_RECORDING;
break;
case CONFIRM_DELETE:
previousState = RECORDER_MENU;
break;
default:
break;
}
currentState = previousState;
menuIndex = 0;
}
}
void digitalInput()
{
if (readInput)
{
/* Lezen van externe digitale inputs */
}
}
void updateDisplay()
{
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
switch (currentState)
{
case HOME:
display.println(F("Home Page"));
drawMenuItems(homeMenu, 3);
break;
case PLAYER_MENU:
display.println(F("Player Menu"));
drawMenuItems(recordings, 5);
break;
case PLAYER_OPTIONS:
display.println(F("Player Options "));
display.print(F("Recording "));
display.println(currentRecording + 1);
drawMenuItems(playerOptions, 3);
break;
case PLAY_INPUT:
display.println(F("Select Digital "));
display.println(F("input"));
drawMenuItems(selectFastInput, 3);
break;
case RECORDER_MENU:
display.println(F("Recorder Menu"));
drawMenuItems(recorderMenu, 3);
break;
case SAVE_RECORDING:
display.println(F("Save to"));
drawMenuItems(recordings, 5);
break;
case CONFIRM_SAVE:
display.print(F("Save recording "));
display.println(currentRecording + 1);
drawMenuItems(confirm, 2);
break;
case CONFIRM_DELETE:
display.println(F("Delete all"));
drawMenuItems(confirm, 2);
break;
}
display.display();
}
void drawMenuItems(const char *menuItems[], int itemCount)
{
int endIndex = min(topVisibleIndex + 5, itemCount);
for (int i = topVisibleIndex; i < endIndex; i++)
{
if (i == menuIndex)
display.print("> ");
else
display.print(" ");
display.println(menuItems[i]);
}
}
// Update the current recording number
void updateCurrentRecording()
{
currentRecording = (menuIndex < 5) ? menuIndex : 0; // Limit to the first five recordings
}
int getItemCount()
{
switch (currentState)
{
case HOME:
return 2;
case PLAYER_MENU:
return 5;
case PLAYER_OPTIONS:
return 3;
case PLAY_INPUT:
return 3;
case RECORDER_MENU:
return 3;
case SAVE_RECORDING:
return 5;
case CONFIRM_SAVE:
return 2;
case CONFIRM_DELETE:
return 2;
default:
return 0;
}
}
/*
void playLoop(){
}
void stopPlay(){
}
void saveRecording(){
}
void deleteAll(){
}
*/