mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 02:11:57 +00:00
Add Simpson board support
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "target.h"
|
||||
|
||||
#include "CardKB.h"
|
||||
#if defined(SIMPSON)
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef WIFI_SSID
|
||||
#include <WiFi.h>
|
||||
#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<HomeScreen*>(home)->showBluetoothPage();
|
||||
_next_refresh = 0;
|
||||
}
|
||||
|
||||
void UITask::gotoGpsHomePage() {
|
||||
setCurrScreen(home);
|
||||
static_cast<HomeScreen*>(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
|
||||
{
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <helpers/ContactInfo.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/sensors/LPPDataHelpers.h>
|
||||
#if defined(SIMPSON)
|
||||
#include <SimpsonKeypad.h>
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user