Added 4 grayscale support to epd
This commit is contained in:
@@ -77,9 +77,9 @@ extern "C" void app_main()
|
||||
|
||||
ESP_LOGI(TAG, "Initializing EPD");
|
||||
epd_init();
|
||||
epd_init_display();
|
||||
epd_init_display(true);
|
||||
// epd_clear(epd_color::WHITE);
|
||||
epd_draw_bitmap(epd_color::WHITE, test_image);
|
||||
epd_draw_bitmap_grayscale(epd_color::WHITE, gImage_4G1);
|
||||
epd_refresh();
|
||||
epd_shutdown_display();
|
||||
|
||||
|
||||
+8417
-2405
File diff suppressed because it is too large
Load Diff
+170
-21
@@ -19,9 +19,11 @@ internal constexpr size_t kTotal_bytes = (EPD_WIDTH * EPD_HEIGHT) / 8;
|
||||
internal uint8 g_scratch_buffer[4096];
|
||||
|
||||
internal struct epd_refresh_stats{
|
||||
time_t last_full_refresh;
|
||||
int fast_count;
|
||||
} g_epd_stats = {0, 0};
|
||||
time_t last_full_refresh_bw;
|
||||
int fast_count_bw;
|
||||
time_t last_full_refresh_4g;
|
||||
int fast_count_4g;
|
||||
} g_epd_stats = {0, 0, 0, 0};
|
||||
|
||||
internal void epd_spi_init(void)
|
||||
{
|
||||
@@ -201,7 +203,7 @@ internal void epd_init_display_fast(void)
|
||||
epd_writedata(0x1F);
|
||||
|
||||
epd_writecommand(0x50); // VCOM AND DATA INTERVAL SETTING
|
||||
epd_writedata(0x10);
|
||||
epd_writedata(0x29);
|
||||
epd_writedata(0x07);
|
||||
|
||||
epd_writecommand(0x04); // POWER ON
|
||||
@@ -221,7 +223,61 @@ internal void epd_init_display_fast(void)
|
||||
epd_writedata(0x5A);
|
||||
}
|
||||
|
||||
void epd_init_display()
|
||||
internal void epd_init_display_4g_full(void)
|
||||
{
|
||||
ESP_LOGI(kTagEPD, "Performing FULL 4-GRAY initialization");
|
||||
epd_writecommand(0X00); // PANEL SETTING
|
||||
epd_writedata(0x1F);
|
||||
|
||||
epd_writecommand(0X50); // VCOM AND DATA INTERVAL SETTING
|
||||
epd_writedata(0x29);
|
||||
epd_writedata(0x07);
|
||||
|
||||
epd_writecommand(0x04); // POWER ON
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // Standard delay for full
|
||||
epd_wait_until_idle();
|
||||
|
||||
// Standard display drive (Full Booster values)
|
||||
epd_writecommand(0x06); // Booster Soft Start
|
||||
epd_writedata(0x17);
|
||||
epd_writedata(0x17);
|
||||
epd_writedata(0x28);
|
||||
epd_writedata(0x17);
|
||||
|
||||
epd_writecommand(0xE0);
|
||||
epd_writedata(0x02);
|
||||
epd_writecommand(0xE5);
|
||||
epd_writedata(0x5F); // 0x5F -- 4 Gray
|
||||
}
|
||||
|
||||
internal void epd_init_display_4g_fast(void)
|
||||
{
|
||||
ESP_LOGI(kTagEPD, "Performing FAST 4-GRAY initialization");
|
||||
epd_writecommand(0X00); // PANEL SETTING
|
||||
epd_writedata(0x1F);
|
||||
|
||||
epd_writecommand(0X50); // VCOM AND DATA INTERVAL SETTING
|
||||
epd_writedata(0x29);
|
||||
epd_writedata(0x07);
|
||||
|
||||
epd_writecommand(0x04); // POWER ON
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
epd_wait_until_idle();
|
||||
|
||||
// Enhanced display drive (Fast Booster values)
|
||||
epd_writecommand(0x06); // Booster Soft Start
|
||||
epd_writedata(0x27);
|
||||
epd_writedata(0x27);
|
||||
epd_writedata(0x18);
|
||||
epd_writedata(0x17);
|
||||
|
||||
epd_writecommand(0xE0);
|
||||
epd_writedata(0x02);
|
||||
epd_writecommand(0xE5);
|
||||
epd_writedata(0x5F); // 0x5F -- 4 Gray
|
||||
}
|
||||
|
||||
void epd_init_display(bool is_4gray)
|
||||
{
|
||||
g_is_asleep = false;
|
||||
|
||||
@@ -232,27 +288,47 @@ void epd_init_display()
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
time_t now = time(NULL);
|
||||
double diff = difftime(now, g_epd_stats.last_full_refresh);
|
||||
|
||||
// LOGIC: Full refresh if > 24 hours OR if we hit 5 fast refreshes
|
||||
// Case: first boot (stats=0) -> force full
|
||||
bool force_full = (g_epd_stats.last_full_refresh == 0) || (diff > 86400.0) ||
|
||||
(g_epd_stats.fast_count >= 5);
|
||||
|
||||
if (force_full)
|
||||
if (is_4gray)
|
||||
{
|
||||
epd_init_display_full();
|
||||
g_epd_stats.last_full_refresh = now;
|
||||
g_epd_stats.fast_count = 0;
|
||||
double diff = difftime(now, g_epd_stats.last_full_refresh_4g);
|
||||
bool force_full = (g_epd_stats.last_full_refresh_4g == 0) || (diff > 86400.0) ||
|
||||
(g_epd_stats.fast_count_4g >= 5);
|
||||
|
||||
if (force_full)
|
||||
{
|
||||
epd_init_display_4g_full();
|
||||
g_epd_stats.last_full_refresh_4g = now;
|
||||
g_epd_stats.fast_count_4g = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
epd_init_display_4g_fast();
|
||||
g_epd_stats.fast_count_4g++;
|
||||
}
|
||||
ESP_LOGI(kTagEPD, "4G Refresh stats: (Fast count: %d/5, Age: %.1f hours)",
|
||||
g_epd_stats.fast_count_4g, diff / 3600.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
epd_init_display_fast();
|
||||
g_epd_stats.fast_count++;
|
||||
}
|
||||
double diff = difftime(now, g_epd_stats.last_full_refresh_bw);
|
||||
bool force_full = (g_epd_stats.last_full_refresh_bw == 0) || (diff > 86400.0) ||
|
||||
(g_epd_stats.fast_count_bw >= 5);
|
||||
|
||||
ESP_LOGI(kTagEPD, "Refresh stats: (Fast count: %d/5, Age: %.1f hours)",
|
||||
g_epd_stats.fast_count, diff / 3600.0);
|
||||
if (force_full)
|
||||
{
|
||||
epd_init_display_full();
|
||||
g_epd_stats.last_full_refresh_bw = now;
|
||||
g_epd_stats.fast_count_bw = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
epd_init_display_fast();
|
||||
g_epd_stats.fast_count_bw++;
|
||||
}
|
||||
ESP_LOGI(kTagEPD, "BW Refresh stats: (Fast count: %d/5, Age: %.1f hours)",
|
||||
g_epd_stats.fast_count_bw, diff / 3600.0);
|
||||
}
|
||||
}
|
||||
|
||||
void epd_shutdown_display(void)
|
||||
@@ -307,4 +383,77 @@ void epd_draw_bitmap(epd_color clearColor, const uint8 *bitmap)
|
||||
epd_write_buffer(bitmap, kTotal_bytes);
|
||||
|
||||
ESP_LOGI(kTagEPD, "Data transmission complete (Refresh required)");
|
||||
}
|
||||
}
|
||||
|
||||
void epd_draw_bitmap_grayscale(epd_color clearColor, const uint8 *bitmap)
|
||||
{
|
||||
ESP_LOGI(kTagEPD, "Drawing 4-GRAY bitmap (with unpacking)");
|
||||
|
||||
// THE LOGIC:
|
||||
// The input bitmap is 2-bits per pixel packed (4 pixels per byte).
|
||||
// Total pixels: 800 * 480 = 384,000.
|
||||
// Input size: 384,000 / 4 = 96,000 bytes.
|
||||
// Output: Two frames of 800 * 480 / 8 = 48,000 bytes each.
|
||||
|
||||
auto process_layer = [&](uint8 cmd, bool is_new_layer)
|
||||
{
|
||||
epd_writecommand(cmd);
|
||||
size_t scratch_idx = 0;
|
||||
|
||||
// Process 48,000 output bytes (each covers 8 pixels)
|
||||
for (size_t i = 0; i < 48000; i++)
|
||||
{
|
||||
uint8 output_byte = 0;
|
||||
// Each output byte comes from 2 input bytes (j=0, j=1)
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
uint8 input_byte = bitmap[i * 2 + j];
|
||||
// Extract 4 pixels from each input byte
|
||||
for (int k = 0; k < 4; k++)
|
||||
{
|
||||
uint8 pixel_bits = (input_byte >> (6 - k * 2)) & 0x03; // Correct bit order
|
||||
bool bit_val = false;
|
||||
|
||||
if (is_new_layer)
|
||||
{
|
||||
// NEW Layer (0x13) Mapping
|
||||
if (pixel_bits == 0x03) bit_val = true; // White (11)
|
||||
else if (pixel_bits == 0x00) bit_val = false; // Black (00)
|
||||
else if (pixel_bits == 0x02) bit_val = true; // Gray1 (10)
|
||||
else if (pixel_bits == 0x01) bit_val = false; // Gray2 (01)
|
||||
}
|
||||
else
|
||||
{
|
||||
// OLD Layer (0x10) Mapping
|
||||
if (pixel_bits == 0x03) bit_val = true; // White (11)
|
||||
else if (pixel_bits == 0x00) bit_val = false; // Black (00)
|
||||
else if (pixel_bits == 0x02) bit_val = false; // Gray1 (10)
|
||||
else if (pixel_bits == 0x01) bit_val = true; // Gray2 (01)
|
||||
}
|
||||
|
||||
if (bit_val) output_byte |= (1 << (7 - (j * 4 + k)));
|
||||
}
|
||||
}
|
||||
|
||||
// The demo code applies a bitwise NOT to the result
|
||||
g_scratch_buffer[scratch_idx++] = ~output_byte;
|
||||
|
||||
if (scratch_idx >= sizeof(g_scratch_buffer))
|
||||
{
|
||||
epd_write_buffer(g_scratch_buffer, scratch_idx);
|
||||
scratch_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (scratch_idx > 0)
|
||||
{
|
||||
epd_write_buffer(g_scratch_buffer, scratch_idx);
|
||||
}
|
||||
};
|
||||
|
||||
process_layer(0x10, false); // Old data
|
||||
process_layer(0x13, true); // New data
|
||||
|
||||
ESP_LOGI(kTagEPD, "Data transmission complete (Refresh required)");
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,10 @@ enum class epd_color : uint8
|
||||
|
||||
void epd_init(void);
|
||||
void epd_shutdown(void);
|
||||
void epd_init_display();
|
||||
void epd_init_display(bool is_4gray);
|
||||
void epd_shutdown_display(void);
|
||||
void epd_refresh(void);
|
||||
void epd_clear(epd_color level);
|
||||
void epd_draw_bitmap(epd_color clearColor, const uint8 *bitmap);
|
||||
void epd_draw_bitmap_grayscale(epd_color clearColor, const uint8 *bitmap);
|
||||
bool epd_is_asleep(void);
|
||||
Reference in New Issue
Block a user