summaryrefslogtreecommitdiffstats
path: root/_projects/e-reader
diff options
context:
space:
mode:
Diffstat (limited to '_projects/e-reader')
-rw-r--r--_projects/e-reader/circuit.svg145
-rw-r--r--_projects/e-reader/ereader.mp4bin0 -> 9775756 bytes
-rw-r--r--_projects/e-reader/index.md90
-rw-r--r--_projects/e-reader/source.tar.gzbin0 -> 14304 bytes
-rw-r--r--_projects/e-reader/thumb.pngbin0 -> 674187 bytes
5 files changed, 235 insertions, 0 deletions
diff --git a/_projects/e-reader/circuit.svg b/_projects/e-reader/circuit.svg
new file mode 100644
index 0000000..fd7508b
--- /dev/null
+++ b/_projects/e-reader/circuit.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Circuit Diagram, cdlibrary.dll 4.0.0.0 -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" width="680" height="360" xmlns="http://www.w3.org/2000/svg">
+ <line x1="360" y1="130" x2="360" y2="330" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="330" x2="360" y2="330" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="250" x2="70" y2="260" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="260" x2="70" y2="275" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="315" x2="70" y2="330" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 70,275 L 70,277 L 63,280 L 77,286 L 63,292 L 77,298 L 63,304 L 77,310 L 70,313 L 70,315" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="56" y="295" style="font-family:Arial;font-size:11px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 56, 295)">10 kΩ</text>
+ <line x1="70" y1="250" x2="100" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="130" y1="250" x2="190" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="100" y1="250" x2="101" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="129" y1="250" x2="130" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <ellipse cx="104" cy="250" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <ellipse cx="126" cy="250" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <line x1="103" y1="242" x2="127" y2="242" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="109" y1="236" x2="121" y2="236" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="115" y1="236" x2="115" y2="242" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="140" x2="190" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="60" x2="70" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="100" x2="100" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="130" y1="100" x2="190" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="70" y1="60" x2="100" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="130" y1="60" x2="190" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="100" y1="100" x2="101" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="129" y1="100" x2="130" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <ellipse cx="104" cy="100" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <ellipse cx="126" cy="100" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <line x1="103" y1="92" x2="127" y2="92" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="109" y1="86" x2="121" y2="86" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="115" y1="86" x2="115" y2="92" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="100" y1="60" x2="101" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="129" y1="60" x2="130" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <ellipse cx="104" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <ellipse cx="126" cy="60" rx="3" ry="3" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <line x1="103" y1="52" x2="127" y2="52" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="109" y1="46" x2="121" y2="46" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="115" y1="46" x2="115" y2="52" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="130" x2="410" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="120" x2="410" y2="120" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="110" x2="410" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="100" x2="410" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="90" x2="410" y2="90" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="80" x2="410" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="70" x2="410" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="310" y1="60" x2="420" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <line x1="450" y1="160" x2="500" y2="160" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:3" />
+ <path d="M 430,120 L 430,110 L 420,100 L 410,100" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,120 L 420,110 L 410,110" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,130 L 420,120 L 410,120" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,140 L 420,130 L 410,130" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,180 L 520,190 L 530,190" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,190 L 520,200 L 530,200" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,200 L 520,210 L 530,210" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,200 L 510,210 L 520,220 L 530,220" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="524" y="185" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 185)">1</text>
+ <text x="524" y="195" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 195)">2</text>
+ <text x="524" y="205" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 205)">3</text>
+ <text x="524" y="215" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 215)">4</text>
+ <line x1="445" y1="155" x2="450" y2="165" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:1" />
+ <line x1="495" y1="155" x2="490" y2="165" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:1" />
+ <path d="M 455,160 L 440,160 L 430,150 L 430,80" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:3" />
+ <path d="M 485,160 L 500,160 L 510,170 L 510,240" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:3" />
+ <path d="M 430,80 L 430,70 L 420,60 L 410,60" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,80 L 420,70 L 410,70" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,90 L 420,80 L 410,80" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 430,100 L 420,90 L 410,90" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="413" y="55" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 55)">1</text>
+ <text x="413" y="65" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 65)">2</text>
+ <text x="413" y="75" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 75)">3</text>
+ <text x="413" y="85" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 85)">4</text>
+ <text x="413" y="95" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 95)">5</text>
+ <text x="413" y="105" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 105)">6</text>
+ <text x="413" y="115" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 115)">7</text>
+ <text x="413" y="125" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 413, 125)">8</text>
+ <path d="M 510,220 L 520,230 L 530,230" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,230 L 520,240 L 530,240" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,240 L 520,250 L 530,250" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <path d="M 510,240 L 510,250 L 520,260 L 530,260" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="524" y="225" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 225)">5</text>
+ <text x="524" y="235" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 235)">6</text>
+ <text x="524" y="245" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 245)">7</text>
+ <text x="524" y="255" style="font-family:Arial;font-size:8px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 524, 255)">8</text>
+ <text x="470" y="155" style="font-family:Arial;font-size:11px;text-anchor:middle" dominant-baseline="baseline" transform="rotate(0, 470, 155)">BUS</text>
+ <text x="590" y="170" style="font-family:Arial;font-size:11px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 590, 170)">E-Paper Display HAT</text>
+ <rect x="540" y="180" width="100" height="90" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <line x1="530" y1="190" x2="540" y2="190" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="190" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 190)">CS</text>
+ <line x1="530" y1="200" x2="540" y2="200" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="200" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 200)">DC</text>
+ <line x1="530" y1="210" x2="540" y2="210" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="210" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 210)">DIN</text>
+ <line x1="530" y1="220" x2="540" y2="220" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="220" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 220)">CLK</text>
+ <line x1="530" y1="230" x2="540" y2="230" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="230" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 230)">BUSY</text>
+ <line x1="530" y1="240" x2="540" y2="240" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="240" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 240)">RST</text>
+ <line x1="530" y1="250" x2="540" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="250" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 250)">GND</text>
+ <line x1="530" y1="260" x2="540" y2="260" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="544" y="260" style="font-family:Arial;font-size:11px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 544, 260)">VCC</text>
+ <rect x="200" y="50" width="100" height="210" style="fill-opacity:0;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <text x="250" y="40" style="font-family:Arial;font-size:11px;text-anchor:middle" dominant-baseline="middle" transform="rotate(0, 250, 40)">ESP-WROOM-32</text>
+ <line x1="190" y1="60" x2="200" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="204" y="60" style="font-family:Arial;font-size:10px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 204, 60)">IO21</text>
+ <text x="196" y="58" style="font-family:Arial;font-size:8px;text-anchor:end" dominant-baseline="baseline" transform="rotate(0, 196, 58)"></text>
+ <line x1="300" y1="60" x2="310" y2="60" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="60" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 60)">IO5</text>
+ <text x="304" y="58" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 58)"></text>
+ <line x1="300" y1="70" x2="310" y2="70" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="70" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 70)">IO16</text>
+ <text x="304" y="68" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 68)"></text>
+ <line x1="300" y1="80" x2="310" y2="80" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="80" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 80)">IO23</text>
+ <text x="304" y="78" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 78)"></text>
+ <line x1="300" y1="90" x2="310" y2="90" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="90" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 90)">IO18</text>
+ <text x="304" y="88" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 88)"></text>
+ <line x1="190" y1="100" x2="200" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="204" y="100" style="font-family:Arial;font-size:10px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 204, 100)">IO22</text>
+ <text x="196" y="98" style="font-family:Arial;font-size:8px;text-anchor:end" dominant-baseline="baseline" transform="rotate(0, 196, 98)"></text>
+ <line x1="300" y1="100" x2="310" y2="100" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="100" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 100)">IO4</text>
+ <text x="304" y="98" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 98)"></text>
+ <line x1="300" y1="110" x2="310" y2="110" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="110" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 110)">IO2</text>
+ <text x="304" y="108" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 108)"></text>
+ <line x1="300" y1="120" x2="310" y2="120" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="120" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 120)">GND</text>
+ <text x="304" y="118" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 118)"></text>
+ <line x1="300" y1="130" x2="310" y2="130" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="296" y="130" style="font-family:Arial;font-size:10px;text-anchor:end" dominant-baseline="middle" transform="rotate(0, 296, 130)">3V3</text>
+ <text x="304" y="128" style="font-family:Arial;font-size:8px;text-anchor:start" dominant-baseline="baseline" transform="rotate(0, 304, 128)"></text>
+ <line x1="190" y1="140" x2="200" y2="140" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="204" y="140" style="font-family:Arial;font-size:10px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 204, 140)">GND</text>
+ <text x="196" y="138" style="font-family:Arial;font-size:8px;text-anchor:end" dominant-baseline="baseline" transform="rotate(0, 196, 138)"></text>
+ <line x1="190" y1="250" x2="200" y2="250" style="stroke:rgb(0, 0, 0);stroke-linecap:square;stroke-width:2" />
+ <text x="204" y="250" style="font-family:Arial;font-size:10px;text-anchor:start" dominant-baseline="middle" transform="rotate(0, 204, 250)">IO15</text>
+ <text x="196" y="248" style="font-family:Arial;font-size:8px;text-anchor:end" dominant-baseline="baseline" transform="rotate(0, 196, 248)"></text>
+ <ellipse cx="360" cy="130" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+ <ellipse cx="70" cy="100" rx="2" ry="2" style="fill-opacity:1;fill:rgb(0, 0, 0);stroke:rgb(0, 0, 0);stroke-width:2" />
+</svg> \ No newline at end of file
diff --git a/_projects/e-reader/ereader.mp4 b/_projects/e-reader/ereader.mp4
new file mode 100644
index 0000000..a57a5b1
--- /dev/null
+++ b/_projects/e-reader/ereader.mp4
Binary files differ
diff --git a/_projects/e-reader/index.md b/_projects/e-reader/index.md
new file mode 100644
index 0000000..a19603a
--- /dev/null
+++ b/_projects/e-reader/index.md
@@ -0,0 +1,90 @@
+---
+title: Prototype e-reader
+date: 2023-10-24T00:00:00+08:00
+author: W. D. Sadeep Madurange
+---
+
+This project features a prototype e-reader powered by a 7.5-inch {{< link
+src="https://www.waveshare.com/" class="external" target="_blank"
+rel="noopener noreferrer">}}Waveshare{{< /link >}} e-paper display and an
+ESP-WROOM-32 development board.
+
+<video style="max-width:100%" controls="" poster=thumb.png>
+ <source src="ereader.mp4" type="video/mp4">
+</video>
+
+{{< toc >}}
+
+## Overview
+
+In 2017, during a short stint as a project manager, I was tasked with
+installing some e-paper displays in a car park. Not knowing how they worked, I
+remember marveling at their sight like a muggle witnessing magic. As someone
+who enjoys reading, I found e-paper to be a true innovation. This project was
+born out of that enduring curiosity and love of e-paper technology.
+
+The prototype, while far from ready for daily use, has some nifty features that
+fellow hobbyists and tinkerers may find interesting. The reader can display
+books of arbitrary sizes by streaming them over HTTP. It employs sleep modes to
+minimize power consumption when not in use and records the reading progress in
+the chip's RTC memory.
+
+The following schematic outlines the electrical connections of the e-reader.
+
+![circuit](circuit.svg)
+
+The biggest challenge when building an e-reader using an ESP32 board is its low
+memory and lack of storage. My ESP-WROOM-32 board has 512 KB of SRAM and 4 MB
+of flash memory, which the freeRTOS, ESP-IDF, and my own program have to share.
+To put things into perspective, compare that to a Kindle Paperwhite, which has
+at least 256 MB of memory and 8 GB of storage.
+
+Despite its constraints, as microcontrollers go, ESP32 is a powerful
+system-on-a-chip with a 160 MHz dual-core processor and integrated WiFi. So, I
+thought it’d be amusing to embrace the constraints and build my e-reader using
+just a $5 MCU and the power of C programming.
+
+## The file format
+
+The file format dictates the complexity of the embedded software. So, I’ll
+begin there. The e-reader works by downloading and rendering a rasterized
+monochrome image of a page (a .ebm file).
+
+The EBM file contains a series of bitmaps, where each bitmap corresponds to a
+page of a book sized to fit the e-paper display. Each byte contains information
+for rendering eight pixels. For my display, which has a resolution of 480x800,
+the bitmaps are laid out along 48 KB boundaries. This simple file format lends
+well to HTTP streaming, which is its main advantage, as we will soon see.
+
+The enclosed pdftoebm.py script in the tarball at the end of the page converts
+PDF documents to an EBM file. I use it to make EBM files before uploading them
+to a web server.
+
+## How does it work?
+
+As the e-reader has no storage, it can't store books locally. Instead, I first
+have to upload the EBM file I want to read to a web server. The location of the
+file is configured via the `EBM_ARCH_URL` setting in the Kconfig.projbuild
+file. To read a different book, I create an EBM file with the same name and
+upload it to the original location. That way, I don't have to recompile the
+embedded software.
+
+Upon powering up, the e-reader checks the reading progress stored in the RTC
+memory. It then downloads three pages (current, previous, and next) to a
+circular buffer in DMA-capable memory. When the user turns a page, one of the
+two cores of the MCU transfers it from the buffer to the display over a Serial
+Peripheral Interface (SPI). The other downloads a new page in the background. I
+use the ESP-IDF task API to pin the two routines to each core.
+
+I designed the EBM format with HTTP streaming in mind. To download a page based
+on the current reading progress, the e-reader specifies the page offset and the
+chunk size using the HTTP Range header.
+
+## Afterword
+
+It's been six years since the car park and the displays. At the time, I knew
+nothing about embedded systems or display drivers. It took a long time to
+develop the skill set, but now, at last, I know how those displays worked and
+how to build my own.
+
+Files: [source.tar.gz](source.tar.gz)
diff --git a/_projects/e-reader/source.tar.gz b/_projects/e-reader/source.tar.gz
new file mode 100644
index 0000000..3e343a7
--- /dev/null
+++ b/_projects/e-reader/source.tar.gz
Binary files differ
diff --git a/_projects/e-reader/thumb.png b/_projects/e-reader/thumb.png
new file mode 100644
index 0000000..1e222d2
--- /dev/null
+++ b/_projects/e-reader/thumb.png
Binary files differ