diff --git a/examples/companion_radio/ui-new/SettingsScreen.h b/examples/companion_radio/ui-new/SettingsScreen.h index 913749e0..02c18683 100644 --- a/examples/companion_radio/ui-new/SettingsScreen.h +++ b/examples/companion_radio/ui-new/SettingsScreen.h @@ -77,7 +77,7 @@ class SettingsScreen : public UIScreen { KEYBOARD_TYPE, KEYBOARD_MAIN_ALPHABET, KEYBOARD_ALPHABET, -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) KEYBOARD_CARDKB_COMPACT, #endif // Contacts section @@ -611,7 +611,7 @@ class SettingsScreen : public UIScreen { display.print("Additional"); display.setCursor(valCol(display), y); display.print(NodePrefs::keyboardAlphabetLabel(p ? p->keyboard_alt_alphabet : 0)); -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) } else if (item == KEYBOARD_CARDKB_COMPACT) { display.print("Ext. KB"); display.setCursor(valCol(display), y); @@ -1020,7 +1020,7 @@ public: _dirty = true; return true; } -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) if (_selected == KEYBOARD_CARDKB_COMPACT && p && (left || right || enter)) { p->keyboard_cardkb_compact ^= 1; _dirty = true; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index fb4163e0..38e01f02 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -1397,11 +1397,14 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no uint32_t aoff = autoOffMillis(); _auto_off = millis() + (aoff > 0 ? aoff : AUTO_OFF_MILLIS); -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) - // Wire1 is already brought up by sensors.begin() (EnvironmentSensorManager), - // which runs before this -- just probe for a CardKB sitting on it. - Wire1.beginTransmission(0x5F); - _has_cardkb = (Wire1.endTransmission() == 0); +#if defined(CARDKB_I2C) + // On the ENV_PIN_SDA/SCL path, CARDKB_I2C is Wire1, already brought up by + // sensors.begin() (EnvironmentSensorManager), which runs before this. On + // 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 #if defined(PIN_HALL_SENSOR) @@ -2115,7 +2118,7 @@ bool UITask::dequeueKey(char& c) { return true; } -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) // CardKB's "fn" column (key_map in M5Stack's unit_CardKB.cpp): Fn+ sends 0x80 + that key's row index, entirely disjoint from every other // code this UI recognises. Indexed by (raw - 0x80); non-letter slots (digits, @@ -2128,7 +2131,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, @@ -2156,7 +2159,7 @@ static const char CARDKB_FN_BASE[48] = { // once), so _cardkb_last_raw debounces it into one press per physical // keypress, same as a MomentaryButton's CLICK event. void UITask::pollCardKB() { -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) if (!_has_cardkb) return; // No artificial throttle: unlike a MomentaryButton (BUTTON_USE_INTERRUPTS // latches every edge in an ISR ring buffer, so it survives a blocking e-ink @@ -2167,9 +2170,9 @@ void UITask::pollCardKB() { // Polling every loop() iteration (same as a digital button's check(), which // has no throttle either) just shrinks that miss window down to exactly the // render() duration instead of render()+30ms. - Wire1.requestFrom(0x5F, 1); - if (!Wire1.available()) return; - uint8_t raw = Wire1.read(); + CARDKB_I2C.requestFrom(0x5F, 1); + if (!CARDKB_I2C.available()) return; + uint8_t raw = CARDKB_I2C.read(); if (raw == _cardkb_last_raw) return; // still held (or still released) -- no new edge _cardkb_last_raw = raw; if (raw == 0) return; // key just released, nothing to enqueue @@ -2536,7 +2539,7 @@ void UITask::loop() { } // Hint popup at bottom (like alert style) _display->setTextSize(1); -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) +#if defined(CARDKB_I2C) const char* hint = _lock_seq_count == 0 ? (_has_cardkb ? "Back+3xEnter/Fn+Esc" : "Hold Back + 3xEnter") : _lock_seq_count == 1 ? "Enter x2 more..." : "Enter x1 more..."; #else diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 995dd046..2a492087 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,12 +208,9 @@ class UITask : public AbstractUITask { void enqueueKey(char c); bool dequeueKey(char& c); - // Optional M5Stack CardKB (I2C keyboard, addr 0x5F) on the Grove/Wire1 bus - // -- reuses ENV_PIN_SDA/ENV_PIN_SCL (already brought up for - // EnvironmentSensorManager) as the "this board has a second I2C bus" gate, - // rather than a new board-specific pin define. No-op entirely on boards - // without that bus, or when nothing ACKs 0x5F at boot. -#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL) + // 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 // same byte for as long as the physical key is held, not just once. Track diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 90cb475f..83b591b8 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -176,4 +176,46 @@ lib_deps = [env:ProMicro_kiss_modem] extends = Promicro build_src_filter = ${Promicro.build_src_filter} - +<../examples/kiss_modem/> \ No newline at end of file + +<../examples/kiss_modem/> +; ============================================================ +; 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 (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 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D BLE_PIN_CODE=123456 + -D DUAL_SERIAL=1 + -D OFFLINE_QUEUE_SIZE=256 + -D DISPLAY_CLASS=SSD1306Display + -D FIRMWARE_SOLO_BUILD=1 + -D UI_SENSORS_PAGE=1 + -D ENABLE_SCREENSHOT + -Os + ; 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} + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${Promicro.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0