Updated svg to make it more informative on readme
Some checks failed
CI / Test (Linux) (push) Has been cancelled
CI / Test (Windows MSVC) (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled

This commit is contained in:
Eric Ratliff
2026-02-22 08:07:42 -06:00
parent 54e1ba14d1
commit fe5df7dc6d

View File

@@ -1,90 +1,124 @@
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="440" viewBox="0 0 720 440">
<svg xmlns="http://www.w3.org/2000/svg" width="740" height="520" viewBox="0 0 740 520">
<style>
@keyframes t1 { 0%, 4% { opacity: 0 } 5% { opacity: 1 } }
@keyframes t2 { 0%, 9% { opacity: 0 } 10% { opacity: 1 } }
@keyframes t3 { 0%, 11% { opacity: 0 } 12% { opacity: 1 } }
@keyframes t4 { 0%, 13% { opacity: 0 } 14% { opacity: 1 } }
@keyframes t5 { 0%, 15% { opacity: 0 } 16% { opacity: 1 } }
@keyframes t6 { 0%, 17% { opacity: 0 } 18% { opacity: 1 } }
@keyframes t7 { 0%, 19% { opacity: 0 } 20% { opacity: 1 } }
@keyframes t8 { 0%, 21% { opacity: 0 } 22% { opacity: 1 } }
@keyframes t9 { 0%, 23% { opacity: 0 } 24% { opacity: 1 } }
@keyframes t10 { 0%, 25% { opacity: 0 } 26% { opacity: 1 } }
@keyframes t11 { 0%, 27% { opacity: 0 } 28% { opacity: 1 } }
@keyframes t12 { 0%, 29% { opacity: 0 } 30% { opacity: 1 } }
@keyframes t13 { 0%, 34% { opacity: 0 } 35% { opacity: 1 } }
@keyframes t14 { 0%, 39% { opacity: 0 } 40% { opacity: 1 } }
@keyframes t15 { 0%, 44% { opacity: 0 } 45% { opacity: 1 } }
@keyframes t16 { 0%, 49% { opacity: 0 } 50% { opacity: 1 } }
@keyframes t17 { 0%, 51% { opacity: 0 } 52% { opacity: 1 } }
@keyframes t18 { 0%, 53% { opacity: 0 } 54% { opacity: 1 } }
@keyframes t19 { 0%, 58% { opacity: 0 } 59% { opacity: 1 } }
@keyframes t20 { 0%, 63% { opacity: 0 } 64% { opacity: 1 } }
@keyframes t21 { 0%, 65% { opacity: 0 } 66% { opacity: 1 } }
@keyframes t22 { 0%, 67% { opacity: 0 } 68% { opacity: 1 } }
@keyframes t23 { 0%, 72% { opacity: 0 } 73% { opacity: 1 } }
@keyframes t24 { 0%, 77% { opacity: 0 } 78% { opacity: 1 } }
/* 40s loop, 3 scenes with crossfade */
@keyframes scene1 { 0% { opacity:1 } 20% { opacity:1 } 22% { opacity:0 } 100% { opacity:0 } }
@keyframes scene2 { 0% { opacity:0 } 22% { opacity:0 } 24% { opacity:1 } 54% { opacity:1 } 56% { opacity:0 } 100% { opacity:0 } }
@keyframes scene3 { 0% { opacity:0 } 56% { opacity:0 } 58% { opacity:1 } 95% { opacity:1 } 97% { opacity:0 } 100% { opacity:0 } }
/* per-line reveals within each scene */
@keyframes s1a { 0%,1% {opacity:0} 2% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1b { 0%,3% {opacity:0} 4% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1c { 0%,5% {opacity:0} 6% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1d { 0%,6% {opacity:0} 7% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1e { 0%,7% {opacity:0} 8% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1f { 0%,8% {opacity:0} 9% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1g { 0%,9% {opacity:0} 10% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1h { 0%,10% {opacity:0} 11% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1i { 0%,11% {opacity:0} 12% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1j { 0%,13% {opacity:0} 14% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s1k { 0%,16% {opacity:0} 17% {opacity:1} 21% {opacity:1} 22% {opacity:0} 100% {opacity:0} }
@keyframes s2a { 0%,24% {opacity:0} 25% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2b { 0%,27% {opacity:0} 28% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2c { 0%,28% {opacity:0} 29% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2d { 0%,29% {opacity:0} 30% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2e { 0%,30% {opacity:0} 31% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2f { 0%,31% {opacity:0} 32% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2g { 0%,32% {opacity:0} 33% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2h { 0%,33% {opacity:0} 34% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2i { 0%,34% {opacity:0} 35% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2j { 0%,35% {opacity:0} 36% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2k { 0%,36% {opacity:0} 37% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2l { 0%,37% {opacity:0} 38% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2m { 0%,38% {opacity:0} 39% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2n { 0%,40% {opacity:0} 41% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2o { 0%,43% {opacity:0} 44% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s2p { 0%,46% {opacity:0} 47% {opacity:1} 55% {opacity:1} 56% {opacity:0} 100% {opacity:0} }
@keyframes s3a { 0%,58% {opacity:0} 59% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3b { 0%,60% {opacity:0} 61% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3c { 0%,61% {opacity:0} 62% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3d { 0%,62% {opacity:0} 63% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3e { 0%,63% {opacity:0} 64% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3f { 0%,64% {opacity:0} 65% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3g { 0%,65% {opacity:0} 66% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3h { 0%,66% {opacity:0} 67% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3i { 0%,68% {opacity:0} 69% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3j { 0%,70% {opacity:0} 71% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3k { 0%,71% {opacity:0} 72% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3l { 0%,73% {opacity:0} 74% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3m { 0%,76% {opacity:0} 77% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3n { 0%,78% {opacity:0} 79% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3o { 0%,81% {opacity:0} 82% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3p { 0%,83% {opacity:0} 84% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3q { 0%,86% {opacity:0} 87% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes s3r { 0%,89% {opacity:0} 90% {opacity:1} 96% {opacity:1} 97% {opacity:0} 100% {opacity:0} }
@keyframes cursor { 0%,49% {opacity:1} 50%,100% {opacity:0} }
.l { font-family: 'Cascadia Code', 'Fira Code', 'SF Mono', 'Consolas', monospace; font-size: 13px; fill: #c0c0c0; }
.pr { fill: #6ec06e; }
.cm { fill: #58d0f0; }
.fl { fill: #c0c0c0; }
.ok { fill: #6ec06e; }
.nm { fill: #f0c060; }
.dm { fill: #888888; }
.l { font-family:'Cascadia Code','Fira Code','SF Mono','Consolas',monospace; font-size:12.5px; }
.pr { fill:#6ec06e } .cmd { fill:#58d0f0 } .fl { fill:#c0c0c0 }
.ok { fill:#6ec06e } .kw { fill:#c586c0 } .ty { fill:#4ec9b0 }
.fn { fill:#dcdcaa } .st { fill:#ce9178 } .cm { fill:#6a9955 }
.nm { fill:#b5cea8 } .op { fill:#d4d4d4 } .pp { fill:#9cdcfe }
.dm { fill:#888888 } .hl { fill:#f0c060 }
.ann { fill:#58d0f0; font-style:italic; font-size:12px }
</style>
<!-- Background -->
<rect width="720" height="440" rx="8" fill="#1e1e2e"/>
<!-- Title bar -->
<rect width="720" height="32" rx="8" fill="#2a2a3c"/>
<rect y="24" width="720" height="8" fill="#2a2a3c"/>
<rect width="740" height="520" rx="8" fill="#1e1e2e"/>
<rect width="740" height="32" rx="8" fill="#2a2a3c"/>
<rect y="24" width="740" height="8" fill="#2a2a3c"/>
<circle cx="18" cy="16" r="6" fill="#f65f57"/>
<circle cx="38" cy="16" r="6" fill="#f9bf2f"/>
<circle cx="58" cy="16" r="6" fill="#30c840"/>
<text x="360" y="20" text-anchor="middle" font-family="Arial" font-size="13" fill="#888">anvil -- terminal</text>
<text x="370" y="20" text-anchor="middle" font-family="Arial" font-size="13" fill="#888">anvil -- from zero to tested in 30 seconds</text>
<!-- Line 1: prompt + command -->
<text y="60" class="l" opacity="0" style="animation: t1 24s infinite">
<tspan x="16" class="pr">$</tspan>
<tspan class="cm"> anvil new weather_station --template weather --board uno</tspan>
</text>
<!-- SCENE 1: Create project -->
<text y="60" class="l" opacity="0" style="animation:s1a 40s infinite"><tspan x="16" class="pr">$</tspan><tspan class="cmd"> anvil new blink --board uno</tspan></text>
<text y="80" class="l" opacity="0" style="animation:s1b 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/blink/blink.ino</tspan></text>
<text y="96" class="l" opacity="0" style="animation:s1c 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/lib/hal/hal.h</tspan></text>
<text y="112" class="l" opacity="0" style="animation:s1d 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/lib/app/blink_app.h</tspan><tspan class="ann"> your code goes here</tspan></text>
<text y="128" class="l" opacity="0" style="animation:s1e 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/test/mocks/mock_hal.h, sim_hal.h</tspan></text>
<text y="144" class="l" opacity="0" style="animation:s1f 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/test/test_unit.cpp</tspan><tspan class="ann"> your tests go here</tspan></text>
<text y="160" class="l" opacity="0" style="animation:s1g 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/build.sh, upload.sh, monitor.sh, test.sh</tspan></text>
<text y="176" class="l" opacity="0" style="animation:s1h 40s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> blink/.anvil.toml, .anvilignore, .gitignore</tspan></text>
<text y="196" class="l" opacity="0" style="animation:s1i 40s infinite"><tspan x="16" class="ok"> done</tspan><tspan class="fl"> Project ready! cd blink</tspan></text>
<text y="232" class="l ann" opacity="0" style="animation:s1j 40s infinite"><tspan x="16">One command. Complete project. No boilerplate to write.</tspan></text>
<text y="252" class="l ann" opacity="0" style="animation:s1k 40s infinite"><tspan x="16">Let's look at what Anvil generated...</tspan></text>
<!-- Lines 2-11: output -->
<text y="78" class="l" opacity="0" style="animation: t2 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/weather_station/weather_station.ino</tspan></text>
<text y="94" class="l" opacity="0" style="animation: t3 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/lib/app/weather_app.h</tspan></text>
<text y="110" class="l" opacity="0" style="animation: t4 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/lib/hal/hal.h</tspan></text>
<text y="126" class="l" opacity="0" style="animation: t5 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/lib/drivers/tmp36/tmp36.h</tspan></text>
<text y="142" class="l" opacity="0" style="animation: t6 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/test/test_weather.cpp</tspan></text>
<text y="158" class="l" opacity="0" style="animation: t7 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/test/test_unit.cpp</tspan></text>
<text y="174" class="l" opacity="0" style="animation: t8 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/build.sh, build.bat</tspan></text>
<text y="190" class="l" opacity="0" style="animation: t9 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/.anvil.toml</tspan></text>
<text y="206" class="l" opacity="0" style="animation: t10 24s infinite"><tspan x="16" class="ok"> create</tspan><tspan class="fl"> weather_station/.anvilignore</tspan></text>
<text y="222" class="l dm" opacity="0" style="animation: t11 24s infinite"><tspan x="16"> ... 28 more files</tspan></text>
<text y="240" class="l" opacity="0" style="animation: t12 24s infinite"><tspan x="16" class="ok"> done</tspan><tspan> Project ready. cd weather_station &amp;&amp; ./test.sh</tspan></text>
<!-- SCENE 2: The code is clean -->
<text y="60" class="l" opacity="0" style="animation:s2a 40s infinite"><tspan x="16" class="pr">$</tspan><tspan class="cmd"> cat lib/app/blink_app.h</tspan><tspan class="dm"> // what did Anvil generate?</tspan></text>
<text y="84" class="l" opacity="0" style="animation:s2b 40s infinite"><tspan x="16" class="pp">#include</tspan><tspan class="st"> "hal.h"</tspan><tspan class="dm"> // the only dependency -- no Arduino.h</tspan></text>
<text y="104" class="l" opacity="0" style="animation:s2c 40s infinite"><tspan x="16" class="kw">class</tspan><tspan class="ty"> BlinkApp</tspan><tspan class="op"> {</tspan></text>
<text y="120" class="l" opacity="0" style="animation:s2d 40s infinite"><tspan x="16" class="kw">public:</tspan></text>
<text y="136" class="l" opacity="0" style="animation:s2e 40s infinite"><tspan x="16"> </tspan><tspan class="ty">BlinkApp</tspan><tspan class="op">(</tspan><tspan class="ty">Hal</tspan><tspan class="op">* </tspan><tspan class="pp">hal</tspan><tspan class="op">) : </tspan><tspan class="pp">hal_</tspan><tspan class="op">(</tspan><tspan class="pp">hal</tspan><tspan class="op">) {}</tspan><tspan class="dm"> // real hardware OR test mock</tspan></text>
<text y="156" class="l" opacity="0" style="animation:s2f 40s infinite"><tspan x="16"> </tspan><tspan class="kw">void</tspan><tspan class="fn"> setup</tspan><tspan class="op">() {</tspan></text>
<text y="172" class="l" opacity="0" style="animation:s2g 40s infinite"><tspan x="16"> </tspan><tspan class="pp">hal_</tspan><tspan class="op">-></tspan><tspan class="fn">pinMode</tspan><tspan class="op">(</tspan><tspan class="nm">13</tspan><tspan class="op">, </tspan><tspan class="nm">OUTPUT</tspan><tspan class="op">);</tspan></text>
<text y="188" class="l" opacity="0" style="animation:s2h 40s infinite"><tspan x="16"> }</tspan></text>
<text y="204" class="l" opacity="0" style="animation:s2i 40s infinite"><tspan x="16"> </tspan><tspan class="kw">void</tspan><tspan class="fn"> loop</tspan><tspan class="op">() {</tspan></text>
<text y="220" class="l" opacity="0" style="animation:s2j 40s infinite"><tspan x="16"> </tspan><tspan class="pp">hal_</tspan><tspan class="op">-></tspan><tspan class="fn">digitalWrite</tspan><tspan class="op">(</tspan><tspan class="nm">13</tspan><tspan class="op">, </tspan><tspan class="nm">HIGH</tspan><tspan class="op">);</tspan><tspan class="dm"> // LED on</tspan></text>
<text y="236" class="l" opacity="0" style="animation:s2k 40s infinite"><tspan x="16"> </tspan><tspan class="pp">hal_</tspan><tspan class="op">-></tspan><tspan class="fn">delay</tspan><tspan class="op">(</tspan><tspan class="nm">500</tspan><tspan class="op">);</tspan></text>
<text y="252" class="l" opacity="0" style="animation:s2l 40s infinite"><tspan x="16"> </tspan><tspan class="pp">hal_</tspan><tspan class="op">-></tspan><tspan class="fn">digitalWrite</tspan><tspan class="op">(</tspan><tspan class="nm">13</tspan><tspan class="op">, </tspan><tspan class="nm">LOW</tspan><tspan class="op">);</tspan><tspan class="dm"> // LED off</tspan></text>
<text y="268" class="l" opacity="0" style="animation:s2m 40s infinite"><tspan x="16"> </tspan><tspan class="pp">hal_</tspan><tspan class="op">-></tspan><tspan class="fn">delay</tspan><tspan class="op">(</tspan><tspan class="nm">500</tspan><tspan class="op">);</tspan></text>
<text y="284" class="l" opacity="0" style="animation:s2m 40s infinite"><tspan x="16"> }</tspan></text>
<text y="300" class="l" opacity="0" style="animation:s2n 40s infinite"><tspan x="16" class="op">};</tspan></text>
<text y="332" class="l ann" opacity="0" style="animation:s2o 40s infinite"><tspan x="16">Clean C++. No hardware coupling. Change the delay, add Serial output,</tspan></text>
<text y="350" class="l ann" opacity="0" style="animation:s2p 40s infinite"><tspan x="16">read a sensor -- just edit this file. Now let's test it without a board...</tspan></text>
<!-- Line 13: second command -->
<text y="270" class="l" opacity="0" style="animation: t13 24s infinite">
<tspan x="16" class="pr">$</tspan>
<tspan class="cm"> cd weather_station &amp;&amp; ./test.sh</tspan>
</text>
<!-- Lines 14-18: test output -->
<text y="288" class="l dm" opacity="0" style="animation: t14 24s infinite"><tspan x="16">[==========] Running 14 tests from 4 test suites.</tspan></text>
<text y="304" class="l" opacity="0" style="animation: t15 24s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan> WeatherMockTest.ReadsTemperature</tspan></text>
<text y="320" class="l" opacity="0" style="animation: t16 24s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan> WeatherSimTest.NoisyReadingsInRange</tspan></text>
<text y="336" class="l dm" opacity="0" style="animation: t17 24s infinite"><tspan x="16"> ... 10 more tests</tspan></text>
<text y="354" class="l" opacity="0" style="animation: t18 24s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan> Tmp36PolymorphismTest.AllImplsWorkThroughBasePointer</tspan></text>
<!-- Lines 19-20: summary -->
<text y="374" class="l" opacity="0" style="animation: t19 24s infinite"><tspan x="16" class="ok">[==========]</tspan><tspan> 14 tests ran. </tspan><tspan class="nm">(12 ms total)</tspan></text>
<text y="390" class="l" opacity="0" style="animation: t20 24s infinite"><tspan x="16" class="ok">[ PASSED ] 14 tests.</tspan></text>
<!-- Line 21: third command -->
<text y="414" class="l" opacity="0" style="animation: t23 24s infinite">
<tspan x="16" class="pr">$</tspan>
<tspan class="cm"> ./upload.sh --monitor</tspan>
</text>
<!-- Blinking cursor -->
<rect x="210" y="404" width="8" height="15" fill="#58d0f0" opacity="0" style="animation: t23 24s infinite, cursor 1s step-end infinite"/>
<!-- SCENE 3: Test it -->
<text y="60" class="l" opacity="0" style="animation:s3a 40s infinite"><tspan x="16" class="pr">$</tspan><tspan class="cmd"> cat test/test_unit.cpp</tspan><tspan class="dm"> // the student writes a quick test</tspan></text>
<text y="84" class="l" opacity="0" style="animation:s3b 40s infinite"><tspan x="16" class="pp">#include</tspan><tspan class="st"> "blink_app.h"</tspan></text>
<text y="100" class="l" opacity="0" style="animation:s3b 40s infinite"><tspan x="16" class="pp">#include</tspan><tspan class="st"> "sim_hal.h"</tspan><tspan class="dm"> // simulated Arduino -- runs on laptop</tspan></text>
<text y="120" class="l" opacity="0" style="animation:s3c 40s infinite"><tspan x="16" class="fn">TEST</tspan><tspan class="op">(BlinkTest, LedTurnsOn) {</tspan></text>
<text y="136" class="l" opacity="0" style="animation:s3d 40s infinite"><tspan x="16"> </tspan><tspan class="ty">SimHal</tspan><tspan class="pp"> hal</tspan><tspan class="op">;</tspan><tspan class="dm"> // fake hardware</tspan></text>
<text y="152" class="l" opacity="0" style="animation:s3e 40s infinite"><tspan x="16"> </tspan><tspan class="ty">BlinkApp</tspan><tspan class="pp"> app</tspan><tspan class="op">(&amp;</tspan><tspan class="pp">hal</tspan><tspan class="op">);</tspan><tspan class="dm"> // inject it</tspan></text>
<text y="168" class="l" opacity="0" style="animation:s3f 40s infinite"><tspan x="16"> </tspan><tspan class="pp">app</tspan><tspan class="op">.</tspan><tspan class="fn">setup</tspan><tspan class="op">();</tspan></text>
<text y="184" class="l" opacity="0" style="animation:s3g 40s infinite"><tspan x="16"> </tspan><tspan class="pp">app</tspan><tspan class="op">.</tspan><tspan class="fn">loop</tspan><tspan class="op">();</tspan></text>
<text y="200" class="l" opacity="0" style="animation:s3h 40s infinite"><tspan x="16"> </tspan><tspan class="fn">EXPECT_EQ</tspan><tspan class="op">(</tspan><tspan class="pp">hal</tspan><tspan class="op">.</tspan><tspan class="fn">getPin</tspan><tspan class="op">(</tspan><tspan class="nm">13</tspan><tspan class="op">), </tspan><tspan class="nm">LOW</tspan><tspan class="op">);</tspan><tspan class="dm"> // ended on LOW after blink</tspan></text>
<text y="216" class="l" opacity="0" style="animation:s3i 40s infinite"><tspan x="16" class="op">}</tspan></text>
<text y="244" class="l" opacity="0" style="animation:s3j 40s infinite"><tspan x="16" class="pr">$</tspan><tspan class="cmd"> ./test.sh</tspan></text>
<text y="268" class="l dm" opacity="0" style="animation:s3k 40s infinite"><tspan x="16">[==========] Running 3 tests from 2 test suites.</tspan></text>
<text y="284" class="l" opacity="0" style="animation:s3l 40s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan class="fl"> BlinkTest.LedTurnsOn</tspan></text>
<text y="300" class="l" opacity="0" style="animation:s3l 40s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan class="fl"> BlinkTest.LedToggles</tspan></text>
<text y="316" class="l" opacity="0" style="animation:s3m 40s infinite"><tspan x="16" class="ok">[ PASSED ]</tspan><tspan class="fl"> BlinkTest.SetsPinMode</tspan></text>
<text y="336" class="l" opacity="0" style="animation:s3n 40s infinite"><tspan x="16" class="ok">[ PASSED ] 3 tests.</tspan><tspan class="hl"> (8 ms)</tspan></text>
<text y="364" class="l" opacity="0" style="animation:s3o 40s infinite"><tspan x="16" class="pr">$</tspan><tspan class="cmd"> ./upload.sh --monitor</tspan></text>
<text y="384" class="l" opacity="0" style="animation:s3p 40s infinite"><tspan x="16" class="ok">Upload complete.</tspan><tspan class="fl"> Opening serial monitor at 115200 baud.</tspan></text>
<text y="416" class="l ann" opacity="0" style="animation:s3q 40s infinite"><tspan x="16">Tests run on your laptop in milliseconds. No board needed.</tspan></text>
<text y="436" class="l ann" opacity="0" style="animation:s3r 40s infinite"><tspan x="16">Find bugs in 5 minutes instead of 2 hours staring at a serial monitor.</tspan></text>
<rect x="16" y="456" width="8" height="14" fill="#58d0f0" opacity="0" style="animation:s3r 40s infinite, cursor 1s step-end infinite"/>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 16 KiB