Skip to content

Commit 3b21b6f

Browse files
authored
Lower NRF Power consumption
1 parent 6d21d95 commit 3b21b6f

2 files changed

Lines changed: 163 additions & 1 deletion

File tree

src/main.cpp

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#include "main.h"
22

33
void setup() {
4+
#ifndef DISABLE_USB_SERIAL
45
Serial.begin(115200);
56
delay(100);
7+
#endif
68
writeSerial("=== FIRMWARE INFO ===");
79
writeSerial("Firmware Version: " + String(getFirmwareMajor()) + "." + String(getFirmwareMinor()));
810
const char* shaCStr = SHA_STRING;
@@ -612,6 +614,13 @@ void full_config_init(){
612614
if (loadGlobalConfig()) {
613615
writeSerial("Global configuration loaded successfully");
614616
printConfigSummary();
617+
#ifdef TARGET_NRF
618+
if (globalConfig.loaded && (globalConfig.system_config.device_flags & DEVICE_FLAG_XIAOINIT)) {
619+
writeSerial("Device flag DEVICE_FLAG_XIAOINIT is set, calling xiaoinit()...");
620+
xiaoinit();
621+
writeSerial("xiaoinit() completed");
622+
}
623+
#endif
615624
} else {
616625
writeSerial("Global configuration load failed or no config found");
617626
}
@@ -755,8 +764,134 @@ void pwrmgm(bool onoff){
755764
}
756765

757766
void writeSerial(String message, bool newLine){
767+
#ifndef DISABLE_USB_SERIAL
758768
if (newLine == true) Serial.println(message);
759769
else Serial.print(message);
770+
#endif
771+
// When USB is disabled, writeSerial does nothing (no-op) to save power
772+
}
773+
774+
void xiaoinit(){
775+
powerDownExternalFlash(20,24,21,25,22,23);
776+
pinMode(31, INPUT);
777+
pinMode(14, INPUT);
778+
pinMode(13, OUTPUT); //that actually does something
779+
digitalWrite(13, LOW);
780+
pinMode(17, INPUT);
781+
//buttons
782+
pinMode(15, INPUT);
783+
pinMode(3, INPUT);
784+
pinMode(28, INPUT);
785+
}
786+
787+
bool powerDownExternalFlash(uint8_t mosiPin, uint8_t misoPin, uint8_t sckPin, uint8_t csPin, uint8_t wpPin, uint8_t holdPin) {
788+
#ifdef TARGET_NRF
789+
// Software SPI transfer function (bit-banging)
790+
auto spiTransfer = [&](uint8_t data) -> uint8_t {
791+
uint8_t result = 0;
792+
for (int i = 7; i >= 0; i--) {
793+
// Set MOSI to current bit
794+
digitalWrite(mosiPin, (data >> i) & 1);
795+
// Clock low
796+
digitalWrite(sckPin, LOW);
797+
delayMicroseconds(1);
798+
// Read MISO
799+
result |= (digitalRead(misoPin) << i);
800+
// Clock high
801+
digitalWrite(sckPin, HIGH);
802+
delayMicroseconds(1);
803+
}
804+
return result;
805+
};
806+
writeSerial("=== External Flash Power-Down ===");
807+
writeSerial("Pin configuration: MOSI=" + String(mosiPin) + " MISO=" + String(misoPin) + " SCK=" + String(sckPin) + " CS=" + String(csPin) + " WP=" + String(wpPin) + " HOLD=" + String(holdPin));
808+
writeSerial("Configuring SPI pins...");
809+
pinMode(mosiPin, OUTPUT);
810+
pinMode(misoPin, INPUT);
811+
pinMode(sckPin, OUTPUT);
812+
pinMode(csPin, OUTPUT);
813+
pinMode(wpPin, OUTPUT);
814+
pinMode(holdPin, OUTPUT);
815+
writeSerial("SPI pins configured");
816+
digitalWrite(sckPin, HIGH); // Clock idle high (SPI mode 0)
817+
digitalWrite(csPin, HIGH); // CS inactive
818+
digitalWrite(wpPin, HIGH); // WP disabled (active-low)
819+
digitalWrite(holdPin, HIGH); // HOLD disabled (active-low)
820+
writeSerial("Control pins set: CS=HIGH, WP=HIGH (disabled), HOLD=HIGH (disabled), SCK=HIGH (idle)");
821+
delay(1);
822+
writeSerial("Attempting to wake flash from deep power-down (command 0xAB)...");
823+
digitalWrite(csPin, LOW);
824+
spiTransfer(0xAB);
825+
digitalWrite(csPin, HIGH);
826+
delay(10); // Wait for flash to wake up (typically 3-35us, using 10ms for safety)
827+
writeSerial("Wake-up command sent, waiting 10ms...");
828+
// Read JEDEC ID before power-down (for verification)
829+
writeSerial("Reading JEDEC ID before power-down...");
830+
digitalWrite(csPin, LOW);
831+
spiTransfer(0x9F); // JEDEC ID command
832+
uint8_t jedecId[3];
833+
for (int i = 0; i < 3; i++) {
834+
jedecId[i] = spiTransfer(0x00);
835+
}
836+
digitalWrite(csPin, HIGH);
837+
String jedecIdStr = "0x";
838+
for (int i = 0; i < 3; i++) {
839+
if (jedecId[i] < 16) jedecIdStr += "0";
840+
jedecIdStr += String(jedecId[i], HEX);
841+
}
842+
jedecIdStr.toUpperCase();
843+
writeSerial("JEDEC ID before: " + jedecIdStr + " (Manufacturer=0x" + String(jedecId[0], HEX) + ", MemoryType=0x" + String(jedecId[1], HEX) + ", Capacity=0x" + String(jedecId[2], HEX) + ")");
844+
bool flashResponding = false;
845+
for (int i = 0; i < 3; i++) {
846+
if (jedecId[i] != 0xFF) {
847+
flashResponding = true;
848+
break;
849+
}
850+
}
851+
delay(1);
852+
writeSerial("Sending deep power-down command (0xB9)...");
853+
digitalWrite(csPin, LOW);
854+
spiTransfer(0xB9);
855+
digitalWrite(csPin, HIGH);
856+
if(false){
857+
writeSerial("Deep power-down command sent, waiting 10ms...");
858+
delay(10); // Wait for command to complete
859+
writeSerial("Reading JEDEC ID after power-down command...");
860+
digitalWrite(csPin, LOW);
861+
spiTransfer(0x9F);
862+
uint8_t jedecIdAfter[3];
863+
for (int i = 0; i < 3; i++) {
864+
jedecIdAfter[i] = spiTransfer(0x00);
865+
}
866+
digitalWrite(csPin, HIGH);
867+
String jedecIdAfterStr = "0x";
868+
for (int i = 0; i < 3; i++) {
869+
if (jedecIdAfter[i] < 16) jedecIdAfterStr += "0";
870+
jedecIdAfterStr += String(jedecIdAfter[i], HEX);
871+
}
872+
jedecIdAfterStr.toUpperCase();
873+
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) + ")");
874+
bool inPowerDown = true;
875+
String mismatchBytes = "";
876+
for (int i = 0; i < 3; i++) {
877+
if (jedecIdAfter[i] != 0xFF) {
878+
inPowerDown = false;
879+
if (mismatchBytes.length() > 0) mismatchBytes += ", ";
880+
mismatchBytes += "byte[" + String(i) + "]=0x" + String(jedecIdAfter[i], HEX) + " (expected 0xFF)";
881+
}
882+
}
883+
}
884+
digitalWrite(csPin, HIGH);
885+
pinMode(wpPin, INPUT);
886+
pinMode(holdPin, INPUT);
887+
pinMode(mosiPin, INPUT);
888+
pinMode(misoPin, INPUT);
889+
pinMode(sckPin, INPUT);
890+
#else
891+
writeSerial("External flash power-down not implemented for ESP32");
892+
return false;
893+
#endif
894+
return false;
760895
}
761896

