Partial refresh, list restart wihtout requiring full refresh

This commit is contained in:
Adolfo Reyna
2025-11-26 18:39:02 -05:00
parent 961b4c069b
commit d2587410e5

View File

@@ -30,13 +30,14 @@ static UBYTE *g_epd_image = NULL; // Black image buffer
static UBYTE *g_epd_red = NULL; // Red image buffer static UBYTE *g_epd_red = NULL; // Red image buffer
// Entry list for display // Entry list for display
#define MAX_ENTRIES 10 #define MAX_ENTRIES 15
#define ENTRY_LENGTH 64 #define ENTRY_LENGTH 64
typedef struct { typedef struct {
char entries[MAX_ENTRIES][ENTRY_LENGTH]; char entries[MAX_ENTRIES][ENTRY_LENGTH];
int count; int count;
} EntryList; } EntryList;
static EntryList g_entry_list = {{}, 0}; static EntryList g_entry_list = {{}, 0};
static bool g_force_full_refresh = false; // Flag to force full refresh when list is full
// Synchronization flag for multicore initialization // Synchronization flag for multicore initialization
static volatile bool g_display_ready = false; static volatile bool g_display_ready = false;
@@ -64,7 +65,7 @@ void init_epaper_display() {
printf("EPD_7IN5B_V2_Init()\r\n"); printf("EPD_7IN5B_V2_Init()\r\n");
EPD_7IN5B_V2_Init_Fast(); EPD_7IN5B_V2_Init_Fast();
printf("EPD_7IN5B_V2_Clear()\r\n"); printf("EPD_7IN5B_V2_Clear()\r\n");
EPD_7IN5B_V2_ClearBlack(); EPD_7IN5B_V2_Clear();
DEV_Delay_ms(500); DEV_Delay_ms(500);
// Create image buffers for black and red content // Create image buffers for black and red content
@@ -91,12 +92,14 @@ void init_epaper_display() {
Paint_Clear(WHITE); Paint_Clear(WHITE);
// Draw header // Draw header
// printf("Drawing header\r\n"); EPD_7IN5B_V2_Init_Part();
// Paint_DrawString_EN(10, 10, "What's new today:", &Font24, BLACK, WHITE); Paint_SelectImage(g_epd_red);
printf("Drawing header\r\n");
Paint_DrawString_EN(10, 10, "What's new today:", &Font24, WHITE, RED);
// Display the image with both black and red buffers // Display the image with both black and red buffers
// printf("display text\r\n"); // printf("display text\r\n");
EPD_7IN5B_V2_Display(g_epd_image, g_epd_red); EPD_7IN5B_V2_Display_Partial(g_epd_red, 0, 0, EPD_7IN5B_V2_WIDTH, EPD_7IN5B_V2_HEIGHT);
// printf("delay\r\n"); // printf("delay\r\n");
// DEV_Delay_ms(1000); // DEV_Delay_ms(1000);
@@ -117,19 +120,18 @@ void init_epaper_display() {
void send_display_update(const char *entry) { void send_display_update(const char *entry) {
if (!g_display_ready) return; // Don't send if display isn't ready if (!g_display_ready) return; // Don't send if display isn't ready
// Check if list is at capacity
if (g_entry_list.count >= MAX_ENTRIES) {
// List is full - clear all entries and start fresh
printf("[Core 0] List is FULL - clearing all entries and starting fresh\n");
g_entry_list.count = 0;
g_force_full_refresh = true;
}
// Add entry to global list // Add entry to global list
if (g_entry_list.count < MAX_ENTRIES) {
strncpy(g_entry_list.entries[g_entry_list.count], entry, ENTRY_LENGTH - 1); strncpy(g_entry_list.entries[g_entry_list.count], entry, ENTRY_LENGTH - 1);
g_entry_list.entries[g_entry_list.count][ENTRY_LENGTH - 1] = '\0'; g_entry_list.entries[g_entry_list.count][ENTRY_LENGTH - 1] = '\0';
g_entry_list.count++; g_entry_list.count++;
} else {
// Shift entries up and add new one at bottom
for (int i = 0; i < MAX_ENTRIES - 1; i++) {
strcpy(g_entry_list.entries[i], g_entry_list.entries[i + 1]);
}
strncpy(g_entry_list.entries[MAX_ENTRIES - 1], entry, ENTRY_LENGTH - 1);
g_entry_list.entries[MAX_ENTRIES - 1][ENTRY_LENGTH - 1] = '\0';
}
// Allocate message structure // Allocate message structure
DisplayMessage *msg = (DisplayMessage *)malloc(sizeof(DisplayMessage)); DisplayMessage *msg = (DisplayMessage *)malloc(sizeof(DisplayMessage));
@@ -141,8 +143,15 @@ void send_display_update(const char *entry) {
// Copy entry list to message // Copy entry list to message
msg->entries = g_entry_list; msg->entries = g_entry_list;
// Decide whether to use partial or full refresh
msg->use_partial = !g_force_full_refresh;
if (g_force_full_refresh) {
printf("[Core 0] Forcing full refresh this update\n");
g_force_full_refresh = false; // Reset flag after setting it in message
}
// Setup partial refresh region (text area at top of display) // Setup partial refresh region (text area at top of display)
msg->use_partial = true;
msg->xstart = 0; msg->xstart = 0;
msg->ystart = 50; // Start below the header msg->ystart = 50; // Start below the header
msg->xend = 800; // Full width msg->xend = 800; // Full width
@@ -186,44 +195,50 @@ void core1_display_init() {
UWORD y_start = msg->ystart; UWORD y_start = msg->ystart;
UWORD y_end = msg->yend; UWORD y_end = msg->yend;
if (msg->use_partial) {
// Clear only the affected region in the buffers
for (UWORD y = y_start; y < y_end; y++) {
for (UWORD x = 0; x < width; x++) {
g_epd_image[x + y * width] = 0xFF; // White
g_epd_red[x + y * width] = 0xFF; // No red
}
}
} else {
// Full clear
for (UWORD i = 0; i < imagesize; i++) {
g_epd_image[i] = 0xFF;
g_epd_red[i] = 0xFF;
}
}
Paint_SelectImage(g_epd_image); Paint_SelectImage(g_epd_image);
Paint_Clear(WHITE);
// Draw header if(!msg->use_partial){
Paint_DrawString_EN(10, 10, "What's new today:", &Font24, WHITE, BLACK); // for loop 5 times display white partial
int i = 0;
for(i = 0; i < 1; i++){
EPD_7IN5B_V2_Display_Partial(g_epd_image, msg->xstart, msg->ystart, msg->xend, msg->yend);
}
}
// Draw all entries starting below header // Draw all entries starting below header
UWORD y_pos = 50; UWORD y_pos = 0;
for (int i = 0; i < msg->entries.count; i++) { /*for (int i = 0; i < msg->entries.count; i++) {
if (y_pos + 20 < 480) { // Don't draw beyond screen if (y_pos + 20 < 480) { // Don't draw beyond screen
Paint_DrawString_EN(20, y_pos, msg->entries.entries[i], &Font16, WHITE, BLACK); Paint_DrawString_EN(20, y_pos, msg->entries.entries[i], &Font16, WHITE, BLACK);
y_pos += 25; // Space between entries y_pos += 25; // Space between entries
} }
}*/
// paint only the last 3 entries
int start_index = msg->entries.count > 2 ? msg->entries.count - 2 : 0;
for (int i = start_index; i < msg->entries.count; i++) {
if (y_pos + 25 < 480) { //Don't draw beyond screen
Paint_DrawString_EN(20, i*25, msg->entries.entries[i], &Font16, WHITE, BLACK);
y_pos += 25; // Space between entries
} else {
printf("Skipping entry to avoid overflow\n");
}
} }
// Use partial or full refresh // Use partial or full refresh
if (msg->use_partial) { //if (msg->use_partial) {
printf("[Core 1] Using partial refresh\n"); printf("[Core 1] Using partial refresh\n");
EPD_7IN5B_V2_Display_Partial(g_epd_image, msg->xstart, msg->ystart, msg->xend, msg->yend); EPD_7IN5B_V2_Display_Partial(g_epd_image, msg->xstart, msg->ystart, msg->xend, msg->yend);
} else { /*} else {
printf("[Core 1] Using full refresh\n"); printf("[Core 1] Using full refresh\n");
EPD_7IN5B_V2_Display(g_epd_image, g_epd_red); // EPD_7IN5B_V2_Init();
} // EPD_7IN5B_V2_Clear();
// DEV_Delay_ms(500);
// Re-initialize partial refresh mode after full refresh
printf("[Core 1] Reinitializing partial refresh mode\n");
EPD_7IN5B_V2_Init_Part();
Paint_SelectImage(g_epd_image);
EPD_7IN5B_V2_Display_Partial(g_epd_image, msg->xstart, msg->ystart, msg->xend, msg->yend);
}*/
} }
// Free the message (it was allocated by core 0) // Free the message (it was allocated by core 0)