Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,14 @@ board_upload.maximum_ram_size = 327680
board_upload.flash_size = 16MB
monitor_speed = 115200

#[env:esp32-N4]
#platform = espressif32
#framework = arduino
#build_flags =
# -DTARGET_ESP32
# -DCONFIG_FREERTOS_WATCHDOG_TIMEOUT_S=120
#board_build.filesystem = littlefs
#board = esp32dev
#board_build.partitions = huge_app.csv
#monitor_speed = 115200
[env:esp32-N4]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
framework = arduino
build_flags =
-DTARGET_ESP32
-DCONFIG_FREERTOS_WATCHDOG_TIMEOUT_S=120
board_build.filesystem = littlefs
board = esp32dev
board_build.partitions = huge_app.csv
monitor_speed = 115200
lib_ignore = Seeed_GFX
22 changes: 22 additions & 0 deletions src/ble_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ void ble_init() {
#endif

#ifdef TARGET_ESP32
volatile bool bleRestartAdvertisingPending = false;

void esp32_restart_ble_advertising(void) {
if (pServer == nullptr) {
bleRestartAdvertisingPending = true;
return;
}
if (pServer->getConnectedCount() > 0) {
bleRestartAdvertisingPending = false;
return;
}
if (epdRefreshInProgress) {
bleRestartAdvertisingPending = true;
return;
}
bleRestartAdvertisingPending = false;
delay(100);
BLEDevice::startAdvertising();
updatemsdata();
writeSerial("BLE advertising restarted");
}

void ble_init_esp32(bool update_manufacturer_data) {
writeSerial("=== Initializing ESP32 BLE ===");
String deviceName = "OD" + getChipIdHex();
Expand Down
2 changes: 2 additions & 0 deletions src/ble_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ void ble_nrf_advertising_start();
#ifdef TARGET_ESP32
void ble_init();
void ble_init_esp32(bool update_manufacturer_data = true);
void esp32_restart_ble_advertising(void);
extern volatile bool bleRestartAdvertisingPending;
#endif

#endif
2 changes: 0 additions & 2 deletions src/config_parser.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "config_parser.h"
#include "structs.h"

static_assert(sizeof(struct WifiConfig) == 160, "wifi_config must match config.yaml (32+32+1+95)");
#include "encryption_state.h"
#include "encryption.h"
#include <Arduino.h>
Expand Down
68 changes: 62 additions & 6 deletions src/display_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "communication.h"
#include "encryption.h"
#include "boot_screen.h"
#include "touch_input.h"
#include "uzlib.h"
#if defined(TARGET_ESP32) && defined(OPENDISPLAY_SEEED_GFX)
#include "display_seeed_gfx.h"
Expand All @@ -24,6 +25,7 @@ extern "C" {

#ifdef TARGET_ESP32
#include <BLEDevice.h>
#include "ble_init.h"
#include "wifi_service.h"
#endif

Expand All @@ -50,9 +52,15 @@ extern bool directWritePlane2;
extern bool directWriteBitplanes;
extern bool directWriteCompressed;
extern bool directWriteActive;
volatile bool epdRefreshInProgress = false;
extern uint8_t* compressedDataBuffer;
#if defined(TARGET_ESP32)
extern uint8_t* dictionaryBuffer;
extern uint8_t* decompressionChunk;
#else
extern uint8_t dictionaryBuffer[];
extern uint8_t decompressionChunk[];
#endif

extern uint32_t displayed_etag;

Expand Down Expand Up @@ -331,19 +339,47 @@ void initDataBuses(){
writeSerial("=== Data Bus Initialization Complete ===", true);
}

#ifdef TARGET_ESP32
static bool s_wire_open_display_ready = false;
static int8_t s_wire_sda_pin = -1;
static int8_t s_wire_scl_pin = -1;
static uint32_t s_wire_clock_hz = 0;
#endif

void invalidateOpenDisplayWire(void) {
#ifdef TARGET_ESP32
s_wire_open_display_ready = false;
#endif
}

void initOrRestoreWireForOpenDisplay(void) {
#ifdef TARGET_ESP32
if (globalConfig.data_bus_count > 0) {
const struct DataBus& bus = globalConfig.data_buses[0];
if (bus.bus_type == 0x01 && bus.pin_1 != 0xFF && bus.pin_2 != 0xFF) {
uint32_t hz = bus.bus_speed_hz ? bus.bus_speed_hz : 100000u;
Wire.begin((int)bus.pin_2, (int)bus.pin_1);
int sda = (int)bus.pin_2;
int scl = (int)bus.pin_1;
if (s_wire_open_display_ready && s_wire_sda_pin == sda && s_wire_scl_pin == scl &&
s_wire_clock_hz == hz) {
return;
}
Wire.begin(sda, scl);
Wire.setClock(hz);
s_wire_sda_pin = (int8_t)sda;
s_wire_scl_pin = (int8_t)scl;
s_wire_clock_hz = hz;
s_wire_open_display_ready = true;
return;
}
}
#endif
if (!s_wire_open_display_ready) {
Wire.begin();
s_wire_open_display_ready = true;
}
#else
Wire.begin();
#endif
}

void initio(){
Expand Down Expand Up @@ -964,12 +1000,16 @@ void initDisplay(){
if (! (globalConfig.displays[0].transmission_modes & TRANSMISSION_MODE_CLEAR_ON_BOOT)){
writeBootScreenWithQr();
writeSerial("EPD refresh: FULL (boot, Seeed)", true);
touchSuspendForEpdRefresh();
seeed_gfx_full_update();
waitforrefresh(60);
seeed_gfx_sleep_after_refresh();
delay(200);
pwrmgm(false);
touchResumeAfterEpdRefresh();
} else {
pwrmgm(false);
}
pwrmgm(false);
} else
#endif
{
Expand All @@ -986,12 +1026,16 @@ void initDisplay(){
if (! (globalConfig.displays[0].transmission_modes & TRANSMISSION_MODE_CLEAR_ON_BOOT)){
writeBootScreenWithQr();
writeSerial("EPD refresh: FULL (boot)", true);
touchSuspendForEpdRefresh();
bbepRefresh(&bbep, REFRESH_FULL);
waitforrefresh(60);
bbepSleep(&bbep, 1);
delay(200);
pwrmgm(false);
touchResumeAfterEpdRefresh();
} else {
pwrmgm(false);
}
pwrmgm(false);
}
}
else{
Expand Down Expand Up @@ -1145,6 +1189,7 @@ void handleDirectWriteCompressedData(uint8_t* data, uint16_t len) {

void decompressDirectWriteData() {
if (directWriteCompressedReceived == 0) return;
if (!dictionaryBuffer || !decompressionChunk) return;
struct uzlib_uncomp d;
memset(&d, 0, sizeof(d));
d.source = directWriteCompressedBuffer;
Expand Down Expand Up @@ -1208,8 +1253,11 @@ void cleanupDirectWriteState(bool refreshDisplay) {
}

void handleDirectWriteStart(uint8_t* data, uint16_t len) {
if (partialCtx.active) cleanup_partial_write_state();
if (directWriteActive) cleanupDirectWriteState(false);
if (partialCtx.active) cleanup_partial_write_state();
if (directWriteActive) {
cleanupDirectWriteState(false);
}
touchSuspendForEpdRefresh();
#if defined(TARGET_ESP32) && defined(OPENDISPLAY_SEEED_GFX)
if (seeed_driver_used()) {
seeed_gfx_prepare_hardware();
Expand All @@ -1232,6 +1280,7 @@ void handleDirectWriteStart(uint8_t* data, uint16_t len) {
if (directWriteCompressed) {
if (!compressedDataBuffer) {
cleanupDirectWriteState(false);
touchResumeAfterEpdRefresh();
uint8_t errorResponse[] = {0xFF, 0xFF};
sendResponse(errorResponse, sizeof(errorResponse));
return;
Expand All @@ -1245,6 +1294,7 @@ void handleDirectWriteStart(uint8_t* data, uint16_t len) {
uint32_t cap = max_compressed_image_rx_bytes(globalConfig.displays[0].transmission_modes);
if (compressedDataLen > cap) {
cleanupDirectWriteState(false);
touchResumeAfterEpdRefresh();
uint8_t errorResponse[] = {0xFF, 0xFF};
sendResponse(errorResponse, sizeof(errorResponse));
return;
Expand Down Expand Up @@ -1466,6 +1516,7 @@ void handleDirectWriteEnd(uint8_t* data, uint16_t len) {
uint8_t ackResponse[] = {0x00, 0x72};
sendResponse(ackResponse, sizeof(ackResponse));
delay(20);
epdRefreshInProgress = true;
bool refreshSuccess = false;
uint32_t newEtag = 0;
bool hasNewEtag = data != nullptr && len >= 5;
Expand All @@ -1482,8 +1533,13 @@ void handleDirectWriteEnd(uint8_t* data, uint16_t len) {
refreshSuccess = waitforrefresh(60);
bbepSleep(&bbep, 1);
}
epdRefreshInProgress = false;
delay(50);
cleanupDirectWriteState(false);
touchResumeAfterEpdRefresh();
#ifdef TARGET_ESP32
esp32_restart_ble_advertising();
#endif
if (refreshSuccess) {
if (hasNewEtag && newEtag != 0) displayed_etag = newEtag;
uint8_t refreshResponse[] = {0x00, 0x73};
Expand Down
3 changes: 3 additions & 0 deletions src/display_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ void initio();
void initDataBuses();
/** Re-apply I2C from data_bus[0] when set; else Wire.begin(). Call before TCON/touch on shared bus. */
void initOrRestoreWireForOpenDisplay(void);
/** Call after Wire.end() so the next touch/sensor access re-inits the bus. */
void invalidateOpenDisplayWire(void);
void scanI2CDevices();
void initSensors();
void initAXP2101(uint8_t busId);
Expand All @@ -29,6 +31,7 @@ void handleDirectWriteCompressedData(uint8_t* data, uint16_t len);
void decompressDirectWriteData();
void cleanupDirectWriteState(bool refreshDisplay);
void handleDirectWriteEnd(uint8_t* data, uint16_t len);
extern volatile bool epdRefreshInProgress;
void handlePartialWriteStart(uint8_t* data, uint16_t len);
int getplane();
int getBitsPerPixel();
Expand Down
19 changes: 11 additions & 8 deletions src/esp32_ble_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <BLEDevice.h>
#include <BLEServer.h>
#include <string.h>
#include "ble_init.h"

#ifndef COMMAND_QUEUE_SIZE
#define COMMAND_QUEUE_SIZE 5
Expand All @@ -29,6 +30,9 @@ extern uint8_t rebootFlag;

void updatemsdata();
void cleanupDirectWriteState(bool refreshDisplay);
void touchResumeAfterEpdRefresh(void);
extern volatile bool epdRefreshInProgress;
extern bool directWriteActive;

class MyBLEServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Expand All @@ -37,16 +41,15 @@ class MyBLEServerCallbacks : public BLEServerCallbacks {
updatemsdata();
}
void onDisconnect(BLEServer* pServer) {
(void)pServer;
writeSerial("=== BLE CLIENT DISCONNECTED (ESP32) ===");
cleanupDirectWriteState(true);
writeSerial("Waiting before restarting advertising...");
delay(500);
if (pServer->getConnectedCount() == 0) {
BLEDevice::startAdvertising();
writeSerial("Advertising restarted");
} else {
writeSerial("not restarting advertising");
if (epdRefreshInProgress) {
writeSerial("EPD refresh in progress — deferring cleanup/advertising to main loop");
} else if (directWriteActive) {
cleanupDirectWriteState(true);
touchResumeAfterEpdRefresh();
}
bleRestartAdvertisingPending = true;
}
};

Expand Down
21 changes: 19 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "display_service.h"
#include "touch_input.h"
#include "encryption.h"
#include "ble_init.h"

#if defined(TARGET_ESP32) && defined(OPENDISPLAY_LOG_UART)
#include <HardwareSerial.h>
Expand All @@ -23,20 +24,28 @@ static HardwareSerial LogSerialPort(1);
#if defined(TARGET_NRF)
static uint8_t s_compressedDataStorage[MAX_COMPRESSED_BUFFER_BYTES];
uint8_t* compressedDataBuffer = s_compressedDataStorage;
#elif defined(TARGET_ESP32) && defined(TARGET_LARGE_MEMORY) && defined(BOARD_HAS_PSRAM)
#elif defined(TARGET_ESP32)
uint8_t* compressedDataBuffer = nullptr;
#else
static uint8_t s_compressedDataStorage[MAX_COMPRESSED_BUFFER_BYTES];
uint8_t* compressedDataBuffer = s_compressedDataStorage;
#endif

void allocCompressedDataBuffer(void) {
#if defined(TARGET_ESP32) && defined(TARGET_LARGE_MEMORY) && defined(BOARD_HAS_PSRAM)
#if defined(TARGET_ESP32)
if (compressedDataBuffer) return;
#if defined(TARGET_LARGE_MEMORY) && defined(BOARD_HAS_PSRAM)
compressedDataBuffer = (uint8_t*)heap_caps_malloc(MAX_COMPRESSED_BUFFER_BYTES, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#endif
if (!compressedDataBuffer) {
compressedDataBuffer = (uint8_t*)heap_caps_malloc(MAX_COMPRESSED_BUFFER_BYTES, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
if (!decompressionChunk) {
decompressionChunk = (uint8_t*)heap_caps_malloc(DECOMP_CHUNK_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
if (!dictionaryBuffer) {
dictionaryBuffer = (uint8_t*)heap_caps_malloc(MAX_DICT_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
#endif
}

Expand Down Expand Up @@ -159,6 +168,9 @@ void loop() {
bleDrain++;
}
}
if (bleRestartAdvertisingPending) {
esp32_restart_ble_advertising();
}
if (directWriteActive && directWriteStartTime > 0) {
uint32_t directWriteDuration = millis() - directWriteStartTime;
if (directWriteDuration > 900000UL) { // 15 minute timeout (upload + refresh window)
Expand All @@ -174,6 +186,8 @@ void loop() {
bool bleActive = (commandQueueTail != commandQueueHead) ||
(responseQueueTail != responseQueueHead) ||
(pServer && pServer->getConnectedCount() > 0) ||
bleRestartAdvertisingPending ||
epdRefreshInProgress ||
wifiLanSession;
if (bleActive) {
processButtonEvents();
Expand Down Expand Up @@ -323,6 +337,7 @@ void pwrmgm(bool onoff){
writeSerial("Powering down AXP2101 PMIC...");
powerDownAXP2101();
Wire.end();
invalidateOpenDisplayWire();
pinMode(47, OUTPUT);
digitalWrite(47, HIGH);
pinMode(48, OUTPUT);
Expand All @@ -348,6 +363,7 @@ void pwrmgm(bool onoff){
else{
SPI.end();
Wire.end();
invalidateOpenDisplayWire();
pinMode(globalConfig.displays[0].reset_pin, INPUT);
pinMode(globalConfig.displays[0].cs_pin, INPUT);
if (globalConfig.displays[0].dc_pin != 0xFF) {
Expand All @@ -362,6 +378,7 @@ void pwrmgm(bool onoff){
} else {
SPI.end();
Wire.end();
invalidateOpenDisplayWire();
}
}
if(globalConfig.system_config.pwr_pin != 0xFF){
Expand Down
Loading
Loading