512 KB PROTOTYPE E-READER
24 OCTOBER 2023
Been dabbling in microcontrollers—mostly Arduino Uno/ATmega328P. Math major, no formal electronics training. This, however, is an ESP-32 project—the first resembling something remotely useful.
ESP-WROOM-32, 7.5” Waveshare e-paper display, three-button interface (prev/next/sleep).
Memory: 512 KB SRAM + 4 MB flash. Internal flash unsuitable for storing books due to P/E cycle limit. Used HTTP Range requests to stream them on-demand. Progress saved to RTC memory to survive deep sleep without flash wear.
PDFs are rasterized and stored as sequences of bitmaps on a server. 1 byte = 8 pixels, 1 page = 48 KB (display resolution), headerless. Optimized for 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);
Three pages (prev/current/next) stored in a circular buffer—max possible. Upon request (via GPIO interrupts), application cycles buffer, updates screen, prefetches next page.
c_page_num++;
pg.page_num = c_page_num + 2;
pg.page_buf = pages[(c_page_num + 1) % PAGE_LEN];
xSemaphoreGive(mutex);
xQueueSend(http_evt_queue, &pg, portMAX_DELAY);
epd_draw_async(pages[c_page_num % PAGE_LEN], PAGE_SIZE);
epd_draw_await();
System isn’t as responsive as I’d hoped. Scheduling GPIO, SPI, and HTTP tasks on a single thread causes input lag. Pinned GPIO/SPI tasks to one core and the HTTP task to the other.
Better, but screen updates block user input.
Moved the SPI buffers to DMA and made the transfers async. Few more cycles saved.
Can’t think of anything else.
Verdict: Functional but limited. Led to Etlas.
Commit: 7f691c4.