diff --git a/examples/companion_radio/ui-new/SettingsScreen.h b/examples/companion_radio/ui-new/SettingsScreen.h index 3271ffc3..02c18683 100644 --- a/examples/companion_radio/ui-new/SettingsScreen.h +++ b/examples/companion_radio/ui-new/SettingsScreen.h @@ -61,6 +61,7 @@ class SettingsScreen : public UIScreen { CUSTOM_FREQ, CUSTOM_SF, CUSTOM_BW, CUSTOM_CR, POWER_SAVE, TX_APC, + SCOPE_NAME, // System section SECTION_SYSTEM, DEVICE_NAME, @@ -555,6 +556,11 @@ class SettingsScreen : public UIScreen { // Suppressed (and locked) while repeating — a repeater holds full TX power. if (p && p->client_repeat) display.print("--"); else display.print((p && p->tx_apc) ? "ON" : "OFF"); + } else if (item == SCOPE_NAME) { + display.print("Scope"); + int vx = valCol(display); + display.drawTextEllipsized(vx, y, display.width() - vx - _reserve, + (p && p->default_scope_name[0]) ? p->default_scope_name : "(none)"); #if AUTO_OFF_MILLIS > 0 } else if (item == AUTO_OFF) { display.print("AutoOff"); @@ -678,6 +684,7 @@ class SettingsScreen : public UIScreen { // Keyboard state for editing message slots int _edit_slot = -1; // -1 = not editing, 0..9 = slot being edited bool _edit_name = false; // editing DEVICE_NAME via the keyboard + bool _edit_scope = false; // editing SCOPE_NAME via the keyboard KeyboardWidget* _kb; // Radio preset picker — names are too long for the value column, so Enter on @@ -701,6 +708,7 @@ public: void onShow() override { _dirty = false; _edit_name = false; + _edit_scope = false; resetList(); _editor.freq.active = false; } @@ -708,7 +716,7 @@ public: int render(DisplayDriver& display) override { display.setTextSize(1); - if (_edit_slot >= 0 || _edit_name || _picker.saving) { + if (_edit_slot >= 0 || _edit_name || _edit_scope || _picker.saving) { return _kb->render(display); } @@ -771,6 +779,19 @@ public: return true; } + // Keyboard editing mode for the scope name + if (_edit_scope) { + auto res = _kb->handleInput(c); + if (res == KeyboardWidget::DONE) { + the_mesh.setPrimaryScope(_kb->buf); + _dirty = true; + _edit_scope = false; + } else if (res == KeyboardWidget::CANCELLED) { + _edit_scope = false; + } + return true; + } + // Digit-by-digit Freq editor if (_editor.active()) { if (_editor.handleFreqInput(c) && p) { _task->applyRadioParams(); _dirty = true; } @@ -966,6 +987,12 @@ public: _kb->clearPlaceholders(); // a device name is literal, not a message return true; } + if (_selected == SCOPE_NAME && p && enter) { + _edit_scope = true; + _kb->begin(p->default_scope_name, (int)sizeof(p->default_scope_name) - 1); + _kb->clearPlaceholders(); // a scope name is literal, not a message + return true; + } if (_selected == REBOOT && enter) { _task->savePrefsIfDirty(_dirty); // don't lose pending edits across the restart _task->showAlert("Rebooting...", 800); diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 16b92980..27998072 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -1398,11 +1398,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no _auto_off = millis() + (aoff > 0 ? aoff : AUTO_OFF_MILLIS); #if defined(CARDKB_I2C) - // On the ENV_PIN_SDA/SCL path, Wire1 is already brought up by + // On the ENV_PIN_SDA/SCL path, CARDKB_I2C is Wire1, already brought up by // sensors.begin() (EnvironmentSensorManager), which runs before this. On - // the CARDKB_USE_PRIMARY_WIRE path, Wire is already brought up by the - // board's own begin() (display/RTC), also before this -- either way, just - // probe for a CardKB sitting on the bus. + // boards that set CARDKB_I2C=Wire directly in platformio.ini, that bus is + // brought up by the board's own begin() instead -- also before this. + // Either way, just probe for a CardKB sitting on it. CARDKB_I2C.beginTransmission(0x5F); _has_cardkb = (CARDKB_I2C.endTransmission() == 0); #endif @@ -2120,7 +2120,7 @@ static const char CARDKB_FN_BASE[48] = { }; #endif -// Poll an optional CardKB (I2C keyboard, addr 0x5F) on Wire1/Grove, feeding +// Poll an optional CardKB (I2C keyboard, addr 0x5F) on CARDKB_I2C, feeding // the same key queue as every physical button. Most of its output needs no // translation at all: CardKB's own arrow/Enter/Esc byte codes are already // identical to this UI's KEY_LEFT/UP/DOWN/RIGHT/ENTER/CANCEL (0xB4-0xB7, 13, diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index f96e010d..c3bc058c 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -23,6 +23,21 @@ #include "../AbstractUITask.h" #include "../NodePrefs.h" #include "../Trail.h" + +// Optional M5Stack CardKB (I2C keyboard, addr 0x5F). CARDKB_I2C names which +// TwoWire it lives on -- set at file scope (not inside the class body, and +// not resolved via an #elif ladder) so both this header and SettingsScreen.h +// see a fully-resolved macro no matter which one gets included first. +// - Boards with a free second I2C bus define ENV_PIN_SDA/ENV_PIN_SCL +// (already brought up for EnvironmentSensorManager) and get Wire1 here, +// same as before. +// - Boards without a free second bus set -D CARDKB_I2C=Wire directly in +// platformio.ini, sharing whatever bus the display/RTC already use. +// Either way it's a no-op on boards that define neither, or when nothing +// ACKs 0x5F at boot. +#if !defined(CARDKB_I2C) && defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) + #define CARDKB_I2C Wire1 +#endif #include "../Waypoint.h" #include "../LiveTrack.h" #include "KeyboardWidget.h" @@ -193,20 +208,8 @@ class UITask : public AbstractUITask { void enqueueKey(char c); bool dequeueKey(char& c); - // Optional M5Stack CardKB (I2C keyboard, addr 0x5F). Two ways to reach it: - // - ENV_PIN_SDA/ENV_PIN_SCL defined -> CardKB rides the dedicated second - // I2C bus (Wire1) that EnvironmentSensorManager already brings up. - // - CARDKB_USE_PRIMARY_WIRE defined instead -> CardKB shares the board's - // main Wire bus (whatever the display/RTC already use), for boards - // where no second bus is free. Mutually exclusive with the above. - // Either way it's a no-op on boards with neither define, or when nothing - // ACKs 0x5F at boot. -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) - #define CARDKB_I2C Wire1 -#elif defined(CARDKB_USE_PRIMARY_WIRE) - #define CARDKB_I2C Wire -#endif - + // Optional M5Stack CardKB (I2C keyboard, addr 0x5F). See the CARDKB_I2C + // definition near the top of this file for which bus it's on and why. #if defined(CARDKB_I2C) bool _has_cardkb = false; // CardKB is level-triggered, not edge-triggered -- it keeps returning the diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 01b0d537..83b591b8 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -178,17 +178,21 @@ extends = Promicro build_src_filter = ${Promicro.build_src_filter} +<../examples/kiss_modem/> ; ============================================================ -; Solo build (UI completa on-device) com CardKB no barramento -; I2C ja usado pelo OLED (SDA=D8, SCL=D7 -- confirmado contra o -; esquematico oficial da fakeTec V5 rev.B). Requer o patch -; CARDKB_USE_PRIMARY_WIRE em UITask.h/.cpp e SettingsScreen.h. +; Solo build (full on-device UI) with CardKB support. +; CardKB shares the board's primary I2C bus (already used by the +; OLED display / RTC) instead of a dedicated second bus: the default +; Wire1 pins on this variant (D13/D14) physically collide with the +; LoRa SPI bus (P_LORA_NSS=13, P_LORA_MOSI=14), and no other free +; GPIO pair is broken out on this board for a second dedicated bus. +; Do NOT define ENV_PIN_SDA/ENV_PIN_SCL here -- that would bring up +; a real Wire1 on the colliding pins instead. ; ============================================================ [env:ProMicro_companion_solo_dual] extends = Promicro board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 -; -Ofast (default do core) infla o flash num build solo feature-completo; -; -Os cabe com folga. +; -Ofast (the core's default) doesn't fit a feature-complete solo build; +; -Os fits with headroom. build_unflags = -Ofast build_flags = ${Promicro.build_flags} -I examples/companion_radio/ui-new @@ -202,9 +206,8 @@ build_flags = ${Promicro.build_flags} -D UI_SENSORS_PAGE=1 -D ENABLE_SCREENSHOT -Os - ; CardKB compartilhando o barramento do OLED/RTC (D8/D7) -- - ; NAO definir ENV_PIN_SDA/SCL aqui, colidiria com o LoRa (D13/D14). - -D CARDKB_USE_PRIMARY_WIRE=1 + ; CardKB on the shared primary bus (D8=SDA / D7=SCL on this board). + -D CARDKB_I2C=Wire ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Promicro.build_src_filter}