From 539271f293cd01085633d5cdd878952abcac2e11 Mon Sep 17 00:00:00 2001 From: sim1988son Date: Thu, 15 Oct 2026 20:39:48 +0200 Subject: [PATCH 1/2] Add Simpson board support --- examples/companion_radio/ui-new/HomeScreen.h | 10 ++ .../companion_radio/ui-new/KeyboardWidget.h | 67 +++++++-- examples/companion_radio/ui-new/UITask.cpp | 135 ++++++++++++++++++ examples/companion_radio/ui-new/UITask.h | 14 ++ solo/simpson/platformio.ini | 27 ++++ src/helpers/ui/SH1106Display.cpp | 3 + variants/promicro/PromicroBoard.h | 4 +- variants/promicro/target.h | 7 +- variants/simpson/SimpsonKeypad.cpp | 70 +++++++++ variants/simpson/SimpsonKeypad.h | 49 +++++++ variants/simpson/platformio.ini | 21 +++ variants/simpson/variant.cpp | 9 ++ variants/simpson/variant.h | 62 ++++++++ 13 files changed, 466 insertions(+), 12 deletions(-) create mode 100644 solo/simpson/platformio.ini create mode 100644 variants/simpson/SimpsonKeypad.cpp create mode 100644 variants/simpson/SimpsonKeypad.h create mode 100644 variants/simpson/platformio.ini create mode 100644 variants/simpson/variant.cpp create mode 100644 variants/simpson/variant.h diff --git a/examples/companion_radio/ui-new/HomeScreen.h b/examples/companion_radio/ui-new/HomeScreen.h index af9f268f..acc76b3a 100644 --- a/examples/companion_radio/ui-new/HomeScreen.h +++ b/examples/companion_radio/ui-new/HomeScreen.h @@ -670,6 +670,16 @@ public: : _task(task), _rtc(rtc), _sensors(sensors), _node_prefs(node_prefs), _page(0), _prev_page(0), _shutdown_init(false), sensors_lpp(200) { } + void showBluetoothPage() { + _page = BLUETOOTH; + _quick_sel = 0; + } + + void showGpsPage() { + _page = STATUS; + _quick_sel = 0; + } + // Flips home screen between LOCK page and the page that was showing before locking void setLocked(bool locked) { if (locked) { diff --git a/examples/companion_radio/ui-new/KeyboardWidget.h b/examples/companion_radio/ui-new/KeyboardWidget.h index 220c7523..acdd1329 100644 --- a/examples/companion_radio/ui-new/KeyboardWidget.h +++ b/examples/companion_radio/ui-new/KeyboardWidget.h @@ -291,6 +291,9 @@ struct KeyboardWidget { // next letter, then reverts) — Hold-Enter on Shift toggles caps_lock, which // keeps it on for a whole run of capitals instead. bool caps_lock = false; + bool _physical_t9_input = false; + const char* input_mode_hint = nullptr; + bool hide_keyboard_grid = false; // Set by render() every time it's actually called; UITask clears it before // curr->render() each frame (beginFrame()) so it reflects only "was the // keyboard the thing on screen this frame" -- lets the alert overlay (new @@ -355,6 +358,16 @@ struct KeyboardWidget { // the #@/abc key's existing cycle (case 4 below) reaches it for free. int totalPages() const { return hasAltAlphabet() ? 3 : 2; } bool pageIsSymbols(int pg) const { return pg == totalPages() - 1; } + void openSymbolsPage() { + if (!_visible || isPin() || _ph_menu.active || cursor_mode || accent_active) return; + page = totalPages() - 1; + t9_cell = -1; + } + + void backspaceTyped() { + if (_visible) handleInput(0x08); + } + // Which script (Latin/Cyrillic/Greek) the given non-symbols page shows. uint8_t scriptAt(int pg) const { return pg == 0 ? mainScript() : altScript(); } @@ -492,6 +505,29 @@ struct KeyboardWidget { insertGlyph(one, false); } +#if defined(SIMPSON) + void typePhysicalT9Cell(int cell, bool uppercase) { + if (!_visible || isPin() || cell < 0 || cell >= KB_T9_ROWS * KB_T9_COLS || + _ph_menu.active || cursor_mode || accent_active) return; + + const int saved_row = row; + const int saved_col = col; + const int saved_page = page; + const bool saved_caps = caps; + row = cell / KB_T9_COLS; + col = cell % KB_T9_COLS; + page = 0; + caps = uppercase; + _physical_t9_input = true; + handleInput(KEY_ENTER); + _physical_t9_input = false; + row = saved_row; + col = saved_col; + page = saved_page; + caps = saved_caps; + } +#endif + void clearPlaceholders() { _ph_count = 0; } void addPlaceholder(const char* ph) { @@ -604,7 +640,8 @@ struct KeyboardWidget { // lines, so the preview keeps the same height whichever mode is on. // A tall screen (the 4.2" panel: 20 lines) gives the keys half a line more each. const int key_lh = display.height() >= 18 * lh ? lh * 3 / 2 : lh; - const int kb_h = compact_ui ? (KB_T9_ROWS + 1) * lh : (rows + 1) * key_lh; + const bool hide_grid = hide_keyboard_grid && !isPin(); + const int kb_h = hide_grid ? lh : (compact_ui ? (KB_T9_ROWS + 1) * lh : (rows + 1) * key_lh); const int preview_h = display.height() - kb_h - display.sepH(); const int prev_lines = (preview_h / lh) > 1 ? (preview_h / lh) : 1; const int sep_y = prev_lines * lh; @@ -794,13 +831,21 @@ struct KeyboardWidget { // submit -- so they get no hint of their own). Physical buttons (if used // instead of/alongside CardKB) still drive row/col/page as normal; it // just won't be visible on this screen which cell is selected. - if (compact_ui) { - display.setColor(UIColor::primary_txt); - if (cursor_mode) { - display.drawTextCentered(display.width() / 2, chars_y, "<> char ^v word"); - } else { - display.drawTextCentered(display.width() / 2, chars_y, "Tab: placeholders"); - display.drawTextCentered(display.width() / 2, chars_y + lh, "Fn+letter: accent"); + if (compact_ui || hide_grid) { + if (!hide_grid) { + display.setColor(UIColor::primary_txt); + if (cursor_mode) { + display.drawTextCentered(display.width() / 2, chars_y, "<> char ^v word"); + } else { + display.drawTextCentered(display.width() / 2, chars_y, "Tab: placeholders"); + display.drawTextCentered(display.width() / 2, chars_y + lh, "Fn+letter: accent"); + } + } else if (input_mode_hint) { + char hint[40]; + snprintf(hint, sizeof(hint), "FN: %s", input_mode_hint); + display.setColor(UIColor::primary_txt); + display.setCursor(display.width() - display.getTextWidth(hint) - 2, display.height() - lh); + display.print(hint); } } else { // character grid @@ -1228,7 +1273,11 @@ struct KeyboardWidget { // the special row's DONE cell -- same as a physical button. CardKB's // own Enter is only ever KEY_ENTER when that's true (see pollCardKB()'s // KEY_KB_ENTER cases just above), so there's no ambiguity here. - if (row < rows && isT9()) { + if (row < rows && isT9() +#if defined(SIMPSON) + && !_physical_t9_input +#endif + ) { int cell = row * cols + col; const char* group = t9GroupStr(cell); int glen = kbUtf8Len(group); // codepoint count, not byte length diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 62e16dc4..78da273e 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -11,6 +11,9 @@ #include "target.h" #include "CardKB.h" +#if defined(SIMPSON) + #include +#endif #ifdef WIFI_SSID #include #endif @@ -120,6 +123,13 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no _sensors = sensors; _node_prefs = node_prefs; _kb.prefs = node_prefs; +#if defined(SIMPSON) + if (!_simpson_keypad.begin()) { + MESH_DEBUG_PRINTLN("Simpson keypad initialization failed"); + } + _kb.input_mode_hint = "Ctl"; + _kb.hide_keyboard_grid = true; +#endif if (node_prefs) battery::useCurve(node_prefs->batt_curve_mv); // Settings > Battery curve uint32_t aoff = autoOffMillis(); _auto_off = millis() + (aoff > 0 ? aoff : AUTO_OFF_MILLIS); @@ -402,6 +412,20 @@ void UITask::gotoMessagesScreen() { setCurrScreen(messages_screen); } +#if defined(SIMPSON) +void UITask::gotoBluetoothHomePage() { + setCurrScreen(home); + static_cast(home)->showBluetoothPage(); + _next_refresh = 0; +} + +void UITask::gotoGpsHomePage() { + setCurrScreen(home); + static_cast(home)->showGpsPage(); + _next_refresh = 0; +} +#endif + #ifdef SIM_PLATFORM void UITask::simMessage(const char* text) { UiEvent ev = {}; @@ -1066,6 +1090,114 @@ void UITask::pollHallSensor() { #endif } +#if defined(SIMPSON) +void UITask::pollSimpsonKeypad() { + const uint8_t key = _simpson_keypad.poll(); + if (key != SIMPSON_KEY_NONE) handleSimpsonKeypadKey(key); +} + +void UITask::handleSimpsonKeypadKey(uint8_t key) { + if (checkDisplayOn(KEY_ENTER) == 0 || (_locked && !_unlock_kb)) return; + + const uint32_t auto_off = autoOffMillis(); + if (auto_off > 0) _auto_off = millis() + auto_off; + + if (key == SIMPSON_KEY_MODE_CHANGED) { + static const char* const modes[] = { "Ctl", "abc", "ABC", "123" }; + _kb.input_mode_hint = modes[_simpson_keypad.mode()]; + _kb.hide_keyboard_grid = true; + showAlert(modes[_simpson_keypad.mode()], 1200); + _next_refresh = 0; + return; + } + + switch (key) { + case SIMPSON_KEY_CANCEL: + enqueueKey(KEY_CANCEL); + break; + case SIMPSON_KEY_UP: + enqueueKey(KEY_UP); + break; + case SIMPSON_KEY_DOWN: + enqueueKey(KEY_DOWN); + break; + case SIMPSON_KEY_LEFT: + enqueueKey(KEY_LEFT); + break; + case SIMPSON_KEY_RIGHT: + enqueueKey(KEY_RIGHT); + break; + case SIMPSON_KEY_ENTER: + enqueueKey(_unlock_kb ? KEY_KB_ENTER : KEY_ENTER); + break; + case SIMPSON_KEY_BLUETOOTH: + if (!_unlock_kb) gotoBluetoothHomePage(); + break; + case SIMPSON_KEY_GPS: + if (!_unlock_kb) gotoGpsHomePage(); + break; + case SIMPSON_KEY_MESSAGES: + if (!_unlock_kb) gotoMessagesScreen(); + break; + case SIMPSON_KEY_BRIGHTNESS_UP: + case SIMPSON_KEY_BRIGHTNESS_DOWN: + if (!_unlock_kb && _node_prefs) { + uint8_t& brightness = _node_prefs->display_brightness; + if (key == SIMPSON_KEY_BRIGHTNESS_UP && brightness < 4) ++brightness; + if (key == SIMPSON_KEY_BRIGHTNESS_DOWN && brightness > 0) --brightness; + applyBrightness(); + bool dirty = true; + savePrefsIfDirty(dirty); + } + break; + case SIMPSON_KEY_SYMBOLS: + if (_unlock_kb) break; + if (_kb.isVisible()) _kb.openSymbolsPage(); + else showAlert("Open a text field first", 1200); + break; + case SIMPSON_KEY_BACKSPACE: + if (_kb.isVisible()) { + if (_unlock_kb) handleUnlockKey(0x08); + else _kb.backspaceTyped(); + } else { + enqueueKey(KEY_CANCEL); + } + break; + default: + if (_kb.isVisible()) { + const auto typeInput = [this](char c) { + if (_unlock_kb) handleUnlockKey(c); + else _kb.handleInput(c); + }; + switch (_simpson_keypad.mode()) { + case SIMPSON_KEYPAD_ABC: + case SIMPSON_KEYPAD_ABC_UPPER: + if (key == ',') { + _kb.typePhysicalT9Cell(0, _simpson_keypad.mode() == SIMPSON_KEYPAD_ABC_UPPER); + } else { + static const char t9_keys[] = "ADGJMPTW"; + const char* found = strchr(t9_keys, (char)key); + if (found) { + _kb.typePhysicalT9Cell((int)(found - t9_keys) + 1, + _simpson_keypad.mode() == SIMPSON_KEYPAD_ABC_UPPER); + } else if (key == ' ') { + typeInput(' '); + } + } + break; + case SIMPSON_KEYPAD_NUMERIC: + if (key >= '0' && key <= '9') typeInput((char)key); + break; + case SIMPSON_KEYPAD_CONTROL: + break; + } + } + break; + } + _next_refresh = 0; +} +#endif + #include "PerfL1.h" void UITask::loop() { @@ -1293,6 +1425,9 @@ void UITask::loop() { } #endif pollCardKB(); +#if defined(SIMPSON) + pollSimpsonKeypad(); +#endif pollHallSensor(); #ifdef ENV_USE_TCA8418 { diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index ba4d5143..5e3ed06b 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -8,6 +8,9 @@ #include #include #include +#if defined(SIMPSON) + #include +#endif #ifndef LED_STATE_ON #define LED_STATE_ON 1 @@ -80,6 +83,9 @@ class UITask : public UITaskBase, public UiCoreHost { // each) + NUL = 372B, rounded up with margin. char _bot_buzz_buf[400]; KeyboardWidget _kb; // shared across all screens — only one active at a time +#if defined(SIMPSON) + SimpsonKeypad _simpson_keypad; +#endif unsigned long _alert_expiry; unsigned long _alert_t0 = 0; // when the banner began to come down // Settings > Message alert Compact: the alert is an envelope and a count @@ -231,6 +237,10 @@ private: #endif #endif void pollCardKB(); +#if defined(SIMPSON) + void pollSimpsonKeypad(); + void handleSimpsonKeypadKey(uint8_t key); +#endif void handleCardKBByte(uint8_t raw); void setCardKBBackground(bool on); // no-op without CardKB / the poll task void startCardKBCapture(); // end of begin(): start the poll task @@ -306,6 +316,10 @@ public: void gotoHomeScreen() { setCurrScreen(home); } void gotoSettingsScreen(); void gotoMessagesScreen(); +#if defined(SIMPSON) + void gotoBluetoothHomePage(); + void gotoGpsHomePage(); +#endif #ifdef SIM_PLATFORM void simCompose(const char* text); // sim tests: a channel post's keyboard holding `text` void simMessage(const char* text); // sim tests: a channel message arrives diff --git a/solo/simpson/platformio.ini b/solo/simpson/platformio.ini new file mode 100644 index 00000000..5cff30fe --- /dev/null +++ b/solo/simpson/platformio.ini @@ -0,0 +1,27 @@ +[env:Simpson_companion_solo] +extends = Simpson +board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld +board_upload.maximum_size = 712704 +build_unflags = -Ofast -D OFFLINE_QUEUE_SIZE=256 +build_flags = ${Simpson.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=128 + -D DISPLAY_CLASS=SH1106Display + -D FIRMWARE_SOLO_BUILD=1 + -D UI_SENSORS_PAGE=1 + -Os +build_src_filter = ${Simpson.build_src_filter} + + + + + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = ${Simpson.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 diff --git a/src/helpers/ui/SH1106Display.cpp b/src/helpers/ui/SH1106Display.cpp index 1824fdb9..5407320b 100644 --- a/src/helpers/ui/SH1106Display.cpp +++ b/src/helpers/ui/SH1106Display.cpp @@ -40,6 +40,9 @@ bool SH1106Display::begin() // spi_dev NULL, and UITask::begin() calls turnOn() regardless of our // return value, which then dereferences the null spi_dev. bool ok = display.begin(addr ? addr : DISPLAY_ADDRESS, true); +#ifdef DISPLAY_ROTATION + display.setRotation(DISPLAY_ROTATION); +#endif return addr != 0 && ok; } diff --git a/variants/promicro/PromicroBoard.h b/variants/promicro/PromicroBoard.h index ee16c965..8b137599 100644 --- a/variants/promicro/PromicroBoard.h +++ b/variants/promicro/PromicroBoard.h @@ -5,7 +5,9 @@ #include #define PIN_VBAT_READ 17 -#define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking +#ifndef ADC_MULTIPLIER + #define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking +#endif class PromicroBoard : public NRF52BoardDCDC { protected: diff --git a/variants/promicro/target.h b/variants/promicro/target.h index e577ab4e..bb189b80 100644 --- a/variants/promicro/target.h +++ b/variants/promicro/target.h @@ -7,7 +7,11 @@ #include #include #ifdef DISPLAY_CLASS - #include + #if defined(SIMPSON) + #include + #else + #include + #endif #include #endif @@ -25,4 +29,3 @@ extern EnvironmentSensorManager sensors; bool radio_init(); mesh::LocalIdentity radio_new_identity(); - diff --git a/variants/simpson/SimpsonKeypad.cpp b/variants/simpson/SimpsonKeypad.cpp new file mode 100644 index 00000000..f1486ea3 --- /dev/null +++ b/variants/simpson/SimpsonKeypad.cpp @@ -0,0 +1,70 @@ +#include "SimpsonKeypad.h" + +#include + +namespace { +char control_keymap[19] = { + SIMPSON_KEY_CANCEL, SIMPSON_KEY_UP, 0, SIMPSON_KEY_BLUETOOTH, + SIMPSON_KEY_LEFT, SIMPSON_KEY_ENTER, SIMPSON_KEY_RIGHT, SIMPSON_KEY_BRIGHTNESS_UP, + SIMPSON_KEY_SYMBOLS, SIMPSON_KEY_DOWN, 0, SIMPSON_KEY_BRIGHTNESS_DOWN, + SIMPSON_KEY_MESSAGES, 0, SIMPSON_KEY_FN, SIMPSON_KEY_GPS, 0, 0, 0 +}; + +char alphabet_keymap[19] = { + ',', 'A', 'D', SIMPSON_KEY_BLUETOOTH, + 'G', 'J', 'M', SIMPSON_KEY_BRIGHTNESS_UP, + 'P', 'T', 'W', SIMPSON_KEY_BRIGHTNESS_DOWN, + SIMPSON_KEY_BACKSPACE, ' ', SIMPSON_KEY_FN, SIMPSON_KEY_GPS, 0, 0, 0 +}; + +char numeric_keymap[19] = { + '1', '2', '3', SIMPSON_KEY_BLUETOOTH, + '4', '5', '6', SIMPSON_KEY_BRIGHTNESS_UP, + '7', '8', '9', SIMPSON_KEY_BRIGHTNESS_DOWN, + SIMPSON_KEY_BACKSPACE, '0', SIMPSON_KEY_FN, SIMPSON_KEY_GPS, 0, 0, 0 +}; +} + +bool SimpsonKeypad::begin() { + if (!_keypad.begin()) return false; + _keypad.setKeyPadMode(I2C_KEYPAD_4x4); + _keypad.setDebounceThreshold(50); + loadModeMap(); + _ready = true; + return true; +} + +void SimpsonKeypad::loadModeMap() { + switch (_mode) { + case SIMPSON_KEYPAD_CONTROL: + _keypad.loadKeyMap(control_keymap); + break; + case SIMPSON_KEYPAD_ABC: + case SIMPSON_KEYPAD_ABC_UPPER: + _keypad.loadKeyMap(alphabet_keymap); + break; + case SIMPSON_KEYPAD_NUMERIC: + _keypad.loadKeyMap(numeric_keymap); + break; + } +} + +uint8_t SimpsonKeypad::poll() { + if (!_ready) return SIMPSON_KEY_NONE; + + uint8_t key = _keypad.getChar(); + if (key == I2C_KEYPAD_THRESHOLD) return SIMPSON_KEY_NONE; + if (key == SIMPSON_KEY_NONE) { + _last_key = SIMPSON_KEY_NONE; + return SIMPSON_KEY_NONE; + } + if (key == _last_key) return SIMPSON_KEY_NONE; + _last_key = key; + + if (key == SIMPSON_KEY_FN) { + _mode = static_cast((_mode + 1) % 4); + loadModeMap(); + return SIMPSON_KEY_MODE_CHANGED; + } + return key; +} diff --git a/variants/simpson/SimpsonKeypad.h b/variants/simpson/SimpsonKeypad.h new file mode 100644 index 00000000..5fb5e2d5 --- /dev/null +++ b/variants/simpson/SimpsonKeypad.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#ifndef SIMPSON_KEYPAD_ADDR + #define SIMPSON_KEYPAD_ADDR 0x20 +#endif + +enum SimpsonKeypadMode : uint8_t { + SIMPSON_KEYPAD_CONTROL, + SIMPSON_KEYPAD_ABC, + SIMPSON_KEYPAD_ABC_UPPER, + SIMPSON_KEYPAD_NUMERIC +}; + +enum SimpsonKeypadKey : uint8_t { + SIMPSON_KEY_NONE = 0, + SIMPSON_KEY_CANCEL = 1, + SIMPSON_KEY_UP, + SIMPSON_KEY_BLUETOOTH, + SIMPSON_KEY_LEFT, + SIMPSON_KEY_ENTER, + SIMPSON_KEY_RIGHT, + SIMPSON_KEY_BRIGHTNESS_UP, + SIMPSON_KEY_SYMBOLS, + SIMPSON_KEY_DOWN, + SIMPSON_KEY_BRIGHTNESS_DOWN, + SIMPSON_KEY_MESSAGES, + SIMPSON_KEY_FN, + SIMPSON_KEY_GPS, + SIMPSON_KEY_BACKSPACE, + SIMPSON_KEY_MODE_CHANGED +}; + +class SimpsonKeypad { + I2CKeyPad _keypad; + SimpsonKeypadMode _mode = SIMPSON_KEYPAD_CONTROL; + uint8_t _last_key = SIMPSON_KEY_NONE; + bool _ready = false; + + void loadModeMap(); + +public: + SimpsonKeypad() : _keypad(SIMPSON_KEYPAD_ADDR, &Wire) {} + bool begin(); + uint8_t poll(); + SimpsonKeypadMode mode() const { return _mode; } +}; diff --git a/variants/simpson/platformio.ini b/variants/simpson/platformio.ini new file mode 100644 index 00000000..b86b1d96 --- /dev/null +++ b/variants/simpson/platformio.ini @@ -0,0 +1,21 @@ +[Simpson] +extends = Promicro +build_unflags = -D PIN_GPS_RX=3 -D PIN_GPS_TX=4 -D ENV_INCLUDE_AHTX0=1 -D ENV_INCLUDE_BME280=1 -D ENV_INCLUDE_BMP280=1 -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 -D ENV_INCLUDE_INA226=1 +build_flags = ${Promicro.build_flags} + -I variants/simpson + -D SIMPSON + -D PIN_GPS_TX=3 + -D PIN_GPS_RX=4 + -D PIN_VIBRATION=1 + -D ADC_MULTIPLIER=1.71 + -D SIMPSON_KEYPAD_ADDR=0x20 + -D DISPLAY_ROTATION=2 + -D ENV_SKIP_GPS_DETECT +build_src_filter = ${nrf52_base.build_src_filter} + + + +<../variants/simpson> + +<../variants/promicro/target.cpp> + +<../variants/promicro/PromicroBoard.cpp> +lib_deps = ${Promicro.lib_deps} + adafruit/Adafruit SH110X @ ^2.1.13 + RobTillaart/I2CKeyPad @ ^0.5.2 diff --git a/variants/simpson/variant.cpp b/variants/simpson/variant.cpp new file mode 100644 index 00000000..2f96e662 --- /dev/null +++ b/variants/simpson/variant.cpp @@ -0,0 +1,9 @@ +#include "variant.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + 8, 6, 17, 20, 22, 24, 32, 11, 36, 38, 9, 10, 43, 45, 47, 2, 29, 31, 33, 34, 37, 13, 15 +}; + +void initVariant() {} diff --git a/variants/simpson/variant.h b/variants/simpson/variant.h new file mode 100644 index 00000000..4ad67242 --- /dev/null +++ b/variants/simpson/variant.h @@ -0,0 +1,62 @@ +/* + * Simpson variant for the Pro Micro nRF52840 carrier used by this device. + * Arduino pin indices map to physical nRF52840 GPIOs in variant.cpp. + */ +#pragma once + +#include "WVariant.h" + +#define VARIANT_MCK (64000000ul) +#define USE_LFRC + +#define PIN_EXT_VCC (21) +#define EXT_VCC PIN_EXT_VCC + +#define BATTERY_PIN (17) +#define ADC_RESOLUTION 12 + +#define PINS_COUNT (23) +#define NUM_DIGITAL_PINS (23) +#define NUM_ANALOG_INPUTS (1) +#define NUM_ANALOG_OUTPUTS (0) + +#define PIN_SERIAL1_TX (4) +#define PIN_SERIAL1_RX (3) + +#define WIRE_INTERFACES_COUNT 1 +#define PIN_WIRE_SDA (8) +#define PIN_WIRE_SCL (7) + +#define SPI_INTERFACES_COUNT 1 +#define PIN_SPI_SCK (12) +#define PIN_SPI_MISO (15) +#define PIN_SPI_MOSI (14) +#define PIN_SPI_NSS (13) + +#define PIN_LED (22) +#define LED_PIN PIN_LED +#define LED_BLUE PIN_LED +#define LED_BUILTIN PIN_LED +#define LED_STATE_ON 1 + +#define PIN_BUTTON1 (6) +#define BUTTON_PIN PIN_BUTTON1 + +#define PIN_BUZZER (0) +#ifndef PIN_VIBRATION + #define PIN_VIBRATION (1) +#endif +#define PIN_GPS_EN (5) + +#define P_LORA_NSS (13) +#define P_LORA_DIO_1 (11) +#define P_LORA_RESET (10) +#define P_LORA_BUSY (16) +#define P_LORA_MISO (15) +#define P_LORA_SCLK (12) +#define P_LORA_MOSI (14) +#define SX126X_POWER_EN (21) +#define SX126X_RXEN (2) +#define SX126X_TXEN (-1) +#define SX126X_DIO2_AS_RF_SWITCH true +#define SX126X_DIO3_TCXO_VOLTAGE (1.8f) From ebada411f7991edc74979f3e560ee89129dbe2e7 Mon Sep 17 00:00:00 2001 From: sim1988son Date: Thu, 15 Oct 2026 22:09:25 +0200 Subject: [PATCH 2/2] Fix Simpson keypad T9 and buzzer settings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- examples/companion_radio/ui-new/KeyboardWidget.h | 8 ++------ variants/simpson/platformio.ini | 1 + variants/simpson/variant.h | 4 +++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/companion_radio/ui-new/KeyboardWidget.h b/examples/companion_radio/ui-new/KeyboardWidget.h index acdd1329..0ba898ad 100644 --- a/examples/companion_radio/ui-new/KeyboardWidget.h +++ b/examples/companion_radio/ui-new/KeyboardWidget.h @@ -325,7 +325,7 @@ struct KeyboardWidget { // that construct a KeyboardWidget standalone, in which case isT9() defaults // to ABC and mainScript()/altScript() default to Latin-only. NodePrefs* prefs = nullptr; - bool isT9() const { return prefs && prefs->keyboard_type == 1; } + bool isT9() const { return _physical_t9_input || (prefs && prefs->keyboard_type == 1); } bool isPin() const { return pin_mode; } // Which script occupies page 0 (the keyboard's default/opening page) and // which occupies page 1 (reached by the #@/abc cycle key) -- Settings > @@ -1273,11 +1273,7 @@ struct KeyboardWidget { // the special row's DONE cell -- same as a physical button. CardKB's // own Enter is only ever KEY_ENTER when that's true (see pollCardKB()'s // KEY_KB_ENTER cases just above), so there's no ambiguity here. - if (row < rows && isT9() -#if defined(SIMPSON) - && !_physical_t9_input -#endif - ) { + if (row < rows && isT9()) { int cell = row * cols + col; const char* group = t9GroupStr(cell); int glen = kbUtf8Len(group); // codepoint count, not byte length diff --git a/variants/simpson/platformio.ini b/variants/simpson/platformio.ini index b86b1d96..8ecd4ea1 100644 --- a/variants/simpson/platformio.ini +++ b/variants/simpson/platformio.ini @@ -4,6 +4,7 @@ build_unflags = -D PIN_GPS_RX=3 -D PIN_GPS_TX=4 -D ENV_INCLUDE_AHTX0=1 -D ENV_IN build_flags = ${Promicro.build_flags} -I variants/simpson -D SIMPSON + -D PIN_BUZZER=0 -D PIN_GPS_TX=3 -D PIN_GPS_RX=4 -D PIN_VIBRATION=1 diff --git a/variants/simpson/variant.h b/variants/simpson/variant.h index 4ad67242..f9462f78 100644 --- a/variants/simpson/variant.h +++ b/variants/simpson/variant.h @@ -42,7 +42,9 @@ #define PIN_BUTTON1 (6) #define BUTTON_PIN PIN_BUTTON1 -#define PIN_BUZZER (0) +#ifndef PIN_BUZZER + #define PIN_BUZZER (0) +#endif #ifndef PIN_VIBRATION #define PIN_VIBRATION (1) #endif