Stitched together an e-reader using an ESP-WROOM-32, a 7.5” Waveshare e-paper display, and a three-button interface (prev/next/sleep).
ESP-WROOM-32 has 512 KB SRAM and 4 MB flash. Internal flash is unsuitable for storing books due to P/E cycle limit. Streamed pages via HTTP on-demand instead. Reading progress is saved in RTC memory to survive deep sleep without flash wear.
Rasterized PDFs into sequences of bitmaps. 1 byte = 8 pixels, 1 page = 48 KB (the display resolution), headerless; optimized for HTTP Range requests without server-side logic:
int r0 = ((page_n - 1) * PAGE_SIZE);
int rn = page_n * PAGE_SIZE - 1;
int n = snprintf(NULL, 0, "bytes=%d-%d", r0, rn) + 1;
char *buf = malloc(sizeof(char) * n);
snprintf(buf, n, "bytes=%d-%d", r0, rn);
esp_http_client_set_header(http_client, "Range", buf);
esp_http_client_perform(http_client);
A circular buffer stores three pages—maximum possible with the 512 KB. Button-triggered GPIO interrupts cycle the buffer, update the screen, and prefetch the next page.
Reader isn’t as responsive as I’d hoped. Scheduling GPIO, SPI, and HTTP tasks on a single core causes input lag.
Pinned the GPIO and SPI tasks to one core and the HTTP task to the other.
Better, but screen updates block user input. Page turning feels sluggish.
Moved SPI buffers to DMA and made transfers async, hoping to offload the CPU.
Can’t think of anything else. Led to Etlas.
Commit: 7f691c4.