<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xml:base="https://extralongdivision.com/">
  <channel>
    <title>Circuitpython on Extra Long Division</title>
    <link>https://extralongdivision.com/tags/circuitpython/</link>
    <description>Recent content in Circuitpython on Extra Long Division</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 03 Sep 2026 00:38:17 +0000</lastBuildDate>
    <atom:link href="https://extralongdivision.com/tags/circuitpython/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Dragon Ball Radar: Devlog 1 - Frankenstein</title>
      <link>https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/</link>
      <pubDate>Sat, 29 Aug 2026 02:38:17 +0000</pubDate>
      <guid>https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/</guid>
      <description>&lt;img src=&#34;https://extralongdivision.com/images/Written-By-a-Human-Not-By-AI-Badge-black.svg&#34; alt=&#34;written by a human not by AI&#34;&gt;

&lt;h2 id=&#34;inspiration&#34;&gt;Inspiration&lt;/h2&gt;
&lt;p&gt;If you want a real life 
&lt;a href=&#34;https://dragonball.fandom.com/wiki/Dragon_Radar&#34;
data-umami-event=&#34;outbound-link-click&#34;
data-umami-event-url=&#34;https://dragonball.fandom.com/wiki/Dragon_Radar&#34;
&gt;
    Dragon Radar
&lt;/a&gt;, there are a small amount of toys to choose from.&lt;/p&gt;

&lt;figure&gt;&lt;img src=&#34;https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/dbz-radar-toys.webp&#34;
			alt=&#34;dragon radar shopping list&#34; loading=&#34;lazy&#34;&gt;
