mirror of
https://github.com/pelgraine/Meck.git
synced 2026-03-28 17:42:44 +01:00
preliminary html web reader app stage 1
This commit is contained in:
57
Web App Guide.md
Normal file
57
Web App Guide.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Web Reader - Integration Summary
|
||||
|
||||
### Conditional Compilation
|
||||
All web reader code is wrapped in `#ifdef MECK_WEB_READER` guards. The flag is set:
|
||||
- **meck_audio_ble**: Yes (`-D MECK_WEB_READER=1`) — WiFi available via BLE radio stack
|
||||
- **meck_4g_ble**: Yes (`-D MECK_WEB_READER=1`) — WiFi now, PPP via A7682E in future
|
||||
- **meck_audio_standalone**: No — excluded to preserve zero-radio-power design
|
||||
|
||||
### 4G Modem / PPP Support
|
||||
The web reader uses `isNetworkAvailable()` which checks both WiFi and (future) PPP connectivity. The `fetchPage()` method uses ESP32's standard `HTTPClient` which routes through whatever network interface is active — WiFi or PPP.
|
||||
|
||||
When PPP support is added to the 4G modem driver, the web reader will work over cellular automatically without code changes. The `isNetworkAvailable()` method has a `TODO` placeholder for the PPP status check.
|
||||
|
||||
---
|
||||
|
||||
## Key Bindings
|
||||
|
||||
### From Home Screen
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `b` | Open web reader |
|
||||
|
||||
### Web Reader - Home View
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `w` / `s` | Navigate up/down in bookmarks/history |
|
||||
| `Enter` | Select URL bar or bookmark/history item |
|
||||
| Type | Enter URL (when URL bar is active) |
|
||||
| `q` | Exit to firmware home |
|
||||
|
||||
### Web Reader - Reading View
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `w` / `a` | Previous page |
|
||||
| `s` / `d` / `Space` | Next page |
|
||||
| `l` or `Enter` | Enter link selection (type link number) |
|
||||
| `g` | Go to new URL (return to web reader home) |
|
||||
| `k` | Bookmark current page |
|
||||
| `q` | Back to web reader home |
|
||||
|
||||
### Web Reader - WiFi Setup
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `w` / `s` | Navigate SSID list |
|
||||
| `Enter` | Select SSID / submit password / retry |
|
||||
| Type | Enter WiFi password |
|
||||
| `q` | Back |
|
||||
|
||||
---
|
||||
|
||||
## SD Card Structure
|
||||
```
|
||||
/web/
|
||||
wifi.cfg - Saved WiFi credentials (auto-reconnect)
|
||||
bookmarks.txt - One URL per line
|
||||
history.txt - Recent URLs, newest first
|
||||
```
|
||||
@@ -8,11 +8,11 @@
|
||||
#define FIRMWARE_VER_CODE 8
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "20 Feb 2026"
|
||||
#define FIRMWARE_BUILD_DATE "22 Feb 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "Meck v0.9.2"
|
||||
#define FIRMWARE_VERSION "Meck v0.9.3"
|
||||
#endif
|
||||
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <Arduino.h> // needed for PlatformIO
|
||||
#include <esp_bt.h> // for esp_bt_controller_mem_release (web reader WiFi)
|
||||
#include <Mesh.h>
|
||||
#include "MyMesh.h"
|
||||
#include "variant.h" // Board-specific defines (HAS_GPS, etc.)
|
||||
@@ -16,6 +17,9 @@
|
||||
#include "ChannelScreen.h"
|
||||
#include "SettingsScreen.h"
|
||||
#include "RepeaterAdminScreen.h"
|
||||
#ifdef MECK_WEB_READER
|
||||
#include "WebReaderScreen.h"
|
||||
#endif
|
||||
extern SPIClass displaySpi; // From GxEPDDisplay.cpp, shared SPI bus
|
||||
|
||||
TCA8418Keyboard keyboard(I2C_ADDR_KEYBOARD, &Wire);
|
||||
@@ -33,6 +37,11 @@
|
||||
static bool composeDM = false;
|
||||
static int composeDMContactIdx = -1;
|
||||
static char composeDMName[32];
|
||||
#ifdef MECK_WEB_READER
|
||||
static unsigned long lastWebReaderRefresh = 0;
|
||||
static bool webReaderNeedsRefresh = false;
|
||||
static bool webReaderTextEntry = false; // True when URL/password entry active
|
||||
#endif
|
||||
// AGC reset - periodically re-assert RX boosted gain to prevent sensitivity drift
|
||||
#define AGC_RESET_INTERVAL_MS 500
|
||||
static unsigned long lastAGCReset = 0;
|
||||
@@ -691,10 +700,21 @@ void loop() {
|
||||
#else
|
||||
bool smsSuppressLoop = false;
|
||||
#endif
|
||||
if (!composeMode && !notesSuppressLoop && !smsSuppressLoop) {
|
||||
#ifdef MECK_WEB_READER
|
||||
// Safety: clear web reader text entry flag if we're no longer on the web reader
|
||||
if (webReaderTextEntry && !ui_task.isOnWebReader()) {
|
||||
webReaderTextEntry = false;
|
||||
webReaderNeedsRefresh = false;
|
||||
}
|
||||
#endif
|
||||
if (!composeMode && !notesSuppressLoop && !smsSuppressLoop
|
||||
#ifdef MECK_WEB_READER
|
||||
&& !webReaderTextEntry
|
||||
#endif
|
||||
) {
|
||||
ui_task.loop();
|
||||
} else {
|
||||
// Handle debounced screen refresh (compose, emoji picker, or notes editor)
|
||||
// Handle debounced screen refresh (compose, emoji picker, notes, or web reader text entry)
|
||||
if (composeNeedsRefresh && (millis() - lastComposeRefresh) >= COMPOSE_REFRESH_INTERVAL) {
|
||||
if (composeMode) {
|
||||
if (emojiPickerMode) {
|
||||
@@ -708,7 +728,7 @@ void loop() {
|
||||
ui_task.loop();
|
||||
} else if (smsSuppressLoop) {
|
||||
// SMS compose: render directly to display, same as mesh compose
|
||||
#ifdef DISPLAY_CLASS
|
||||
#if defined(DISPLAY_CLASS) && defined(HAS_4G_MODEM)
|
||||
display.startFrame();
|
||||
((SMSScreen*)ui_task.getSMSScreen())->render(display);
|
||||
display.endFrame();
|
||||
@@ -717,6 +737,28 @@ void loop() {
|
||||
lastComposeRefresh = millis();
|
||||
composeNeedsRefresh = false;
|
||||
}
|
||||
#ifdef MECK_WEB_READER
|
||||
if (webReaderNeedsRefresh && (millis() - lastWebReaderRefresh) >= COMPOSE_REFRESH_INTERVAL) {
|
||||
WebReaderScreen* wr2 = (WebReaderScreen*)ui_task.getWebReaderScreen();
|
||||
if (wr2) {
|
||||
display.startFrame();
|
||||
wr2->render(display);
|
||||
display.endFrame();
|
||||
}
|
||||
lastWebReaderRefresh = millis();
|
||||
webReaderNeedsRefresh = false;
|
||||
}
|
||||
// Password reveal expiry: re-render to mask character after 800ms
|
||||
if (webReaderTextEntry && !webReaderNeedsRefresh) {
|
||||
WebReaderScreen* wr3 = (WebReaderScreen*)ui_task.getWebReaderScreen();
|
||||
if (wr3 && wr3->needsRevealRefresh() && (millis() - lastWebReaderRefresh) >= 850) {
|
||||
display.startFrame();
|
||||
wr3->render(display);
|
||||
display.endFrame();
|
||||
lastWebReaderRefresh = millis();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Track reader/notes/audiobook mode state for key routing
|
||||
readerMode = ui_task.isOnTextReader();
|
||||
@@ -1214,6 +1256,51 @@ void handleKeyboardInput() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// *** WEB READER TEXT INPUT MODE ***
|
||||
// Match compose mode pattern: key handler sets a flag and returns instantly.
|
||||
// Main loop renders with 100ms debounce (same as COMPOSE_REFRESH_INTERVAL).
|
||||
// This way the key handler never blocks for 648ms during a render.
|
||||
#ifdef MECK_WEB_READER
|
||||
if (ui_task.isOnWebReader()) {
|
||||
WebReaderScreen* wr = (WebReaderScreen*)ui_task.getWebReaderScreen();
|
||||
bool urlEdit = wr ? wr->isUrlEditing() : false;
|
||||
bool passEdit = wr ? wr->isPasswordEntry() : false;
|
||||
bool formEdit = wr ? wr->isFormFilling() : false;
|
||||
if (wr && (urlEdit || passEdit || formEdit)) {
|
||||
webReaderTextEntry = true; // Suppress ui_task.loop() in main loop
|
||||
wr->handleInput(key); // Updates buffer instantly, no render
|
||||
|
||||
// Check if text entry ended (submitted, cancelled, etc.)
|
||||
if (!wr->isUrlEditing() && !wr->isPasswordEntry() && !wr->isFormFilling()) {
|
||||
// Text entry ended
|
||||
webReaderTextEntry = false;
|
||||
webReaderNeedsRefresh = false;
|
||||
// fetchPage()/submitForm() handle their own rendering, or mode changed —
|
||||
// let ui_task.loop() resume on next iteration
|
||||
} else {
|
||||
// Still typing — request debounced refresh
|
||||
webReaderNeedsRefresh = true;
|
||||
lastWebReaderRefresh = millis();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// Not in text entry — clear flag so ui_task.loop() resumes
|
||||
webReaderTextEntry = false;
|
||||
|
||||
// Q from HOME mode exits the web reader entirely (like text reader)
|
||||
if ((key == 'q' || key == 'Q') && wr && wr->isHome() && !wr->isUrlEditing()) {
|
||||
Serial.println("Exiting web reader");
|
||||
ui_task.gotoHomeScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
// Route keys through normal UITask for navigation/scrolling
|
||||
ui_task.injectKey(key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Normal mode - not composing
|
||||
switch (key) {
|
||||
case 'c':
|
||||
@@ -1258,6 +1345,50 @@ void handleKeyboardInput() {
|
||||
ui_task.gotoSMSScreen();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef MECK_WEB_READER
|
||||
case 'b':
|
||||
// Open web reader (browser)
|
||||
Serial.println("Opening web reader");
|
||||
{
|
||||
static bool webReaderWifiReady = false;
|
||||
if (!webReaderWifiReady) {
|
||||
// WiFi needs ~40KB contiguous heap. The BLE controller holds ~30KB,
|
||||
// leaving only ~30KB largest block. We MUST release BLE memory first.
|
||||
//
|
||||
// This disables BLE for the duration of the session.
|
||||
// BLE comes back on reboot.
|
||||
Serial.printf("WebReader: heap BEFORE BT release: free=%d, largest=%d\n",
|
||||
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
|
||||
// 1) Stop BLE controller (disable + deinit)
|
||||
btStop();
|
||||
delay(50);
|
||||
|
||||
// 2) Release the BT controller's reserved memory region back to heap
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
|
||||
delay(50);
|
||||
|
||||
Serial.printf("WebReader: heap AFTER BT release: free=%d, largest=%d\n",
|
||||
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
|
||||
// 3) Now init WiFi while we have maximum contiguous heap
|
||||
if (WiFi.mode(WIFI_STA)) {
|
||||
Serial.println("WebReader: WiFi STA init OK");
|
||||
webReaderWifiReady = true;
|
||||
} else {
|
||||
Serial.println("WebReader: WiFi STA init FAILED even after BT release");
|
||||
// Clean up partial WiFi init to avoid memory leak
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
|
||||
Serial.printf("WebReader: heap after WiFi init: free=%d, largest=%d\n",
|
||||
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
}
|
||||
}
|
||||
ui_task.gotoWebReader();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'n':
|
||||
// Open notes
|
||||
@@ -1274,9 +1405,13 @@ void handleKeyboardInput() {
|
||||
break;
|
||||
|
||||
case 's':
|
||||
// Open settings (from home), or navigate down on channel/contacts/admin
|
||||
if (ui_task.isOnChannelScreen() || ui_task.isOnContactsScreen() || ui_task.isOnRepeaterAdmin()) {
|
||||
ui_task.injectKey('s'); // Pass directly for channel/contacts scrolling
|
||||
// Open settings (from home), or navigate down on channel/contacts/admin/web
|
||||
if (ui_task.isOnChannelScreen() || ui_task.isOnContactsScreen() || ui_task.isOnRepeaterAdmin()
|
||||
#ifdef MECK_WEB_READER
|
||||
|| ui_task.isOnWebReader()
|
||||
#endif
|
||||
) {
|
||||
ui_task.injectKey('s'); // Pass directly for scrolling
|
||||
} else {
|
||||
Serial.println("Opening settings");
|
||||
ui_task.gotoSettingsScreen();
|
||||
@@ -1285,8 +1420,12 @@ void handleKeyboardInput() {
|
||||
|
||||
case 'w':
|
||||
// Navigate up/previous (scroll on channel screen)
|
||||
if (ui_task.isOnChannelScreen() || ui_task.isOnContactsScreen() || ui_task.isOnRepeaterAdmin()) {
|
||||
ui_task.injectKey('w'); // Pass directly for channel/contacts switching
|
||||
if (ui_task.isOnChannelScreen() || ui_task.isOnContactsScreen() || ui_task.isOnRepeaterAdmin()
|
||||
#ifdef MECK_WEB_READER
|
||||
|| ui_task.isOnWebReader()
|
||||
#endif
|
||||
) {
|
||||
ui_task.injectKey('w'); // Pass directly for scrolling
|
||||
} else {
|
||||
Serial.println("Nav: Previous");
|
||||
ui_task.injectKey(0xF2); // KEY_PREV
|
||||
@@ -1371,6 +1510,17 @@ void handleKeyboardInput() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef MECK_WEB_READER
|
||||
// If web reader is in reading/link/wifi mode, inject q for internal navigation
|
||||
// (reading→home, wifi→home). Only exit to firmware home if already on web home.
|
||||
if (ui_task.isOnWebReader()) {
|
||||
WebReaderScreen* wr = (WebReaderScreen*)ui_task.getWebReaderScreen();
|
||||
if (wr && !wr->isHome()) {
|
||||
ui_task.injectKey('q');
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Go back to home screen (admin mode handled above)
|
||||
Serial.println("Nav: Back to home");
|
||||
ui_task.gotoHomeScreen();
|
||||
@@ -1395,6 +1545,13 @@ void handleKeyboardInput() {
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef MECK_WEB_READER
|
||||
// Pass unhandled keys to web reader (l=link, g=go, k=bookmark, 0-9=link#)
|
||||
if (ui_task.isOnWebReader()) {
|
||||
ui_task.injectKey(key);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Serial.printf("Unhandled key in normal mode: '%c' (0x%02X)\n", key, key);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -340,6 +340,10 @@ public:
|
||||
display.drawTextCentered(display.width() / 2, y, "[E] Reader [P] Audiobooks");
|
||||
#else
|
||||
display.drawTextCentered(display.width() / 2, y, "[E] Reader ");
|
||||
#endif
|
||||
#ifdef MECK_WEB_READER
|
||||
y += 10;
|
||||
display.drawTextCentered(display.width() / 2, y, "[B] Browser ");
|
||||
#endif
|
||||
y += 14;
|
||||
|
||||
@@ -1446,6 +1450,28 @@ void UITask::gotoRepeaterAdmin(int contactIdx) {
|
||||
_next_refresh = 100;
|
||||
}
|
||||
|
||||
#ifdef MECK_WEB_READER
|
||||
void UITask::gotoWebReader() {
|
||||
// Lazy-initialize on first use (same pattern as audiobook player)
|
||||
if (web_reader == nullptr) {
|
||||
Serial.printf("WebReader: lazy init - free heap: %d, largest block: %d\n",
|
||||
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
web_reader = new WebReaderScreen(this);
|
||||
Serial.printf("WebReader: init complete - free heap: %d\n", ESP.getFreeHeap());
|
||||
}
|
||||
WebReaderScreen* wr = (WebReaderScreen*)web_reader;
|
||||
if (_display != NULL) {
|
||||
wr->enter(*_display);
|
||||
}
|
||||
setCurrScreen(web_reader);
|
||||
if (_display != NULL && !_display->isOn()) {
|
||||
_display->turnOn();
|
||||
}
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS;
|
||||
_next_refresh = 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
void UITask::onAdminLoginResult(bool success, uint8_t permissions, uint32_t server_time) {
|
||||
if (repeater_admin && isOnRepeaterAdmin()) {
|
||||
((RepeaterAdminScreen*)repeater_admin)->onLoginResult(success, permissions, server_time);
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "SMSScreen.h"
|
||||
#endif
|
||||
|
||||
#ifdef MECK_WEB_READER
|
||||
#include "WebReaderScreen.h"
|
||||
#endif
|
||||
|
||||
class UITask : public AbstractUITask {
|
||||
DisplayDriver* _display;
|
||||
SensorManager* _sensors;
|
||||
@@ -66,6 +70,9 @@ class UITask : public AbstractUITask {
|
||||
UIScreen* sms_screen; // SMS messaging screen (4G variant only)
|
||||
#endif
|
||||
UIScreen* repeater_admin; // Repeater admin screen
|
||||
#ifdef MECK_WEB_READER
|
||||
UIScreen* web_reader; // Web reader screen (lazy-init, WiFi required)
|
||||
#endif
|
||||
UIScreen* curr;
|
||||
|
||||
void userLedHandler();
|
||||
@@ -97,6 +104,9 @@ public:
|
||||
void gotoOnboarding(); // Navigate to settings in onboarding mode
|
||||
void gotoAudiobookPlayer(); // Navigate to audiobook player
|
||||
void gotoRepeaterAdmin(int contactIdx); // Navigate to repeater admin
|
||||
#ifdef MECK_WEB_READER
|
||||
void gotoWebReader(); // Navigate to web reader (browser)
|
||||
#endif
|
||||
#ifdef HAS_4G_MODEM
|
||||
void gotoSMSScreen();
|
||||
bool isOnSMSScreen() const { return curr == sms_screen; }
|
||||
@@ -114,6 +124,9 @@ public:
|
||||
bool isOnSettingsScreen() const { return curr == settings_screen; }
|
||||
bool isOnAudiobookPlayer() const { return curr == audiobook_screen; }
|
||||
bool isOnRepeaterAdmin() const { return curr == repeater_admin; }
|
||||
#ifdef MECK_WEB_READER
|
||||
bool isOnWebReader() const { return curr == web_reader; }
|
||||
#endif
|
||||
|
||||
#ifdef MECK_AUDIO_VARIANT
|
||||
// Check if audio is playing/paused in the background (for status indicators)
|
||||
@@ -150,6 +163,9 @@ public:
|
||||
UIScreen* getAudiobookScreen() const { return audiobook_screen; }
|
||||
void setAudiobookScreen(UIScreen* s) { audiobook_screen = s; }
|
||||
UIScreen* getRepeaterAdminScreen() const { return repeater_admin; }
|
||||
#ifdef MECK_WEB_READER
|
||||
UIScreen* getWebReaderScreen() const { return web_reader; }
|
||||
#endif
|
||||
|
||||
// from AbstractUITask
|
||||
void msgRead(int msgcount) override;
|
||||
|
||||
3008
examples/companion_radio/ui-new/Webreaderscreen.h
Normal file
3008
examples/companion_radio/ui-new/Webreaderscreen.h
Normal file
File diff suppressed because it is too large
Load Diff
16
examples/companion_radio/ui-new/webreaderdeps.cpp
Normal file
16
examples/companion_radio/ui-new/webreaderdeps.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// WebReaderDeps.cpp
|
||||
// -----------------------------------------------------------------------
|
||||
// PlatformIO library dependency finder (LDF) hint file.
|
||||
//
|
||||
// The web reader's WiFi/HTTP includes live in WebReaderScreen.h (header-only),
|
||||
// but PlatformIO's LDF can't always trace framework library dependencies
|
||||
// through conditional #include chains in headers. This .cpp file exposes
|
||||
// the includes at the top level where the scanner reliably finds them.
|
||||
//
|
||||
// No actual code here — just #include directives for the dependency finder.
|
||||
// -----------------------------------------------------------------------
|
||||
#ifdef MECK_WEB_READER
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@ build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
|
||||
-D LORA_FREQ=869.525
|
||||
-D LORA_BW=250
|
||||
-D LORA_SF=11
|
||||
-D ENABLE_ADVERT_ON_BOOT=1
|
||||
-D ENABLE_PRIVATE_KEY_IMPORT=1 ; NOTE: comment these out for more secure firmware
|
||||
-D ENABLE_PRIVATE_KEY_EXPORT=1
|
||||
-D RADIOLIB_EXCLUDE_CC1101=1
|
||||
@@ -58,6 +59,7 @@ platform = platformio/espressif32@6.11.0
|
||||
monitor_filters = esp32_exception_decoder
|
||||
extra_scripts = merge-bin.py
|
||||
build_flags = ${arduino_base.build_flags}
|
||||
-D ESP32_PLATFORM
|
||||
; -D ESP32_CPU_FREQ=80 ; change it to your need
|
||||
build_src_filter = ${arduino_base.build_src_filter}
|
||||
|
||||
@@ -67,10 +69,10 @@ lib_deps =
|
||||
file://arch/esp32/AsyncElegantOTA
|
||||
|
||||
; esp32c6 uses arduino framework 3.x
|
||||
; WARNING: experimental. pioarduino on esp32c6 needs work - it's not considered stable and has issues.
|
||||
; WARNING: experimental. May not work as stable as other platforms.
|
||||
[esp32c6_base]
|
||||
extends = esp32_base
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.12/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13-1/platform-espressif32.zip
|
||||
|
||||
; ----------------- NRF52 ---------------------
|
||||
|
||||
@@ -79,7 +81,7 @@ extends = arduino_base
|
||||
platform = nordicnrf52
|
||||
platform_packages =
|
||||
framework-arduinoadafruitnrf52 @ 1.10700.0
|
||||
extra_scripts =
|
||||
extra_scripts =
|
||||
create-uf2.py
|
||||
arch/nrf52/extra_scripts/patch_bluefruit.py
|
||||
build_flags = ${arduino_base.build_flags}
|
||||
@@ -147,4 +149,4 @@ lib_deps =
|
||||
adafruit/Adafruit_VL53L0X @ ^1.2.4
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
adafruit/Adafruit BME680 Library @ ^2.0.4
|
||||
adafruit/Adafruit BMP085 Library @ ^1.2.4
|
||||
adafruit/Adafruit BMP085 Library @ ^1.2.4
|
||||
@@ -80,7 +80,7 @@ build_flags =
|
||||
-D PIN_DISPLAY_BL=45
|
||||
-D PIN_USER_BTN=0
|
||||
-D CST328_PIN_RST=38
|
||||
-D FIRMWARE_VERSION='"Meck v0.9.1A"'
|
||||
-D FIRMWARE_VERSION='"Meck v0.9.3A"'
|
||||
-D ARDUINO_LOOP_STACK_SIZE=32768
|
||||
build_src_filter = ${esp32_base.build_src_filter}
|
||||
+<../variants/LilyGo_TDeck_Pro>
|
||||
@@ -107,6 +107,7 @@ build_flags =
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D MECK_AUDIO_VARIANT
|
||||
-D MECK_WEB_READER=1
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
@@ -120,6 +121,7 @@ lib_deps =
|
||||
bitbank2/JPEGDEC
|
||||
|
||||
; Audio standalone (audio-player hardware, no BLE/WiFi — maximum battery life)
|
||||
; No MECK_WEB_READER: WiFi power draw conflicts with zero-radio-power design.
|
||||
[env:meck_audio_standalone]
|
||||
extends = LilyGo_TDeck_Pro
|
||||
build_flags =
|
||||
@@ -152,6 +154,7 @@ build_flags =
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D HAS_4G_MODEM=1
|
||||
-D MECK_WEB_READER=1
|
||||
-D FIRMWARE_VERSION='"Meck v0.9.2-4G"'
|
||||
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
|
||||
Reference in New Issue
Block a user