#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <GyverButton.h>
#include "interface.h"
// Пины
#define OLED_SCL 22
#define OLED_SDA 21
#define BTN_UP 33 // K1 (Up)
#define BTN_DOWN 25 // K2 (Down)
#define BTN_OK 27 // K3 (OK)
#define BTN_BACK 14 // K4 (Back)
// OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Кнопки
GButton btn_up(BTN_UP, HIGH_PULL, NORM_OPEN);
GButton btn_down(BTN_DOWN, HIGH_PULL, NORM_OPEN);
GButton btn_ok(BTN_OK, HIGH_PULL, NORM_OPEN);
GButton btn_back(BTN_BACK, HIGH_PULL, NORM_OPEN);
// Состояния меню
enum emMenuState {
menuLogo,
menuMain,
menuSettings,
menuAbout
} menuState = menuLogo;
byte menuIndex = 0;
const int menuItemsCount = 3; // Settings, About, Exit
// Таймеры
unsigned long stTimer = 0;
// Прототипы функций
void OLED_printLogo(Adafruit_SSD1306 &display);
void OLED_printMenu(Adafruit_SSD1306 &display, byte menuIndex);
void OLED_printSettings();
void OLED_printAbout();
void OLED_printError(String st, bool err = true);
void setup() {
Serial.begin(115200);
delay(100);
Serial.println(F("=== ESP-Simple Project ==="));
Serial.println(F("Initializing..."));
// Настройка кнопок
btn_up.setDebounce(50);
btn_up.setTimeout(500);
btn_up.setClickTimeout(300);
btn_up.setStepTimeout(200);
btn_down.setDebounce(50);
btn_down.setTimeout(500);
btn_down.setClickTimeout(300);
btn_down.setStepTimeout(200);
btn_ok.setDebounce(50);
btn_ok.setTimeout(500);
btn_ok.setClickTimeout(300);
btn_ok.setStepTimeout(200);
btn_back.setDebounce(50);
btn_back.setTimeout(500);
btn_back.setClickTimeout(300);
btn_back.setStepTimeout(200);
btn_up.setTickMode(MANUAL);
btn_down.setTickMode(MANUAL);
btn_ok.setTickMode(MANUAL);
btn_back.setTickMode(MANUAL);
// Инициализация OLED
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
Serial.println(F("OLED initialized"));
OLED_printLogo(display);
// Инициализация EEPROM
EEPROM.begin(512);
Serial.println(F("EEPROM initialized"));
// Ждём кнопку для выхода с лого
while (!(btn_up.isClick() || btn_down.isClick() || btn_ok.isClick() || btn_back.isClick())) {
btn_up.tick();
btn_down.tick();
btn_ok.tick();
btn_back.tick();
delay(10);
}
menuState = menuMain;
menuIndex = 0;
OLED_printMenu(display, menuIndex);
Serial.println(F("Entering main menu"));
}
void loop() {
btn_up.tick();
btn_down.tick();
btn_ok.tick();
btn_back.tick();
// Обработка меню
if (menuState == menuLogo) {
if (btn_up.isClick() || btn_down.isClick() || btn_ok.isClick() || btn_back.isClick()) {
menuState = menuMain;
OLED_printMenu(display, menuIndex);
}
}
else if (menuState == menuMain) {
// Навигация по меню
if (btn_up.isClick()) {
menuIndex = (menuIndex == 0) ? (menuItemsCount - 1) : menuIndex - 1;
OLED_printMenu(display, menuIndex);
stTimer = millis();
}
if (btn_down.isClick()) {
menuIndex = (menuIndex == menuItemsCount - 1) ? 0 : menuIndex + 1;
OLED_printMenu(display, menuIndex);
stTimer = millis();
}
// Выбор пункта меню
if (btn_ok.isClick()) {
if (menuIndex == 0) {
menuState = menuSettings;
OLED_printSettings();
} else if (menuIndex == 1) {
menuState = menuAbout;
OLED_printAbout();
} else if (menuIndex == 2) {
// Exit - возврат к лого
menuState = menuLogo;
OLED_printLogo(display);
}
stTimer = millis();
}
// Возврат к лого
if (btn_back.isClick()) {
menuState = menuLogo;
OLED_printLogo(display);
stTimer = millis();
}
}
else if (menuState == menuSettings) {
// Настройки
if (btn_back.isClick()) {
menuState = menuMain;
OLED_printMenu(display, menuIndex);
stTimer = millis();
}
}
else if (menuState == menuAbout) {
// О программе
if (btn_back.isClick()) {
menuState = menuMain;
OLED_printMenu(display, menuIndex);
stTimer = millis();
}
}
delay(10);
}
void OLED_printLogo(Adafruit_SSD1306 &display) {
display.clearDisplay();
display.setTextColor(1);
display.setTextSize(2);
display.setTextWrap(false);
display.setCursor(13, 24);
display.print("ESP-Simple");
display.setTextSize(1);
display.setCursor(12, 48);
display.print("v1.0");
display.setCursor(7, 7);
display.print("by kyrexX");
display.drawBitmap(93, 13, image_satellite_dish_bits, 15, 16, 1);
display.display();
}
void OLED_printMenu(Adafruit_SSD1306 &display, byte menuIndex) {
display.clearDisplay();
display.setTextColor(1);
display.setTextWrap(false);
// Отображение текстур для каждого пункта меню
if (menuIndex == 0) {
// Settings - используем текстуру Scanning
display.drawBitmap(5, 12, image_Scanning_bits, 123, 52, 1);
display.setCursor(42, 4);
display.print("Settings");
} else if (menuIndex == 1) {
// About - используем текстуру DolphinSuccess
display.drawBitmap(5, 12, image_DolphinSuccess_bits, 96, 52, 1);
display.setCursor(42, 4);
display.print("About");
} else if (menuIndex == 2) {
// Exit - используем текстуру Scanning_short
display.drawBitmap(5, 12, image_Scanning_short_bits, 96, 52, 1);
display.setCursor(47, 4);
display.print("Exit");
}
// Стрелки навигации
display.setCursor(2, 4);
display.print("<");
display.setCursor(120, 4);
display.print(">");
display.display();
}
void OLED_printSettings() {
display.clearDisplay();
display.setTextColor(1);
display.setTextWrap(false);
display.setCursor(35, 4);
display.print("Settings");
display.setCursor(10, 20);
display.print("Button UP: GPIO ");
display.print(BTN_UP);
display.setCursor(10, 30);
display.print("Button DOWN: GPIO ");
display.print(BTN_DOWN);
display.setCursor(10, 40);
display.print("Button OK: GPIO ");
display.print(BTN_OK);
display.setCursor(10, 50);
display.print("Button BACK: GPIO ");
display.print(BTN_BACK);
display.display();
}
void OLED_printAbout() {
display.clearDisplay();
display.drawBitmap(5, 12, image_DolphinSuccess_bits, 96, 52, 1);
display.setTextColor(1);
display.setTextWrap(false);
display.setCursor(42, 4);
display.print("About");
display.setCursor(10, 20);
display.print("ESP-Simple v1.0");
display.setCursor(10, 30);
display.print("Simple menu system");
display.setCursor(10, 40);
display.print("with textures");
display.setCursor(10, 50);
display.print("Press BACK to return");
display.display();
}
void OLED_printError(String st, bool err) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print(err ? F("Error!") : F("OK"));
display.setCursor(0, 12);
display.print(st);
display.display();
}