#include <Arduino.h>
#include <Wire.h>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiWire.h>
#define I2C_ADDRESS 0x3C // Change this to your display's I2C address
SSD1306AsciiWire oled; // Create an instance of the SSD1306Ascii class
// 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
const int INPUT_EX_1 = 8; // Pin for external button 1
const int INPUT_EX_2 = 9; // Pin for external button 2
// 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;
unsigned long previousMillis = 0; // Used to store the last time the state was checked
// 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
Wire.begin(); // Start I2C
oled.begin(&Adafruit128x64, I2C_ADDRESS); // Initialize the display
oled.setFont(System5x7); // Set a default font
oled.clear(); // Clear the display
pinMode(BUTTON_ENTER, INPUT_PULLUP);
pinMode(BUTTON_BACK, INPUT_PULLUP);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(INPUT_EX_1, INPUT_PULLUP); // Set button 1 pin as input with internal pull-up
pinMode(INPUT_EX_2, INPUT_PULLUP); // Set button 2 pin as input with internal pull-up
updateDisplay();
}
void loop()
{
handleMenu();
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;
updateDisplay();
}
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;
updateDisplay();
}
// 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 + 1;
Serial.print("Digital input 01 Recording nr ");
Serial.println(currentRecording + 1);
}
else if (menuIndex == 1)
{
readInput = true;
recordingInput10 = currentRecording + 1;
Serial.print("Digital input 10 Recording nr ");
Serial.println(currentRecording + 1);
}
else if (menuIndex == 2)
{
readInput = true;
recordingInput11 = currentRecording + 1;
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;
}
updateDisplay();
}
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;
updateDisplay();
}
}
void digitalInput()
{
if (readInput)
{
/* Lezen van externe digitale inputs */
unsigned long currentMillis = millis();
// Only check button states at set intervals
if (currentMillis - previousMillis >= debounceDelay)
{
previousMillis = currentMillis;
// Check for button press states and print accordingly
if (!digitalRead(INPUT_EX_1) && !digitalRead(INPUT_EX_2))
{
while (!digitalRead(INPUT_EX_1) && !digitalRead(INPUT_EX_2))
;
Serial.println("Input 11");
if (recordingInput11 != 0) // Recording 0 betekent dat er geen recording is toegewezen
{
Serial.print("Recording ");
Serial.println(recordingInput11);
}
}
else if (!digitalRead(INPUT_EX_1))
{
while (!digitalRead(INPUT_EX_1))
;
Serial.println("Input 01");
if (recordingInput01 != 0) // Recording 0 betekent dat er geen recording is toegewezen
{
Serial.print("Recording ");
Serial.println(recordingInput01);
}
}
else if (!digitalRead(INPUT_EX_2))
{
while (!digitalRead(INPUT_EX_2))
;
Serial.println("Input 10");
if (recordingInput10 != 0) // Recording 0 betekent dat er geen recording is toegewezen
{
Serial.print("Recording ");
Serial.println(recordingInput10);
}
}
}
}
}
void updateDisplay()
{
oled.clear(); // Clear the display
oled.setCursor(0, 0); // Set cursor position
switch (currentState)
{
case HOME:
oled.println(F("Home Page"));
drawMenuItems(homeMenu, 3);
break;
case PLAYER_MENU:
oled.println(F("Player Menu"));
drawMenuItems(recordings, 5);
break;
case PLAYER_OPTIONS:
oled.println(F("Player Options "));
oled.print(F("Recording "));
oled.println(currentRecording + 1);
drawMenuItems(playerOptions, 3);
break;
case PLAY_INPUT:
oled.println(F("Select Digital "));
oled.println(F("input"));
drawMenuItems(selectFastInput, 3);
break;
case RECORDER_MENU:
oled.println(F("Recorder Menu"));
drawMenuItems(recorderMenu, 3);
break;
case SAVE_RECORDING:
oled.println(F("Save to"));
drawMenuItems(recordings, 5);
break;
case CONFIRM_SAVE:
oled.print(F("Save recording "));
oled.println(currentRecording + 1);
drawMenuItems(confirm, 2);
break;
case CONFIRM_DELETE:
oled.println(F("Delete all"));
drawMenuItems(confirm, 2);
break;
}
}
void drawMenuItems(const char *menuItems[], int itemCount)
{
int endIndex = min(topVisibleIndex + 5, itemCount);
for (int i = topVisibleIndex; i < endIndex; i++)
{
if (i == menuIndex)
oled.print("> ");
else
oled.print(" ");
oled.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()
{
readInput = false;
recordingInput01 = 0;
recordingInput10 = 0;
recordingInput11 = 0;
}