Fix L1 E-Ink InkHUD issues (#10804)

* Fixes

* Update KeyboardApplet.cpp

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
HarukiToreda
2026-06-28 16:27:01 -04:00
committed by GitHub
parent 0baf8b1db6
commit 29b3cfaeca
7 changed files with 245 additions and 15 deletions

View File

@@ -16,6 +16,12 @@ bool usePortraitKeyboardSizing()
InkHUD::KeyboardApplet::KeyboardApplet()
{
for (uint8_t row = 0; row < LEGACY_KBD_ROWS; row++) {
legacyRowWidths[row] = 0;
for (uint8_t col = 0; col < KBD_COLS; col++)
legacyRowWidths[row] += legacyKeyWidths[row * KBD_COLS + col];
}
mode = MODE_TEXT;
lastTypingMode = MODE_TEXT;
emotePage = 0;
@@ -26,6 +32,11 @@ InkHUD::KeyboardApplet::KeyboardApplet()
void InkHUD::KeyboardApplet::onRender(bool full)
{
if (!useTouchKeyboard()) {
renderLegacyKeyboard(full);
return;
}
const bool showSelection = showSelectionHighlight();
if (full) {
@@ -39,6 +50,94 @@ void InkHUD::KeyboardApplet::onRender(bool full)
prevSelectedKey = selectedKey;
}
bool InkHUD::KeyboardApplet::useTouchKeyboard() const
{
return inkhud->hasTouchEnabledProvider();
}
void InkHUD::KeyboardApplet::renderLegacyKeyboard(bool full)
{
uint16_t em = fontSmall.lineHeight();
uint16_t keyH = Y(1.0) / LEGACY_KBD_ROWS;
int16_t keyTopPadding = (keyH - fontSmall.lineHeight()) / 2;
if (full) {
for (uint8_t row = 0; row < LEGACY_KBD_ROWS; row++) {
int16_t keyXPadding = X(1.0) - ((legacyRowWidths[row] * em) >> 4);
uint16_t xPos = 0;
for (uint8_t col = 0; col < KBD_COLS; col++) {
Color fgcolor = BLACK;
uint8_t index = row * KBD_COLS + col;
uint16_t keyX = ((xPos * em) >> 4) + ((col * keyXPadding) / (KBD_COLS - 1));
uint16_t keyY = row * keyH;
uint16_t keyW = (legacyKeyWidths[index] * em) >> 4;
if (index == selectedKey) {
fgcolor = WHITE;
fillRect(keyX, keyY, keyW, keyH, BLACK);
}
drawLegacyKeyLabel(keyX, keyY + keyTopPadding, keyW, legacyKeys[index], fgcolor);
xPos += legacyKeyWidths[index];
}
}
} else if (selectedKey != prevSelectedKey) {
uint8_t row = prevSelectedKey / KBD_COLS;
int16_t keyXPadding = X(1.0) - ((legacyRowWidths[row] * em) >> 4);
uint16_t xPos = 0;
for (uint8_t i = prevSelectedKey - (prevSelectedKey % KBD_COLS); i < prevSelectedKey; i++)
xPos += legacyKeyWidths[i];
uint16_t keyX = ((xPos * em) >> 4) + (((prevSelectedKey % KBD_COLS) * keyXPadding) / (KBD_COLS - 1));
uint16_t keyY = row * keyH;
uint16_t keyW = (legacyKeyWidths[prevSelectedKey] * em) >> 4;
fillRect(keyX, keyY, keyW, keyH, WHITE);
drawLegacyKeyLabel(keyX, keyY + keyTopPadding, keyW, legacyKeys[prevSelectedKey], BLACK);
row = selectedKey / KBD_COLS;
keyXPadding = X(1.0) - ((legacyRowWidths[row] * em) >> 4);
xPos = 0;
for (uint8_t i = selectedKey - (selectedKey % KBD_COLS); i < selectedKey; i++)
xPos += legacyKeyWidths[i];
keyX = ((xPos * em) >> 4) + (((selectedKey % KBD_COLS) * keyXPadding) / (KBD_COLS - 1));
keyY = row * keyH;
keyW = (legacyKeyWidths[selectedKey] * em) >> 4;
fillRect(keyX, keyY, keyW, keyH, BLACK);
drawLegacyKeyLabel(keyX, keyY + keyTopPadding, keyW, legacyKeys[selectedKey], WHITE);
}
prevSelectedKey = selectedKey;
}
void InkHUD::KeyboardApplet::drawLegacyKeyLabel(uint16_t left, uint16_t top, uint16_t width, char key, Color color)
{
if (key == '\b') {
const uint8_t bsBitmap[] = {0x0f, 0xf8, 0x18, 0x08, 0x32, 0x28, 0x61, 0x48, 0xc0,
0x88, 0x61, 0x48, 0x32, 0x28, 0x18, 0x08, 0x0f, 0xf8};
uint16_t leftPadding = (width - 13) >> 1;
drawBitmap(left + leftPadding, top + 1, bsBitmap, 13, 9, color);
} else if (key == '\n') {
const uint8_t doneBitmap[] = {0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x01, 0x80, 0x03,
0x00, 0xc6, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x10, 0x00};
uint16_t leftPadding = (width - 12) >> 1;
drawBitmap(left + leftPadding, top + 1, doneBitmap, 12, 9, color);
} else if (key == ' ') {
const uint8_t spaceBitmap[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x08, 0x80, 0x08, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00};
uint16_t leftPadding = (width - 13) >> 1;
drawBitmap(left + leftPadding, top + 1, spaceBitmap, 13, 9, color);
} else if (key == '\x1b') {
setTextColor(color);
std::string keyText = "ESC";
uint16_t leftPadding = (width - getTextWidth(keyText)) >> 1;
printAt(left + leftPadding, top, keyText);
} else {
setTextColor(color);
if (key >= 0x61)
key -= 32;
std::string keyText = std::string(1, key);
uint16_t leftPadding = (width - getTextWidth(keyText)) >> 1;
printAt(left + leftPadding, top, keyText);
}
}
void InkHUD::KeyboardApplet::drawKey(uint8_t index, bool selected)
{
uint16_t keyX = 0;
@@ -104,14 +203,40 @@ void InkHUD::KeyboardApplet::onBackground()
void InkHUD::KeyboardApplet::onButtonShortPress()
{
if (!useTouchKeyboard()) {
handleLegacyInput(false);
return;
}
inputSelectedKey(false);
}
void InkHUD::KeyboardApplet::onButtonLongPress()
{
if (!useTouchKeyboard()) {
handleLegacyInput(true);
return;
}
inputSelectedKey(true);
}
void InkHUD::KeyboardApplet::handleLegacyInput(bool longPress)
{
char key = legacyKeys[selectedKey];
if (key == '\n') {
inkhud->freeTextDone();
inkhud->closeKeyboard();
} else if (key == '\x1b') {
inkhud->freeTextCancel();
inkhud->closeKeyboard();
} else {
if (longPress && key >= 0x61)
key -= 32;
inkhud->freeText(key);
}
}
void InkHUD::KeyboardApplet::onExitShort()
{
inkhud->freeTextCancel();
@@ -126,6 +251,17 @@ void InkHUD::KeyboardApplet::onExitLong()
void InkHUD::KeyboardApplet::onNavUp()
{
if (!useTouchKeyboard()) {
if (selectedKey < KBD_COLS)
selectedKey += KBD_COLS * (LEGACY_KBD_ROWS - 1);
else
selectedKey -= KBD_COLS;
requestUpdate(EInk::UpdateTypes::FAST, false);
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
return;
}
if (selectedKey < KBD_COLS)
selectedKey += KBD_COLS * (KBD_ROWS - 1);
else
@@ -137,6 +273,14 @@ void InkHUD::KeyboardApplet::onNavUp()
void InkHUD::KeyboardApplet::onNavDown()
{
if (!useTouchKeyboard()) {
selectedKey += KBD_COLS;
selectedKey %= LEGACY_KBD_KEY_COUNT;
requestUpdate(EInk::UpdateTypes::FAST, false);
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
return;
}
selectedKey += KBD_COLS;
selectedKey %= KBD_KEY_COUNT;
normalizeSelection();
@@ -145,6 +289,17 @@ void InkHUD::KeyboardApplet::onNavDown()
void InkHUD::KeyboardApplet::onNavLeft()
{
if (!useTouchKeyboard()) {
if (selectedKey % KBD_COLS == 0)
selectedKey += KBD_COLS - 1;
else
selectedKey--;
requestUpdate(EInk::UpdateTypes::FAST, false);
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
return;
}
if (selectedKey % KBD_COLS == 0)
selectedKey += KBD_COLS - 1;
else
@@ -156,6 +311,17 @@ void InkHUD::KeyboardApplet::onNavLeft()
void InkHUD::KeyboardApplet::onNavRight()
{
if (!useTouchKeyboard()) {
if (selectedKey % KBD_COLS == KBD_COLS - 1)
selectedKey -= KBD_COLS - 1;
else
selectedKey++;
requestUpdate(EInk::UpdateTypes::FAST, false);
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
return;
}
if (selectedKey % KBD_COLS == KBD_COLS - 1)
selectedKey -= KBD_COLS - 1;
else
@@ -418,6 +584,12 @@ bool InkHUD::KeyboardApplet::isKeyEnabledAt(uint8_t index) const
void InkHUD::KeyboardApplet::normalizeSelection()
{
if (!useTouchKeyboard()) {
if (selectedKey >= LEGACY_KBD_KEY_COUNT)
selectedKey = 0;
return;
}
if (selectedKey >= KBD_KEY_COUNT)
selectedKey = 0;
@@ -492,6 +664,10 @@ bool InkHUD::KeyboardApplet::showSelectionHighlight() const
uint16_t InkHUD::KeyboardApplet::getKeyboardHeight()
{
const auto *hud = NicheGraphics::InkHUD::InkHUD::getInstance();
if (!hud || !hud->hasTouchEnabledProvider())
return static_cast<uint16_t>(fontSmall.lineHeight() * 1.2f) * LEGACY_KBD_ROWS;
// Keep touch keys tall and roomy for finger input.
// In portrait orientation we increase row height for larger touch targets.
const uint16_t rowUnit = fontSmall.lineHeight() + 8;

View File

@@ -37,6 +37,11 @@ class KeyboardApplet : public SystemApplet
static uint16_t getKeyboardHeight(); // used to set the keyboard tile height
private:
bool useTouchKeyboard() const;
void renderLegacyKeyboard(bool full);
void handleLegacyInput(bool longPress);
void drawLegacyKeyLabel(uint16_t left, uint16_t top, uint16_t width, char key, Color color);
enum KeyCode : int16_t {
KEY_NONE = -1,
KEY_BACKSPACE = 256,
@@ -69,6 +74,8 @@ class KeyboardApplet : public SystemApplet
bool showSelectionHighlight() const;
static const uint8_t KBD_COLS = 11;
static const uint8_t LEGACY_KBD_ROWS = 4;
static const uint8_t LEGACY_KBD_KEY_COUNT = KBD_COLS * LEGACY_KBD_ROWS;
static const uint8_t KBD_ROWS = 5;
static const uint8_t KBD_KEY_COUNT = KBD_COLS * KBD_ROWS;
static const uint8_t EMOTE_SLOT_COUNT = KBD_COLS * (KBD_ROWS - 1); // top 4 rows
@@ -137,6 +144,22 @@ class KeyboardApplet : public SystemApplet
static constexpr uint8_t KEY_GAP_X = 3;
static constexpr uint8_t KEY_GAP_Y = 4;
static constexpr uint8_t KEY_RADIUS = 4;
const char legacyKeys[LEGACY_KBD_KEY_COUNT] = {
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\b', // row 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '\n', // row 1
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '!', ' ', // row 2
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '?', '\x1b' // row 3
};
const uint16_t legacyKeyWidths[LEGACY_KBD_KEY_COUNT] = {
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, // row 0
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, // row 1
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, // row 2
16, 16, 16, 16, 16, 16, 16, 10, 10, 12, 40 // row 3
};
uint16_t legacyRowWidths[LEGACY_KBD_ROWS];
};
} // namespace NicheGraphics::InkHUD

View File

@@ -22,6 +22,16 @@
#include "wiring_constants.h"
#include "wiring_digital.h"
namespace
{
void configureWakeOnPress(uint8_t digitalPin)
{
const uint32_t gpioPin = g_ADigitalPinMap[digitalPin];
nrf_gpio_cfg_input(gpioPin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(gpioPin, NRF_GPIO_PIN_SENSE_LOW);
}
} // namespace
/**
* @brief Digital pin to GPIO port/pin mapping table
*
@@ -93,4 +103,9 @@ void initVariant()
pinMode(PIN_LED2, OUTPUT);
digitalWrite(PIN_LED2, LOW);
pinMode(PIN_LED2, OUTPUT);
}
}
void variant_shutdown()
{
configureWakeOnPress(CANCEL_BUTTON_PIN);
}

View File

@@ -105,7 +105,9 @@ static const uint8_t SCL = PIN_WIRE_SCL;
// Power Management
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#define BAT_READ 30 // D30 = P0.04 Reads battery voltage from divider on signal board.
#define BAT_READ 30 // D30 = P0.04 Battery divider enable (BAT_CTL) on signal board.
#define ADC_CTRL BAT_READ
#define ADC_CTRL_ENABLED HIGH
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define ADC_MULTIPLIER 2.0
#define BATTERY_PIN PIN_VBAT // PIN_A7
@@ -178,4 +180,4 @@ extern "C" {
}
#endif
#endif // _SEEED_SOLAR_NODE_H_
#endif // _SEEED_TRACKER_L1_H_

View File

@@ -40,19 +40,16 @@ debug_tool = jlink
[env:seeed_wio_tracker_L1_eink-inkhud]
board = seeed_wio_tracker_L1
extends = nrf52840_base, inkhud
extends = env:seeed_wio_tracker_L1_eink, inkhud
build_flags =
${nrf52840_base.build_flags}
${env:seeed_wio_tracker_L1_eink.build_flags}
${inkhud.build_flags}
-I variants/nrf52840/seeed_wio_tracker_L1_eink
-D SEEED_WIO_TRACKER_L1
-D BUTTON_PIN=D13
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
build_src_filter =
${nrf52_base.build_src_filter}
build_src_filter =
${env:seeed_wio_tracker_L1_eink.build_src_filter}
${inkhud.build_src_filter}
+<../variants/nrf52840/seeed_wio_tracker_L1_eink>
lib_deps =
${inkhud.lib_deps} ; Before base libs_deps, so we use ZinggJM/GFXRoot instead of AdafruitGFX (saves space)
${nrf52840_base.lib_deps}
${env:seeed_wio_tracker_L1_eink.lib_deps}
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
debug_tool = jlink

View File

@@ -22,6 +22,16 @@
#include "wiring_constants.h"
#include "wiring_digital.h"
namespace
{
void configureWakeOnPress(uint8_t digitalPin)
{
const uint32_t gpioPin = g_ADigitalPinMap[digitalPin];
nrf_gpio_cfg_input(gpioPin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(gpioPin, NRF_GPIO_PIN_SENSE_LOW);
}
} // namespace
/**
* @brief Digital pin to GPIO port/pin mapping table
*
@@ -100,4 +110,9 @@ void initVariant()
digitalWrite(PIN_LED1, LOW);
pinMode(PIN_LED2, OUTPUT);
digitalWrite(PIN_LED2, LOW);
}
}
void variant_shutdown()
{
configureWakeOnPress(CANCEL_BUTTON_PIN);
}

View File

@@ -113,7 +113,9 @@ static const uint8_t SCL = PIN_WIRE_SCL;
// Power Management
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#define BAT_READ 30 // D30 = P0.04 Reads battery voltage from divider on signal board.
#define BAT_READ 30 // D30 = P0.04 Battery divider enable (BAT_CTL) on signal board.
#define ADC_CTRL BAT_READ
#define ADC_CTRL_ENABLED HIGH
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define ADC_MULTIPLIER 2.0
#define BATTERY_PIN PIN_VBAT // PIN_A7
@@ -189,4 +191,4 @@ extern "C" {
}
#endif
#endif // _SEEED_TRACKER_L1_H_
#endif // _SEEED_TRACKER_L1_H_