--- title: 512KB e-reader date: 2023-10-24 layout: post project: true thumbnail: thumb_sm.png --- First project with e-paper. ESP-WROOM-32, 7.5" Waveshare e-paper display, three-button interface (prev/next/sleep). Memory: 512KB SRAM + 4MB 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 = 48KB (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) held in a buffer—maximum possible. Upon request, embedded software cycles the buffer, updates the screen, prefetches the 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](../etlas/). Commit: 7f691c4.