Skip to content

Commit 2519aff

Browse files
committed
fix(x4): assert the battery-MOSFET latch at boot
One X4 hardware revision does not self-latch its battery rail, so it seems unresponsive off USB power. selectDevice(XteinkX4) runs holdPowerRails(), which asserts GPIO13; that is a no-op on units that self-latch through a pull. Matches the fix CrossInk shipped in 1.5.0-rc-2. Deliberately no panel-controller probe on either device. Probing the X4 display bus hung display init (bit-banged GPIO on pins the mounted SD card shares), and calling selectDevice(XteinkX3) before Storage.begin() switched sd.powerEnable to GPIO13 and hung SD mount on X3. X3 keeps ACTIVE on the XTEINK_X4 default until setDisplayX3(), as in every prior release, so its boot path is unchanged from 4.7.1. Adds XteinkDetect to lib_deps, a CRUMBLE_DISABLE_PANEL_PROBE escape hatch and a tiny-bitter-noprobe diagnostic env.
1 parent fc55d4c commit 2519aff

3 files changed

Lines changed: 65 additions & 1 deletion

File tree

lib/hal/HalDisplay.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include <HalDisplay.h>
22
#include <HalGPIO.h>
3+
#include <XteinkDetect.h>
34

45
#include "HalSpiBus.h"
6+
#include "Logging.h"
57

68
// Global HalDisplay instance
79
HalDisplay display;
@@ -20,6 +22,8 @@ void HalDisplay::begin(bool seamless) {
2022
einkDisplay.setDisplayX3();
2123
}
2224

25+
// No panel-controller probe here: bit-banging the display bus at this point
26+
// hung X4 boot (SD shares SCLK/MOSI and is already mounted). See setup().
2327
einkDisplay.begin();
2428