&lt;/figure&gt;
&lt;p&gt;None of those can really function as the radar from the anime. The maker in me wanted to change that.&lt;/p&gt;
&lt;p&gt;There were some bumps along the way, but the first revision turned out alright. I&amp;rsquo;ll disclose all those bumps, and the eventual working prototype, in this dev&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;log.&lt;/p&gt;</description>
      <image>
        <url>https://cloud.umami.is/p/O9irZWsyx</url>
      </image>
      <content:encoded><![CDATA[
<img src="https://extralongdivision.com/images/Written-By-a-Human-Not-By-AI-Badge-black.svg" alt="written by a human not by AI">

<h2 id="inspiration">Inspiration</h2>
<p>If you want a real life 
<a href="https://dragonball.fandom.com/wiki/Dragon_Radar"
data-umami-event="outbound-link-click"
data-umami-event-url="https://dragonball.fandom.com/wiki/Dragon_Radar"
>
    Dragon Radar
</a>, there are a small amount of toys to choose from.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/dbz-radar-toys.webp"
			alt="dragon radar shopping list" loading="lazy">
</figure>
<p>None of those can really function as the radar from the anime. The maker in me wanted to change that.</p>
<p>There were some bumps along the way, but the first revision turned out alright. I&rsquo;ll disclose all those bumps, and the eventual working prototype, in this dev<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>log.</p>
<h2 id="prototyping">Prototyping</h2>
<h3 id="circutpython">CircutPython</h3>
<p>A Dragon Radar requires a circular screen. In recent years, these have become more available to the hobbyist maker. There are lots on Alibaba and Aliexpress, but Adafruit has 
<a href="https://www.adafruit.com/product/5793"
data-umami-event="outbound-link-click"
data-umami-event-url="https://www.adafruit.com/product/5793"
>
    4&#34;
</a> and 
<a href="https://www.adafruit.com/product/5793"
data-umami-event="outbound-link-click"
data-umami-event-url="https://www.adafruit.com/product/5793"
>
    2.8&#34;
</a> varieties that are not only well documented but have a complementary dev board: the 
<a href="https://www.adafruit.com/product/5800"
data-umami-event="outbound-link-click"
data-umami-event-url="https://www.adafruit.com/product/5800"
>
    ESP32-S3 Qualia.
</a></p>
<p>This is where I began prototyping and quickly hit an impasse. Adafruit prioritizes CircuitPython and I couldn&rsquo;t get the <code>CIRCUITPY</code> drive to show up on my Linux machine. I bumbled around factory reset and bootloader repair documentation only for flashing to work first try after connecting the Qualia to a Windows machine. Not sure why.</p>
<p>Once I flashed the newest CircuitPython onto the Qualia, it showed up on my Linux machine. Maybe it&rsquo;s on old bug that&rsquo;s hence been repaired.</p>
<h3 id="display-driver">Display Driver</h3>
<p>Once CircuitPython worked, driving the display was easy using Adafruit&rsquo;s provided example code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> displayio <span style="color:#f92672">import</span> release_displays
</span></span><span style="display:flex;"><span>release_displays()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> displayio
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> busio
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> board
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> dotclockframebuffer
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> framebufferio <span style="color:#f92672">import</span> FramebufferDisplay
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>init_sequence_hd40015c40 <span style="color:#f92672">=</span> bytes((
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;obnoxiously long init code, scroll to the end for the repo containing the full code&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tft_pins <span style="color:#f92672">=</span> dict(board<span style="color:#f92672">.</span>TFT_PINS)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tft_timings <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;frequency&#34;</span>: <span style="color:#ae81ff">16000000</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;width&#34;</span>: <span style="color:#ae81ff">720</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;height&#34;</span>: <span style="color:#ae81ff">720</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;hsync_pulse_width&#34;</span>: <span style="color:#ae81ff">2</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;hsync_back_porch&#34;</span>: <span style="color:#ae81ff">44</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;hsync_front_porch&#34;</span>: <span style="color:#ae81ff">46</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;hsync_idle_low&#34;</span>: <span style="color:#66d9ef">False</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;vsync_pulse_width&#34;</span>: <span style="color:#ae81ff">16</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;vsync_back_porch&#34;</span>: <span style="color:#ae81ff">16</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;vsync_front_porch&#34;</span>: <span style="color:#ae81ff">50</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;vsync_idle_low&#34;</span>: <span style="color:#66d9ef">False</span>,
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;pclk_active_high&#34;</span>: <span style="color:#66d9ef">True</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;pclk_idle_high&#34;</span>: <span style="color:#66d9ef">False</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;de_idle_high&#34;</span>: <span style="color:#66d9ef">False</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>board<span style="color:#f92672">.</span>I2C()<span style="color:#f92672">.</span>deinit()
</span></span><span style="display:flex;"><span>i2c <span style="color:#f92672">=</span> busio<span style="color:#f92672">.</span>I2C(board<span style="color:#f92672">.</span>SCL, board<span style="color:#f92672">.</span>SDA)
</span></span><span style="display:flex;"><span>tft_io_expander <span style="color:#f92672">=</span> dict(board<span style="color:#f92672">.</span>TFT_IO_EXPANDER)
</span></span><span style="display:flex;"><span><span style="color:#75715e">#tft_io_expander[&#39;i2c_address&#39;] = 0x38 # uncomment for rev B</span>
</span></span><span style="display:flex;"><span>dotclockframebuffer<span style="color:#f92672">.</span>ioexpander_send_init_sequence(i2c, init_sequence_hd40015c40, <span style="color:#f92672">**</span>tft_io_expander)
</span></span><span style="display:flex;"><span>i2c<span style="color:#f92672">.</span>deinit()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>bitmap <span style="color:#f92672">=</span> displayio<span style="color:#f92672">.</span>OnDiskBitmap(<span style="color:#e6db74">&#34;/round-display-ruler-720p.bmp&#34;</span>) <span style="color:#75715e"># place this file in the root of CIRCUITPY</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fb <span style="color:#f92672">=</span> dotclockframebuffer<span style="color:#f92672">.</span>DotClockFramebuffer(<span style="color:#f92672">**</span>tft_pins, <span style="color:#f92672">**</span>tft_timings)
</span></span><span style="display:flex;"><span>display <span style="color:#f92672">=</span> FramebufferDisplay(fb, auto_refresh<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Create a TileGrid to hold the bitmap</span>
</span></span><span style="display:flex;"><span>tile_grid <span style="color:#f92672">=</span> displayio<span style="color:#f92672">.</span>TileGrid(bitmap, pixel_shader<span style="color:#f92672">=</span>bitmap<span style="color:#f92672">.</span>pixel_shader)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Center the image</span>
</span></span><span style="display:flex;"><span>tile_grid<span style="color:#f92672">.</span>x <span style="color:#f92672">-=</span> (bitmap<span style="color:#f92672">.</span>width <span style="color:#f92672">-</span> display<span style="color:#f92672">.</span>width) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>tile_grid<span style="color:#f92672">.</span>y <span style="color:#f92672">-=</span> (bitmap<span style="color:#f92672">.</span>height <span style="color:#f92672">-</span> display<span style="color:#f92672">.</span>height) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Create a Group to hold the TileGrid</span>
</span></span><span style="display:flex;"><span>group <span style="color:#f92672">=</span> displayio<span style="color:#f92672">.</span>Group()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Add the TileGrid to the Group</span>
</span></span><span style="display:flex;"><span>group<span style="color:#f92672">.</span>append(tile_grid)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Add the Group to the Display</span>
</span></span><span style="display:flex;"><span>display<span style="color:#f92672">.</span>root_group <span style="color:#f92672">=</span> group
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>display<span style="color:#f92672">.</span>auto_refresh <span style="color:#f92672">=</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Loop forever so you can enjoy your image</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">pass</span>
</span></span></code></pre></div><p>I should note that I ran into an error when trying to program the board.</p>
<pre tabindex="0"><code>OSError: [Errno 5] Input/output error
</code></pre><p>This prevented me from updating the code. 
<a href="https://github.com/adafruit/circuitpython/issues/8449"
data-umami-event="outbound-link-click"
data-umami-event-url="https://github.com/adafruit/circuitpython/issues/8449"
>
    Other people have had this problem too apparently.
</a> I still don&rsquo;t know the root cause, but the work around I used on Linux was:</p>
<pre tabindex="0"><code>sudo cp code.py /media/&lt;username&gt;/CIRCUITPY/code.py
</code></pre><h3 id="sound">Sound</h3>
<p>This was the first hiccup. This demo of the Adafruit team playing Star Trek on the Qualia made me confident that the board could be the base for a Dragon Radar.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/yKRatudQSsI?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<p>Those familiar with the Dragon Ball series will know the radar makes this sound:</p>

<audio src="radar-beep.ogg" controls muted loading="lazy"></audio>

<p>My implementation didn&rsquo;t sound as good. I bought a breakout board for the same I2S<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> chip used in the above demo, the MAX98357, and connected it to the Qualia board.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/sound-prototype.webp"
			alt="Qualia and MAX98357 breakout prototype" loading="lazy">
</figure>
<p>The first audio file in this section sounded like this played through my prototype hardware (put the volume down):</p>

<audio src="cursed-beep.ogg" controls muted loading="lazy"></audio>

<p>The crackling sound is not your speakers. That&rsquo;s actually what was coming out of my breadboard set up. I used, what I believe to be, the same speakers as the one Adafruit demoed as well as a 8 ohm variant, but that didn&rsquo;t change anything. Modifying the gain or the stereo/L/R output of the amp didn&rsquo;t fix the issue either.</p>
<p>I doubt the code is suspect but here it is in case you can find something wrong with it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># SPDX-License-Identifier: MIT</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> audiocore
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> board
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> audiobusio
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>wave_file <span style="color:#f92672">=</span> open(<span style="color:#e6db74">&#34;beep.wav&#34;</span>, <span style="color:#e6db74">&#34;rb&#34;</span>)  <span style="color:#75715e"># must be CIRCUITPY filesystem</span>
</span></span><span style="display:flex;"><span>wave <span style="color:#f92672">=</span> audiocore<span style="color:#f92672">.</span>WaveFile(wave_file)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># For Feather M4 Express</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># For Metro M4 Express</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># audio = audiobusio.I2SOut(board.D3, board.D9, board.D8)</span>
</span></span><span style="display:flex;"><span>i2s_bit_pin <span style="color:#f92672">=</span> board<span style="color:#f92672">.</span>A1
</span></span><span style="display:flex;"><span>i2s_word_pin <span style="color:#f92672">=</span> board<span style="color:#f92672">.</span>A0
</span></span><span style="display:flex;"><span>i2s_data_pin <span style="color:#f92672">=</span> board<span style="color:#f92672">.</span>TX
</span></span><span style="display:flex;"><span>audio <span style="color:#f92672">=</span> audiobusio<span style="color:#f92672">.</span>I2SOut(i2s_bit_pin, i2s_word_pin, i2s_data_pin)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:
</span></span><span style="display:flex;"><span>    audio<span style="color:#f92672">.</span>play(wave)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">while</span> audio<span style="color:#f92672">.</span>playing:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">pass</span>
</span></span></code></pre></div><p>I don&rsquo;t have a lot of familiarity with I2S or sound circuits in general. Since <em>something</em> played I suspect the haphazard wiring is the culprit. Hopefully a PCB<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> will fix the issue. So I pressed on to electrical-mechanical design.</p>
<h2 id="enclosure-design">Enclosure Design</h2>
<h3 id="display-mounting">Display Mounting</h3>
<p>Given the unique shape of the Dragon Radar, I started with designing a 3D model. In the anime, it took on slightly different looks.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/dragon-radars.webp"
			alt="dragon radars" loading="lazy">
</figure>
<p>There are two constraints mandatory to match the anime:</p>
<ol>
<li>The display has to be at the center of the enclosure</li>
<li>The activation button must be at the top of the enclosure, aligned with the vertical symmetrical axis</li>
</ol>
<p>These two constraints seem simple, but forced my hand during mechanical design.</p>
<p>I decided to use the 4&quot; display, HD40015C40, since I figured a display that was too big was better than one that was too small. I didn&rsquo;t have the display in hand yet when designing the enclosure so I had to go off its datasheet.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/HD40015C40-drawing.webp"
			alt="display mechanical drawing" loading="lazy">
</figure>
<p>It was in Chinglish and honestly frustrating to interpret. What I could figure, though, was the visible pixels on the screen are not centered in the display assembly. In fact, the center of the display assembly&rsquo;s bounding box and the center of the active pixel area are offset by 2.44 mm.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/aa-offset.webp"
			alt="render of screen and display assembly" loading="lazy">
</figure>
<p>I was able to reduce the offset to 1.5 mm in the opposite direction with the activation button&rsquo;s placement. I used a THT<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> switch for mechanical strength, which forced the PCB to be bigger than the display so the switch&rsquo;s leads didn&rsquo;t cause a collision.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/aa-pcb-offset.webp"
			alt="render of display on PCBA" loading="lazy">
</figure>
<p>To keep the screen centered in the end product, I had to put a sizable bevel around the enclosure&rsquo;s edges.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/bevel-length.webp"
			alt="render of enclosure over display assembly" loading="lazy">
</figure>
<p>This is close enough to the anime. Finishing the mechanical design for the user input changed things though.</p>
<h3 id="activation-button">Activation Button</h3>
<p>The button to turn the device on and off is actually an assembly of a shaft and cap. There&rsquo;s heat-set inserts in each part and they&rsquo;re assembled together with a set-screw.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/actuator-xray.webp"
			alt="transparent view of actuator button" loading="lazy">
</figure>
<p>This is where the beveled edges on the enclosure became a problem. Bear with me because this dependency tree is a little convoluted. Because the switch is on the same PCB as the display, and switches are only available at certain heights, and the activation button must be on the same axis as the switch&rsquo;s actuator: the shaft for the activation button can&rsquo;t sit on the top of the enclosure like in the anime.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/switch-actuator.webp"
			alt="switch and actuator side view" loading="lazy">
</figure>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/render-vs-anime.webp"
			alt="modeled activation button vs anime&#39;s activation button" loading="lazy">
</figure>
<p>This is fine for this first revision. I&rsquo;ll probably 3D print a nonfunctional version that looks more like the anime then decide which is better.</p>
<h3 id="power-cable-routing">Power Cable Routing</h3>
<p>For practical reasons, I wanted the radar to run off a rechargeable battery. The slot for the charger would be easiest to put into the enclosure&rsquo;s back, which would thus require a vertical connector. USB-C is the default nowadays, so I went with the USB4220 series from GCT. This ultimately resulted in some problems, but more on that in the bring up phase.</p>
<p>I&rsquo;m doing a little time bending here because I placed the USB-C connector in the PCB layout before defining the charging port&rsquo;s location in the mechanical design. I did this because electrical constraints defined the connector&rsquo;s position more than mechanical ones.</p>
<p>Also, at this point I knew there was a lot of empty space on the board, so I didn&rsquo;t leave a special mounting place for the battery. I&rsquo;ll attach it to the board with some double sided tape.</p>
<h3 id="mounting-points">Mounting Points</h3>
<p>Snap-fits are the premiere way to assemble parts together. But I&rsquo;m too lazy to iterate through a bunch of tolerances before everything assembles well. Instead, I used heat-set inserts to mount the PCB and assemble the enclosure together. To preserve 
<a href="https://en.wikipedia.org/wiki/Poka-yoke"
data-umami-event="outbound-link-click"
data-umami-event-url="https://en.wikipedia.org/wiki/Poka-yoke"
>
    poka-yoke
</a>, I used different threads for the PCB mounting and fastening the enclosure front and back together.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/mounting-holes.webp"
			alt="render with PCB and enclosure mounting holes" loading="lazy">
</figure>
<p>One of the sizes was M1 which were surprisingly expensive to source from the usually suspects. I ultimately found some on Amazon.</p>
<h3 id="speaker">Speaker</h3>
<p>The speakers I&rsquo;m using thankfully ship with adhesive foam. I cut a small nest about ~0.25 mm bigger than the speaker in the enclosure&rsquo;s back as a mounting location. Hopefully the adhesive is enough to keep it into place. Add some holes so the sound escapes and mechanical design is done!</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/speaker-nest.webp"
			alt="render of enclosure back" loading="lazy">
</figure>
<h2 id="electronics-design">Electronics Design</h2>
<h3 id="schematic-capture">Schematic Capture</h3>
<p>Adafruit did most of the work. &ldquo;My&rdquo; design is a mashup up of the Qualia board, MAX98357 breakout, and the charging circuit from the 
<a href="https://learn.adafruit.com/assets/110822"
data-umami-event="outbound-link-click"
data-umami-event-url="https://learn.adafruit.com/assets/110822"
>
    Adafruit Feather ESP32-S3
</a>.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/schematic.webp"
			alt="schematic" loading="lazy">
</figure>
<p>The few modifications I made were:</p>
<ul>
<li>Remove the <code>DN</code> and <code>UP</code> buttons and replaced them with the button chosen in the mechanical enclosure section</li>
<li>Remove the STEMMA QT/Qwiic connector</li>
<li>Replace the JST connector with 2.54&quot; spaced THTs and connected all unused IO<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> to it</li>
<li>Add a heartbeat LED<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup></li>
<li>Replaced jumpers with 0 ohm resistors, depopulating the ones I don&rsquo;t want</li>
<li>Various quality of life changes like adding more test points and egregious amount of 0 ohm resistors in series with interesting traces</li>
</ul>
<h3 id="pcb-layout">PCB Layout</h3>
<h4 id="placement">Placement</h4>
<p>The mechanical design dictated the position of the mounting holes, activation button, and the FFC<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup> connector (<em>technically I could physically rotate the display and rotate the image in software but I opted just to put the connector and activation button at the vertical symmetrical axis of the device</em>).</p>
<p>This choice forced me to rotate the ESP32 package 45 degrees to avoid a THT inside a keep-out zone. I put the ESP32 on the top right of the board to give the most amount of space to place other components.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/pcb-render.webp"
			alt="render of PCBA" loading="lazy">
</figure>
<p>I&rsquo;m actually still violating the layout rules provided by Espressif. They recommend the antenna hang off the board ideally or, if not possible, the end of the antenna be at least 15 mm away from a cutout and that the feed point be max 2 mm from a board edge.</p>

<figure><img src="https://docs.espressif.com/projects/esp-hardware-design-guidelines/en/latest/esp32s3/_images/esp32s3-module-place-on-base-board-right.png"
			alt="hanging ESP32-WROOM guidelines" loading="lazy">
</figure>

<figure><img src="https://docs.espressif.com/projects/esp-hardware-design-guidelines/en/latest/esp32s3/_images/esp32s3-module-clearance.png"
			alt="ESP32 module 15mm from board cutout and 1mm from board edge" loading="lazy">
</figure>
<p>If I hung the antenna off the board it&rsquo;d collide with the enclosure and I didn&rsquo;t want to make it any larger.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/esp32-placement-render.webp"
			alt="render of ESP32 module in assembly" loading="lazy">
</figure>
<p>To make rework and hand-soldering easier, I used 0805 sized components wherever I could. This would make my life easier once the boards came back.</p>
<h4 id="stack-up">Stack-up</h4>
<p>I decided to do a 1.6 mm thick (foreshadowing), 4 layer stack-up of <code>signal+ground/ground/ground/signal+ground</code>. The RGB565<sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup> parallel signals were my greatest concern. The two inner ground layers would shield signals on layer 4 from the RGB. Layer 1 would have the USB<sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup> 2.0 traces which technically should be fabricated to 90 ohm, but in practice I&rsquo;ve never had problems omitting a controlled impedance. I still routed the signals differential though. The four layer stack-up also made it much easier to route 3.3 V power rail on layer 4.</p>
<h4 id="routing">Routing</h4>
<p>The most interesting part to route was the USB-C connector. It has a keep-out zone near the pads that make it almost impossible to connect the USB D+/D- pins and VBUS<sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup> pins together.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/usbc-drawing.webp"
			alt="USB-C connector keep out zone" loading="lazy">
</figure>
<p>I interpreted the keep-out zone as only for components and not for all copper. I&rsquo;m justifying this conclusion with the metal flaps on the side of the connector (these will rear their ugly head once the board is made).</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/usb-flap.webp"
			alt="metal slaps of USB-C connector" loading="lazy">
</figure>
<p>Everything else was fairly straight forward to route.</p>
<h3 id="ordering">Ordering</h3>
<p>While ordering the board, I realized that I assigned a 100 <em>uF</em> decoupling capacitor for the ESP32 instead of a 100 <em>nF</em> cap. If you hadn&rsquo;t caught on to the trend, I am lazy. I didn&rsquo;t want to regenerate the gerbers so I just DNP<sup id="fnref:11"><a href="#fn:11" class="footnote-ref" role="doc-noteref">11</a></sup>&rsquo;d the cap.</p>
<p>The USB-C connector was also out-of-stock. I already designed the mechanical enclosure around that connectors height and (re: lazy) DNP&rsquo;d that part thinking I could hand solder it on once the boards arrive. That was not a safe assumption.</p>
<h2 id="board-bring-up">Board Bring-Up</h2>
<h3 id="physical-inspection">Physical Inspection</h3>
<p>Once the boards came back, I realized just how large they are.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/board-in-hand.webp"
			alt="PCBA in my hand" loading="lazy">
</figure>
<p>The PCBAs<sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup> are about as large as they can comfortably fit in my hand and that&rsquo;s before they&rsquo;re put in a larger assembly. I&rsquo;ll certainly have to use a wrist strap for the final build.</p>
<h3 id="smoke-test">Smoke Test</h3>
<p>I plugged in a battery into the board and… smoke. Quickly, I realized my mistake. I swapped the battery connector polarity. The Adafruit designed I based it on used a horizontal connector, while mine is vertical. This shouldn&rsquo;t matter, but the manufacturer flipped the location of pin 1 on the datasheet.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/jst-ph-footprint.webp"
			alt="battery connector footprint" loading="lazy">
</figure>
<p>I should&rsquo;ve caught this, but I will remind JST that pin 1 should be on the top left of a footprint to comply with an IPC<sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup> 
<a href="https://www.protoexpress.com/blog/features-of-ipc-7351-standards-to-design-pcb-component-footprint/#zero-component-orientation"
data-umami-event="outbound-link-click"
data-umami-event-url="https://www.protoexpress.com/blog/features-of-ipc-7351-standards-to-design-pcb-component-footprint/#zero-component-orientation"
>
    7351
</a>. Thankfully Q1 and D7 act as reverse polarity protection for the rest of the circuitry.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/q1-d7.webp"
			alt="reverse polarity circuit" loading="lazy">
</figure>
<h3 id="usb-c">USB-C</h3>
<p>Now comes the most egregious mistake I made in the design that I so un-elegantly foreshadowed earlier. I couldn&rsquo;t connect a battery so next step was to solder on the USB-C connector.</p>
<p>While earlier I mentioned how surprisingly large the board was. The USB-C pads were surprisingly <em>small</em>.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/usbc-pads.webp"
			alt="unpopulated USB-C connector" loading="lazy">
</figure>
<p>I figured I had my work cutout for me, but then I placed the USB-C connector on the board and spotted another grievous error. The mounting pins for the connector were 1.2 mm long, but the board is 1.6 mm thick.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/usbc-tht-length.webp"
			alt="USB connector mounting pin drawing" loading="lazy">
</figure>
<p>Even if it was in stock, no company on the planet could assemble the connector onto the board. The next revision will have to use a thinner PCB. If you scroll up to the <a href="#routing">PCB Routing section</a> you&rsquo;ll notice the footprint has a 1.2 mm PCB thickness recommendation.</p>
<p>But the mistakes didn&rsquo;t end there. With the connector on the board, the SMT<sup id="fnref:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup> pads are inaccessible thanks to those aforementioned side flaps.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/usb-connector-on-board.webp"
			alt="USB connector on PCB" loading="lazy">
</figure>
<p>Thankfully, the connector I chose was USB 2.0, not 3.0. With some bodge wires and a spare USB-A plug, I made a haphazard USB cable… which created a short across VBUS and ground. My second attempt worked though. I was able to flash the ESP32 with CircuitPython and upload code to it 😎.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/bodge-cable.webp"
			alt="bodged on USB 2.0 cable" loading="lazy">
</figure>
<p>Notice how the D+/D- wires are on the side of ESD<sup id="fnref:15"><a href="#fn:15" class="footnote-ref" role="doc-noteref">15</a></sup> diode closest to the connector. This ensures that an ESD event doesn&rsquo;t damage the ESP32.</p>
<p>Also, the process to get CircuitPython on my board was slightly different than the Qualia. This is the tutorial I followed to do it: 
<a href="https://learn.adafruit.com/circuitpython-with-esp32-quick-start/installing-circuitpython"
data-umami-event="outbound-link-click"
data-umami-event-url="https://learn.adafruit.com/circuitpython-with-esp32-quick-start/installing-circuitpython"
>
    https://learn.adafruit.com/circuitpython-with-esp32-quick-start/installing-circuitpython
</a>.</p>
<h3 id="battery-chargingmonitoring">Battery Charging/Monitoring</h3>
<p>I had some faith the battery charger, MCP73831, still functioned because its status LED blinked when the board was on with no battery connected. In the absence of a battery emulator, I connected a lipo<sup id="fnref:16"><a href="#fn:16" class="footnote-ref" role="doc-noteref">16</a></sup> to the board with some hook-to-DuPont connectors, a 2-pin JST-PH pigtail cable, and the enduring will of the human spirit.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/battery-bodge.webp"
			alt="battery questionably attached to the board" loading="lazy">
</figure>
<p>According to the datasheet, the status LED should be on during charging and off otherwise.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/charge-stat-table.webp"
			alt="MCP73831 STAT pin truth table" loading="lazy">
</figure>
<p>This is exactly what happened. I found a some CircuitPython test code for the battery monitor and easily read the voltage.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># SPDX-FileCopyrightText: Copyright (c) 2022 ladyada for Adafruit Industries</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># SPDX-License-Identifier: Unlicense</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> time
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> board
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> adafruit_max1704x
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>i2c <span style="color:#f92672">=</span> board<span style="color:#f92672">.</span>I2C()  <span style="color:#75715e"># uses board.SCL and board.SDA</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a microcontroller</span>
</span></span><span style="display:flex;"><span>max17 <span style="color:#f92672">=</span> adafruit_max1704x<span style="color:#f92672">.</span>MAX17048(i2c)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Found MAX1704x with chip version&#34;</span>,
</span></span><span style="display:flex;"><span>    hex(max17<span style="color:#f92672">.</span>chip_version),
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;and id&#34;</span>,
</span></span><span style="display:flex;"><span>    hex(max17<span style="color:#f92672">.</span>chip_id),
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Quick starting allows an instant &#39;auto-calibration&#39; of the battery. However, its a bad idea</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># to do this right when the battery is first plugged in or if there&#39;s a lot of load on the battery</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># so uncomment only if you&#39;re sure you want to &#39;reset&#39; the chips charge calculator.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># print(&#34;Quick starting&#34;)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># max17.quick_start = True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Battery voltage: </span><span style="color:#e6db74">{</span>max17<span style="color:#f92672">.</span>cell_voltage<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> Volts&#34;</span>)
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Battery state  : </span><span style="color:#e6db74">{</span>max17<span style="color:#f92672">.</span>cell_percent<span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> %&#34;</span>)
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#34;&#34;</span>)
</span></span><span style="display:flex;"><span>    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">1</span>)
</span></span></code></pre></div><p>I didn&rsquo;t bother testing how accurate the monitor was as the battery discharged since it&rsquo;d be hard to track with the USB cable disconnected.</p>
<h3 id="display">Display</h3>
<p>I plugged in a known good 4&quot; display into my PCBA, programmed the board with example code, and… nothing. The display&rsquo;s back-light turned on which tells me that the pin-out for the connector was correct and that I2C<sup id="fnref:17"><a href="#fn:17" class="footnote-ref" role="doc-noteref">17</a></sup> works (only partially true, keep reading) since the I2C expander controls the LED driver.</p>
<p>I began to search TTL<sup id="fnref:18"><a href="#fn:18" class="footnote-ref" role="doc-noteref">18</a></sup> RGB routing guidelines to see if I violated any rules, but I didn&rsquo;t find anything specific. What ultimately led me to the cause was comparing the waveforms on my board vs the Qualia. All the RGB565 signals looked fine, but when the Qualia booted, its I2C expander (the PCA9554) sent SPI<sup id="fnref:19"><a href="#fn:19" class="footnote-ref" role="doc-noteref">19</a></sup> signals to the display. There were no SPI signals on my board. The ESP32 produced the expected I2C signals, but the PCA9554 didn&rsquo;t respond. I realized the problem after doing a port scan.</p>
<p>The example code from Adafruit assumed the I2C address was <code>0x63</code>while my board configures it to <code>0x27</code>. I actually left a note about this confusion on my schematic.</p>

<figure><img src="https://extralongdivision.com/projects/dbz-radar/dbz-radar-devlog-1/io-expander-schematic.webp"
			alt="schematic of IO expander" loading="lazy">
</figure>
<p>Setting the proper I2C address made the display work properly.</p>
<h3 id="sound-1">Sound</h3>
<p>When I plugged in a speaker and loaded up example code… nothing. Not even the crackling sound I heard during the prototyping phase. I probed the pins of the I2S chip, the MAX98357, and quickly realized the pin assignment for the PCB and the breadboard prototype were different.</p>
<p>For easier routing, I made the following changes from prototype to PCB:</p>
<table>
	<thead>
			<tr>
					<th>MAX98357 Pin</th>
					<th>Qualia Pin Assignment</th>
					<th>Custom Board Assignment</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Bit Clock</td>
					<td>board.A1</td>
					<td>board.A0</td>
			</tr>
			<tr>
					<td>Left/Right Clock</td>
					<td>board.A0</td>
					<td>board.RX</td>
			</tr>
			<tr>
					<td>Data In</td>
					<td>board.TX</td>
					<td>board.A1</td>
			</tr>
	</tbody>
</table>
<p>Everything worked after changing the pin assignments in firmware. The sound output was clean too. This makes me confident that the horrendous sound coming out of the prototype was due to bad wiring.</p>
<p>While I&rsquo;m 99% sure the mismapped pinout was the only problem, before I discovered it, I replaced the pull up resistor on the <code>SD_MODE</code> pin with an 1M ohm one to match Adafruit&rsquo;s breakout board. I would swap back to the original 5.1k resistor, but I consider the board verified at this point.</p>
<h2 id="next-steps">Next Steps</h2>
<ul>
<li>
<p>I have to swap the polarity of the battery connector.</p>
</li>
<li>
<p>I have to make the board thinner.</p>
</li>
</ul>
<p>That&rsquo;s it. Not bad for a first revision. At this point, I could try to assemble the display and PCB into the enclosure, but it&rsquo;d be inconvenient to have to disassemble the entire project just to charge the battery. I&rsquo;ll sort out mechanical assembly once the new PCB comes in.</p>
<p>The repository for this project, though completely undocumented as of writing this, is hosted on 
<a href="https://codeberg.org/extralongdivision/dbz-radar"
data-umami-event="outbound-link-click"
data-umami-event-url="https://codeberg.org/extralongdivision/dbz-radar"
>
    Codeberg.
</a>. I&rsquo;ll post another write up here when it&rsquo;s ready. <a href="https://cloud.umami.is/q/4vO3PdsPN
">Subscribe to my RSS feed</a> to get the update as soon as it drops.</p>
<div class="author-byline">
  
  <img class="author-byline" src="https://extralongdivision.com/images/prof-pic.webp" alt="prof-pic">
  <p><a href="https://extralongdivision.com/id/"><b>Extra Long Division</b></a> is a maker of questionably functional things and haver of equally questionable opinions. <a href="https://cloud.umami.is/q/OqNJhRxBC">Subscribe to my RSS feed</a> if you liked what you read.</p>
</div>
<br>
<div class="donations-container">
  <div class="donations-flexbox">
  
  <img src="https://extralongdivision.com/images/homeless-emoji.webp" alt="homeless-emoji" width="48px" height="48px">
  <div class="donations-payments">
    
    <a href="https://ko-fi.com/extralongdivision/"
    data-umami-event="outbound-link-click"
    data-umami-event-url="https://ko-fi.com/extralongdivision/"
    >
      <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" stroke="none" width="48" height="48">
        <path d="M11.351 2.715c-2.7 0-4.986.025-6.83.26C2.078 3.285 0 5.154 0 8.61c0 3.506.182 6.13 1.585 8.493 1.584 2.701 4.233 4.182 7.662 4.182h.83c4.209 0 6.494-2.234 7.637-4a9.5 9.5 0 0 0 1.091-2.338C21.792 14.688 24 12.22 24 9.208v-.415c0-3.247-2.13-5.507-5.792-5.87-1.558-.156-2.65-.208-6.857-.208m0 1.947c4.208 0 5.09.052 6.571.182 2.624.311 4.13 1.584 4.13 4v.39c0 2.156-1.792 3.844-3.87 3.844h-.935l-.156.649c-.208 1.013-.597 1.818-1.039 2.546-.909 1.428-2.545 3.064-5.922 3.064h-.805c-2.571 0-4.831-.883-6.078-3.195-1.09-2-1.298-4.155-1.298-7.506 0-2.181.857-3.402 3.012-3.714 1.533-.233 3.559-.26 6.39-.26m6.547 2.287c-.416 0-.65.234-.65.546v2.935c0 .311.234.545.65.545 1.324 0 2.051-.754 2.051-2s-.727-2.026-2.052-2.026m-10.39.182c-1.818 0-3.013 1.48-3.013 3.142 0 1.533.858 2.857 1.949 3.897.727.701 1.87 1.429 2.649 1.896a1.47 1.47 0 0 0 1.507 0c.78-.467 1.922-1.195 2.623-1.896 1.117-1.039 1.974-2.364 1.974-3.897 0-1.662-1.247-3.142-3.039-3.142-1.065 0-1.792.545-2.338 1.298-.493-.753-1.246-1.298-2.312-1.298" />
      </svg>
    </a>
    <a href="https://liberapay.com/extralongdivision/"
    data-umami-event="outbound-link-click"
    data-umami-event-url="https://liberapay.com/extralongdivision/"
    >
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" fill="currentColor" width="48" height="48">
        <g transform="translate(-78.37-208.06)">
          <path d="m104.28 271.1c-3.571 0-6.373-.466-8.41-1.396-2.037-.93-3.495-2.199-4.375-3.809-.88-1.609-1.308-3.457-1.282-5.544.025-2.086.313-4.311.868-6.675l9.579-40.05 11.69-1.81-10.484 43.44c-.202.905-.314 1.735-.339 2.489-.026.754.113 1.421.415 1.999.302.579.817 1.044 1.546 1.395.729.353 1.747.579 3.055.679l-2.263 9.278" />
          <path d="m146.52 246.14c0 3.671-.604 7.03-1.811 10.07-1.207 3.043-2.879 5.669-5.01 7.881-2.138 2.213-4.702 3.935-7.693 5.167-2.992 1.231-6.248 1.848-9.767 1.848-1.71 0-3.42-.151-5.129-.453l-3.394 13.651h-11.162l12.52-52.19c2.01-.603 4.311-1.143 6.901-1.622 2.589-.477 5.393-.716 8.41-.716 2.815 0 5.242.428 7.278 1.282 2.037.855 3.708 2.024 5.02 3.507 1.307 1.484 2.274 3.219 2.904 5.205.627 1.987.942 4.11.942 6.373m-27.378 15.461c.854.202 1.91.302 3.167.302 1.961 0 3.746-.364 5.355-1.094 1.609-.728 2.979-1.747 4.111-3.055 1.131-1.307 2.01-2.877 2.64-4.714.628-1.835.943-3.858.943-6.071 0-2.161-.479-3.998-1.433-5.506-.956-1.508-2.615-2.263-4.978-2.263-1.61 0-3.118.151-4.525.453l-5.28 21.948" />
        </g>
      </svg>
    </a>
    <a href="https://buymeacoffee.com/extralongdivision/"
    data-umami-event="outbound-link-click"
    data-umami-event-url="https://buymeacoffee.com/extralongdivision/"
    >
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 884 1279" fill="none" stroke="currentColor" stroke-width="2" width="48" height="48">
        <path d="M791.109 297.518L790.231 297.002L788.201 296.383C789.018 297.072 790.04 297.472 791.109 297.518Z" fill="currentColor"></path>
        <path d="M803.896 388.891L802.916 389.166L803.896 388.891Z" fill="currentColor"></path>
        <path
            d="M791.484 297.377C791.359 297.361 791.237 297.332 791.118 297.29C791.111 297.371 791.111 297.453 791.118 297.534C791.252 297.516 791.379 297.462 791.484 297.377Z"
            fill="currentColor"></path>
        <path d="M791.113 297.529H791.244V297.447L791.113 297.529Z" fill="currentColor"></path>
        <path
            d="M803.111 388.726L804.591 387.883L805.142 387.573L805.641 387.04C804.702 387.444 803.846 388.016 803.111 388.726Z"
            fill="currentColor"></path>
        <path d="M793.669 299.515L792.223 298.138L791.243 297.605C791.77 298.535 792.641 299.221 793.669 299.515Z"
            fill="currentColor"></path>
        <path
            d="M430.019 1186.18C428.864 1186.68 427.852 1187.46 427.076 1188.45L427.988 1187.87C428.608 1187.3 429.485 1186.63 430.019 1186.18Z"
            fill="currentColor"></path>
        <path
            d="M641.187 1144.63C641.187 1143.33 640.551 1143.57 640.705 1148.21C640.705 1147.84 640.86 1147.46 640.929 1147.1C641.015 1146.27 641.084 1145.46 641.187 1144.63Z"
            fill="currentColor"></path>
        <path
            d="M619.284 1186.18C618.129 1186.68 617.118 1187.46 616.342 1188.45L617.254 1187.87C617.873 1187.3 618.751 1186.63 619.284 1186.18Z"
            fill="currentColor"></path>
        <path
            d="M281.304 1196.06C280.427 1195.3 279.354 1194.8 278.207 1194.61C279.136 1195.06 280.065 1195.51 280.684 1195.85L281.304 1196.06Z"
            fill="currentColor"></path>
        <path
            d="M247.841 1164.01C247.704 1162.66 247.288 1161.35 246.619 1160.16C247.093 1161.39 247.489 1162.66 247.806 1163.94L247.841 1164.01Z"
            fill="currentColor"></path>
        <path
            d="M472.623 590.836C426.682 610.503 374.546 632.802 306.976 632.802C278.71 632.746 250.58 628.868 223.353 621.274L270.086 1101.08C271.74 1121.13 280.876 1139.83 295.679 1153.46C310.482 1167.09 329.87 1174.65 349.992 1174.65C349.992 1174.65 416.254 1178.09 438.365 1178.09C462.161 1178.09 533.516 1174.65 533.516 1174.65C553.636 1174.65 573.019 1167.08 587.819 1153.45C602.619 1139.82 611.752 1121.13 613.406 1101.08L663.459 570.876C641.091 563.237 618.516 558.161 593.068 558.161C549.054 558.144 513.591 573.303 472.623 590.836Z"
            fill="currentColor"></path>
        <path d="M78.6885 386.132L79.4799 386.872L79.9962 387.182C79.5987 386.787 79.1603 386.435 78.6885 386.132Z"
            fill="currentColor"></path>
        <path
            d="M879.567 341.849L872.53 306.352C866.215 274.503 851.882 244.409 819.19 232.898C808.711 229.215 796.821 227.633 788.786 220.01C780.751 212.388 778.376 200.55 776.518 189.572C773.076 169.423 769.842 149.257 766.314 129.143C763.269 111.85 760.86 92.4243 752.928 76.56C742.604 55.2584 721.182 42.8009 699.88 34.559C688.965 30.4844 677.826 27.0375 666.517 24.2352C613.297 10.1947 557.342 5.03277 502.591 2.09047C436.875 -1.53577 370.983 -0.443234 305.422 5.35968C256.625 9.79894 205.229 15.1674 158.858 32.0469C141.91 38.224 124.445 45.6399 111.558 58.7341C95.7448 74.8221 90.5829 99.7026 102.128 119.765C110.336 134.012 124.239 144.078 138.985 150.737C158.192 159.317 178.251 165.846 198.829 170.215C256.126 182.879 315.471 187.851 374.007 189.968C438.887 192.586 503.87 190.464 568.44 183.618C584.408 181.863 600.347 179.758 616.257 177.304C634.995 174.43 647.022 149.928 641.499 132.859C634.891 112.453 617.134 104.538 597.055 107.618C594.095 108.082 591.153 108.512 588.193 108.942L586.06 109.252C579.257 110.113 572.455 110.915 565.653 111.661C551.601 113.175 537.515 114.414 523.394 115.378C491.768 117.58 460.057 118.595 428.363 118.647C397.219 118.647 366.058 117.769 334.983 115.722C320.805 114.793 306.661 113.611 292.552 112.177C286.134 111.506 279.733 110.801 273.333 110.009L267.241 109.235L265.917 109.046L259.602 108.134C246.697 106.189 233.792 103.953 221.025 101.251C219.737 100.965 218.584 100.249 217.758 99.2193C216.932 98.1901 216.482 96.9099 216.482 95.5903C216.482 94.2706 216.932 92.9904 217.758 91.9612C218.584 90.9319 219.737 90.2152 221.025 89.9293H221.266C232.33 87.5721 243.479 85.5589 254.663 83.8038C258.392 83.2188 262.131 82.6453 265.882 82.0832H265.985C272.988 81.6186 280.026 80.3625 286.994 79.5366C347.624 73.2301 408.614 71.0801 469.538 73.1014C499.115 73.9618 528.676 75.6996 558.116 78.6935C564.448 79.3474 570.746 80.0357 577.043 80.8099C579.452 81.1025 581.878 81.4465 584.305 81.7391L589.191 82.4445C603.438 84.5667 617.61 87.1419 631.708 90.1703C652.597 94.7128 679.422 96.1925 688.713 119.077C691.673 126.338 693.015 134.408 694.649 142.03L696.732 151.752C696.786 151.926 696.826 152.105 696.852 152.285C701.773 175.227 706.7 198.169 711.632 221.111C711.994 222.806 712.002 224.557 711.657 226.255C711.312 227.954 710.621 229.562 709.626 230.982C708.632 232.401 707.355 233.6 705.877 234.504C704.398 235.408 702.75 235.997 701.033 236.236H700.895L697.884 236.649L694.908 237.044C685.478 238.272 676.038 239.419 666.586 240.486C647.968 242.608 629.322 244.443 610.648 245.992C573.539 249.077 536.356 251.102 499.098 252.066C480.114 252.57 461.135 252.806 442.162 252.771C366.643 252.712 291.189 248.322 216.173 239.625C208.051 238.662 199.93 237.629 191.808 236.58C198.106 237.389 187.231 235.96 185.029 235.651C179.867 234.928 174.705 234.177 169.543 233.397C152.216 230.798 134.993 227.598 117.7 224.793C96.7944 221.352 76.8005 223.073 57.8906 233.397C42.3685 241.891 29.8055 254.916 21.8776 270.735C13.7217 287.597 11.2956 305.956 7.64786 324.075C4.00009 342.193 -1.67805 361.688 0.472751 380.288C5.10128 420.431 33.165 453.054 73.5313 460.35C111.506 467.232 149.687 472.807 187.971 477.556C338.361 495.975 490.294 498.178 641.155 484.129C653.44 482.982 665.708 481.732 677.959 480.378C681.786 479.958 685.658 480.398 689.292 481.668C692.926 482.938 696.23 485.005 698.962 487.717C701.694 490.429 703.784 493.718 705.08 497.342C706.377 500.967 706.846 504.836 706.453 508.665L702.633 545.797C694.936 620.828 687.239 695.854 679.542 770.874C671.513 849.657 663.431 928.434 655.298 1007.2C653.004 1029.39 650.71 1051.57 648.416 1073.74C646.213 1095.58 645.904 1118.1 641.757 1139.68C635.218 1173.61 612.248 1194.45 578.73 1202.07C548.022 1209.06 516.652 1212.73 485.161 1213.01C450.249 1213.2 415.355 1211.65 380.443 1211.84C343.173 1212.05 297.525 1208.61 268.756 1180.87C243.479 1156.51 239.986 1118.36 236.545 1085.37C231.957 1041.7 227.409 998.039 222.9 954.381L197.607 711.615L181.244 554.538C180.968 551.94 180.693 549.376 180.435 546.76C178.473 528.023 165.207 509.681 144.301 510.627C126.407 511.418 106.069 526.629 108.168 546.76L120.298 663.214L145.385 904.104C152.532 972.528 159.661 1040.96 166.773 1109.41C168.15 1122.52 169.44 1135.67 170.885 1148.78C178.749 1220.43 233.465 1259.04 301.224 1269.91C340.799 1276.28 381.337 1277.59 421.497 1278.24C472.979 1279.07 524.977 1281.05 575.615 1271.72C650.653 1257.95 706.952 1207.85 714.987 1130.13C717.282 1107.69 719.576 1085.25 721.87 1062.8C729.498 988.559 737.115 914.313 744.72 840.061L769.601 597.451L781.009 486.263C781.577 480.749 783.905 475.565 787.649 471.478C791.392 467.391 796.352 464.617 801.794 463.567C823.25 459.386 843.761 452.245 859.023 435.916C883.318 409.918 888.153 376.021 879.567 341.849ZM72.4301 365.835C72.757 365.68 72.1548 368.484 71.8967 369.792C71.8451 367.813 71.9483 366.058 72.4301 365.835ZM74.5121 381.94C74.6842 381.819 75.2003 382.508 75.7337 383.334C74.925 382.576 74.4089 382.009 74.4949 381.94H74.5121ZM76.5597 384.641C77.2996 385.897 77.6953 386.689 76.5597 384.641V384.641ZM80.672 387.979H80.7752C80.7752 388.1 80.9645 388.22 81.0333 388.341C80.9192 388.208 80.7925 388.087 80.6548 387.979H80.672ZM800.796 382.989C793.088 390.319 781.473 393.726 769.996 395.43C641.292 414.529 510.713 424.199 380.597 419.932C287.476 416.749 195.336 406.407 103.144 393.382C94.1102 392.109 84.3197 390.457 78.1082 383.798C66.4078 371.237 72.1548 345.944 75.2003 330.768C77.9878 316.865 83.3218 298.334 99.8572 296.355C125.667 293.327 155.64 304.218 181.175 308.09C211.917 312.781 242.774 316.538 273.745 319.36C405.925 331.405 540.325 329.529 671.92 311.91C695.906 308.686 719.805 304.941 743.619 300.674C764.835 296.871 788.356 289.731 801.175 311.703C809.967 326.673 811.137 346.701 809.778 363.615C809.359 370.984 806.139 377.915 800.779 382.989H800.796Z"
            fill="currentColor"></path>
      </svg>
    </a>
  </div>
  </div>
</div>
<br>
<p><a href="https://extralongdivision.com/articles/please-define-your-jargon/">Why are there footnotes?</a></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>developer&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>inter-integrated circuit sound&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>printed circuit board&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>through hole technology&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>input/output&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>light emitting diode&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>flat flex cable&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p>red, blue, green 5 bit, 6 bit, 5 bit&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p>Universal serial bus&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p>voltage bus&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:11">
<p>do not populate&#160;<a href="#fnref:11" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:12">
<p>printed circuit board assembly&#160;<a href="#fnref:12" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:13">
<p>previously known as Institute of Printed Circuits, but known known as Global Electronics Association&#160;<a href="#fnref:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:14">
<p>surface mount technology&#160;<a href="#fnref:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:15">
<p>electrostatic discharge or &ldquo;static shock&rdquo;&#160;<a href="#fnref:15" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:16">
<p>lithium polymer battery&#160;<a href="#fnref:16" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:17">
<p>inter-integrated circuit&#160;<a href="#fnref:17" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:18">
<p>transistor-transistor logic&#160;<a href="#fnref:18" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:19">
<p>serial peripheral interface&#160;<a href="#fnref:19" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
