Skip to content

Commit 44d5676

Browse files
committed
lower EN04 and EN05 slep/idle current
1 parent d7045d1 commit 44d5676

5 files changed

Lines changed: 182 additions & 70 deletions

File tree

‎src/config_parser.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ void printConfigSummary(){
573573
writeSerial("Battery Sense Pin: " + String(globalConfig.power_option.battery_sense_pin));
574574
writeSerial("Battery Sense Enable Pin: " + String(globalConfig.power_option.battery_sense_enable_pin));
575575
writeSerial("Battery Sense Flags: 0x" + String(globalConfig.power_option.battery_sense_flags, HEX));
576+
writeSerial(" ENABLE_INVERTED: " + String((globalConfig.power_option.battery_sense_flags & BATTERY_SENSE_FLAG_ENABLE_INVERTED) ? "yes" : "no"));
576577
writeSerial("Capacity Estimator: " + String(globalConfig.power_option.capacity_estimator));
577578
writeSerial("Voltage Scaling Factor: " + String(globalConfig.power_option.voltage_scaling_factor));
578579
writeSerial("Deep Sleep Current: " + String(globalConfig.power_option.deep_sleep_current_ua) + " uA");

‎src/display_service.cpp‎

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ extern "C" {
2121
#include "nrf_soc.h"
2222
}
2323
#include <bluefruit.h>
24+
#include "nrf.h"
25+
#include "nrf_gpio.h"
2426
#endif
2527

2628
#ifdef TARGET_ESP32
@@ -101,6 +103,58 @@ void bbepWriteData(BBEPDISP *pBBEP, uint8_t *pData, int iLen);
101103
void bbepFill(BBEPDISP *pBBEP, unsigned char ucColor, int iPlane);
102104
bool bbepIsBusy(BBEPDISP *pBBEP);
103105
void flashLed(uint8_t color, uint8_t brightness);
106+
bool waitforrefresh(int timeout);
107+
108+
#ifdef TARGET_NRF
109+
static bool nrfVbusPresent() {
110+
return (NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk) != 0;
111+
}
112+
#else
113+
static bool nrfVbusPresent() { return true; }
114+
#endif
115+
116+
static void epdBsPinLowIfNrf() {
117+
#ifdef TARGET_NRF
118+
pinMode(13, OUTPUT);
119+
digitalWrite(13, LOW);
120+
#endif
121+
}
122+
123+
// First full refresh on battery needs the panel rail up longer than USB-powered boot.
124+
static void prepareEpdRailForBoot() {
125+
epdBsPinLowIfNrf();
126+
pwrmgm(true);
127+
#ifdef TARGET_NRF
128+
if (!nrfVbusPresent()) {
129+
delay(500);
130+
pwrmgm(false);
131+
delay(150);
132+
epdBsPinLowIfNrf();
133+
pwrmgm(true);
134+
delay(500);
135+
}
136+
#endif
137+
}
138+
139+
static void initBbepPanelSession() {
140+
const DisplayConfig& d = globalConfig.displays[0];
141+
bbepInitIO(&bbep, d.dc_pin, d.reset_pin, d.busy_pin, d.cs_pin, d.data_pin, d.clk_pin, 8000000);
142+
bbepWakeUp(&bbep);
143+
bbepSendCMDSequence(&bbep, bbep.pInitFull);
144+
delay(200);
145+
}
146+
147+
static bool refreshBootScreenFull() {
148+
if (!writeBootScreenWithQr()) {
149+
writeSerial("Boot screen render failed", true);
150+
return false;
151+
}
152+
writeSerial("EPD refresh: FULL (boot)", true);
153+
touchSuspendForEpdRefresh();
154+
bbepRefresh(&bbep, REFRESH_FULL);
155+
return waitforrefresh(60);
156+
}
157+
104158
static void cleanup_partial_write_state(void);
105159
static bool partial_consume_bytes(uint8_t* data, uint32_t len);
106160
static void partial_prepare_panel_ram(void);
@@ -397,10 +451,15 @@ void initio(){
397451
for (uint8_t i = 0; i < globalConfig.led_count; i++) {
398452
if (globalConfig.leds[i].led_type == 0) {
399453
activeLedInstance = i;
400-
flashLed(0xE0, 15);
401-
flashLed(0x1C, 15);
402-
flashLed(0x03, 15);
403-
flashLed(0xFF, 15);
454+
#ifdef TARGET_NRF
455+
if (nrfVbusPresent())
456+
#endif
457+
{
458+
flashLed(0xE0, 15);
459+
flashLed(0x1C, 15);
460+
flashLed(0x03, 15);
461+
flashLed(0xFF, 15);
462+
}
404463
}
405464
}
406465
}
@@ -1000,23 +1059,27 @@ void initDisplay(){
10001059
} else
10011060
#endif
10021061
{
1003-
pwrmgm(true);
1062+
prepareEpdRailForBoot();
10041063
memset(&bbep, 0, sizeof(BBEPDISP));
10051064
int panelType = mapEpd(globalConfig.displays[0].panel_ic_type);
10061065
bbepSetPanelType(&bbep, panelType);
10071066
bbepSetRotation(&bbep, globalConfig.displays[0].rotation * 90);
1008-
bbepInitIO(&bbep, globalConfig.displays[0].dc_pin, globalConfig.displays[0].reset_pin, globalConfig.displays[0].busy_pin, globalConfig.displays[0].cs_pin, globalConfig.displays[0].data_pin, globalConfig.displays[0].clk_pin, 8000000);
10091067
writeSerial(String("Height: ") + String(globalConfig.displays[0].pixel_height), true);
10101068
writeSerial(String("Width: ") + String(globalConfig.displays[0].pixel_width), true);
1011-
bbepWakeUp(&bbep);
1012-
bbepSendCMDSequence(&bbep, bbep.pInitFull);
1013-
delay(200);
1069+
initBbepPanelSession();
10141070
if (! (globalConfig.displays[0].transmission_modes & TRANSMISSION_MODE_CLEAR_ON_BOOT)){
1015-
writeBootScreenWithQr();
1016-
writeSerial("EPD refresh: FULL (boot)", true);
1017-
touchSuspendForEpdRefresh();
1018-
bbepRefresh(&bbep, REFRESH_FULL);
1019-
waitforrefresh(60);
1071+
bool bootOk = refreshBootScreenFull();
1072+
if (!bootOk && !nrfVbusPresent()) {
1073+
writeSerial("Boot refresh failed on battery — re-powering panel and retrying", true);
1074+
pwrmgm(false);
1075+
delay(200);
1076+
prepareEpdRailForBoot();
1077+
initBbepPanelSession();
1078+
bootOk = refreshBootScreenFull();
1079+
}
1080+
if (!bootOk) {
1081+
writeSerial("Boot screen refresh did not complete", true);
1082+
}
10201083
bbepSleep(&bbep, 1);
10211084
delay(200);
10221085
pwrmgm(false);
@@ -1058,10 +1121,15 @@ float readBatteryVoltage() {
10581121
uint8_t sensePin = globalConfig.power_option.battery_sense_pin;
10591122
uint8_t enablePin = globalConfig.power_option.battery_sense_enable_pin;
10601123
uint16_t scalingFactor = globalConfig.power_option.voltage_scaling_factor;
1124+
const bool enableInverted =
1125+
(globalConfig.power_option.battery_sense_flags & BATTERY_SENSE_FLAG_ENABLE_INVERTED) != 0;
1126+
const uint8_t enableLevel = enableInverted ? LOW : HIGH;
1127+
const uint8_t disableLevel = enableInverted ? HIGH : LOW;
1128+
10611129
pinMode(sensePin, INPUT);
10621130
if (enablePin != 0xFF) {
10631131
pinMode(enablePin, OUTPUT);
1064-
digitalWrite(enablePin, HIGH);
1132+
digitalWrite(enablePin, enableLevel);
10651133
delay(10);
10661134
}
10671135
const int numSamples = 10;
@@ -1071,7 +1139,14 @@ float readBatteryVoltage() {
10711139
delay(2);
10721140
}
10731141
uint32_t adcAverage = adcSum / numSamples;
1074-
if (enablePin != 0xFF) digitalWrite(enablePin, LOW);
1142+
if (enablePin != 0xFF) {
1143+
digitalWrite(enablePin, disableLevel);
1144+
}
1145+
if (enableInverted) {
1146+
#ifdef TARGET_NRF
1147+
nrf_gpio_cfg_default(sensePin);
1148+
#endif
1149+
}
10751150
if (scalingFactor > 0) return (adcAverage * scalingFactor) / (100000.0);
10761151
return -1.0;
10771152
}

‎src/main.cpp‎

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,13 @@ void setup() {
5858
writeSerial("Starting setup...");
5959
full_config_init();
6060
initio();
61-
#ifdef TARGET_NRF
62-
// SoftDevice must start before display/SPI; advertising starts after boot screen.
63-
ble_nrf_stack_init();
64-
#endif
6561
initDisplay();
6662
writeSerial("Display initialized");
6763
#ifdef TARGET_ESP32
6864
// Full BLE after display: ESP32 queues commands for loop() until setup returns.
6965
ble_init();
7066
#elif defined(TARGET_NRF)
67+
ble_nrf_stack_init();
7168
ble_nrf_advertising_start();
7269
#endif
7370
#ifdef TARGET_ESP32
@@ -304,6 +301,34 @@ void enterDeepSleep() {
304301
}
305302
#endif
306303

304+
// Panel rail is cut after this — drive control lines LOW; BUSY stays an input.
305+
static void configureDisplayPinsLowPower() {
306+
const DisplayConfig& d = globalConfig.displays[0];
307+
const uint8_t pins[] = {
308+
d.cs_pin, d.clk_pin, d.data_pin, d.dc_pin, d.reset_pin,
309+
};
310+
for (uint8_t pin : pins) {
311+
if (pin == 0xFF) continue;
312+
pinMode(pin, OUTPUT);
313+
digitalWrite(pin, LOW);
314+
}
315+
if (d.busy_pin != 0xFF) {
316+
pinMode(d.busy_pin, INPUT);
317+
}
318+
319+
if (!(globalConfig.system_config.device_flags & DEVICE_FLAG_BATTERY_LATCH)) {
320+
const uint8_t auxPins[] = {
321+
globalConfig.system_config.pwr_pin_2,
322+
globalConfig.system_config.pwr_pin_3,
323+
};
324+
for (uint8_t pin : auxPins) {
325+
if (pin == 0xFF || pin == 0) continue;
326+
pinMode(pin, OUTPUT);
327+
digitalWrite(pin, LOW);
328+
}
329+
}
330+
}
331+
307332
void pwrmgm(bool onoff){
308333
if(globalConfig.display_count == 0){
309334
writeSerial("No display configured");
@@ -340,50 +365,53 @@ void pwrmgm(bool onoff){
340365
#else
341366
const bool seeed_driver_spi = false;
342367
#endif
343-
if (!seeed_driver_spi) {
344-
if(onoff){
345-
pinMode(globalConfig.displays[0].reset_pin, OUTPUT);
346-
pinMode(globalConfig.displays[0].cs_pin, OUTPUT);
347-
if (globalConfig.displays[0].dc_pin != 0xFF) {
348-
pinMode(globalConfig.displays[0].dc_pin, OUTPUT);
349-
}
350-
pinMode(globalConfig.displays[0].clk_pin, OUTPUT);
351-
pinMode(globalConfig.displays[0].data_pin, OUTPUT);
352-
delay(200);
368+
const DisplayConfig& disp = globalConfig.displays[0];
369+
if (onoff) {
370+
if (globalConfig.system_config.pwr_pin != 0xFF) {
371+
digitalWrite(globalConfig.system_config.pwr_pin, HIGH);
372+
delay(800);
373+
} else {
374+
writeSerial("Power pin not set");
353375
}
354-
else{
355-
SPI.end();
356-
Wire.end();
357-
invalidateOpenDisplayWire();
358-
pinMode(globalConfig.displays[0].reset_pin, INPUT);
359-
pinMode(globalConfig.displays[0].cs_pin, INPUT);
360-
if (globalConfig.displays[0].dc_pin != 0xFF) {
361-
pinMode(globalConfig.displays[0].dc_pin, INPUT);
376+
if (!seeed_driver_spi) {
377+
if (disp.reset_pin != 0xFF) {
378+
pinMode(disp.reset_pin, OUTPUT);
379+
digitalWrite(disp.reset_pin, HIGH);
380+
}
381+
if (disp.cs_pin != 0xFF) {
382+
pinMode(disp.cs_pin, OUTPUT);
383+
digitalWrite(disp.cs_pin, HIGH);
384+
}
385+
if (disp.dc_pin != 0xFF) {
386+
pinMode(disp.dc_pin, OUTPUT);
387+
digitalWrite(disp.dc_pin, LOW);
388+
}
389+
if (disp.clk_pin != 0xFF) {
390+
pinMode(disp.clk_pin, OUTPUT);
391+
digitalWrite(disp.clk_pin, LOW);
362392
}
363-
pinMode(globalConfig.displays[0].clk_pin, INPUT);
364-
pinMode(globalConfig.displays[0].data_pin, INPUT);
393+
if (disp.data_pin != 0xFF) {
394+
pinMode(disp.data_pin, OUTPUT);
395+
digitalWrite(disp.data_pin, LOW);
396+
}
397+
if (disp.busy_pin != 0xFF) {
398+
pinMode(disp.busy_pin, INPUT);
399+
}
400+
delay(100);
401+
} else {
402+
delay(200);
365403
}
366404
} else {
367-
if (onoff) {
368-
delay(200);
369-
} else {
405+
if (!seeed_driver_spi) {
370406
SPI.end();
371-
Wire.end();
372-
invalidateOpenDisplayWire();
407+
}
408+
Wire.end();
409+
invalidateOpenDisplayWire();
410+
configureDisplayPinsLowPower();
411+
if (globalConfig.system_config.pwr_pin != 0xFF) {
412+
digitalWrite(globalConfig.system_config.pwr_pin, LOW);
373413
}
374414
}
375-
if(globalConfig.system_config.pwr_pin != 0xFF){
376-
if(onoff){
377-
digitalWrite(globalConfig.system_config.pwr_pin, HIGH);
378-
delay(200);
379-
}
380-
else{
381-
digitalWrite(globalConfig.system_config.pwr_pin, LOW);
382-
}
383-
}
384-
else{
385-
writeSerial("Power pin not set");
386-
}
387415
}
388416

389417
void writeSerial(String message, bool newLine){
@@ -398,15 +426,11 @@ void writeSerial(String message, bool newLine){
398426

399427
void xiaoinit(){
400428
powerDownExternalFlash(20,24,21,25,22,23);
401-
pinMode(31, INPUT);
402-
pinMode(14, INPUT);
429+
//pinMode(31, INPUT);
430+
//pinMode(14, INPUT);
403431
pinMode(13, OUTPUT); //that actually does something
404432
digitalWrite(13, LOW);
405-
pinMode(17, INPUT);
406-
//buttons
407-
pinMode(15, INPUT);
408-
pinMode(3, INPUT);
409-
pinMode(28, INPUT);
433+
//pinMode(17, INPUT);
410434
}
411435

412436
void ws_pp_init(){
@@ -517,12 +541,18 @@ bool powerDownExternalFlash(uint8_t mosiPin, uint8_t misoPin, uint8_t sckPin, ui
517541
jedecIdAfterStr.toUpperCase();
518542
writeSerial("JEDEC ID after: " + jedecIdAfterStr + " (byte[0]=0x" + String(jedecIdAfter[0], HEX) + ", byte[1]=0x" + String(jedecIdAfter[1], HEX) + ", byte[2]=0x" + String(jedecIdAfter[2], HEX) + ")");
519543
}
520-
digitalWrite(csPin, HIGH);
521-
pinMode(wpPin, INPUT);
522-
pinMode(holdPin, INPUT);
523-
pinMode(mosiPin, INPUT);
524-
pinMode(misoPin, INPUT);
525-
pinMode(sckPin, INPUT);
544+
// CS/WP/HOLD are active-low: keep HIGH so the chip stays deselected and in deep sleep.
545+
// CLK/MOSI/MISO LOW — defined idle levels, no floating buffers on the MCU side.
546+
const uint8_t qspiLow[] = { mosiPin, misoPin, sckPin };
547+
for (uint8_t pin : qspiLow) {
548+
pinMode(pin, OUTPUT);
549+
digitalWrite(pin, LOW);
550+
}
551+
const uint8_t qspiHigh[] = { csPin, wpPin, holdPin };
552+
for (uint8_t pin : qspiHigh) {
553+
pinMode(pin, OUTPUT);
554+
digitalWrite(pin, HIGH);
555+
}
526556
#else
527557
writeSerial("External flash power-down not implemented for ESP32");
528558
return false;

‎src/structs.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct PowerOption {
5757
uint8_t reserved[10]; // Reserved bytes for future use
5858
} __attribute__((packed));
5959

60+
// battery_sense_flags (power_option)
61+
#define BATTERY_SENSE_FLAG_ENABLE_INVERTED (1 << 0) // Enable active-low (e.g. XIAO ~READ_BAT on P0.14)
62+
6063
// Panel IDs must match web/firmware/toolbox/config.yaml display.panel_ic_type enum values.
6164
// Decimal 3000–3999 = Seeed_GFX / OpenDisplay runtime epaper (add new IDs here as panels ship).
6265
#define PANEL_IC_SEEED_ED103TC2_1872X1404 3000u

‎src/touch_input.cpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ void touchResumeAfterEpdRefresh(void) {
351351
if (s_epd_refresh_suspend != 0) {
352352
return;
353353
}
354+
if (globalConfig.touch_controller_count == 0) {
355+
return;
356+
}
354357
invalidateOpenDisplayWire();
355358
initOrRestoreWireForOpenDisplay();
356359
delay(GT911_POST_RESET_SETTLE_MS);

0 commit comments

Comments
 (0)