2529
if (seamless) {

platformio.ini

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ crossink_version = 1.3.0
4949
; the stock 6.25 MB slot again (SD-card flash from CrossInk works).
5050
; v4.7.1: Portuguese hyphenation (+ 'pol' ISO mapping), status-bar deghost
5151
; zone sized from layout math, prebake tool-build repair.
52-
crumble_version = 4.7.1
52+
; v4.7.2: freeink-sdk resynced to upstream e6a8048; X4 battery-latch assert
53+
; for the non-self-latching revision; settings deferred-save log
54+
; spam fixed. Newer UC8279/UC8179 panels remain unsupported.
55+
crumble_version = 4.7.2
5356

5457
[base]
5558
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
@@ -280,6 +283,14 @@ lib_deps =
280283
SDCardManager=symlink://freeink-sdk/libs/hardware/SDCardManager
281284
BoardConfig=symlink://freeink-sdk/libs/hardware/BoardConfig
282285
PowerManager=symlink://freeink-sdk/libs/hardware/PowerManager
286+
; CrumBLE 4.7.2: XteinkDetect supplies applyXteinkDisplayController(), the
287+
; bus probe that tells an original X4/X3 (SSD1677 / UC8253) from the newer
288+
; production runs that swapped in an UltraChip UC8179 / UC8279. Without it
289+
; BoardConfig::ACTIVE.displayController never leaves its profile default and
290+
; a new-panel unit picks the wrong driver -> dead display. We keep using our
291+
; own gpio.deviceIsX3() for the X3-vs-X4 split; only the controller probe is
292+
; taken from here.
293+
XteinkDetect=symlink://freeink-sdk/libs/hardware/XteinkDetect
283294
bblanchon/ArduinoJson @ 7.4.2
284295
ricmoo/QRCode @ 0.0.1
285296
bitbank2/PNGdec @ ^1.0.0
@@ -541,3 +552,13 @@ extends = simulator_base
541552
build_flags =
542553
${simulator_base.build_flags}
543554
-DSIMULATOR_DEVICE_X3
555+
556+
; Diagnostic variant of tiny-bitter: identical firmware with the boot-time
557+
; panel-controller probe compiled out, plus DBG logging. Used to bisect whether
558+
; a boot problem comes from the probe or from the freeink-sdk update itself.
559+
; Not a shipping env.
560+
[env:tiny-bitter-noprobe]
561+
extends = env:tiny-bitter
562+
build_flags =
563+
${env:tiny-bitter.build_flags}
564+
-DCRUMBLE_DISABLE_PANEL_PROBE

src/main.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <Arduino.h>
22
#include <BluetoothHIDManager.h>
3+
#include <BoardConfig.h> // CrumBLE 4.7.2: panel-controller profile selection
4+
#include <XteinkDetect.h> // CrumBLE 4.7.2: pre-SD panel-controller probe
35

46
// v18.9.9.245: for BT-off-by-default boot-time memory release. Same header
57
// used by CrossPointWebServerActivity's FT-enter release path.
@@ -2830,6 +2832,43 @@ void setup() {
28302832
gpio.deviceIsX3() ? "X3" : "X4", gpio.isUsbConnected() ? 1 : 0, isSilentReboot ? 1 : 0,
28312833
static_cast<unsigned long>(snapshotTarget));
28322834

2835+
// CrumBLE 4.7.2: resolve which panel controller this unit carries, BEFORE the
2836+
// SD card is mounted. Xteink switched newer X4/X3 runs from SSD1677/UC8253 to
2837+
// the UltraChip UC8179/UC8279 on the same board, so the driver can only be
2838+
// picked by asking the silicon -- but the probe bit-bangs the display pins as
2839+
// raw GPIO, and SD shares SCLK/MOSI on this hardware. Running it after
2840+
// Storage.begin() hung X4 boot (the disturbed card clamps the shared bus and
2841+
// the panel never hears CMD_SOFT_RESET); XteinkDetect.h's contract is to call
2842+
// it before SDCardManager::begin(), which is what this placement honors.
2843+
//
2844+
// The probe reads its pins from BoardConfig::ACTIVE, so the X3/X4 profile has
2845+
// to be chosen first. ACTIVE defaults to XTEINK_X4; point it at the X3 sibling
2846+
// when our own fingerprint says X3, so the promotion lands on UC8253->UC8279
2847+
// rather than SSD1677->UC8179. On a confirmed X3 promotion, switch to the
2848+
// XteinkX3Uc8279 profile: HalDisplay::begin()'s setDisplayX3() re-selects
2849+
// XteinkX3 otherwise, which would reset displayController back to UC8253.
2850+
//
2851+
// Fail-safe: promotion needs two independent passes to both match the UC81xx
2852+
// VER/FLG signature AND agree byte-for-byte. An original SSD1677/UC8253 does
2853+
// not answer register 0x70 at all, so the bus floats, both passes fail, and
2854+
// the profile default stands -- existing units keep today's driver.
2855+
#ifndef CRUMBLE_DISABLE_PANEL_PROBE
2856+
// v4.7.2: assert the X4 battery-MOSFET latch (GPIO13) via holdPowerRails().
2857+
// No-op on self-latching X4s; the revision that doesn't self-latch stays
2858+
// powered only while the button is held without it.
2859+
//
2860+
// X4 only, and nothing here on X3 -- both learned on hardware. Probing the X4
2861+
// display bus hung display init; calling selectDevice(XteinkX3) here switched
2862+
// sd.powerEnable to GPIO13 and hung Storage.begin(). X3 must keep ACTIVE on the
2863+
// XTEINK_X4 default until setDisplayX3(), as every release before this one.
2864+
if (!gpio.deviceIsX3()) {
2865+
BoardConfig::selectDevice(BoardConfig::Board::XteinkX4);
2866+
LOG_INF("DISPLAY", "X4: SSD1677 (default); battery latch asserted");
2867+
} else {
2868+
LOG_INF("DISPLAY", "X3: UC8253 (default); profile deferred to setDisplayX3()");
2869+
}
2870+
#endif
2871+
28332872
// SD Card Initialization
28342873
// We need 6 open files concurrently when parsing a new chapter
28352874
if (!Storage.begin()) {

0 commit comments

Comments
 (0)