mirror of
https://github.com/pelgraine/Meck.git
synced 2026-08-08 17:52:44 +02:00
T-Echo Card audio support initial stages - codec2 attempts
This commit is contained in:
@@ -322,7 +322,9 @@ private:
|
||||
AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table
|
||||
int next_ack_idx;
|
||||
|
||||
#define ADVERT_PATH_TABLE_SIZE 1000
|
||||
#ifndef ADVERT_PATH_TABLE_SIZE
|
||||
#define ADVERT_PATH_TABLE_SIZE 1000
|
||||
#endif
|
||||
AdvertPath* advert_paths; // PSRAM-allocated in begin(), size = ADVERT_PATH_TABLE_SIZE
|
||||
|
||||
// Sent message repeat tracking
|
||||
|
||||
@@ -894,7 +894,7 @@
|
||||
#endif
|
||||
|
||||
// --- T-Echo Lite: CardKB keyboard, GxEPD2 e-ink, no touch ---
|
||||
#if defined(LILYGO_TECHO_LITE)
|
||||
#if defined(LILYGO_TECHO_LITE) || defined(LILYGO_TECHO_CARD)
|
||||
#include "ContactsScreen.h"
|
||||
#include "ChannelScreen.h"
|
||||
#include "ChannelPickerScreen.h"
|
||||
@@ -904,6 +904,12 @@
|
||||
#include "LastHeardScreen.h"
|
||||
#include "PathEditorScreen.h"
|
||||
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
#include "TechoCardHomeScreen.h"
|
||||
static TechoCardHomeScreen* _techoHome = nullptr;
|
||||
static int _techoC2Debug = 0;
|
||||
#endif
|
||||
|
||||
#ifdef MECK_CARDKB
|
||||
#include "CardKBKeyboard.h"
|
||||
static CardKBKeyboard cardkb;
|
||||
@@ -1027,8 +1033,8 @@ static uint32_t _atoi(const char* sp) {
|
||||
/* GLOBAL OBJECTS */
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include "UITask.h"
|
||||
#if HAS_GPS
|
||||
#include "MapScreen.h" // After BLE — PNGdec headers conflict with BLE if included earlier
|
||||
#if HAS_GPS && !defined(LILYGO_TECHO_CARD)
|
||||
#include "MapScreen.h" // After BLE -- PNGdec headers conflict with BLE if included earlier
|
||||
#endif
|
||||
UITask ui_task(&board, &serial_interface);
|
||||
#endif
|
||||
@@ -2101,6 +2107,16 @@ void setup() {
|
||||
MESH_DEBUG_PRINTLN("setup() - about to call ui_task.begin()");
|
||||
ui_task.begin(disp, &sensors, the_mesh.getNodePrefs());
|
||||
MESH_DEBUG_PRINTLN("setup() - ui_task.begin() done");
|
||||
|
||||
// T-Echo Card: replace the generic HomeScreen with the 72x40 OLED home screen
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
{
|
||||
_techoHome = new TechoCardHomeScreen(&ui_task, &rtc_clock,
|
||||
the_mesh.getNodePrefs());
|
||||
ui_task.setHomeScreen(_techoHome);
|
||||
MESH_DEBUG_PRINTLN("setup() - TechoCardHomeScreen installed");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -2387,6 +2403,12 @@ void setup() {
|
||||
Serial.printf("setup() complete - free heap: %d, largest block: %d\n",
|
||||
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
#endif
|
||||
{
|
||||
void* p25 = malloc(25000); void* p10 = malloc(10000); void* p4 = malloc(4000);
|
||||
Serial.printf("setup() heap probe: 25K=%s 10K=%s 4K=%s\n",
|
||||
p25?"yes":"no", p10?"yes":"no", p4?"yes":"no");
|
||||
if (p4) free(p4); if (p10) free(p10); if (p25) free(p25);
|
||||
}
|
||||
MESH_DEBUG_PRINTLN("=== setup() - COMPLETE ===");
|
||||
}
|
||||
|
||||
@@ -2414,10 +2436,49 @@ void otaResumeRadio() {
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
// T-Echo Card: lazy Codec2 init from shallow stack context.
|
||||
// codec2_create needs ~3KB stack for FFT/trig init. The loop task
|
||||
// has only 4KB total. Calling from render() (deep call chain) overflows.
|
||||
// Calling from here (top of loop) works because stack depth is minimal.
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
if (_techoHome && _techoHome->needsCodec2()) {
|
||||
void* probe = malloc(25000);
|
||||
Serial.printf("Voice: heap probe 25K=%s, creating codec2...\n", probe?"yes":"no");
|
||||
if (probe) free(probe);
|
||||
Serial.flush();
|
||||
|
||||
struct CODEC2* c2 = codec2_create(VC_C2_MODE);
|
||||
Serial.printf("Voice: codec2_create returned %p\n", c2);
|
||||
Serial.flush();
|
||||
|
||||
if (c2) {
|
||||
_techoHome->setCodec2Instance(c2);
|
||||
void* postProbe = malloc(1000);
|
||||
Serial.printf("Voice: set OK, post-probe=%s\n", postProbe?"yes":"no");
|
||||
if (postProbe) free(postProbe);
|
||||
Serial.flush();
|
||||
_techoC2Debug = 99999; // Keep printing to test if yields prevent crash
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MECK_OTA_UPDATE
|
||||
if (!otaRadioPaused) {
|
||||
#endif
|
||||
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
if (_techoC2Debug > 0) {
|
||||
Serial.print("[pre-mesh]"); Serial.flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
the_mesh.loop();
|
||||
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
if (_techoC2Debug > 0) {
|
||||
Serial.print("[post-mesh]"); Serial.flush();
|
||||
}
|
||||
#endif
|
||||
#ifdef MECK_OTA_UPDATE
|
||||
} else {
|
||||
// OTA/File Manager active — poll the web server from the main loop for fast response.
|
||||
@@ -2457,7 +2518,7 @@ void loop() {
|
||||
|
||||
// Map screen: periodically update own GPS position and contact markers
|
||||
#ifdef DISPLAY_CLASS
|
||||
#if HAS_GPS
|
||||
#if HAS_GPS && !defined(LILYGO_TECHO_CARD)
|
||||
if (ui_task.isOnMapScreen()) {
|
||||
static unsigned long lastMapUpdate = 0;
|
||||
if (millis() - lastMapUpdate > 30000) { // Every 30 seconds
|
||||
@@ -2927,7 +2988,13 @@ void loop() {
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
if (_techoC2Debug > 0) { Serial.print("[pre-ui]"); Serial.flush(); }
|
||||
#endif
|
||||
ui_task.loop();
|
||||
#ifdef LILYGO_TECHO_CARD
|
||||
if (_techoC2Debug > 0) { Serial.print("[post-ui]"); Serial.flush(); _techoC2Debug--; }
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
rtc_clock.tick();
|
||||
@@ -3601,7 +3668,7 @@ void loop() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Low-power loop throttle — yield CPU when lock screen is active.
|
||||
// Low-power loop throttle -- yield CPU when lock screen is active.
|
||||
// The RTOS idle task executes WFI (wait-for-interrupt) during delay(),
|
||||
// dramatically reducing CPU power draw. 50 ms gives 20 loop cycles/sec
|
||||
// which is ample for LoRa packet reception (radio has hardware FIFO).
|
||||
|
||||
@@ -2814,9 +2814,11 @@ public:
|
||||
} else if (type == ROW_GPS_BAUD) {
|
||||
_editPickerIdx--;
|
||||
if (_editPickerIdx < 0) _editPickerIdx = GPS_BAUD_OPTION_COUNT - 1;
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
} else if (type == ROW_AUTO_LOCK) {
|
||||
_editPickerIdx--;
|
||||
if (_editPickerIdx < 0) _editPickerIdx = AUTO_LOCK_OPTION_COUNT - 1;
|
||||
#endif
|
||||
} else if (type == ROW_FONT_STYLE) {
|
||||
_editPickerIdx--;
|
||||
if (_editPickerIdx < 0) _editPickerIdx = MECK_FONT_STYLE_COUNT - 1;
|
||||
@@ -2835,9 +2837,11 @@ public:
|
||||
} else if (type == ROW_GPS_BAUD) {
|
||||
_editPickerIdx++;
|
||||
if (_editPickerIdx >= GPS_BAUD_OPTION_COUNT) _editPickerIdx = 0;
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
} else if (type == ROW_AUTO_LOCK) {
|
||||
_editPickerIdx++;
|
||||
if (_editPickerIdx >= AUTO_LOCK_OPTION_COUNT) _editPickerIdx = 0;
|
||||
#endif
|
||||
} else if (type == ROW_FONT_STYLE) {
|
||||
_editPickerIdx++;
|
||||
if (_editPickerIdx >= MECK_FONT_STYLE_COUNT) _editPickerIdx = 0;
|
||||
@@ -2859,12 +2863,14 @@ public:
|
||||
_editMode = EDIT_NONE;
|
||||
Serial.printf("Settings: GPS baud set to %lu (reboot to apply)\n",
|
||||
(unsigned long)_prefs->gps_baudrate);
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
} else if (type == ROW_AUTO_LOCK) {
|
||||
_prefs->auto_lock_minutes = AUTO_LOCK_OPTIONS[_editPickerIdx];
|
||||
the_mesh.savePrefs();
|
||||
_editMode = EDIT_NONE;
|
||||
Serial.printf("Settings: Auto lock = %s\n",
|
||||
autoLockLabel(_prefs->auto_lock_minutes));
|
||||
#endif
|
||||
} else if (type == ROW_FONT_STYLE) {
|
||||
_prefs->ui_font_style = _editPickerIdx;
|
||||
the_mesh.savePrefs();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "UITask.h"
|
||||
#include <helpers/TxtDataHelpers.h>
|
||||
#include "../MyMesh.h"
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
#include "NotesScreen.h"
|
||||
#endif
|
||||
#include "RepeaterAdminScreen.h"
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifdef MECK_WEB_READER
|
||||
#include "WebReaderScreen.h"
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#if HAS_GPS && !defined(LILYGO_TECHO_CARD)
|
||||
#include "MapScreen.h"
|
||||
#endif
|
||||
#include "target.h"
|
||||
@@ -52,7 +52,7 @@
|
||||
#include "ChannelScreen.h"
|
||||
#include "ChannelPickerScreen.h"
|
||||
#include "ContactsScreen.h"
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
#include "TextReaderScreen.h"
|
||||
#endif
|
||||
#include "SettingsScreen.h"
|
||||
@@ -1342,7 +1342,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
((ChannelPickerScreen*)channel_picker_screen)->setChannelScreen((ChannelScreen*)channel_screen);
|
||||
contacts_screen = new ContactsScreen(this, &rtc_clock);
|
||||
((ContactsScreen*)contacts_screen)->setDMUnreadPtr(_dmUnread);
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
text_reader = new TextReaderScreen(this, node_prefs);
|
||||
notes_screen = new NotesScreen(this, node_prefs);
|
||||
#else
|
||||
@@ -1365,7 +1365,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
#ifdef HAS_4G_MODEM
|
||||
sms_screen = new SMSScreen(this, node_prefs);
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#if HAS_GPS && !defined(LILYGO_TECHO_CARD)
|
||||
map_screen = new MapScreen(this);
|
||||
#else
|
||||
map_screen = nullptr;
|
||||
@@ -1379,6 +1379,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
#endif
|
||||
|
||||
// Apply saved dark mode preference (both T-Deck Pro and T5S3)
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
if (_node_prefs->dark_mode) {
|
||||
::display.setDarkMode(true);
|
||||
}
|
||||
@@ -1387,6 +1388,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
if (_node_prefs->ui_font_style > 0) {
|
||||
::display.setFontStyle(_node_prefs->ui_font_style);
|
||||
}
|
||||
#endif
|
||||
|
||||
setCurrScreen(splash);
|
||||
}
|
||||
@@ -1723,7 +1725,7 @@ void UITask::loop() {
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
} else {
|
||||
// Navigate back: reader reading→file list, file list→home, others→home
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
if (isOnTextReader()) {
|
||||
TextReaderScreen* reader = (TextReaderScreen*)text_reader;
|
||||
if (reader && reader->isReading()) {
|
||||
@@ -1890,23 +1892,27 @@ if (curr) curr->poll();
|
||||
_next_refresh = millis() + 500; // Re-check in 500ms
|
||||
} else {
|
||||
// Sync dark mode with prefs (settings toggle takes effect here)
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
if (_node_prefs && display.isDarkMode() != (_node_prefs->dark_mode != 0)) {
|
||||
display.setDarkMode(_node_prefs->dark_mode != 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||
// Sync portrait mode with prefs (T5S3 only)
|
||||
if (_node_prefs && display.isPortraitMode() != (_node_prefs->portrait_mode != 0)) {
|
||||
display.setPortraitMode(_node_prefs->portrait_mode != 0);
|
||||
// Text reader layout depends on orientation — force recalculation
|
||||
// Text reader layout depends on orientation -- force recalculation
|
||||
if (text_reader) {
|
||||
((TextReaderScreen*)text_reader)->invalidateLayout();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Sync font style with prefs (settings toggle takes effect here)
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
if (_node_prefs && display.getFontStyle() != _node_prefs->ui_font_style) {
|
||||
display.setFontStyle(_node_prefs->ui_font_style);
|
||||
}
|
||||
#endif
|
||||
_display->startFrame();
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||
if (_vkbActive) {
|
||||
@@ -2425,7 +2431,7 @@ void UITask::onVKBSubmit() {
|
||||
break;
|
||||
}
|
||||
case VKB_NOTES: {
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
NotesScreen* notes = (NotesScreen*)getNotesScreen();
|
||||
if (notes && strlen(text) > 0) {
|
||||
for (int i = 0; text[i]; i++) {
|
||||
@@ -2494,7 +2500,7 @@ void UITask::onVKBSubmit() {
|
||||
}
|
||||
#endif
|
||||
case VKB_TEXT_PAGE: {
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
if (strlen(text) > 0) {
|
||||
int pageNum = atoi(text);
|
||||
TextReaderScreen* reader = (TextReaderScreen*)getTextReaderScreen();
|
||||
@@ -2735,7 +2741,7 @@ void UITask::gotoContactsScreen() {
|
||||
|
||||
void UITask::gotoTextReader() {
|
||||
if (!text_reader) return; // Not available on this platform
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
TextReaderScreen* reader = (TextReaderScreen*)text_reader;
|
||||
if (_display != NULL) {
|
||||
reader->enter(*_display);
|
||||
@@ -2751,7 +2757,7 @@ void UITask::gotoTextReader() {
|
||||
|
||||
void UITask::gotoNotesScreen() {
|
||||
if (!notes_screen) return; // Not available on this platform
|
||||
#if !defined(LILYGO_TECHO_LITE)
|
||||
#if !defined(LILYGO_TECHO_LITE) && !defined(LILYGO_TECHO_CARD)
|
||||
NotesScreen* notes = (NotesScreen*)notes_screen;
|
||||
if (_display != NULL) {
|
||||
notes->enter(*_display);
|
||||
@@ -3011,6 +3017,8 @@ void UITask::gotoWebReader() {
|
||||
|
||||
#if HAS_GPS
|
||||
void UITask::gotoMapScreen() {
|
||||
if (!map_screen) return; // Not available on this platform (T-Echo Card)
|
||||
#if !defined(LILYGO_TECHO_CARD)
|
||||
MapScreen* map = (MapScreen*)map_screen;
|
||||
if (_display != NULL) {
|
||||
map->enter(*_display);
|
||||
@@ -3021,6 +3029,7 @@ void UITask::gotoMapScreen() {
|
||||
}
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS;
|
||||
_next_refresh = 100;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -325,6 +325,7 @@ public:
|
||||
NodePrefs* getNodePrefs() const { return _node_prefs; }
|
||||
UIScreen* getAudiobookScreen() const { return audiobook_screen; }
|
||||
void setAudiobookScreen(UIScreen* s) { audiobook_screen = s; }
|
||||
void setHomeScreen(UIScreen* s) { if (home) delete home; home = s; }
|
||||
#ifdef MECK_AUDIO_VARIANT
|
||||
UIScreen* getAlarmScreen() const { return alarm_screen; }
|
||||
void setAlarmScreen(UIScreen* s) { alarm_screen = s; }
|
||||
|
||||
Reference in New Issue
Block a user