Skip to content

Commit 7f42d19

Browse files
TheRealHaoLiuclaude
andcommitted
Add dual-firmware OTA switching and display improvements for M5Stack Unit C6L
- Add OTA partition switching via BOOT button hold during startup, allowing switching between repeater and companion firmware without reflashing. Buzzer feedback indicates switch or error. - Fix SSD1306 64x48 display garbled output by setting correct COM pins configuration (0x12) after Adafruit library init, which lacks a 64x48 case. Disable text wrap to prevent long text from overflowing. - Fix ESP32-C6 BLE build by adding missing esp_mac.h include for esp_efuse_mac_get_default(). - Add display support to repeater build with C6L-specific UITask featuring boot screen, marquee scrolling for long node names, and I2C expander button wake. - Add boot screen to companion UITask showing MeshCore version and mode, with marquee scrolling and unread message count. - Reorganize variant UITask files into companion/ and repeater/ subdirectories for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3505d12 commit 7f42d19

File tree

10 files changed

+360
-165
lines changed

10 files changed

+360
-165
lines changed

src/helpers/esp32/SerialBLEInterface.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "SerialBLEInterface.h"
2+
#include <esp_mac.h>
23

34
// See the following for generating UUIDs:
45
// https://www.uuidgenerator.net/

src/helpers/ui/SSD1306SPIDisplay.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ bool SSD1306SPIDisplay::lazyInit() {
3131
return false;
3232
}
3333
Serial.println("SSD1306: display.begin() OK");
34+
35+
// Fix for 64x48 displays: Adafruit library lacks this case and defaults
36+
// to comPins=0x02 (sequential). Displays taller than 32px need 0x12
37+
// (alternative COM pin config) or the output is garbled.
38+
#if defined(DISPLAY_WIDTH) && defined(DISPLAY_HEIGHT)
39+
#if (DISPLAY_WIDTH == 64) && (DISPLAY_HEIGHT == 48)
40+
display.ssd1306_command(SSD1306_SETCOMPINS);
41+
display.ssd1306_command(0x12);
42+
#endif
43+
#endif
44+
3445
// Clear any garbage in the display buffer
3546
display.clearDisplay();
3647
display.display();
@@ -63,6 +74,7 @@ void SSD1306SPIDisplay::startFrame(Color bkg) {
6374
display.setTextColor(_color);
6475
display.setFont(NULL); // Default 6x8 font
6576
display.setTextSize(1);
77+
display.setTextWrap(false);
6678
display.cp437(true);
6779
}
6880

variants/m5stack_unit_c6l/M5StackUnitC6LBoard.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <Arduino.h>
44
#include <Wire.h>
5+
#include <esp_ota_ops.h>
56
#include <helpers/ESP32Board.h>
67

78
// PI4IO I/O Expander (I2C address 0x43)
@@ -44,6 +45,52 @@ class M5StackUnitC6LBoard : public ESP32Board {
4445
return true;
4546
}
4647

48+
void checkOTASwitch() {
49+
// If BOOT button (P0) is held during startup, switch to the other OTA partition
50+
if (!isButtonPressed()) return;
51+
52+
// Button is pressed — wait a moment and confirm it's still held
53+
delay(500);
54+
if (!isButtonPressed()) return;
55+
56+
const esp_partition_t* running = esp_ota_get_running_partition();
57+
const esp_partition_t* next = esp_ota_get_next_update_partition(running);
58+
if (next == NULL) {
59+
Serial.println("OTA switch: no other partition found");
60+
return;
61+
}
62+
63+
// Verify the other partition has valid firmware
64+
esp_app_desc_t app_desc;
65+
if (esp_ota_get_partition_description(next, &app_desc) != ESP_OK) {
66+
Serial.println("OTA switch: other partition has no valid firmware");
67+
#ifdef PIN_BUZZER
68+
// Error buzzer: three short beeps
69+
for (int i = 0; i < 3; i++) {
70+
tone(PIN_BUZZER, 200, 100);
71+
delay(200);
72+
}
73+
noTone(PIN_BUZZER);
74+
#endif
75+
return;
76+
}
77+
78+
Serial.printf("OTA switch: %s -> %s\n", running->label, next->label);
79+
80+
#ifdef PIN_BUZZER
81+
// Confirmation buzzer: ascending two-tone
82+
tone(PIN_BUZZER, 1000, 150);
83+
delay(200);
84+
tone(PIN_BUZZER, 1500, 150);
85+
delay(200);
86+
noTone(PIN_BUZZER);
87+
#endif
88+
89+
esp_ota_set_boot_partition(next);
90+
delay(200);
91+
ESP.restart();
92+
}
93+
4794
void initIOExpander() {
4895
// Initialize PI4IO I/O expander for LoRa control pins
4996
// P5: LNA Enable, P6: RF Switch, P7: LoRa Reset
@@ -105,6 +152,9 @@ class M5StackUnitC6LBoard : public ESP32Board {
105152
pinMode(PIN_BUZZER, OUTPUT);
106153
digitalWrite(PIN_BUZZER, LOW);
107154
#endif
155+
156+
// Check if BOOT button is held to switch firmware
157+
checkOTASwitch();
108158
}
109159

110160
const char* getManufacturerName() const override {

variants/m5stack_unit_c6l/UITask.cpp

Lines changed: 0 additions & 94 deletions
This file was deleted.

variants/m5stack_unit_c6l/UnitC6LBoard.cpp

Lines changed: 0 additions & 49 deletions
This file was deleted.

variants/m5stack_unit_c6l/UnitC6LBoard.h

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)