ESP32 E-READER PROTOTYPE

24 OCTOBER 2023

First project with e-paper displays and ESP32.

ESP-WROOM-32, 7.5” Waveshare e-paper display, three buttons (prev/next/sleep).

No local storage—streams books over HTTP. RTC memory tracks reading progress between sessions.

ESP32: 512KB SRAM, 4MB flash (shared with FreeRTOS, ESP-IDF). Not enough to store books. Stream from webserver instead.

Custom EBM file format. Rasterized monochrome bitmaps, one per page (480x800). One byte = 8 pixels. Pages on 48KB boundaries—HTTP Range requests work without server logic. pdftoebm.py converts PDFs.

Circular buffer holds 3 pages (prev/current/next)–page table. Single-threaded approach too slow—user input, SPI, and HTTP on one core causes lag.

Optimizations: pin the GPIO task (responding to user input and updating display) to one core, pin the HTTP task to the other core.

Better, but system unresponsive during screen updates. Made SPI transfer async:

void epd_draw_async(const uint8_t *buf, size_t n)
{
    static spi_transaction_t t[3];

    memset(&t[0], 0, sizeof(t[0])); 
    t[0].length = 8;
    t[0].tx_data[0] = 0x13;
    t[0].user = (void*) 0; 
    t[0].flags = SPI_TRANS_USE_TXDATA;

    memset(&t[1], 0, sizeof(t[1])); 
    t[1].length = 8 * n;
    t[1].tx_buffer = buf;
    t[1].user = (void*) 1; 

    memset(&t[2], 0, sizeof(t[2])); 
    t[2].length = 8;
    t[2].tx_data[0] = 0x12;
    t[2].user = (void*) 0; 
    t[2].flags = SPI_TRANS_USE_TXDATA;

    for (int i = 0; i < 3; i++)
        spi_device_queue_trans(spi, &t[i], portMAX_DELAY);
}

Much better. Squeeze a few more cycles by moving SPI buffer to DMA.

Can’t think of anything else.

Outcome: Works but limited. Led to Etlas.

Commit: 7f691c4