diff --git a/TecktroHack.ino b/TecktroHack/TecktroHack.ino similarity index 69% rename from TecktroHack.ino rename to TecktroHack/TecktroHack.ino index 78df484..10c7158 100644 --- a/TecktroHack.ino +++ b/TecktroHack/TecktroHack.ino @@ -23,13 +23,24 @@ #define I2C_MIN_ADDR 0x50 #define I2C_MAX_ADDR 0x57 -#define SDA_PIN 21 -#define SCL_PIN 22 +#define SDA_PIN 8 +#define SCL_PIN 9 uint8_t eeprom_addr = 0; +uint16_t versionAddr = 0x54; // версия начинается с этого адреса uint16_t startAddr = 0x04; // адрес записи строк по умолчанию +char moduleStr[32] = {0}; // буфер для модуля char versionStr[32] = {0}; // буфер для версии + +bool ensureEEPROM() { + if (eeprom_addr == 0) { // 0 - значит еще не найдена + return findEEPROM(); + } + return true; +} + + bool findEEPROM() { Serial.println("Scanning for EEPROM..."); @@ -49,6 +60,10 @@ bool findEEPROM() { void eepromWriteByte(uint8_t addr, uint8_t data) { + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return; + } Wire.beginTransmission(eeprom_addr); Wire.write(addr); Wire.write(data); @@ -57,6 +72,11 @@ void eepromWriteByte(uint8_t addr, uint8_t data) { } uint8_t eepromReadByte(uint8_t addr) { + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return 0xFF; + } + Wire.beginTransmission(eeprom_addr); Wire.write(addr); Wire.endTransmission(); @@ -70,10 +90,27 @@ uint8_t eepromReadByte(uint8_t addr) { } void writeStringToEEPROM(const char* str, uint16_t addr) { + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return; + } + size_t len = strlen(str); if (addr + len + 1 > EEPROM_SIZE) len = EEPROM_SIZE - addr - 1; + if (addr < versionAddr) { + // Очистить всё пространство от addr до versionAddr (не включая versionAddr) + for (uint16_t i = addr; i < versionAddr; i++) { + eepromWriteByte(i, 0xFF); + } + } else { + // Очистить только область для новой строки (len + 1 — включая нулевой терминатор) + for (size_t i = 0; i < len + 1; i++) { + eepromWriteByte(addr + i, 0xFF); + } + } + Serial.print("Writing to EEPROM @ 0x"); Serial.print(addr, HEX); Serial.print(": "); @@ -85,20 +122,54 @@ void writeStringToEEPROM(const char* str, uint16_t addr) { eepromWriteByte(addr + len, 0); // null-терминатор } +void readModuleFromEEPROM() { + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return; + } + memset(moduleStr, 0, sizeof(moduleStr)); + for (size_t i = 0; i < sizeof(moduleStr) - 1; i++) { + uint8_t b = eepromReadByte(startAddr + i); + if (b == 0 || b == 0xFF) { + moduleStr[i] = 0; + break; + } + moduleStr[i] = (char)b; + } + moduleStr[sizeof(moduleStr)-1] = 0; + + Serial.print("[EEPROM] Module read: "); + Serial.println(moduleStr); +} + void readVersionFromEEPROM() { - // Читаем строку версии из EEPROM начиная с 0 + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return; + } + memset(versionStr, 0, sizeof(versionStr)); + for (size_t i = 0; i < sizeof(versionStr) - 1; i++) { - uint8_t b = eepromReadByte(i); + uint8_t b = eepromReadByte(versionAddr + i); if (b == 0 || b == 0xFF) { versionStr[i] = 0; break; } versionStr[i] = (char)b; } - versionStr[sizeof(versionStr)-1] = 0; + + versionStr[sizeof(versionStr) - 1] = 0; + + Serial.print("[EEPROM] Version read: "); + Serial.println(versionStr); } + void readAndDumpEEPROM() { + if (!ensureEEPROM()) { + Serial.println("EEPROM not found! Write aborted."); + return; + } Serial.println("\nDumping full EEPROM contents:\n"); for (uint16_t base = 0; base < EEPROM_SIZE; base += 16) { @@ -134,8 +205,8 @@ void setup() { bool eeprom_found = findEEPROM(); if (eeprom_found) { + readModuleFromEEPROM(); readVersionFromEEPROM(); - readAndDumpEEPROM(); } Serial.println("Ready."); @@ -171,7 +242,7 @@ void loop() { String ver = inputBuffer.substring(4); ver.trim(); ver.toCharArray(versionStr, sizeof(versionStr)); - writeStringToEEPROM(versionStr, 0); + writeStringToEEPROM(versionStr, versionAddr); Serial.print("Version written: "); Serial.println(versionStr); } diff --git a/TecktroHack/ui_interface.ino b/TecktroHack/ui_interface.ino new file mode 100644 index 0000000..609fc56 --- /dev/null +++ b/TecktroHack/ui_interface.ino @@ -0,0 +1,442 @@ +#include +#include +#include +#include +#include + +#define FONT u8g2_font_8x13_tr +#define LITTLE_FONT u8g2_font_5x8_tr +#define LINE_SPACING 16 + +// OLED дисплей 128x64, I2C адрес по умолчанию — 0x3C +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 +#define OLED_RESET -1 +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + +// Инициализация дисплея SSD1306 128x64 по I2C +// Выбери нужный конструктор в зависимости от контроллера +// Этот - для SSD1306, I2C, с аппаратным reset (если нет reset - поставить U8G2_R0 и -1) +U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); + + +// Кнопки +#define BTN_UP_PIN 3 +#define BTN_DOWN_PIN 2 +#define BTN_OK_PIN 1 // # +#define BTN_BACK_PIN 0 // * + +extern uint16_t startAddr; +extern uint16_t versionAddr; +extern void writeStringToEEPROM(const char* str, uint16_t addr); +extern void readModuleFromEEPROM(); +extern void readVersionFromEEPROM(); +extern char versionStr[32]; +extern char moduleStr[32]; + + +enum MenuState { + MENU_MAIN, + MENU_SELECT_MODEL, + MENU_SELECT_OPTION, + MENU_SELECT_VERSION, + MENU_SHOW_EEPROM +}; + + +const char* modelList[] = { "MDO5", "MDO4", "MDO3", "MDO2", "MDO1", "DPO5", "DPO4", "DPO3", "DPO2", "DPO1" }; +const uint8_t modelCount = sizeof(modelList) / sizeof(modelList[0]); + +const char* optionList[] = { + "BND", // Bundle (all-in-one) + "AERO", // Aerospace serial buses + "AFG", // Arbitrary Function Generator + "AUDIO", // Audio serial buses + "AUTO", // Automotive serial buses + "AUTOMAX",// Automotive serial buses + "COMP", // Computer serial buses + "EMBD", // Embedded systems + "ENET", // Ethernet + "FLEX", // FlexRay + "LMT", // Limit testing and mask testing + "MSO", // Mixed Signal Option + "PWR", // Power analysis + "SA", // Spectrum Analyzer + "SA3", // Spectrum Analyzer + "SA6", // Spectrum Analyzer + "SEC", // Security extension + "TRIG", // RF Power Level Trigger + "USB", // USB analysis + "VID" // Video signal triggering +}; + +const char* optionDescriptions[] = { + "Include all available options in one", + "Aerospace buses: MIL-STD-1553, ARINC 429", + "Waveform generator for custom signals", + "Audio buses: I2S, TDM, LJ, RJ", + "Cars buses: CAN FD, CAN, LIN", + "Cars buses: CAN FD, CAN, LIN, FlexRay", + "Computer buses: SPI, I2C, RS-232, PS/2", + "Embedded protocols: I2C, SPI, UART, GPIO", + "Ethernet: 10/100/1000BASE-T", + "Cars bus FlexRay", + "Limit and mask testing: Go/No-Go", + "Mixed Signal Oscill: analog + digital", + "Power analysis: efficiency, ripple, Bode", + "Spectrum analysis: RF, high-frequency", + "Spectr analysis (3 MHz): RF, high-frequency", + "Spectr analysis (6 MHz): RF, high-frequency", + "Security extension: access control", + "RF power level triggering", + "USB decoding: USB 1.x/2.0/3.x", + "Video triggering: HDMI, VGA, analog" +}; + + +const uint8_t optionCount = sizeof(optionList) / sizeof(optionList[0]); + +uint8_t selectedModel = 0; +uint8_t selectedOption = 0; + +MenuState currentMenu = MENU_MAIN; +uint8_t cursorPos = 0; +char editableVersion[16] = "v1.00"; +uint8_t editIndex = 0; +bool editingVersion = false; + + +void setupUI() { + pinMode(BTN_UP_PIN, INPUT_PULLUP); + pinMode(BTN_DOWN_PIN, INPUT_PULLUP); + pinMode(BTN_OK_PIN, INPUT_PULLUP); + pinMode(BTN_BACK_PIN, INPUT_PULLUP); + + if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { + Serial.println(F("SSD1306 not found")); + while (true); + } + //display.clearDisplay(); + //display.setFont(&FONT); + //display.setTextSize(1); + //display.setTextColor(SSD1306_WHITE); + //display.display(); + + u8g2.begin(); + + // Выбираем шрифт - очень маленький, около 6pt (пример: u8g2_font_6x10_tr) + u8g2.setFont(FONT); + + + showMainMenu(); +} + +void loopUI() { + static uint32_t lastPress = 0; + if (millis() - lastPress < 200) return; + + if (currentMenu == MENU_SELECT_VERSION && editingVersion) { + if (!digitalRead(BTN_UP_PIN)) { + if (editableVersion[editIndex] >= '0' && editableVersion[editIndex] <= '9') { + if (editableVersion[editIndex] == '9') editableVersion[editIndex] = '0'; + else editableVersion[editIndex]++; + } + updateMenuDisplay(); + lastPress = millis(); + return; + } + + if (!digitalRead(BTN_DOWN_PIN)) { + if (editableVersion[editIndex] >= '0' && editableVersion[editIndex] <= '9') { + if (editableVersion[editIndex] == '0') editableVersion[editIndex] = '9'; + else editableVersion[editIndex]--; + } + updateMenuDisplay(); + lastPress = millis(); + return; + } + + if (!digitalRead(BTN_OK_PIN)) { + // Перейти к следующему редактируемому символу, пропуская точки и буквы + do { + editIndex++; + } while (editIndex < strlen(editableVersion) && (editableVersion[editIndex] < '0' || editableVersion[editIndex] > '9')); + + if (editIndex >= strlen(editableVersion)) { + // Закончили редактировать + writeStringToEEPROM(editableVersion, versionAddr); + strncpy(versionStr, editableVersion, sizeof(versionStr)); + editingVersion = false; + currentMenu = MENU_MAIN; + cursorPos = 0; + } + + updateMenuDisplay(); + lastPress = millis(); + return; + } + + if (!digitalRead(BTN_BACK_PIN)) { + // Назад по цифрам + do { + if (editIndex == 0) { + editingVersion = false; + currentMenu = MENU_MAIN; + cursorPos = 0; + break; + } else { + editIndex--; + } + } while (editableVersion[editIndex] < '0' || editableVersion[editIndex] > '9'); + + updateMenuDisplay(); + lastPress = millis(); + return; + } + + return; + } + + + if (!digitalRead(BTN_UP_PIN)) { + if (cursorPos > 0) cursorPos--; + updateMenuDisplay(); + lastPress = millis(); + } else if (!digitalRead(BTN_DOWN_PIN)) { + cursorPos++; + updateMenuDisplay(); + lastPress = millis(); + } else if (!digitalRead(BTN_OK_PIN)) { + handleOk(); + lastPress = millis(); + } else if (!digitalRead(BTN_BACK_PIN)) { + handleBack(); + lastPress = millis(); + } +} + +void showMainMenu() { + currentMenu = MENU_MAIN; + cursorPos = 0; + updateMenuDisplay(); +} + +void drawStringWrapped(int x, int y, int maxWidth, const char* text, int lineHeight) { + int lineStart = 0; + int textLen = strlen(text); + + while (lineStart < textLen) { + int lineEnd = lineStart; + int lastSpace = -1; + int width = 0; + + while (lineEnd < textLen) { + char c = text[lineEnd]; + // Вычисляем ширину подстроки с lineStart до lineEnd + 1 + char buffer[64]; // должен быть достаточного размера + int length = lineEnd - lineStart + 1; + if (length >= sizeof(buffer)) length = sizeof(buffer) - 1; + memcpy(buffer, text + lineStart, length); + buffer[length] = '\0'; + + int w = u8g2.getStrWidth(buffer); + + if (w > maxWidth) { + break; + } + + if (c == ' ' || c == '-' || c == '\t') { + lastSpace = lineEnd; + } + + lineEnd++; + } + + // Если мы вышли за предел maxWidth + if (lineEnd == lineStart) { + // Если один символ не помещается — выводим его все равно (чтобы не зацикливаться) + lineEnd = lineStart + 1; + } else if (lineEnd < textLen && lastSpace != -1) { + // Откатываемся до последнего пробела, чтобы не разрывать слово + lineEnd = lastSpace; + } + + // Подстрока для вывода длиной (lineEnd - lineStart) + char buf[128]; + int len = lineEnd - lineStart; + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + strncpy(buf, text + lineStart, len); + buf[len] = 0; + + u8g2.drawStr(x, y, buf); + + y += lineHeight; + lineStart = (lineEnd == lastSpace) ? lineEnd + 1 : lineEnd; + } +} + + +void updateMenuDisplay() { + u8g2.clearBuffer(); + //display.clearDisplay(); + //display.setCursor(0, LINE_SPACING); + + if (currentMenu == MENU_MAIN) { + // Выводим три строки меню с курсором > + if(cursorPos > 2) + { + cursorPos = 2; + } + u8g2.drawStr(0, LINE_SPACING * 1, cursorPos == 0 ? ">Set Options" : " Set Options"); + u8g2.drawStr(0, LINE_SPACING * 2, cursorPos == 1 ? ">Set Version" : " Set Version"); + u8g2.drawStr(0, LINE_SPACING * 3, cursorPos == 2 ? ">Read Module" : " Read Module"); + /*display.print(cursorPos == 0 ? ">Set Options" : " Set Options"); + display.setCursor(0, LINE_SPACING *2); + display.print(cursorPos == 1 ? ">Set Version" : " Set Version"); + display.setCursor(0, LINE_SPACING *3); + display.print(cursorPos == 2 ? ">Read" : " Read");*/ + + } else if (currentMenu == MENU_SELECT_MODEL) { + u8g2.drawStr(0, LINE_SPACING * 1, "Model:"); + + // Формируем строку ">ModelName" + char line[20]; + snprintf(line, sizeof(line), ">%s", modelList[cursorPos % modelCount]); + u8g2.drawStr(0, LINE_SPACING * 2, line); + /*display.print("Model:"); + display.setCursor(0, LINE_SPACING *2); + display.print(">"); + display.print(modelList[cursorPos % modelCount]);*/ + + } else if (currentMenu == MENU_SELECT_OPTION) { + u8g2.setFont(FONT); // основной шрифт + u8g2.drawStr(0, LINE_SPACING * 1, "Option:"); + + char line[20]; + uint8_t optIndex = cursorPos % optionCount; + snprintf(line, sizeof(line), ">%s", optionList[optIndex]); + u8g2.drawStr(0, LINE_SPACING * 2, line); + + // Мелкий шрифт — описание + u8g2.setFont(LITTLE_FONT); + drawStringWrapped(0, LINE_SPACING * 3 + 4, SCREEN_WIDTH, optionDescriptions[optIndex], 10); + u8g2.setFont(FONT); + /*display.print("Option:"); + display.setCursor(0, LINE_SPACING *2); + display.print(">"); + display.print(optionList[cursorPos % optionCount]);*/ + + } else if (currentMenu == MENU_SELECT_VERSION) { + u8g2.drawStr(0, LINE_SPACING * 1, "UART set ver:"); + + // Для версии выводим символы с квадратными скобками вокруг редактируемого + int x = 0; + for (uint8_t i = 0; i < strlen(editableVersion); i++) { + char buf[4]; + if (i == editIndex && editingVersion) { + snprintf(buf, sizeof(buf), "[%c]", editableVersion[i]); + } else { + snprintf(buf, sizeof(buf), " %c ", editableVersion[i]); + } + u8g2.drawStr(x, LINE_SPACING * 2, buf); + x += u8g2.getStrWidth(buf); // смещение курсора вправо на ширину предыдущей части + } + + + /*display.print("UART set ver:"); + display.setCursor(0, LINE_SPACING *2); + + for (uint8_t i = 0; i < strlen(editableVersion); i++) { + if (i == editIndex && editingVersion) { + display.print("["); + display.print(editableVersion[i]); + display.print("]"); + } else { + display.print(" "); + display.print(editableVersion[i]); + display.print(" "); + } + }*/ + } else if (currentMenu == MENU_SHOW_EEPROM) { + char buf[40]; + + snprintf(buf, sizeof(buf), "Model Option:"); + u8g2.drawStr(0, LINE_SPACING * 1, buf); + + snprintf(buf, sizeof(buf), " %s", moduleStr); + u8g2.drawStr(0, LINE_SPACING * 2, buf); + + snprintf(buf, sizeof(buf), "Version:"); + u8g2.drawStr(0, LINE_SPACING * 3, buf); + + snprintf(buf, sizeof(buf), " %s", versionStr); + u8g2.drawStr(0, LINE_SPACING * 4, buf); + + /*display.print("Mod:"); + display.println(moduleStr); + display.setCursor(0, LINE_SPACING *3); + display.print("Ver:"); + display.println(versionStr);*/ + } + + //display.display(); + u8g2.sendBuffer(); +} + + +void handleOk() { + if (currentMenu == MENU_MAIN) { + if (cursorPos == 0) { + currentMenu = MENU_SELECT_MODEL; + cursorPos = 0; + } else if (cursorPos == 1) { + currentMenu = MENU_SELECT_VERSION; + } else if (cursorPos == 2) { + readVersionFromEEPROM(); + readModuleFromEEPROM(); + currentMenu = MENU_SHOW_EEPROM; + } + + } else if (currentMenu == MENU_SELECT_MODEL) { + selectedModel = cursorPos % modelCount; + cursorPos = 0; + currentMenu = MENU_SELECT_OPTION; + + } else if (currentMenu == MENU_SELECT_OPTION) { + selectedOption = cursorPos % optionCount; + + char fullModule[32]; + snprintf(fullModule, sizeof(fullModule), "%s%s", modelList[selectedModel], optionList[selectedOption]); + writeStringToEEPROM(fullModule, startAddr); + readAndDumpEEPROM(); + strncpy(moduleStr, fullModule, sizeof(moduleStr) - 1); + moduleStr[sizeof(moduleStr) - 1] = 0; + + Serial.print("[UI] Options written: "); + Serial.println(fullModule); + + currentMenu = MENU_MAIN; + cursorPos = 0; + + } else if (currentMenu == MENU_SELECT_VERSION) { + editingVersion = true; + editIndex = 1; + } + + + updateMenuDisplay(); +} + + + + +void handleBack() { + if (currentMenu == MENU_SELECT_OPTION) { + currentMenu = MENU_SELECT_MODEL; + } else { + currentMenu = MENU_MAIN; + } + cursorPos = 0; + updateMenuDisplay(); +} + diff --git a/ui_interface.ino b/ui_interface.ino deleted file mode 100644 index 56c0b68..0000000 --- a/ui_interface.ino +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include - -// OLED дисплей 128x64, I2C адрес по умолчанию — 0x3C -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 -#define OLED_RESET -1 -Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); - -// Кнопки -#define BTN_UP_PIN 32 -#define BTN_DOWN_PIN 33 -#define BTN_OK_PIN 25 // # -#define BTN_BACK_PIN 26 // * - -extern uint16_t startAddr; -extern void writeStringToEEPROM(const char* str, uint16_t addr); -extern void readVersionFromEEPROM(); -extern char versionStr[32]; -char moduleStr[32] = {0}; // буфер для считанного модуля -extern uint8_t eepromReadByte(uint8_t addr); -extern uint16_t startAddr; - -enum MenuState { - MENU_MAIN, - MENU_SELECT_MODULE, - MENU_SELECT_VERSION, - MENU_SHOW_EEPROM -}; - - -const char* moduleOptions[] = { - "DPO4COMP", "DPO2EMBD", "DPO4EMBD", "DPO4AUTO", "DPO4AUTOMAX", "DPO4PWR", - "DPO4USB", "DPO4ENET", "DPO4LMT", "DPO4AUDIO", "MSO5204B 5RL", "MDO4MSO", "MDO4EMBD", - "MDO4AERO", "MDO4AUTO", "MDO4COMP", "MDO4FLEX", "MDO4LMT", "MDO4SA", "MDO4SA3", - "MDO4SA6", "MDO4AFG", "MDO4PWR", "MDO4BND", "MDO4SEC", "MDO4AUDIO" -}; -const uint8_t moduleCount = sizeof(moduleOptions) / sizeof(moduleOptions[0]); - -MenuState currentMenu = MENU_MAIN; -uint8_t cursorPos = 0; - -extern char versionStr[32]; // Используется из основного кода - -void readModuleFromEEPROM() { - memset(moduleStr, 0, sizeof(moduleStr)); - for (size_t i = 0; i < sizeof(moduleStr) - 1; i++) { - uint8_t b = eepromReadByte(startAddr + i); - if (b == 0 || b == 0xFF) { - moduleStr[i] = 0; - break; - } - moduleStr[i] = (char)b; - } - moduleStr[sizeof(moduleStr)-1] = 0; -} - - -void setupUI() { - pinMode(BTN_UP_PIN, INPUT_PULLUP); - pinMode(BTN_DOWN_PIN, INPUT_PULLUP); - pinMode(BTN_OK_PIN, INPUT_PULLUP); - pinMode(BTN_BACK_PIN, INPUT_PULLUP); - - if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { - Serial.println(F("SSD1306 not found")); - while (true); - } - display.clearDisplay(); - display.setTextSize(1); - display.setTextColor(SSD1306_WHITE); - display.display(); - - showMainMenu(); -} - -void loopUI() { - static uint32_t lastPress = 0; - if (millis() - lastPress < 200) return; - - if (!digitalRead(BTN_UP_PIN)) { - if (cursorPos > 0) cursorPos--; - updateMenuDisplay(); - lastPress = millis(); - } else if (!digitalRead(BTN_DOWN_PIN)) { - cursorPos++; - updateMenuDisplay(); - lastPress = millis(); - } else if (!digitalRead(BTN_OK_PIN)) { - handleOk(); - lastPress = millis(); - } else if (!digitalRead(BTN_BACK_PIN)) { - handleBack(); - lastPress = millis(); - } -} - -void showMainMenu() { - currentMenu = MENU_MAIN; - cursorPos = 0; - updateMenuDisplay(); -} - -void updateMenuDisplay() { - display.clearDisplay(); - display.setCursor(0, 0); - - if (currentMenu == MENU_MAIN) { - display.setCursor(0, 0); - display.print(cursorPos == 0 ? "> Module" : " Module"); - - display.setCursor(0, 10); - display.print(cursorPos == 1 ? "> Version" : " Version"); - - display.setCursor(0, 20); - display.print(cursorPos == 2 ? "> Read" : " Read"); - } else if (currentMenu == MENU_SELECT_MODULE) { - display.print("Module:"); - display.setCursor(0, 10); - display.print(">"); - display.print(moduleOptions[cursorPos % moduleCount]); - } else if (currentMenu == MENU_SELECT_VERSION) { - display.print("Set version via UART:"); - display.setCursor(0, 10); - display.print("VER=1.23"); - } else if (currentMenu == MENU_SHOW_EEPROM) { - display.setCursor(0, 0); - display.print("Module: "); - display.println(moduleStr); - - display.setCursor(0, 20); - display.print("Version: "); - display.println(versionStr); -} - display.display(); -} - -void handleOk() { - if (currentMenu == MENU_MAIN) { - if (cursorPos == 0) { - currentMenu = MENU_SELECT_MODULE; - cursorPos = 0; - } else if (cursorPos == 1) { - currentMenu = MENU_SELECT_VERSION; - } else if (cursorPos == 2) { - // Считать из EEPROM - readVersionFromEEPROM(); // версия из 0x00 - readModuleFromEEPROM(); // модуль из startAddr - currentMenu = MENU_SHOW_EEPROM; - } - } - else if (currentMenu == MENU_SELECT_MODULE) { - const char* sel = moduleOptions[cursorPos % moduleCount]; - writeStringToEEPROM(sel, startAddr); - readAndDumpEEPROM(); - strncpy(versionStr, sel, sizeof(versionStr) - 1); - versionStr[sizeof(versionStr) - 1] = 0; - Serial.print("[UI] Module written to EEPROM: "); - Serial.println(sel); - showMainMenu(); - } - else if (currentMenu == MENU_SELECT_VERSION) { - writeStringToEEPROM("v1.23", 0); - readAndDumpEEPROM(); - strncpy(versionStr, "v1.23", sizeof(versionStr) - 1); - versionStr[sizeof(versionStr) - 1] = 0; - Serial.print("[UI] Version written to EEPROM: "); - Serial.println(versionStr); - showMainMenu(); - } - - updateMenuDisplay(); -} - - - -void handleBack() { - showMainMenu(); -}