красота, можно сказать уже готовое утсройство
This commit is contained in:
		
							parent
							
								
									7075f11e2b
								
							
						
					
					
						commit
						8a91973100
					
				@ -23,13 +23,24 @@
 | 
				
			|||||||
#define I2C_MIN_ADDR 0x50
 | 
					#define I2C_MIN_ADDR 0x50
 | 
				
			||||||
#define I2C_MAX_ADDR 0x57
 | 
					#define I2C_MAX_ADDR 0x57
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SDA_PIN 21
 | 
					#define SDA_PIN 8
 | 
				
			||||||
#define SCL_PIN 22
 | 
					#define SCL_PIN 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t eeprom_addr = 0;
 | 
					uint8_t eeprom_addr = 0;
 | 
				
			||||||
 | 
					uint16_t versionAddr = 0x54;  // версия начинается с этого адреса
 | 
				
			||||||
uint16_t startAddr = 0x04;  // адрес записи строк по умолчанию
 | 
					uint16_t startAddr = 0x04;  // адрес записи строк по умолчанию
 | 
				
			||||||
 | 
					char moduleStr[32] = {0};  // буфер для модуля
 | 
				
			||||||
char versionStr[32] = {0};  // буфер для версии
 | 
					char versionStr[32] = {0};  // буфер для версии
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ensureEEPROM() {
 | 
				
			||||||
 | 
					  if (eeprom_addr == 0) {  // 0 - значит еще не найдена
 | 
				
			||||||
 | 
					    return findEEPROM();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool findEEPROM() {
 | 
					bool findEEPROM() {
 | 
				
			||||||
  Serial.println("Scanning for EEPROM...");
 | 
					  Serial.println("Scanning for EEPROM...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,6 +60,10 @@ bool findEEPROM() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void eepromWriteByte(uint8_t addr, uint8_t data) {
 | 
					void eepromWriteByte(uint8_t addr, uint8_t data) {
 | 
				
			||||||
 | 
					  if (!ensureEEPROM()) {
 | 
				
			||||||
 | 
					    Serial.println("EEPROM not found! Write aborted.");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  Wire.beginTransmission(eeprom_addr);
 | 
					  Wire.beginTransmission(eeprom_addr);
 | 
				
			||||||
  Wire.write(addr);
 | 
					  Wire.write(addr);
 | 
				
			||||||
  Wire.write(data);
 | 
					  Wire.write(data);
 | 
				
			||||||
@ -57,6 +72,11 @@ void eepromWriteByte(uint8_t addr, uint8_t data) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t eepromReadByte(uint8_t addr) {
 | 
					uint8_t eepromReadByte(uint8_t addr) {
 | 
				
			||||||
 | 
					  if (!ensureEEPROM()) {
 | 
				
			||||||
 | 
					    Serial.println("EEPROM not found! Write aborted.");
 | 
				
			||||||
 | 
					    return 0xFF;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Wire.beginTransmission(eeprom_addr);
 | 
					  Wire.beginTransmission(eeprom_addr);
 | 
				
			||||||
  Wire.write(addr);
 | 
					  Wire.write(addr);
 | 
				
			||||||
  Wire.endTransmission();
 | 
					  Wire.endTransmission();
 | 
				
			||||||
@ -70,10 +90,27 @@ uint8_t eepromReadByte(uint8_t addr) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void writeStringToEEPROM(const char* str, uint16_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);
 | 
					  size_t len = strlen(str);
 | 
				
			||||||
  if (addr + len + 1 > EEPROM_SIZE)
 | 
					  if (addr + len + 1 > EEPROM_SIZE)
 | 
				
			||||||
    len = EEPROM_SIZE - addr - 1;
 | 
					    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("Writing to EEPROM @ 0x");
 | 
				
			||||||
  Serial.print(addr, HEX);
 | 
					  Serial.print(addr, HEX);
 | 
				
			||||||
  Serial.print(": ");
 | 
					  Serial.print(": ");
 | 
				
			||||||
@ -85,20 +122,54 @@ void writeStringToEEPROM(const char* str, uint16_t addr) {
 | 
				
			|||||||
  eepromWriteByte(addr + len, 0);  // null-терминатор
 | 
					  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() {
 | 
					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++) {
 | 
					  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) {
 | 
					    if (b == 0 || b == 0xFF) {
 | 
				
			||||||
      versionStr[i] = 0;
 | 
					      versionStr[i] = 0;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    versionStr[i] = (char)b;
 | 
					    versionStr[i] = (char)b;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  versionStr[sizeof(versionStr)-1] = 0;
 | 
					
 | 
				
			||||||
 | 
					  versionStr[sizeof(versionStr) - 1] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Serial.print("[EEPROM] Version read: ");
 | 
				
			||||||
 | 
					  Serial.println(versionStr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void readAndDumpEEPROM() {
 | 
					void readAndDumpEEPROM() {
 | 
				
			||||||
 | 
					  if (!ensureEEPROM()) {
 | 
				
			||||||
 | 
					    Serial.println("EEPROM not found! Write aborted.");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  Serial.println("\nDumping full EEPROM contents:\n");
 | 
					  Serial.println("\nDumping full EEPROM contents:\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (uint16_t base = 0; base < EEPROM_SIZE; base += 16) {
 | 
					  for (uint16_t base = 0; base < EEPROM_SIZE; base += 16) {
 | 
				
			||||||
@ -134,8 +205,8 @@ void setup() {
 | 
				
			|||||||
  bool eeprom_found = findEEPROM();
 | 
					  bool eeprom_found = findEEPROM();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eeprom_found) {
 | 
					  if (eeprom_found) {
 | 
				
			||||||
 | 
					    readModuleFromEEPROM();
 | 
				
			||||||
    readVersionFromEEPROM();
 | 
					    readVersionFromEEPROM();
 | 
				
			||||||
    readAndDumpEEPROM();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Serial.println("Ready.");
 | 
					  Serial.println("Ready.");
 | 
				
			||||||
@ -171,7 +242,7 @@ void loop() {
 | 
				
			|||||||
          String ver = inputBuffer.substring(4);
 | 
					          String ver = inputBuffer.substring(4);
 | 
				
			||||||
          ver.trim();
 | 
					          ver.trim();
 | 
				
			||||||
          ver.toCharArray(versionStr, sizeof(versionStr));
 | 
					          ver.toCharArray(versionStr, sizeof(versionStr));
 | 
				
			||||||
          writeStringToEEPROM(versionStr, 0);
 | 
					          writeStringToEEPROM(versionStr, versionAddr);
 | 
				
			||||||
          Serial.print("Version written: ");
 | 
					          Serial.print("Version written: ");
 | 
				
			||||||
          Serial.println(versionStr);
 | 
					          Serial.println(versionStr);
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
							
								
								
									
										442
									
								
								TecktroHack/ui_interface.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								TecktroHack/ui_interface.ino
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,442 @@
 | 
				
			|||||||
 | 
					#include <Wire.h>
 | 
				
			||||||
 | 
					#include <Adafruit_GFX.h>
 | 
				
			||||||
 | 
					#include <Adafruit_SSD1306.h>
 | 
				
			||||||
 | 
					#include <U8g2lib.h>
 | 
				
			||||||
 | 
					#include <Fonts/FreeSans9pt7b.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										180
									
								
								ui_interface.ino
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								ui_interface.ino
									
									
									
									
									
								
							@ -1,180 +0,0 @@
 | 
				
			|||||||
#include <Wire.h>
 | 
					 | 
				
			||||||
#include <Adafruit_GFX.h>
 | 
					 | 
				
			||||||
#include <Adafruit_SSD1306.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user