summaryrefslogtreecommitdiffstats
path: root/_log/e-reader.md
blob: a754a52d4a723eba15cf209cc1e3b5172e5c4db1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
---
title: Built a 0 MB streaming e-reader
date: 2023-10-24
layout: post
project: true
thumbnail: thumb_sm.png
---

Built an e-reader using an ESP-WROOM-32, a 7.5" Waveshare e-paper display, and
a three-button interface (prev/next/sleep).

<video style="max-width:100%;" controls="" poster="poster.png">
  <source src="ereader.mp4" type="video/mp4">
</video>

ESP-32-WROOM has 512 KB SRAM and 4 MB flash. Internal flash is unsuitable for
storing books due to P/E cycle limit. Used HTTP Range requests to stream them
on-demand. Saved reading progress to RTC memory to survive deep sleep without
flash wear.

Rasterized PDFs into sequences of bitmaps. 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);
```

Implemented a three-page circular buffer (prev/current/next)—maximum possible
with 512 KB. GPIO interrupts triggered by button presses cycle the buffer,
update the screen, and prefetch 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 core causes input lag. Pinned the GPIO/SPI tasks to one core and
the HTTP task to the other.

Better, but screen updates block user input; page turning feels sluggish. 

Moved the SPI buffers to DMA and made the transfers async, hoping to shave off
a few more cycles.

Can't think of anything else. Led to [Etlas](../etlas/).

Commit: <a
href="https://git.asciimx.com/esp32-e-reader/commit/?id=7f691c46093933b67aab466c0ca582ace8ab73d4"
class="external" target="_blank" rel="noopener noreferrer">7f691c4</a>.