Compare commits
40
Commits
badges
..
c62b8eff38
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c62b8eff38 | ||
|
|
73102392dd | ||
|
|
5f38e3865e | ||
|
|
0e6a8d53eb | ||
|
|
25b20fdbbd | ||
|
|
a1775baa76 | ||
|
|
70c0b4a1f2 | ||
|
|
5a573c901e | ||
|
|
4b4e9612a0 | ||
|
|
c76f8696c7 | ||
|
|
d6bdc2ce40 | ||
|
|
dd392d2e15 | ||
|
|
8f6205dcfe | ||
|
|
0f9e38eb7c | ||
|
|
a552eb0951 | ||
|
|
01e79dfa4b | ||
|
|
678e1acf29 | ||
|
|
b1e75528e5 | ||
|
|
b2ede1c481 | ||
|
|
472606dfa5 | ||
|
|
31e4c0c1ee | ||
|
|
2aae1a88ea | ||
|
|
18be4306bf | ||
|
|
7518bcf835 | ||
|
|
5d3e7fae7b | ||
|
|
b5ae08c2b5 | ||
|
|
cda1ec3363 | ||
|
|
fe140ba91f | ||
|
|
4811367905 | ||
|
|
11dc30ba8d | ||
|
|
531d02735c | ||
|
|
1993b0bf48 | ||
|
|
284a6e3393 | ||
|
|
60426432a0 | ||
|
|
06c4a8504b | ||
|
|
131d39080e | ||
|
|
c4b4b0a298 | ||
|
|
68b3570040 | ||
|
|
9862c3124a | ||
|
|
2e926ab87a |
@@ -1,58 +0,0 @@
|
|||||||
<svg width="140" height="20" viewBox="0 0 140 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
|
||||||
<title>interrogate: 99.7%</title>
|
|
||||||
<g transform="matrix(1,0,0,1,22,0)">
|
|
||||||
<g id="backgrounds" transform="matrix(1.32789,0,0,1,-22.3892,0)">
|
|
||||||
<rect x="0" y="0" width="71" height="20" style="fill:rgb(85,85,85);"/>
|
|
||||||
</g>
|
|
||||||
<rect x="71" y="0" width="47" height="20" data-interrogate="color" style="fill:#4c1"/>
|
|
||||||
<g transform="matrix(1.19746,0,0,1,-22.3744,-4.85723e-16)">
|
|
||||||
<rect x="0" y="0" width="118" height="20" style="fill:url(#_Linear1);"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
|
||||||
<text x="590" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="610">interrogate</text>
|
|
||||||
<text x="590" y="140" transform="scale(.1)" textLength="610">interrogate</text>
|
|
||||||
<text x="1160" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370" data-interrogate="result">99.7%</text>
|
|
||||||
<text x="1160" y="140" transform="scale(.1)" textLength="370" data-interrogate="result">99.7%</text>
|
|
||||||
</g>
|
|
||||||
<g id="logo-shadow" serif:id="logo shadow" transform="matrix(0.854876,0,0,0.854876,-6.73514,1.732)">
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M50,64.25C52.76,64.25 55,61.13 55,59.75C55,58.37 52.76,57.25 50,57.25C47.24,57.25 45,58.37 45,59.75C45,61.13 47.24,64.25 50,64.25Z" style="fill:rgb(1,1,1);fill-opacity:0.3;fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M88,49.05C86.506,43.475 83.018,38.638 78.2,35.46C72.969,32.002 66.539,30.844 60.43,32.26C56.576,33.145 52.995,34.958 50,37.54C46.998,34.958 43.411,33.149 39.55,32.27C33.441,30.853 27.011,32.011 21.78,35.47C16.97,38.652 13.489,43.489 12,49.06L12,49.13C11.82,49.79 11.66,50.46 11.53,51.13C11.146,53.207 11.021,55.323 11.16,57.43C11.16,58.03 11.26,58.63 11.34,59.23C11.34,59.51 11.43,59.79 11.48,60.07C11.53,60.35 11.58,60.68 11.64,60.98C11.7,61.28 11.8,61.69 11.89,62.05C11.98,62.41 11.99,62.47 12.05,62.68C12.16,63.07 12.28,63.46 12.41,63.84L12.58,64.34C12.72,64.74 12.88,65.14 13.04,65.53L13.23,65.98C13.403,66.373 13.583,66.767 13.77,67.16L13.99,67.59C14.19,67.97 14.39,68.35 14.61,68.73L14.87,69.15C15.1,69.52 15.33,69.89 15.58,70.26L15.58,70.32L15.99,70.93C16.14,71.14 16.29,71.36 16.45,71.57C20.206,75.83 25.086,78.95 30.53,80.57C36.839,82.48 43.41,83.385 50,83.25C56.599,83.374 63.177,82.456 69.49,80.53C74.644,78.978 79.303,76.102 83,72.19C83.34,71.78 83.65,71.35 84,70.92L84.18,70.66L84.33,70.44L84.41,70.32C84.55,70.12 84.67,69.9 84.81,69.7C85.07,69.3 85.32,68.89 85.55,68.48C85.78,68.07 86.02,67.65 86.23,67.22C86.31,67.05 86.39,66.88 86.47,66.7C86.67,66.28 86.85,65.87 87.03,65.44L87.23,64.92C87.397,64.487 87.55,64.05 87.69,63.61L87.85,63.09C87.98,62.64 88.1,62.19 88.21,61.74C88.21,61.57 88.3,61.39 88.33,61.22C88.43,60.75 88.52,60.22 88.6,59.79C88.6,59.64 88.66,59.49 88.68,59.33C88.77,58.71 88.84,58.08 88.88,57.45L88.88,54.17C88.817,53.164 88.693,52.162 88.51,51.17C88.38,50.5 88.23,49.84 88.05,49.17L88,49.05ZM85.89,56.44L85.89,57.23C85.89,57.78 85.79,58.32 85.72,58.86C85.72,59.01 85.72,59.15 85.65,59.3C85.59,59.7 85.51,60.11 85.43,60.51L85.32,60.99C85.23,61.38 85.12,61.77 85.01,62.16C85.01,62.31 84.93,62.46 84.88,62.6C84.74,63.04 84.59,63.47 84.42,63.9L84.27,64.28C84.1,64.71 83.91,65.14 83.71,65.56C83.51,65.98 83.43,66.12 83.28,66.4L83.01,66.91C82.83,67.223 82.643,67.537 82.45,67.85L82.35,68.01C79.121,68.047 75.918,67.434 72.93,66.21C64.27,62.74 59,55.52 61.18,50.11C62.18,47.6 64.7,45.82 68.26,45.11C72.489,44.395 76.835,44.908 80.78,46.59C82.141,47.144 83.453,47.813 84.7,48.59C84.76,48.76 84.82,48.93 84.88,49.1C84.94,49.27 85.05,49.63 85.12,49.9C85.28,50.5 85.44,51.1 85.55,51.73C85.691,52.507 85.792,53.292 85.85,54.08L85.85,55.89C85.85,56.12 85.91,56.25 85.91,56.45L85.89,56.44ZM17.66,68C16.668,66.435 15.869,64.756 15.28,63L15.17,62.68C15.06,62.35 14.96,62.01 14.87,61.68C14.823,61.493 14.777,61.31 14.73,61.13C14.66,60.84 14.59,60.55 14.53,60.27C14.47,59.99 14.43,59.72 14.38,59.44C14.33,59.16 14.3,59 14.27,58.78C14.2,58.27 14.15,57.78 14.11,57.23L14.11,57.03C14.008,55.236 14.122,53.437 14.45,51.67C14.56,51.06 14.71,50.46 14.88,49.87C14.96,49.59 15.04,49.32 15.13,49.05C15.22,48.78 15.24,48.72 15.3,48.55C16.548,47.774 17.859,47.105 19.22,46.55C27.86,43.09 36.65,44.67 38.82,50.08C40.99,55.49 35.73,62.74 27.09,66.2C24.101,67.431 20.893,68.043 17.66,68ZM68.57,77.68C62.554,79.508 56.287,80.376 50,80.25C43.737,80.37 37.495,79.506 31.5,77.69C27.185,76.38 23.243,74.062 20,70.93C22.815,70.706 25.58,70.055 28.2,69C38.37,64.92 44.39,56 41.6,49C38.81,42 28.27,39.72 18.1,43.8L17.43,44.09C18.973,41.648 21.019,39.561 23.43,37.97C26.671,35.824 30.473,34.68 34.36,34.68C35.884,34.681 37.404,34.852 38.89,35.19C42.694,36.049 46.191,37.935 49,40.64L50,41.64L51,40.64C53.797,37.937 57.279,36.049 61.07,35.18C66.402,33.947 72.014,34.968 76.57,38C78.98,39.588 81.026,41.671 82.57,44.11L81.9,43.82C77.409,41.921 72.464,41.355 67.66,42.19C63.08,43.12 59.79,45.54 58.39,49.02C55.6,55.97 61.62,64.94 71.79,69.02C74.414,70.07 77.182,70.714 80,70.93C76.776,74.05 72.859,76.363 68.57,77.68Z" style="fill:rgb(1,1,1);fill-opacity:0.3;fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<circle cx="71.33" cy="56" r="5.16" style="fill:rgb(1,1,1);fill-opacity:0.3;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<circle cx="28.67" cy="56" r="5.16" style="fill:rgb(1,1,1);fill-opacity:0.3;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M58,66C55.912,68.161 53.003,69.339 50,69.24C46.997,69.339 44.088,68.161 42,66C41.714,65.677 41.302,65.491 40.87,65.491C40.042,65.491 39.361,66.172 39.361,67C39.361,67.368 39.496,67.724 39.74,68C42.403,70.804 46.134,72.35 50,72.25C53.862,72.347 57.59,70.802 60.25,68C60.495,67.725 60.63,67.369 60.63,67C60.63,66.174 59.951,65.495 59.125,65.495C58.695,65.495 58.285,65.679 58,66Z" style="fill:rgb(1,1,1);fill-opacity:0.3;fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="logo-pink" serif:id="logo pink" transform="matrix(0.854876,0,0,0.854876,-6.73514,0.877124)">
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M50,64.25C52.76,64.25 55,61.13 55,59.75C55,58.37 52.76,57.25 50,57.25C47.24,57.25 45,58.37 45,59.75C45,61.13 47.24,64.25 50,64.25Z" style="fill:rgb(222,120,160);fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M88,49.05C86.506,43.475 83.018,38.638 78.2,35.46C72.969,32.002 66.539,30.844 60.43,32.26C56.576,33.145 52.995,34.958 50,37.54C46.998,34.958 43.411,33.149 39.55,32.27C33.441,30.853 27.011,32.011 21.78,35.47C16.97,38.652 13.489,43.489 12,49.06L12,49.13C11.82,49.79 11.66,50.46 11.53,51.13C11.146,53.207 11.021,55.323 11.16,57.43C11.16,58.03 11.26,58.63 11.34,59.23C11.34,59.51 11.43,59.79 11.48,60.07C11.53,60.35 11.58,60.68 11.64,60.98C11.7,61.28 11.8,61.69 11.89,62.05C11.98,62.41 11.99,62.47 12.05,62.68C12.16,63.07 12.28,63.46 12.41,63.84L12.58,64.34C12.72,64.74 12.88,65.14 13.04,65.53L13.23,65.98C13.403,66.373 13.583,66.767 13.77,67.16L13.99,67.59C14.19,67.97 14.39,68.35 14.61,68.73L14.87,69.15C15.1,69.52 15.33,69.89 15.58,70.26L15.58,70.32L15.99,70.93C16.14,71.14 16.29,71.36 16.45,71.57C20.206,75.83 25.086,78.95 30.53,80.57C36.839,82.48 43.41,83.385 50,83.25C56.599,83.374 63.177,82.456 69.49,80.53C74.644,78.978 79.303,76.102 83,72.19C83.34,71.78 83.65,71.35 84,70.92L84.18,70.66L84.33,70.44L84.41,70.32C84.55,70.12 84.67,69.9 84.81,69.7C85.07,69.3 85.32,68.89 85.55,68.48C85.78,68.07 86.02,67.65 86.23,67.22C86.31,67.05 86.39,66.88 86.47,66.7C86.67,66.28 86.85,65.87 87.03,65.44L87.23,64.92C87.397,64.487 87.55,64.05 87.69,63.61L87.85,63.09C87.98,62.64 88.1,62.19 88.21,61.74C88.21,61.57 88.3,61.39 88.33,61.22C88.43,60.75 88.52,60.22 88.6,59.79C88.6,59.64 88.66,59.49 88.68,59.33C88.77,58.71 88.84,58.08 88.88,57.45L88.88,54.17C88.817,53.164 88.693,52.162 88.51,51.17C88.38,50.5 88.23,49.84 88.05,49.17L88,49.05ZM85.89,56.44L85.89,57.23C85.89,57.78 85.79,58.32 85.72,58.86C85.72,59.01 85.72,59.15 85.65,59.3C85.59,59.7 85.51,60.11 85.43,60.51L85.32,60.99C85.23,61.38 85.12,61.77 85.01,62.16C85.01,62.31 84.93,62.46 84.88,62.6C84.74,63.04 84.59,63.47 84.42,63.9L84.27,64.28C84.1,64.71 83.91,65.14 83.71,65.56C83.51,65.98 83.43,66.12 83.28,66.4L83.01,66.91C82.83,67.223 82.643,67.537 82.45,67.85L82.35,68.01C79.121,68.047 75.918,67.434 72.93,66.21C64.27,62.74 59,55.52 61.18,50.11C62.18,47.6 64.7,45.82 68.26,45.11C72.489,44.395 76.835,44.908 80.78,46.59C82.141,47.144 83.453,47.813 84.7,48.59C84.76,48.76 84.82,48.93 84.88,49.1C84.94,49.27 85.05,49.63 85.12,49.9C85.28,50.5 85.44,51.1 85.55,51.73C85.691,52.507 85.792,53.292 85.85,54.08L85.85,55.89C85.85,56.12 85.91,56.25 85.91,56.45L85.89,56.44ZM17.66,68C16.668,66.435 15.869,64.756 15.28,63L15.17,62.68C15.06,62.35 14.96,62.01 14.87,61.68C14.823,61.493 14.777,61.31 14.73,61.13C14.66,60.84 14.59,60.55 14.53,60.27C14.47,59.99 14.43,59.72 14.38,59.44C14.33,59.16 14.3,59 14.27,58.78C14.2,58.27 14.15,57.78 14.11,57.23L14.11,57.03C14.008,55.236 14.122,53.437 14.45,51.67C14.56,51.06 14.71,50.46 14.88,49.87C14.96,49.59 15.04,49.32 15.13,49.05C15.22,48.78 15.24,48.72 15.3,48.55C16.548,47.774 17.859,47.105 19.22,46.55C27.86,43.09 36.65,44.67 38.82,50.08C40.99,55.49 35.73,62.74 27.09,66.2C24.101,67.431 20.893,68.043 17.66,68ZM68.57,77.68C62.554,79.508 56.287,80.376 50,80.25C43.737,80.37 37.495,79.506 31.5,77.69C27.185,76.38 23.243,74.062 20,70.93C22.815,70.706 25.58,70.055 28.2,69C38.37,64.92 44.39,56 41.6,49C38.81,42 28.27,39.72 18.1,43.8L17.43,44.09C18.973,41.648 21.019,39.561 23.43,37.97C26.671,35.824 30.473,34.68 34.36,34.68C35.884,34.681 37.404,34.852 38.89,35.19C42.694,36.049 46.191,37.935 49,40.64L50,41.64L51,40.64C53.797,37.937 57.279,36.049 61.07,35.18C66.402,33.947 72.014,34.968 76.57,38C78.98,39.588 81.026,41.671 82.57,44.11L81.9,43.82C77.409,41.921 72.464,41.355 67.66,42.19C63.08,43.12 59.79,45.54 58.39,49.02C55.6,55.97 61.62,64.94 71.79,69.02C74.414,70.07 77.182,70.714 80,70.93C76.776,74.05 72.859,76.363 68.57,77.68Z" style="fill:rgb(222,120,160);fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<circle cx="71.33" cy="56" r="5.16" style="fill:rgb(222,120,160);"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<circle cx="28.67" cy="56" r="5.16" style="fill:rgb(222,120,160);"/>
|
|
||||||
</g>
|
|
||||||
<g transform="matrix(0.299012,0,0,0.299012,9.70229,-6.68582)">
|
|
||||||
<path d="M58,66C55.912,68.161 53.003,69.339 50,69.24C46.997,69.339 44.088,68.161 42,66C41.714,65.677 41.302,65.491 40.87,65.491C40.042,65.491 39.361,66.172 39.361,67C39.361,67.368 39.496,67.724 39.74,68C42.403,70.804 46.134,72.35 50,72.25C53.862,72.347 57.59,70.802 60.25,68C60.495,67.725 60.63,67.369 60.63,67C60.63,66.174 59.951,65.495 59.125,65.495C58.695,65.495 58.285,65.679 58,66Z" style="fill:rgb(222,120,160);fill-rule:nonzero;"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.22465e-15,20,-20,1.22465e-15,0,0)">
|
|
||||||
<stop offset="0" style="stop-color:rgb(187,187,187);stop-opacity:0.1"/>
|
|
||||||
<stop offset="1" style="stop-color:black;stop-opacity:0.1"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="20" role="img" aria-label="coverage: failed"><title>coverage: failed</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="100" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="39" height="20" fill="#e05d44"/><rect width="100" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="795" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">failed</text><text x="795" y="140" transform="scale(.1)" fill="#fff" textLength="290">failed</text></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
Executable
+201
@@ -0,0 +1,201 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simple test to verify the hardware HAL can display images.
|
||||||
|
Creates a test pattern and displays it on the e-ink screen.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import asyncio
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
# Add parent directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from dreader.hal_hardware import HardwareDisplayHAL
|
||||||
|
|
||||||
|
|
||||||
|
def create_test_image(width=1404, height=1872 ):
|
||||||
|
"""Create a test pattern image."""
|
||||||
|
print("Creating test image...")
|
||||||
|
|
||||||
|
# Create white background
|
||||||
|
img = Image.new('RGBA', (width, height), color='white')
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Draw border
|
||||||
|
border_width = 10
|
||||||
|
draw.rectangle(
|
||||||
|
[(border_width, border_width),
|
||||||
|
(width - border_width, height - border_width)],
|
||||||
|
outline='black',
|
||||||
|
width=border_width
|
||||||
|
)
|
||||||
|
|
||||||
|
# Draw title
|
||||||
|
try:
|
||||||
|
font_large = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 80)
|
||||||
|
font_medium = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 50)
|
||||||
|
except:
|
||||||
|
font_large = ImageFont.load_default()
|
||||||
|
font_medium = ImageFont.load_default()
|
||||||
|
|
||||||
|
# Center text
|
||||||
|
title = "Hardware Display Test"
|
||||||
|
title_bbox = draw.textbbox((0, 0), title, font=font_large)
|
||||||
|
title_width = title_bbox[2] - title_bbox[0]
|
||||||
|
title_x = (width - title_width) // 2
|
||||||
|
draw.text((title_x, 100), title, fill='black', font=font_large)
|
||||||
|
|
||||||
|
# Instructions
|
||||||
|
instructions = [
|
||||||
|
"If you can see this, the display is working!",
|
||||||
|
"",
|
||||||
|
"Test pattern includes:",
|
||||||
|
"• Border around the screen",
|
||||||
|
"• Centered text",
|
||||||
|
"• Diagonal lines",
|
||||||
|
"• Corner markers"
|
||||||
|
]
|
||||||
|
|
||||||
|
y = 250
|
||||||
|
for line in instructions:
|
||||||
|
if line:
|
||||||
|
bbox = draw.textbbox((0, 0), line, font=font_medium)
|
||||||
|
line_width = bbox[2] - bbox[0]
|
||||||
|
x = (width - line_width) // 2
|
||||||
|
draw.text((x, y), line, fill='black', font=font_medium)
|
||||||
|
y += 70
|
||||||
|
|
||||||
|
# Draw diagonal lines
|
||||||
|
draw.line([(50, 50), (width-50, height-50)], fill='black', width=3)
|
||||||
|
draw.line([(width-50, 50), (50, height-50)], fill='black', width=3)
|
||||||
|
|
||||||
|
# Draw corner markers
|
||||||
|
marker_size = 100
|
||||||
|
# Top-left
|
||||||
|
draw.rectangle([(20, 20), (20 + marker_size, 20 + marker_size)],
|
||||||
|
fill='black')
|
||||||
|
draw.text((30, 30), "TL", fill='white', font=font_medium)
|
||||||
|
|
||||||
|
# Top-right
|
||||||
|
draw.rectangle([(width - 20 - marker_size, 20),
|
||||||
|
(width - 20, 20 + marker_size)],
|
||||||
|
fill='black')
|
||||||
|
draw.text((width - 100, 30), "TR", fill='white', font=font_medium)
|
||||||
|
|
||||||
|
# Bottom-left
|
||||||
|
draw.rectangle([(20, height - 20 - marker_size),
|
||||||
|
(20 + marker_size, height - 20)],
|
||||||
|
fill='black')
|
||||||
|
draw.text((30, height - 100), "BL", fill='white', font=font_medium)
|
||||||
|
|
||||||
|
# Bottom-right
|
||||||
|
draw.rectangle([(width - 20 - marker_size, height - 20 - marker_size),
|
||||||
|
(width - 20, height - 20)],
|
||||||
|
fill='black')
|
||||||
|
draw.text((width - 100, height - 100), "BR", fill='white', font=font_medium)
|
||||||
|
|
||||||
|
print(f"Test image created: {width}x{height} RGBA")
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
async def main(args):
|
||||||
|
"""Test hardware display."""
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("Hardware Display Test")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Get VCOM from args
|
||||||
|
vcom = args.vcom if hasattr(args, 'vcom') else -1.65
|
||||||
|
print(f"Using VCOM: {vcom}V")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Create test image
|
||||||
|
test_image = create_test_image(1872, 1404)
|
||||||
|
|
||||||
|
# Save test image for reference
|
||||||
|
output_file = "test_pattern.png"
|
||||||
|
test_image.save(output_file)
|
||||||
|
print(f"Test pattern saved to: {output_file}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Initialize hardware HAL
|
||||||
|
print("Initializing hardware HAL...")
|
||||||
|
hal = HardwareDisplayHAL(
|
||||||
|
width=1872,
|
||||||
|
height=1404,
|
||||||
|
vcom=vcom,
|
||||||
|
config_file="hardware_config.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Initializing hardware components...")
|
||||||
|
await hal.initialize()
|
||||||
|
print("✓ Hardware initialized")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Display the test image
|
||||||
|
print("Displaying test image on e-ink screen...")
|
||||||
|
print("(This may take a few seconds for the full refresh)")
|
||||||
|
print(f"Converting image from {test_image.mode} to grayscale for e-ink...")
|
||||||
|
|
||||||
|
# Convert RGBA to grayscale (L mode) for e-ink display
|
||||||
|
if test_image.mode == 'RGBA':
|
||||||
|
# Convert RGBA to RGB first (flatten alpha)
|
||||||
|
rgb_image = Image.new('RGB', test_image.size, (255, 255, 255))
|
||||||
|
rgb_image.paste(test_image, mask=test_image.split()[3]) # Use alpha as mask
|
||||||
|
test_image_gray = rgb_image.convert('L')
|
||||||
|
else:
|
||||||
|
test_image_gray = test_image.convert('L')
|
||||||
|
|
||||||
|
print(f"Image converted to {test_image_gray.mode} mode")
|
||||||
|
await hal.show_image(test_image_gray)
|
||||||
|
print("✓ Image displayed!")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("SUCCESS!")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
print("If you can see the test pattern on the screen, the")
|
||||||
|
print("hardware display is working correctly!")
|
||||||
|
print()
|
||||||
|
print("Check that you can see:")
|
||||||
|
print(" • Black border around the edges")
|
||||||
|
print(" • Title text centered at the top")
|
||||||
|
print(" • Diagonal lines crossing the screen")
|
||||||
|
print(" • Corner markers labeled TL, TR, BL, BR")
|
||||||
|
print()
|
||||||
|
print("Press Ctrl+C to exit")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Keep running so user can see the image
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nCleaning up...")
|
||||||
|
await hal.cleanup()
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Test hardware display')
|
||||||
|
parser.add_argument('--vcom', type=float, default=-1.65,
|
||||||
|
help='VCOM voltage (check your display label, default: -1.65)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
asyncio.run(main(args))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nTest interrupted")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\nERROR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
Executable
+175
@@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to render the library view and display it on hardware.
|
||||||
|
Combines library rendering with hardware display testing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import asyncio
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add parent directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from dreader.library import LibraryManager
|
||||||
|
from dreader.hal_hardware import HardwareDisplayHAL
|
||||||
|
|
||||||
|
|
||||||
|
async def main(args):
|
||||||
|
"""Test library rendering on hardware display."""
|
||||||
|
|
||||||
|
library_path = args.library_path
|
||||||
|
output_path = "library_render_test.png"
|
||||||
|
vcom = args.vcom
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("Library Rendering on Hardware Test")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Library path: {library_path}")
|
||||||
|
print(f"VCOM: {vcom}V")
|
||||||
|
print(f"Output file: {output_path}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Step 1: Create library manager and scan
|
||||||
|
print("Step 1: Creating library manager...")
|
||||||
|
library = LibraryManager(
|
||||||
|
library_path=library_path,
|
||||||
|
page_size=(1872, 1404)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Scanning library...")
|
||||||
|
library.scan_library()
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(f"Found {len(library.books)} books:")
|
||||||
|
for i, book in enumerate(library.books[:10], 1): # Show first 10
|
||||||
|
print(f" {i}. {book['title']} by {book['author']}")
|
||||||
|
if len(library.books) > 10:
|
||||||
|
print(f" ... and {len(library.books) - 10} more")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Step 2: Create and render library table
|
||||||
|
print("Step 2: Creating library table (page 1)...")
|
||||||
|
table = library.create_library_table(page=0)
|
||||||
|
print(f"✓ Library table created: {table is not None}")
|
||||||
|
if table:
|
||||||
|
print(f" Table has {len(table.rows)} rows")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Rendering library view...")
|
||||||
|
image = library.render_library()
|
||||||
|
|
||||||
|
if not image:
|
||||||
|
print("ERROR: No image rendered!")
|
||||||
|
print(f" library.library_table = {library.library_table}")
|
||||||
|
print(f" library.rendered_page = {library.rendered_page}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print(f"✓ Library rendered: {image.size} {image.mode}")
|
||||||
|
|
||||||
|
# Check if image is not blank
|
||||||
|
import numpy as np
|
||||||
|
img_array = np.array(image)
|
||||||
|
unique_colors = len(np.unique(img_array.reshape(-1, img_array.shape[-1]), axis=0))
|
||||||
|
print(f" Image has {unique_colors} unique colors (blank would be ~1)")
|
||||||
|
|
||||||
|
# Sample some pixels to see what we have
|
||||||
|
print(f" Sample pixels:")
|
||||||
|
print(f" Top-left corner: {image.getpixel((10, 10))}")
|
||||||
|
print(f" Center: {image.getpixel((936, 702))}")
|
||||||
|
print(f" Bottom-right: {image.getpixel((1860, 1390))}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Save for reference
|
||||||
|
print(f"Saving to {output_path}...")
|
||||||
|
image.save(output_path)
|
||||||
|
print(f"✓ Saved to {output_path}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Step 3: Initialize hardware HAL
|
||||||
|
print("Step 3: Initializing hardware HAL...")
|
||||||
|
hal = HardwareDisplayHAL(
|
||||||
|
width=1872,
|
||||||
|
height=1404,
|
||||||
|
vcom=vcom,
|
||||||
|
config_file="hardware_config.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Initializing hardware components...")
|
||||||
|
await hal.initialize()
|
||||||
|
print("✓ Hardware initialized")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Step 4: Display on e-ink screen
|
||||||
|
print("Step 4: Displaying library on e-ink screen...")
|
||||||
|
print("(This may take a few seconds for the full refresh)")
|
||||||
|
print(f"Converting image from {image.mode} to grayscale for e-ink...")
|
||||||
|
|
||||||
|
# Convert to grayscale (L mode) for e-ink display
|
||||||
|
if image.mode == 'RGBA':
|
||||||
|
# Convert RGBA to RGB first (flatten alpha)
|
||||||
|
rgb_image = Image.new('RGB', image.size, (255, 255, 255))
|
||||||
|
rgb_image.paste(image, mask=image.split()[3]) # Use alpha as mask
|
||||||
|
image_gray = rgb_image.convert('L')
|
||||||
|
else:
|
||||||
|
image_gray = image.convert('L')
|
||||||
|
|
||||||
|
print(f"Image converted to {image_gray.mode} mode")
|
||||||
|
await hal.show_image(image_gray)
|
||||||
|
print("✓ Image displayed!")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("SUCCESS!")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
print("The library view should now be visible on your e-ink screen.")
|
||||||
|
print()
|
||||||
|
print(f"You can also view the saved PNG: {output_path}")
|
||||||
|
print()
|
||||||
|
print("Press Ctrl+C to exit")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Keep running so user can see the image
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nCleaning up...")
|
||||||
|
await hal.cleanup()
|
||||||
|
print("Done!")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Test library rendering on hardware display'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'library_path',
|
||||||
|
nargs='?',
|
||||||
|
default='tests/data/library-epub',
|
||||||
|
help='Path to library directory (default: tests/data/library-epub)'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--vcom',
|
||||||
|
type=float,
|
||||||
|
default=-1.65,
|
||||||
|
help='VCOM voltage (check your display label, default: -1.65)'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
exit_code = asyncio.run(main(args))
|
||||||
|
sys.exit(exit_code or 0)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nTest interrupted")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\nERROR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
Executable
+89
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to render the library view and save it as PNG.
|
||||||
|
This helps verify the rendering is working correctly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add parent directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from dreader.library import LibraryManager
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Test library rendering and save as PNG."""
|
||||||
|
|
||||||
|
library_path = "tests/data/library-epub"
|
||||||
|
output_path = "library_render_test.png"
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("Library Rendering Test")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Library path: {library_path}")
|
||||||
|
print(f"Output file: {output_path}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Create library manager
|
||||||
|
print("Creating library manager...")
|
||||||
|
library = LibraryManager(
|
||||||
|
library_path=library_path,
|
||||||
|
page_size=(1872, 1404)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Scan library
|
||||||
|
print("Scanning library...")
|
||||||
|
library.scan_library()
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(f"Found {len(library.books)} books:")
|
||||||
|
for book in library.books:
|
||||||
|
print(f" - {book['title']} by {book['author']}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Create library table (renders the first page)
|
||||||
|
print("Creating library table (page 1)...")
|
||||||
|
library.create_library_table(page=0)
|
||||||
|
|
||||||
|
# Render the table
|
||||||
|
print("Rendering library view...")
|
||||||
|
image = library.render_library()
|
||||||
|
|
||||||
|
if image:
|
||||||
|
print(f"Image size: {image.size}")
|
||||||
|
print(f"Image mode: {image.mode}")
|
||||||
|
|
||||||
|
# Save as PNG
|
||||||
|
print(f"Saving to {output_path}...")
|
||||||
|
image.save(output_path)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("=" * 60)
|
||||||
|
print("SUCCESS!")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Library view saved to: {output_path}")
|
||||||
|
print()
|
||||||
|
print("You can view the image with:")
|
||||||
|
print(f" xdg-open {output_path} # Linux")
|
||||||
|
print(f" open {output_path} # macOS")
|
||||||
|
print()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
print()
|
||||||
|
print("=" * 60)
|
||||||
|
print("ERROR: No image rendered")
|
||||||
|
print("=" * 60)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
sys.exit(main())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\nERROR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
Executable
+126
@@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simplest possible test - half black, half white screen.
|
||||||
|
This verifies the display can show black pixels.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import asyncio
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
|
# Add parent directory to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from dreader.hal_hardware import HardwareDisplayHAL
|
||||||
|
|
||||||
|
|
||||||
|
def create_simple_test():
|
||||||
|
"""Create a simple half-black, half-white test image."""
|
||||||
|
print("Creating simple test pattern...")
|
||||||
|
print("Left half: BLACK")
|
||||||
|
print("Right half: WHITE")
|
||||||
|
|
||||||
|
width, height = 1872, 1404
|
||||||
|
|
||||||
|
# Create grayscale image (L mode = 8-bit grayscale)
|
||||||
|
img = Image.new('L', (width, height), color=255) # Start with white
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Draw left half black
|
||||||
|
draw.rectangle(
|
||||||
|
[(0, 0), (width // 2, height)],
|
||||||
|
fill=0 # 0 = black
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Test image created: {width}x{height} grayscale")
|
||||||
|
print(f" Left half ({width//2}px): BLACK (0)")
|
||||||
|
print(f" Right half ({width//2}px): WHITE (255)")
|
||||||
|
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
async def main(args):
|
||||||
|
"""Test hardware display with simple pattern."""
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("Simple Display Test - Half Black, Half White")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
|
||||||
|
vcom = args.vcom
|
||||||
|
print(f"Using VCOM: {vcom}V")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Create simple test image
|
||||||
|
test_image = create_simple_test()
|
||||||
|
|
||||||
|
# Save test image for reference
|
||||||
|
output_file = "simple_test.png"
|
||||||
|
test_image.save(output_file)
|
||||||
|
print(f"Test pattern saved to: {output_file}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Initialize hardware HAL
|
||||||
|
print("Initializing hardware HAL...")
|
||||||
|
hal = HardwareDisplayHAL(
|
||||||
|
width=1872,
|
||||||
|
height=1404,
|
||||||
|
vcom=vcom,
|
||||||
|
config_file="hardware_config.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Initializing hardware components...")
|
||||||
|
await hal.initialize()
|
||||||
|
print("✓ Hardware initialized")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Display the test image
|
||||||
|
print("Displaying test pattern on e-ink screen...")
|
||||||
|
print("(This may take a few seconds for the full refresh)")
|
||||||
|
await hal.show_image(test_image)
|
||||||
|
print("✓ Image displayed!")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("CHECK YOUR SCREEN:")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
print("You should see:")
|
||||||
|
print(" • LEFT HALF: BLACK")
|
||||||
|
print(" • RIGHT HALF: WHITE")
|
||||||
|
print()
|
||||||
|
print("If you see this, the display is working!")
|
||||||
|
print("If the screen is all white, there may be a driver issue.")
|
||||||
|
print()
|
||||||
|
print("Press Ctrl+C to exit")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Keep running so user can see the image
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nCleaning up...")
|
||||||
|
await hal.cleanup()
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Simple display test')
|
||||||
|
parser.add_argument('--vcom', type=float, default=-1.65,
|
||||||
|
help='VCOM voltage (check your display label, default: -1.65)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
asyncio.run(main(args))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nTest interrupted")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\nERROR: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
"display": {
|
"display": {
|
||||||
"width": 1872,
|
"width": 1872,
|
||||||
"height": 1404,
|
"height": 1404,
|
||||||
"vcom": -2.0,
|
"vcom": -1.7,
|
||||||
"spi_hz": 24000000,
|
"spi_hz": 24000000,
|
||||||
|
"rotate": "CW",
|
||||||
"auto_sleep": true
|
"auto_sleep": true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user