762897
int mapEpd(int id){
@@ -844,9 +979,11 @@ void initDisplay(){
844979
bbepSendCMDSequence(&bbep, bbep.pInitFull);
845980
String chipId = getChipIdHex();
846981
String infoText = "openepaperlink.org\nName: OEPL" + chipId + "\nFW: " + String(getFirmwareMajor()) + "." + String(getFirmwareMinor()) + "\nEpaper driver by\nLarry Bank\ngithub.com/bitbank2";
847-
writeTextAndFill(infoText.c_str());
982+
if (globalConfig.displays[0].transmission_modes & TRANSMISSION_MODE_CLEAR_ON_BOOT) writeTextAndFill("");
983+
else writeTextAndFill(infoText.c_str());
848984
bbepRefresh(&bbep, REFRESH_FULL);
849985
waitforrefresh(60);
986+
pwrmgm(false);
850987
}
851988
else{
852989
writeSerial("No display found");
@@ -1476,6 +1613,10 @@ void printConfigSummary(){
14761613
writeSerial("IC Type: 0x" + String(globalConfig.system_config.ic_type, HEX));
14771614
writeSerial("Communication Modes: 0x" + String(globalConfig.system_config.communication_modes, HEX));
14781615
writeSerial("Device Flags: 0x" + String(globalConfig.system_config.device_flags, HEX));
1616+
writeSerial(" PWR_PIN flag: " + String((globalConfig.system_config.device_flags & DEVICE_FLAG_PWR_PIN) ? "enabled" : "disabled"));
1617+
#ifdef TARGET_NRF
1618+
writeSerial(" XIAOINIT flag: " + String((globalConfig.system_config.device_flags & DEVICE_FLAG_XIAOINIT) ? "enabled" : "disabled"));
1619+
#endif
14791620
writeSerial("Power Pin: " + String(globalConfig.system_config.pwr_pin));
14801621
writeSerial("");
14811622
// Manufacturer Data
@@ -1519,6 +1660,11 @@ void printConfigSummary(){
15191660
writeSerial(" Partial Update: " + String(globalConfig.displays[i].partial_update_support ? "Yes" : "No"));
15201661
writeSerial(" Color Scheme: 0x" + String(globalConfig.displays[i].color_scheme, HEX));
15211662
writeSerial(" Transmission Modes: 0x" + String(globalConfig.displays[i].transmission_modes, HEX));
1663+
writeSerial(" RAW: " + String((globalConfig.displays[i].transmission_modes & TRANSMISSION_MODE_RAW) ? "enabled" : "disabled"));
1664+
writeSerial(" ZIP: " + String((globalConfig.displays[i].transmission_modes & TRANSMISSION_MODE_ZIP) ? "enabled" : "disabled"));
1665+
writeSerial(" G5: " + String((globalConfig.displays[i].transmission_modes & TRANSMISSION_MODE_G5) ? "enabled" : "disabled"));
1666+
writeSerial(" DIRECT_WRITE: " + String((globalConfig.displays[i].transmission_modes & TRANSMISSION_MODE_DIRECT_WRITE) ? "enabled" : "disabled"));
1667+
writeSerial(" CLEAR_ON_BOOT: " + String((globalConfig.displays[i].transmission_modes & TRANSMISSION_MODE_CLEAR_ON_BOOT) ? "enabled" : "disabled"));
15221668
writeSerial("");
15231669
}
15241670
// LEDs
@@ -1699,6 +1845,8 @@ void handleDirectWriteStart(uint8_t* data, uint16_t len) {
16991845
writeSerial("Expected total bytes: " + String(directWriteTotalBytes) + (directWriteBitplanes ? " per plane" : ""));
17001846
directWriteActive = true;
17011847
directWriteBytesWritten = 0;
1848+
pwrmgm(true);
1849+
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);
17021850
bbepWakeUp(&bbep);
17031851
bbepSendCMDSequence(&bbep, bbep.pInitFull);// important for some displays
17041852
bbepSetAddrWindow(&bbep, 0, 0, globalConfig.displays[0].pixel_width, globalConfig.displays[0].pixel_height);
@@ -2231,6 +2379,7 @@ void handleDirectWriteEnd() {
22312379
}
22322380
bbepRefresh(&bbep, REFRESH_FULL);
22332381
waitforrefresh(60);
2382+
pwrmgm(false);
22342383
directWriteActive = false;
22352384
directWriteCompressed = false;
22362385
directWriteBytesWritten = 0;

src/main.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ using namespace Adafruit_LittleFS_Namespace;
4747
// Response buffer constants
4848
#define MAX_RESPONSE_DATA_SIZE 100 // Maximum data size in response buffer
4949

50+
// Device flags bit definitions (for system_config.device_flags)
51+
#define DEVICE_FLAG_PWR_PIN (1 << 0) // Bit 0: Device has external power management pin
52+
#define DEVICE_FLAG_XIAOINIT (1 << 1) // Bit 1: Call xiaoinit() after config load (nRF52840 only)
53+
54+
// Transmission mode bit definitions (for display.transmission_modes)
55+
#define TRANSMISSION_MODE_RAW (1 << 0) // Bit 0: Raw transfer
56+
#define TRANSMISSION_MODE_ZIP (1 << 1) // Bit 1: ZIP compressed transfer
57+
#define TRANSMISSION_MODE_G5 (1 << 2) // Bit 2: Group 5 compression
58+
#define TRANSMISSION_MODE_DIRECT_WRITE (1 << 3) // Bit 3: Direct write mode (bufferless)
59+
#define TRANSMISSION_MODE_CLEAR_ON_BOOT (1 << 7) // Bit 7: Clear screen at bootup (writeTextAndFill with empty string)
60+
5061
#ifdef TARGET_NRF
5162
#include <bluefruit.h>
5263
extern BLEDfu bledfu;
@@ -122,6 +133,8 @@ uint8_t* directWriteCompressedBuffer = nullptr; // Pointer to compressedDataBuf
122133

123134
bool waitforrefresh(int timeout);
124135
void pwrmgm(bool onoff);
136+
bool powerDownExternalFlash(uint8_t mosiPin, uint8_t misoPin, uint8_t sckPin, uint8_t csPin, uint8_t wpPin, uint8_t holdPin);
137+
void xiaoinit();
125138
void writeSerial(String message, bool newLine = true);
126139
void connect_callback(uint16_t conn_handle);
127140
void disconnect_callback(uint16_t conn_handle, uint8_t reason);

0 commit comments

Comments
 (0)