mirror of
https://github.com/pelgraine/Meck.git
synced 2026-10-31 04:02:01 +01:00
v1.15: Settings > Experimental Features (delete all contacts, Alt+B-only backlight); TEMP Max charger readout
Version - MyMesh.h: FIRMWARE_VERSION default "Meck v1.14" -> "Meck v1.15"; FIRMWARE_BUILD_DATE updated. - variants/lilygo_tdeck_pro/platformio.ini, variants/lilygo_tdeck_max/platformio.ini: FIRMWARE_VERSION strings v1.14 -> v1.15. Settings > Experimental Features - SettingsScreen.h: new "Experimental Features >>" folder row as the last top-level Settings row, opening "Settings > Experimental". - Delete all contacts (all T-Deck builds), ported from Meck-P4 v0.7.4. Flow: "Delete all contacts?" box (Enter:Yes Q:No) -> second "Are you sure? This cannot be undone." popup (its Enter is ignored for the first second) -> "Purging" -> "Contacts deleted" or "Purge failed" -> restart 3 s later. Removes every contact, with favourites and custom paths, and the DM history; channel messages are kept. Q cancels at either confirmation; keys are ignored once the purge starts. - MyMesh.h: purgeAllContacts() closes any chunked contact save still in progress, empties the contact table and saves the empty set. - ChannelScreen.h: purgeDMs() marks the DM entries in /meshcore/messages.bin empty in place and re-saves, keeping channel messages, and clears the DM unread count. - main.cpp: meckPurgeAllContacts() runs both and checks the contacts file is empty afterwards. All touch is ignored while the purge box is open. - Change Backlight to Alt+B (Max only): ON stops the heart touch key toggling the frontlight, and Alt+B then lights it at the Backlight Brightness setting. OFF leaves both as before. - NodePrefs.h, DataStore.cpp: new pref backlight_alt_b_only at byte 1522 (prefs file now 1523 bytes); older files load it as 0 (heart key on). Timezones comment "these final fields" -> "these fields". TEMPORARY (Max only; remove after the charging investigation) - TDeckProMaxBoard.h, TDeckProMaxBoard.cpp: chargerDebugPrint(), a read-only SY6970 status, fault and register dump plus a BQ27220 gauge line on serial. - UITask.cpp: calls it every 10 s from UITask::loop().
This commit is contained in:
1 parent
3fc6e73014
commit
2ca97fa8ce
12 files changed
+360
-21
No files matched your search
@@ -291,6 +291,9 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
if (file.read((uint8_t *)&_prefs.clock_slot_b, sizeof(_prefs.clock_slot_b)) != sizeof(_prefs.clock_slot_b)) {
|
||||
_prefs.clock_slot_b = 0; // default: Zone 2 at UTC+0
|
||||
}
|
||||
if (file.read((uint8_t *)&_prefs.backlight_alt_b_only, sizeof(_prefs.backlight_alt_b_only)) != sizeof(_prefs.backlight_alt_b_only)) {
|
||||
_prefs.backlight_alt_b_only = 0; // default: heart key on
|
||||
}
|
||||
|
||||
// Clamp to valid ranges
|
||||
if (_prefs.dark_mode > 1) _prefs.dark_mode = 0;
|
||||
@@ -308,6 +311,7 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
if (_prefs.kb_backlight_pct < 5 || _prefs.kb_backlight_pct > 100) _prefs.kb_backlight_pct = 50;
|
||||
if (_prefs.clock_slot_a < -12 || _prefs.clock_slot_a > 14) _prefs.clock_slot_a = 0;
|
||||
if (_prefs.clock_slot_b < -12 || _prefs.clock_slot_b > 14) _prefs.clock_slot_b = 0;
|
||||
if (_prefs.backlight_alt_b_only > 1) _prefs.backlight_alt_b_only = 0;
|
||||
// Force NUL termination on each canned message slot in case of garbage
|
||||
for (int i = 0; i < (int)(sizeof(_prefs.canned_msgs) / sizeof(_prefs.canned_msgs[0])); i++) {
|
||||
_prefs.canned_msgs[i][sizeof(_prefs.canned_msgs[0]) - 1] = '\0';
|
||||
@@ -378,6 +382,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
||||
file.write((uint8_t *)_prefs.canned_msgs, sizeof(_prefs.canned_msgs)); // 177
|
||||
file.write((uint8_t *)&_prefs.clock_slot_a, sizeof(_prefs.clock_slot_a)); // 1520
|
||||
file.write((uint8_t *)&_prefs.clock_slot_b, sizeof(_prefs.clock_slot_b)); // 1521
|
||||
file.write((uint8_t *)&_prefs.backlight_alt_b_only, sizeof(_prefs.backlight_alt_b_only)); // 1522
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
@@ -2950,6 +2950,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
// as upstream replies to a command it does not have.
|
||||
char *text = (char *)&cmd_frame[1];
|
||||
text[len - 1] = 0; // ensure null
|
||||
Serial.printf("APP CLI: %s\n", text); // TEMPORARY test print: each command the app sends
|
||||
while (*text == ' ') text++; // skip leading spaces
|
||||
char reply_buf[166];
|
||||
char *reply = reply_buf;
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#define FIRMWARE_VER_CODE 11
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "15 Sept 2026"
|
||||
#define FIRMWARE_BUILD_DATE "7 Oct 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "Meck v1.14"
|
||||
#define FIRMWARE_VERSION "Meck v1.15"
|
||||
#endif
|
||||
|
||||
#if defined(STM32_PLATFORM)
|
||||
@@ -311,6 +311,15 @@ public:
|
||||
void saveContacts() {
|
||||
_store->saveContacts(this);
|
||||
}
|
||||
// Settings > Experimental Features > Delete all contacts (Meck-P4 port).
|
||||
// Empties the in-RAM contact table (BaseChatMesh::resetContacts is
|
||||
// protected) and saves the empty set. A chunked background save still in
|
||||
// progress is closed first, so it cannot later put an older list back.
|
||||
void purgeAllContacts() {
|
||||
if (_store->isSaveInProgress()) _store->finishSaveContacts();
|
||||
resetContacts();
|
||||
_store->saveContacts(this);
|
||||
}
|
||||
void saveMainIdentity() {
|
||||
_store->saveMainIdentity(self_id);
|
||||
}
|
||||
|
||||
@@ -92,11 +92,17 @@ struct NodePrefs { // persisted to file
|
||||
|
||||
// --- Timezones home page (world clock) ---
|
||||
// UTC offsets (-12..+14) of the page's two extra zones; its Home row is
|
||||
// utc_offset_hours. Older prefs files short-read these final fields and
|
||||
// utc_offset_hours. Older prefs files short-read these fields and
|
||||
// keep the default 0 (UTC+0).
|
||||
int8_t clock_slot_a; // Zone 1 UTC offset, default 0
|
||||
int8_t clock_slot_b; // Zone 2 UTC offset, default 0
|
||||
|
||||
// --- Experimental Features ---
|
||||
// 1 = "Change Backlight to Alt+B" is on: the Max's heart touch key no
|
||||
// longer toggles the frontlight, leaving Alt+B. Older prefs files
|
||||
// short-read this final field and keep the default 0 (heart key on).
|
||||
uint8_t backlight_alt_b_only; // default 0
|
||||
|
||||
// --- Font helpers (inline, no overhead) ---
|
||||
// Returns the DisplayDriver text-size index for "small/body" text.
|
||||
// T-Deck Pro: 0 = built-in 6×8 (or 7pt with custom fonts), 1 = 9pt.
|
||||
|
||||
@@ -896,6 +896,26 @@ MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store
|
||||
|
||||
/* END GLOBAL OBJECTS */
|
||||
|
||||
#if defined(LilyGo_TDeck_Pro)
|
||||
// ---------------------------------------------------------------------------
|
||||
// Settings > Experimental Features > Delete all contacts (ported from
|
||||
// Meck-P4 v0.7.4). Empties the contact table and saves the empty set, and
|
||||
// removes the direct-message history from the SD message store (channel
|
||||
// messages are kept). SettingsScreen restarts the device afterwards.
|
||||
// ---------------------------------------------------------------------------
|
||||
void meckPurgeAllContacts(int* contactsRemoved, bool* contactsOk, int* dmsRemoved) {
|
||||
*contactsRemoved = the_mesh.getNumContacts();
|
||||
the_mesh.purgeAllContacts();
|
||||
File f = SPIFFS.open("/contacts3", "r");
|
||||
*contactsOk = f && f.size() == 0;
|
||||
if (f) f.close();
|
||||
ChannelScreen* chScr = (ChannelScreen*)ui_task.getChannelScreen();
|
||||
*dmsRemoved = chScr ? chScr->purgeDMs() : -1;
|
||||
Serial.printf("Purge: %d contacts removed, contacts file %s, DMs removed %d\n",
|
||||
*contactsRemoved, *contactsOk ? "empty" : "NOT EMPTY", *dmsRemoved);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
|
||||
// ---------------------------------------------------------------------------
|
||||
// Combined BLE + WiFi companion (meck_max_ble_wifi test build)
|
||||
@@ -1302,6 +1322,9 @@ static void openMapScreen() {
|
||||
if (!pressed) return;
|
||||
switch (key_id) {
|
||||
case 0: // heart -- toggle frontlight at the user-set brightness
|
||||
// Settings > Experimental Features "Change Backlight to Alt+B" turns
|
||||
// the heart key off, leaving Alt+B as the backlight toggle.
|
||||
if (the_mesh.getNodePrefs()->backlight_alt_b_only) break;
|
||||
if (board.isBacklightOn()) {
|
||||
board.backlightOff();
|
||||
} else {
|
||||
@@ -3518,6 +3541,12 @@ void loop() {
|
||||
{
|
||||
// Guard: skip touch when locked
|
||||
bool touchBlocked = ui_task.isLocked();
|
||||
// Settings > Experimental Features "Delete all contacts" box open: keys
|
||||
// only, so a stray touch can't confirm it or leave Settings mid-purge
|
||||
if (ui_task.isOnSettingsScreen()) {
|
||||
SettingsScreen* purgeSS = (SettingsScreen*)ui_task.getSettingsScreen();
|
||||
if (purgeSS && purgeSS->isPurgeBoxOpen()) touchBlocked = true;
|
||||
}
|
||||
#ifdef HAS_4G_MODEM
|
||||
// SMS dialer has its own dedicated touch handler — don't consume touch data here
|
||||
if (smsMode) {
|
||||
@@ -3855,6 +3884,12 @@ void handleKeyboardInput() {
|
||||
// Alt+B toggles the e-ink frontlight (MAX only -- working backlight on IO41)
|
||||
if (key == KB_KEY_BACKLIGHT) {
|
||||
if (board.isBacklightOn()) board.backlightOff();
|
||||
else if (the_mesh.getNodePrefs()->backlight_alt_b_only) {
|
||||
// Experimental "Change Backlight to Alt+B" on: use the Backlight
|
||||
// Brightness setting, as the heart key does
|
||||
uint8_t blPct = the_mesh.getNodePrefs()->backlight_brightness_pct;
|
||||
board.backlightSetBrightness((uint8_t)((blPct * 255 + 50) / 100));
|
||||
}
|
||||
else board.backlightOn();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -603,6 +603,28 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// Settings > Experimental Features > Delete all contacts: drop every direct
|
||||
// message and save, keeping channel messages. The file keeps the circular-
|
||||
// buffer layout, so DM slots are marked empty in place. Returns how many
|
||||
// were removed, or -1 if the SD card is not ready (nothing could be saved).
|
||||
int purgeDMs() {
|
||||
#if defined(HAS_SDCARD) && defined(ESP32)
|
||||
if (!_sdReady) return -1;
|
||||
int removed = 0;
|
||||
for (int i = 0; i < CHANNEL_MSG_HISTORY_SIZE; i++) {
|
||||
if (_messages[i].valid && _messages[i].channel_idx == 0xFF) {
|
||||
_messages[i].valid = false;
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
_unread[MAX_GROUP_CHANNELS] = 0; // DM unread slot
|
||||
saveToSD();
|
||||
return removed;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load message buffer from SD card. Returns true if messages were loaded.
|
||||
bool loadFromSD() {
|
||||
#if defined(HAS_SDCARD) && defined(ESP32)
|
||||
|
||||
@@ -195,6 +195,11 @@ enum SettingsRowType : uint8_t {
|
||||
ROW_OPERATOR_INFO, // Carrier/operator display (read-only)
|
||||
ROW_APN, // APN setting (editable)
|
||||
#endif
|
||||
ROW_EXPERIMENTAL_SUBMENU, // Folder row: enters Experimental Features sub-screen (last row)
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
ROW_ALT_B_BACKLIGHT, // Toggle: heart touch key off, Alt+B only toggles the backlight (MAX only)
|
||||
#endif
|
||||
ROW_PURGE_CONTACTS, // "Delete all contacts": confirm, purge, restart
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -216,6 +221,7 @@ enum EditMode : uint8_t {
|
||||
EDIT_OTA, // OTA firmware update flow (multi-phase overlay)
|
||||
EDIT_FILEMGR, // SD file manager flow (WiFi file browser)
|
||||
#endif
|
||||
EDIT_PURGE, // Delete all contacts: confirm / purging / result overlay
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -233,6 +239,15 @@ enum SubScreen : uint8_t {
|
||||
SUB_EXPORT_IMPORT, // Export/Import menu
|
||||
SUB_EXPORT_FLAGS, // Export checkboxes + trigger
|
||||
#endif
|
||||
SUB_EXPERIMENTAL, // Experimental Features sub-screen
|
||||
};
|
||||
|
||||
// Delete all contacts (Experimental Features) overlay phases
|
||||
enum PurgePhase : uint8_t {
|
||||
PURGE_CONFIRM, // "Delete all contacts?" Enter:Yes Q:No
|
||||
PURGE_CONFIRM2, // second confirmation popup ("Are you sure?"); Enter accepted after 1 s
|
||||
PURGE_RUNNING, // "Purging" shown; the work runs from poll()
|
||||
PURGE_DONE, // result shown; restart follows
|
||||
};
|
||||
|
||||
#ifdef MECK_OTA_UPDATE
|
||||
@@ -317,6 +332,13 @@ private:
|
||||
// Sub-screen navigation
|
||||
SubScreen _subScreen;
|
||||
int _savedTopCursor; // cursor position to restore when leaving sub-screen
|
||||
|
||||
// Experimental Features > Delete all contacts (EDIT_PURGE overlay)
|
||||
uint8_t _purgePhase; // PurgePhase
|
||||
unsigned long _purgeAt; // CONFIRM2: when Enter is accepted; RUNNING: when the purge runs; DONE: when the restart happens
|
||||
int _purgeContacts; // contacts removed (count shown on the confirm box)
|
||||
int _purgeDMs; // direct messages removed, -1 = SD card not ready
|
||||
bool _purgeContactsOk; // the contacts file is empty afterwards
|
||||
#ifdef HAS_SDCARD
|
||||
int _savedExportCursor; // cursor in SUB_EXPORT_IMPORT when entering SUB_EXPORT_FLAGS
|
||||
uint8_t _exportFlags; // bitmask of MECK_EXPORT_* flags for export checkboxes
|
||||
@@ -483,6 +505,12 @@ private:
|
||||
addRow(ROW_EXPORT_AUTOADD);
|
||||
addRow(ROW_EXPORT_NOW);
|
||||
#endif
|
||||
} else if (_subScreen == SUB_EXPERIMENTAL) {
|
||||
// --- Experimental Features sub-screen ---
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
addRow(ROW_ALT_B_BACKLIGHT);
|
||||
#endif
|
||||
addRow(ROW_PURGE_CONTACTS);
|
||||
} else {
|
||||
// --- Top-level settings list ---
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
@@ -549,6 +577,9 @@ private:
|
||||
addRow(ROW_OPERATOR_INFO);
|
||||
addRow(ROW_APN);
|
||||
#endif
|
||||
|
||||
// Experimental Features (last row)
|
||||
addRow(ROW_EXPERIMENTAL_SUBMENU);
|
||||
}
|
||||
|
||||
// Clamp cursor
|
||||
@@ -711,6 +742,11 @@ public:
|
||||
_sharePickerScroll = 0;
|
||||
_shareRequested = false;
|
||||
_shareContactIdx = -1;
|
||||
_purgePhase = PURGE_CONFIRM;
|
||||
_purgeAt = 0;
|
||||
_purgeContacts = 0;
|
||||
_purgeDMs = 0;
|
||||
_purgeContactsOk = false;
|
||||
#ifdef MECK_OTA_UPDATE
|
||||
_otaServer = nullptr;
|
||||
_otaPhase = OTA_PHASE_CONFIRM;
|
||||
@@ -768,6 +804,7 @@ public:
|
||||
|
||||
bool isOnboarding() const { return _onboarding; }
|
||||
bool isEditing() const { return _editMode != EDIT_NONE; }
|
||||
bool isPurgeBoxOpen() const { return _editMode == EDIT_PURGE; } // main.cpp ignores touch while open
|
||||
bool hasRadioChanges() const { return _radioChanged; }
|
||||
bool isOnChannelsSubScreen() const { return _subScreen == SUB_CHANNELS; }
|
||||
bool isOnDeletableChannel() const {
|
||||
@@ -1736,6 +1773,8 @@ public:
|
||||
} else if (_subScreen == SUB_OTA_TOOLS) {
|
||||
display.print("Settings > OTA Tools");
|
||||
#endif
|
||||
} else if (_subScreen == SUB_EXPERIMENTAL) {
|
||||
display.print("Settings > Experimental");
|
||||
} else {
|
||||
display.print("Settings");
|
||||
}
|
||||
@@ -2225,6 +2264,23 @@ public:
|
||||
display.print(tmp);
|
||||
break;
|
||||
|
||||
case ROW_EXPERIMENTAL_SUBMENU:
|
||||
display.setColor(selected ? DisplayDriver::DARK : DisplayDriver::GREEN);
|
||||
display.print("Experimental Features >>");
|
||||
break;
|
||||
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
case ROW_ALT_B_BACKLIGHT:
|
||||
snprintf(tmp, sizeof(tmp), "Change Backlight to Alt+B: %s",
|
||||
_prefs->backlight_alt_b_only ? "ON" : "OFF");
|
||||
display.print(tmp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ROW_PURGE_CONTACTS:
|
||||
display.print("Delete all contacts");
|
||||
break;
|
||||
|
||||
#ifdef HAS_4G_MODEM
|
||||
case ROW_IMEI: {
|
||||
const char* imei = modemManager.getIMEI();
|
||||
@@ -2320,6 +2376,85 @@ public:
|
||||
display.setTextSize(1);
|
||||
}
|
||||
|
||||
// === Delete all contacts overlay (Experimental Features) ===
|
||||
if (_editMode == EDIT_PURGE) {
|
||||
int bx = 2, by = 14, bw = display.width() - 4;
|
||||
int bh = display.height() - 28;
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.fillRect(bx, by, bw, bh);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawRect(bx, by, bw, bh);
|
||||
|
||||
display.setTextSize(_prefs->smallTextSize());
|
||||
int lh = _prefs->smallLineH();
|
||||
int cx = display.width() / 2;
|
||||
int y = by + 4;
|
||||
if (_purgePhase == PURGE_CONFIRM || _purgePhase == PURGE_CONFIRM2) {
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
display.drawTextCentered(cx, y, "Delete all contacts?");
|
||||
y += lh + 2;
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
snprintf(tmp, sizeof(tmp), "All %d contact%s, with", _purgeContacts, _purgeContacts == 1 ? "" : "s");
|
||||
display.drawTextCentered(cx, y, tmp); y += lh;
|
||||
display.drawTextCentered(cx, y, "favourites and custom"); y += lh;
|
||||
display.drawTextCentered(cx, y, "paths, and the DM history"); y += lh;
|
||||
display.drawTextCentered(cx, y, "will be deleted. Channel"); y += lh;
|
||||
display.drawTextCentered(cx, y, "messages are kept."); y += lh + 2;
|
||||
display.setColor(DisplayDriver::RED);
|
||||
display.drawTextCentered(cx, y, "The device will RESTART.");
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextCentered(cx, by + bh - lh - 2, "Enter:Yes Q:No");
|
||||
if (_purgePhase == PURGE_CONFIRM2) {
|
||||
// Second confirmation popup, drawn over the first box
|
||||
int tx = 10, tw = display.width() - 20;
|
||||
int th = lh * 3 + 12;
|
||||
int ty = by + (bh - th) / 2;
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.fillRect(tx, ty, tw, th);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawRect(tx, ty, tw, th);
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
display.drawTextCentered(cx, ty + 3, "Are you sure?");
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextCentered(cx, ty + 3 + lh + 2, "This cannot be undone.");
|
||||
display.drawTextCentered(cx, ty + th - lh - 2, "Enter:Yes Q:No");
|
||||
}
|
||||
} else if (_purgePhase == PURGE_RUNNING) {
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
display.drawTextCentered(cx, y, "Purging");
|
||||
y += lh + 2;
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextCentered(cx, y, "Deleting all contacts and"); y += lh;
|
||||
display.drawTextCentered(cx, y, "the DM history."); y += lh;
|
||||
display.drawTextCentered(cx, y, "Please wait..."); y += lh + 4;
|
||||
display.setColor(DisplayDriver::RED);
|
||||
display.drawTextCentered(cx, y, "Do not switch off. The"); y += lh;
|
||||
display.drawTextCentered(cx, y, "device restarts when done.");
|
||||
} else {
|
||||
bool ok = _purgeContactsOk && _purgeDMs >= 0;
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
display.drawTextCentered(cx, y, ok ? "Contacts deleted" : "Purge failed");
|
||||
y += lh + 2;
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
if (ok) {
|
||||
snprintf(tmp, sizeof(tmp), "Done. %d contact%s and the", _purgeContacts, _purgeContacts == 1 ? "" : "s");
|
||||
display.drawTextCentered(cx, y, tmp); y += lh;
|
||||
display.drawTextCentered(cx, y, "DM history have been"); y += lh;
|
||||
display.drawTextCentered(cx, y, "deleted from this device."); y += lh + 4;
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "Contacts file: %s", _purgeContactsOk ? "ok" : "failed");
|
||||
display.drawTextCentered(cx, y, tmp); y += lh;
|
||||
snprintf(tmp, sizeof(tmp), "DM history: %s", _purgeDMs >= 0 ? "ok" : "SD not ready");
|
||||
display.drawTextCentered(cx, y, tmp); y += lh;
|
||||
display.drawTextCentered(cx, y, "The restart reloads what"); y += lh;
|
||||
display.drawTextCentered(cx, y, "storage still holds."); y += lh + 4;
|
||||
}
|
||||
display.setColor(DisplayDriver::RED);
|
||||
display.drawTextCentered(cx, y, "RESTARTING NOW...");
|
||||
}
|
||||
display.setTextSize(1);
|
||||
}
|
||||
|
||||
// === Notification sound picker overlay ===
|
||||
#if defined(MECK_AUDIO_VARIANT) || defined(HAS_4G_MODEM)
|
||||
if (_editMode == EDIT_NOTIF_SOUND) {
|
||||
@@ -2853,6 +2988,29 @@ public:
|
||||
return true; // consume all keys in confirm mode
|
||||
}
|
||||
|
||||
// --- Delete all contacts (Experimental Features) ---
|
||||
if (_editMode == EDIT_PURGE) {
|
||||
if (_purgePhase == PURGE_CONFIRM || _purgePhase == PURGE_CONFIRM2) {
|
||||
if (c == KEY_CANCEL || c == 'q') {
|
||||
_editMode = EDIT_NONE;
|
||||
return true;
|
||||
}
|
||||
if (c == '\r' || c == 13) {
|
||||
if (_purgePhase == PURGE_CONFIRM) {
|
||||
// First Yes: show the second confirmation. Its Enter is ignored for
|
||||
// 1 s, so a double press or key bounce can't pass both boxes.
|
||||
_purgePhase = PURGE_CONFIRM2;
|
||||
_purgeAt = millis() + 1000;
|
||||
} else if ((long)(millis() - _purgeAt) >= 0) {
|
||||
_purgePhase = PURGE_RUNNING;
|
||||
_purgeAt = millis() + 1500; // let the "Purging" box reach the e-ink first
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true; // other keys ignored; no dismissing once the purge has started
|
||||
}
|
||||
|
||||
// --- Notification sound picker ---
|
||||
#if defined(MECK_AUDIO_VARIANT) || defined(HAS_4G_MODEM)
|
||||
if (_editMode == EDIT_NOTIF_SOUND) {
|
||||
@@ -3713,6 +3871,27 @@ public:
|
||||
startEditCanned(_rows[_cursor].param);
|
||||
break;
|
||||
|
||||
case ROW_EXPERIMENTAL_SUBMENU:
|
||||
_savedTopCursor = _cursor;
|
||||
_subScreen = SUB_EXPERIMENTAL;
|
||||
_cursor = 0;
|
||||
_scrollTop = 0;
|
||||
rebuildRows();
|
||||
Serial.println("Settings: entered Experimental Features sub-screen");
|
||||
break;
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
case ROW_ALT_B_BACKLIGHT:
|
||||
_prefs->backlight_alt_b_only = _prefs->backlight_alt_b_only ? 0 : 1;
|
||||
the_mesh.savePrefs();
|
||||
Serial.printf("Settings: Change Backlight to Alt+B = %s\n",
|
||||
_prefs->backlight_alt_b_only ? "ON" : "OFF");
|
||||
break;
|
||||
#endif
|
||||
case ROW_PURGE_CONTACTS:
|
||||
_purgeContacts = the_mesh.getNumContacts();
|
||||
_purgePhase = PURGE_CONFIRM;
|
||||
_editMode = EDIT_PURGE;
|
||||
break;
|
||||
#ifdef MECK_OTA_UPDATE
|
||||
case ROW_OTA_TOOLS_SUBMENU:
|
||||
#ifndef MECK_40MHZ_TEST
|
||||
@@ -3965,6 +4144,22 @@ public:
|
||||
}
|
||||
|
||||
// Override handleInput for UIScreen compatibility (used by injectKey)
|
||||
// Delete all contacts: run the purge once the "Purging" box has been drawn,
|
||||
// then restart a few seconds after the result is on screen. The restart
|
||||
// rebuilds everything keyed by contact index from the empty store.
|
||||
void poll() override {
|
||||
if (_editMode != EDIT_PURGE) return;
|
||||
if (_purgePhase == PURGE_RUNNING && (long)(millis() - _purgeAt) >= 0) {
|
||||
extern void meckPurgeAllContacts(int* contactsRemoved, bool* contactsOk, int* dmsRemoved);
|
||||
meckPurgeAllContacts(&_purgeContacts, &_purgeContactsOk, &_purgeDMs);
|
||||
_purgePhase = PURGE_DONE;
|
||||
_purgeAt = millis() + 3000; // result stays on screen before the restart
|
||||
} else if (_purgePhase == PURGE_DONE && (long)(millis() - _purgeAt) >= 0) {
|
||||
Serial.println("Settings: purge done, restarting");
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
||||
bool handleInput(char c) override {
|
||||
return handleKeyInput(c);
|
||||
}
|
||||
|
||||
@@ -2426,6 +2426,17 @@ if (curr) curr->poll();
|
||||
next_batt_chck = millis() + 8000;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
// TEMPORARY: charger + fuel gauge readout on serial every 10 s (read-only)
|
||||
{
|
||||
static unsigned long nextChargerDump = 0;
|
||||
if ((long)(millis() - nextChargerDump) >= 0) {
|
||||
nextChargerDump = millis() + 10000;
|
||||
board.chargerDebugPrint();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
char UITask::checkDisplayOn(char c) {
|
||||
|
||||
@@ -865,4 +865,55 @@ int16_t TDeckProMaxBoard::getBattTemperature() {
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---- TEMPORARY: charger + fuel gauge readout (read-only) ----
|
||||
// Register decoding follows XPowersLib's PowersSY6970.hpp (lewisxhe). Reading
|
||||
// REG0C returns the fault bits and clears the latched ones.
|
||||
static int sy6970_readReg(uint8_t reg) {
|
||||
Wire.beginTransmission(I2C_ADDR_SY6970);
|
||||
Wire.write(reg);
|
||||
if (Wire.endTransmission(false) != 0) return -1;
|
||||
if (Wire.requestFrom((uint8_t)I2C_ADDR_SY6970, (uint8_t)1) != 1) return -1;
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
void TDeckProMaxBoard::chargerDebugPrint() {
|
||||
static const char* const kInput[8] = { "none", "USB-SDP", "USB-CDP", "USB-DCP",
|
||||
"HVDCP", "adapter", "non-std-adapter", "OTG" };
|
||||
static const char* const kState[4] = { "not-charging", "pre-charge", "fast-charge", "charge-done" };
|
||||
int r[0x15];
|
||||
for (uint8_t i = 0; i <= 0x14; i++) r[i] = sy6970_readReg(i);
|
||||
|
||||
if (r[0x0B] < 0) {
|
||||
Serial.println("CHG: SY6970 not responding at 0x6A");
|
||||
} else {
|
||||
int vregCode = (r[0x06] & 0xFC) >> 2;
|
||||
int vreg = (vregCode > 0x30) ? 4608 : vregCode * 16 + 3840;
|
||||
int ntc = r[0x0C] & 0x07;
|
||||
const char* ntcName = (ntc == 0) ? "normal" : (ntc == 2) ? "warm" : (ntc == 3) ? "cool"
|
||||
: (ntc == 5) ? "cold" : (ntc == 6) ? "hot" : "other";
|
||||
Serial.printf("CHG: input=%s pg=%d state=%s hiz=%d chg_en=%d vreg=%dmV ichg=%dmA iinlim=%dmA term_en=%d wdt=%d timer_en=%d\n",
|
||||
kInput[(r[0x0B] >> 5) & 0x07], (r[0x0B] >> 2) & 1, kState[(r[0x0B] >> 3) & 0x03],
|
||||
(r[0x00] >> 7) & 1, (r[0x03] >> 4) & 1,
|
||||
vreg, (r[0x04] & 0x7F) * 64, (r[0x00] & 0x3F) * 50 + 100,
|
||||
(r[0x07] >> 7) & 1, (r[0x07] >> 4) & 0x03, (r[0x07] >> 3) & 1);
|
||||
Serial.printf("CHG: fault=0x%02X watchdog=%d boost=%d charge(bits5:4)=%d battery=%d ntc=%s(%d)\n",
|
||||
r[0x0C] & 0xFF, (r[0x0C] >> 7) & 1, (r[0x0C] >> 6) & 1, (r[0x0C] >> 4) & 0x03,
|
||||
(r[0x0C] >> 3) & 1, ntcName, ntc);
|
||||
}
|
||||
Serial.print("CHG regs:");
|
||||
for (uint8_t i = 0; i <= 0x14; i++) {
|
||||
if (r[i] < 0) Serial.printf(" %02X=--", i);
|
||||
else Serial.printf(" %02X=%02X", i, r[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
#if HAS_BQ27220
|
||||
int16_t t = getBattTemperature();
|
||||
Serial.printf("GAUGE: V=%umV I=%dmA avgI=%dmA remain=%umAh full=%umAh design=%umAh soc=%u%% T=%d.%dC\n",
|
||||
getBattMilliVolts(), (int16_t)bq27220_read16(BQ27220_REG_CURRENT), getAvgCurrent(),
|
||||
getRemainingCapacity(), bq27220_read16(BQ27220_REG_FULL_CAP), getDesignCapacity(),
|
||||
bq27220_read16(BQ27220_REG_SOC), t / 10, abs(t % 10));
|
||||
#endif
|
||||
}
|
||||
@@ -134,6 +134,10 @@ public:
|
||||
uint16_t getDesignCapacity();
|
||||
int16_t getBattTemperature();
|
||||
bool configureFuelGauge(uint16_t designCapacity_mAh = BQ27220_DESIGN_CAPACITY_MAH);
|
||||
// TEMPORARY: read-only charger (SY6970) and fuel gauge readout on serial,
|
||||
// called every 10 s from UITask::loop() while the charging stop is
|
||||
// investigated. Writes nothing to either chip.
|
||||
void chargerDebugPrint();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Sleep / power-off (moved verbatim from TDeckBoard when MAX was decoupled).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; =============================================================================
|
||||
; T-Deck Pro MAX V0.1 — Meck Build Environments
|
||||
; T-Deck Pro MAX V0.1-v0.3 — Meck Build Environments
|
||||
;
|
||||
; Hardware: ESP32-S3 + XL9555 I/O expander + combined 4G (A7682E) + Audio (ES8311)
|
||||
;
|
||||
@@ -179,7 +179,7 @@ build_flags =
|
||||
; -D MECK_BLE_SMALL_MTU_SPLIT=1
|
||||
; -D MECK_WATCH_EXT=1
|
||||
; -D MECK_BLE_SLOW_INTERVAL=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -213,7 +213,7 @@ build_flags =
|
||||
-D MECK_BLE_SMALL_MTU_SPLIT=1
|
||||
-D MECK_WATCH_EXT=1
|
||||
-D MECK_BLE_SLOW_INTERVAL=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -250,7 +250,7 @@ build_flags =
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D EINK_FASTLUT_EXPERIMENT=1
|
||||
-D FAST_LUT_FRAMES=9
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX.FASTLUT"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX.FASTLUT"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -282,7 +282,7 @@ build_flags =
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D HAS_4G_MODEM=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX.WiFi"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX.WiFi"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -316,7 +316,7 @@ build_flags =
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D HAS_4G_MODEM=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX.BLE-WiFi"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX.BLE-WiFi"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -342,7 +342,7 @@ build_flags =
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D HAS_4G_MODEM=1
|
||||
-D MECK_WEB_READER=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX.SA"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX.SA"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -398,7 +398,7 @@ build_flags =
|
||||
-D CPU_FREQ_BOOST=40
|
||||
-D CPU_FREQ_LOW_POWER=40
|
||||
;-D MESH_DEBUG=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.MAX.SA40"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.MAX.SA40"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
|
||||
@@ -164,7 +164,7 @@ build_flags =
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D EINK_FASTLUT_EXPERIMENT=1
|
||||
-D FAST_LUT_FRAMES=9
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.FASTLUT"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.FASTLUT"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -211,7 +211,7 @@ build_flags =
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D MECK_PRO_HYN_TOUCH=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.HYN"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.HYN"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -249,7 +249,7 @@ build_flags =
|
||||
-D MECK_AUDIO_VARIANT
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.WiFi"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.WiFi"'
|
||||
;-D WIFI_DEBUG_LOGGING=1
|
||||
;-D MESH_PACKET_LOGGING=1
|
||||
;-D MESH_DEBUG=1
|
||||
@@ -288,7 +288,7 @@ build_flags =
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D MECK_PRO_HYN_TOUCH=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.WiFi.HYN"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.WiFi.HYN"'
|
||||
;-D WIFI_DEBUG_LOGGING=1
|
||||
;-D MESH_PACKET_LOGGING=1
|
||||
;-D MESH_DEBUG=1
|
||||
@@ -357,7 +357,7 @@ build_flags =
|
||||
-D MECK_AUDIO_VARIANT
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D MECK_PRO_HYN_TOUCH=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.A.SA.HYN"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.A.SA.HYN"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
-<helpers/esp32/SerialBLEInterface.cpp>
|
||||
@@ -409,7 +409,7 @@ build_flags =
|
||||
-D CPU_FREQ_BOOST=40
|
||||
-D CPU_FREQ_LOW_POWER=40
|
||||
-D MESH_DEBUG=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.A.SA40"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.A.SA40"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
-<helpers/esp32/SerialBLEInterface.cpp>
|
||||
@@ -444,7 +444,7 @@ build_flags =
|
||||
-D HAS_4G_MODEM=1
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.4G"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.4G"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -480,7 +480,7 @@ build_flags =
|
||||
-D HAS_4G_MODEM=1
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.4G.WiFi"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.4G.WiFi"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
-<helpers/esp32/SerialBLEInterface.cpp>
|
||||
@@ -514,7 +514,7 @@ build_flags =
|
||||
-D HAS_4G_MODEM=1
|
||||
-D MECK_WEB_READER=1
|
||||
-D MECK_OTA_UPDATE=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.4G.SA"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.4G.SA"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
-<helpers/esp32/SerialBLEInterface.cpp>
|
||||
@@ -557,7 +557,7 @@ build_flags =
|
||||
-D CPU_FREQ_BOOST=40
|
||||
-D CPU_FREQ_LOW_POWER=40
|
||||
-D MESH_DEBUG=1
|
||||
-D FIRMWARE_VERSION='"Meck v1.14.4G.SA40"'
|
||||
-D FIRMWARE_VERSION='"Meck v1.15.4G.SA40"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
-<helpers/esp32/SerialBLEInterface.cpp>
|
||||
|
||||
Reference in new issue
Block a user