<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>embedded-ideas.de - Blog on </title>
        <link>https://www.embedded-ideas.de/posts/</link>
        <description>Recent content in embedded-ideas.de - Blog on </description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Fri, 24 Jul 2026 01:00:00 +0100</lastBuildDate>
        <atom:link href="https://www.embedded-ideas.de/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>Mouth Operated Mouse II</title>
            <link>https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/</link>
            <pubDate>Fri, 24 Jul 2026 01:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/</guid>
            <description>TL;DR DIY mouth-operated USB HID mouse for appr. 10$ in materials. Built from hand-solderable, easy-to-source components and 3D-printed parts. Custom PCB with an open-source firmware. Includes a 3D-printed sip/puff pressure sensor. Appears as a standard USB HID mouse can be calibrated via serial terminal. Complete hardware files, firmware, BOM, and assembly instructions are available below. Introduction It has been a while since I published my design for a mouth-operated mouse in 2015 (3D Printed Mouth-Operated Mouse).</description>
            <content type="html"><![CDATA[<p><img alt="Project Overview" src="/posts/260724_mouth_mouse_2/images/title.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>DIY mouth-operated USB HID mouse for <strong>appr. 10$</strong> in materials.</li>
<li>Built from <strong>hand-solderable, easy-to-source components</strong> and 3D-printed parts.</li>
<li>Custom PCB with an <strong>open-source firmware</strong>.</li>
<li>Includes a <strong>3D-printed sip/puff pressure sensor</strong>.</li>
<li>Appears as a <strong>standard USB HID mouse</strong> can be calibrated via serial terminal.</li>
<li>Complete hardware files, firmware, BOM, and assembly instructions are available below.</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>It has been a while since I published my design for a mouth-operated mouse in 2015 (<a href="https://www.thingiverse.com/thing:1090461">3D Printed Mouth-Operated Mouse</a>). Even after more than 10 years, it remains one of the designs that continues to receive a surprising amount of attention on Thingiverse. That made me think it might be worth revisiting the concept.</p>
<p>A lot has changed since then. Affordable PCB manufacturing has become widely available, electronic components are much easier to source, and 3D printing has evolved significantly, making it more accessible than ever. The DIY assistive technology ecosystem has also grown, with projects such as:</p>
<ul>
<li><a href="https://github.com/DeathMegatron3000/Mouth-Operated-Mouse-V3">Mouth-Operated Mouse V3</a></li>
<li><a href="https://github.com/makersmakingchange/LipSync">LipSync</a></li>
<li><a href="https://github.com/asterics/FLipMouse/">FLipMouse</a></li>
</ul>
<p>to name just a few.</p>
<p>Even so, I think there is still room for an updated version of my original design. My goals for this revision were:</p>
<ul>
<li>Maintain the low cost, or reduce it even further.</li>
<li>Use components that are easy to source.</li>
<li>Optimize the design for production in small batches (5-10 units), for example in makerspaces.</li>
</ul>
<h2 id="disclaimer">Disclaimer</h2>
<p>The design focuses on cost-effectiveness. However, it is not intended for mass production. All components have been chosen to be easily sourced in most locations. It does not use any parts that require specialized soldering equipment. The goal was to provide a product that can be assembled by a person with intermediate skills, for example in a makerspace, using a basic soldering iron and simple magnification, along with widely available consumables such as super glue and access to a 3D printer capable of printing PLA.</p>
<p>I hope this design is helpful or sparks some creative ideas! It&rsquo;s not a ready-to-go product, though, so it does take a bit of skill to make and may not work perfectly on the first try. Have fun experimenting, and feel free to adapt it for your own projects. If you have any problems, I&rsquo;m happy to help as long as I have the time, but if I&rsquo;m busy, you&rsquo;re on your own.</p>
<h2 id="design">Design</h2>
<p>The old design relied on off-the-shelf parts. Most of these were available from AliExpress-style shops, along with a pressure sensor salvaged from an e-cigarette. While this approach worked for some time, most of those parts are no longer available and have been difficult to source for quite a while.</p>
<p><img alt="Old Design" src="/posts/260724_mouth_mouse_2/images/old.png"></p>
<p>This time, I wanted to avoid those dependencies. The new design uses a custom double-sided PCB that can be ordered from your preferred PCB manufacturer. It exclusively uses components that can be soldered by hand with basic SMD soldering skills. There are no extremely fine-pitch parts or QFN packages. The BOM has also been optimized to keep both the total component count and the number of different component types as low as possible.</p>
<p><img alt="New PCB" src="/posts/260724_mouth_mouse_2/images/pcb.JPG"></p>
<p>One thing the design does not use is an off-the-shelf pressure sensor. I found that pressure sensors suitable for a project like this are either relatively expensive compared to the overall project cost or difficult to source. I recently wrote an article about <a href="/posts/260702_pressure_sensor/">how to build a pressure sensor</a> using strain gauges and 3D printing. Developing that sensor was a prerequisite for this project, as I wanted a solution that was inexpensive and easy to source.</p>
<p><img alt="New Sensor" src="/posts/260724_mouth_mouse_2/images/sensor_case.png"></p>
<p>In addition to the pressure sensor and the assembled PCB, you&rsquo;ll need a few 3D-printed parts, some hardware such as screws, and a length of silicone tubing.</p>
<h2 id="cost">Cost</h2>
<p>The design mainly focuses on cost-effectiveness. To support that claim, I&rsquo;d like to take a closer look at the actual cost breakdown.</p>
<p>The costs were calculated based on the components required to build 10 units. I did not cut corners on critical parts such as the joystick and generally chose components from well-known manufacturers. Most prices are based on listings from LCSC and AliExpress, so there is still some potential to reduce the overall cost further.</p>
<p>The calculation does not include taxes, shipping, customs fees, or assembly consumables such as solder, flux, adhesive tape, and similar materials.</p>
<p>The main takeaway is that the material cost of a single device is around <strong>7 EUR</strong> (7.35 EUR). Even when accounting for the fact that many components must be purchased in larger quantities than required for a batch of 10 units, the effective cost remains below <strong>10 EUR</strong> per device (9.88 EUR).</p>
<h3 id="pcb">PCB</h3>
<table>
<thead>
<tr>
<th>Item</th>
<th>Remarks</th>
<th style="text-align:right">Quantity</th>
<th style="text-align:right">Order Quantity</th>
<th style="text-align:right">Order Cost</th>
<th style="text-align:right">Cost per Unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>PCB</td>
<td>Lead-free</td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">5.41 €</td>
<td style="text-align:right">0.54 €</td>
</tr>
<tr>
<td>Capacitor</td>
<td>10 µF</td>
<td style="text-align:right">5</td>
<td style="text-align:right">100</td>
<td style="text-align:right">7.35 €</td>
<td style="text-align:right">0.37 €</td>
</tr>
<tr>
<td>Capacitor</td>
<td>100 nF</td>
<td style="text-align:right">12</td>
<td style="text-align:right">150</td>
<td style="text-align:right">4.55 €</td>
<td style="text-align:right">0.36 €</td>
</tr>
<tr>
<td>Capacitor</td>
<td>20 pF</td>
<td style="text-align:right">2</td>
<td style="text-align:right">50</td>
<td style="text-align:right">1.10 €</td>
<td style="text-align:right">0.04 €</td>
</tr>
<tr>
<td>Resistor</td>
<td>15 kΩ</td>
<td style="text-align:right">7</td>
<td style="text-align:right">100</td>
<td style="text-align:right">0.30 €</td>
<td style="text-align:right">0.02 €</td>
</tr>
<tr>
<td>Resistor</td>
<td>75 kΩ</td>
<td style="text-align:right">3</td>
<td style="text-align:right">100</td>
<td style="text-align:right">0.31 €</td>
<td style="text-align:right">0.01 €</td>
</tr>
<tr>
<td>Resistor</td>
<td>5.1 kΩ</td>
<td style="text-align:right">3</td>
<td style="text-align:right">100</td>
<td style="text-align:right">0.30 €</td>
<td style="text-align:right">0.01 €</td>
</tr>
<tr>
<td>Resistor</td>
<td>348 Ω</td>
<td style="text-align:right">2</td>
<td style="text-align:right">100</td>
<td style="text-align:right">0.24 €</td>
<td style="text-align:right">0.00 €</td>
</tr>
<tr>
<td>Resistor</td>
<td>51 Ω</td>
<td style="text-align:right">2</td>
<td style="text-align:right">100</td>
<td style="text-align:right">0.30 €</td>
<td style="text-align:right">0.01 €</td>
</tr>
<tr>
<td>Pushbutton</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">0.50 €</td>
<td style="text-align:right">0.05 €</td>
</tr>
<tr>
<td>Joystick</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">10.69 €</td>
<td style="text-align:right">1.07 €</td>
</tr>
<tr>
<td>Microcontroller</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">5.97 €</td>
<td style="text-align:right">0.60 €</td>
</tr>
<tr>
<td>Voltage Regulator</td>
<td></td>
<td style="text-align:right">2</td>
<td style="text-align:right">30</td>
<td style="text-align:right">14.95 €</td>
<td style="text-align:right">1.00 €</td>
</tr>
<tr>
<td>Protection Diode</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">0.40 €</td>
<td style="text-align:right">0.04 €</td>
</tr>
<tr>
<td>HX717</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">4.64 €</td>
<td style="text-align:right">0.46 €</td>
</tr>
<tr>
<td>USB connector</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">3.06 €</td>
<td style="text-align:right">0,31 €</td>
</tr>
<tr>
<td>Crystal</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">0.89 €</td>
<td style="text-align:right">0.09 €</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"><strong>4.98 €</strong></td>
</tr>
</tbody>
</table>
<h3 id="case">Case</h3>
<table>
<thead>
<tr>
<th>Item</th>
<th>Remarks</th>
<th style="text-align:right">Quantity</th>
<th style="text-align:right">Order Quantity</th>
<th style="text-align:right">Order Cost</th>
<th style="text-align:right">Cost per Unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Case</td>
<td>32.53 g PLA</td>
<td style="text-align:right">32.53 g</td>
<td style="text-align:right">1000 g</td>
<td style="text-align:right">16.90 €</td>
<td style="text-align:right">0.55 €</td>
</tr>
<tr>
<td>Screw M3×20</td>
<td>M3×20</td>
<td style="text-align:right">5</td>
<td style="text-align:right">50</td>
<td style="text-align:right">5.59 €</td>
<td style="text-align:right">0.56 €</td>
</tr>
<tr>
<td>Nut M3</td>
<td></td>
<td style="text-align:right">5</td>
<td style="text-align:right">50</td>
<td style="text-align:right">4.49 €</td>
<td style="text-align:right">0.45 €</td>
</tr>
<tr>
<td>1/4&quot; Nut</td>
<td></td>
<td style="text-align:right">1</td>
<td style="text-align:right">10</td>
<td style="text-align:right">2.49 €</td>
<td style="text-align:right">0.25 €</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"><strong>1.81 €</strong></td>
</tr>
</tbody>
</table>
<h3 id="sensor">Sensor</h3>
<table>
<thead>
<tr>
<th>Item</th>
<th>Remarks</th>
<th style="text-align:right">Quantity</th>
<th style="text-align:right">Order Quantity</th>
<th style="text-align:right">Order Cost</th>
<th style="text-align:right">Cost per Unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sensor Body</td>
<td>1.45 g PLA</td>
<td style="text-align:right">1.45 g</td>
<td style="text-align:right">1000 g</td>
<td style="text-align:right">16.90 €</td>
<td style="text-align:right">0.02 €</td>
</tr>
<tr>
<td>Screw M2×5</td>
<td></td>
<td style="text-align:right">2</td>
<td style="text-align:right">50</td>
<td style="text-align:right">0.73 €</td>
<td style="text-align:right">0.03 €</td>
</tr>
<tr>
<td>Silicone Hose</td>
<td></td>
<td style="text-align:right">160 mm</td>
<td style="text-align:right">5000 mm</td>
<td style="text-align:right">4.97 €</td>
<td style="text-align:right">0.16 €</td>
</tr>
<tr>
<td>Wire</td>
<td>3 × 10 cm</td>
<td style="text-align:right">300 mm</td>
<td style="text-align:right">10000 mm</td>
<td style="text-align:right">1.15 €</td>
<td style="text-align:right">0.03 €</td>
</tr>
<tr>
<td>Strain Gauges</td>
<td>BF350</td>
<td style="text-align:right">2</td>
<td style="text-align:right">10</td>
<td style="text-align:right">1.59 €</td>
<td style="text-align:right">0.32 €</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"></td>
<td style="text-align:right"><strong>0.57 €</strong></td>
</tr>
</tbody>
</table>
<h2 id="assembly">Assembly</h2>
<p>To build the device, you will need the following parts:</p>
<ul>
<li>Electronics
<ul>
<li>Assembled PCB</li>
<li>Assembled pressure sensor</li>
</ul>
</li>
<li>3D-Printed Parts
<ul>
<li>Case bottom</li>
<li>Case front cover</li>
<li>Spacer</li>
<li>Mouthpiece mount</li>
<li>Mouthpiece</li>
<li>Mounting nut cover</li>
</ul>
</li>
<li>Hardware
<ul>
<li>5× M3×20 screws (e.g. DIN 7985)</li>
<li>5× M3 hex nuts (DIN 934)</li>
<li>1× 1/4&quot;-20 nut</li>
<li>2× M2×5 countersunk screws (or self-tapping screws)</li>
</ul>
</li>
<li>Silicone hose (4mm OD / 2mm ID)</li>
</ul>
<p><img alt="Assembly overview" src="/posts/260724_mouth_mouse_2/images/assembly.JPG"></p>
<h2 id="pcb-1">PCB</h2>
<p>All files required to manufacture and assemble the PCB are available in the <a href="https://codeberg.org/embedded-ideas/MouthOperatedMouse2-HW/releases">Releases section</a> of the hardware repository.</p>
<p>To order the PCB, Gerber files are provided. For assembly, an interactive Bill of Materials (BOM) is also included.</p>
<p>Not every listed component needs to be populated. Components marked DNP (Do Not Populate) should be omitted. These parts are normally hidden in the interactive BOM.</p>
<p><img alt="New Sensor" src="/posts/260724_mouth_mouse_2/images/pcb_render.png"></p>
<h2 id="pressure-sensor">Pressure Sensor</h2>
<p>The pressure sensor is covered in a separate article. Please refer to:</p>
<p><strong><a href="/posts/260702_pressure_sensor/">3D Printed Pressure Sensor</a></strong></p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/P3040892.JPG"></p>
<h2 id="update-09082026-alternative-pressure-sensor">UPDATE 09.08.2026: Alternative Pressure Sensor</h2>
<p>There is a second option for the sensor. If you don&rsquo;t want to build the DIY sensor, there is a commercial drop-in replacement. The XGZP160010S from CFSensor can be connected mostly in the same way as the DIY sensor.</p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/cf_sensor/PXL_20260809_184341248.jpg"></p>
<p>To make mounting easier, a carrier PCB is provided here: <a href="https://codeberg.org/embedded-ideas/ahid_hw_cf_sensor_single/releases">https://codeberg.org/embedded-ideas/ahid_hw_cf_sensor_single/releases</a></p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/cf_sensor/PXL_20260809_184146102.jpg"></p>
<p>There is an additional model for the back of the case that allows you to mount the assembled board. The connections to the board are as follows:</p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/cf_sensor/cf_con.png"></p>
<p>Remove R13 and R14 and connect the positive signal line from the sensor board to either the lower pad of R13 or the upper pad of R14. If you want, you can also bridge those pads, as they are connected anyway.</p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/cf_sensor/pad4.png"></p>
<p>The sensor can be screwed to the case using two M3x6 mm screws and two M3 nuts.</p>
<p><img alt="Pressure sensor" src="/posts/260724_mouth_mouse_2/images/cf_sensor/PXL_20260809_184027723.jpg"></p>
<h2 id="device-assembly">Device Assembly</h2>
<blockquote>
<p><strong>⚠️ Before starting assembly, make sure the firmware has been flashed onto the PCB.</strong></p>
</blockquote>
<p><img alt="New Sensor" src="/posts/260724_mouth_mouse_2/images/exploded4.png"></p>
<ol>
<li>Insert the 1/4&quot;-20 nut into the corresponding cutout in the case and secure it using the mounting nut cover.</li>
<li>Insert an M3 nut into each of the four corner slots of the case.</li>
<li>Connect the pressure sensor to the PCB using the solder pad connections.</li>
<li>Mount the sensor inside the case using the two M2 screws. Make sure it is installed in the correct orientation.</li>
<li>Carefully place the PCB into the case. Ensure that the sensor wires are routed underneath the PCB without being pinched. There should be a small gap between the PCB and the wires.</li>
<li>Install the mouthpiece mount onto the joystick.</li>
<li>Fit the front cover, making sure it is correctly oriented. The cover includes a cutout that aligns with the pressure sensor.</li>
<li>Insert the remaining M3 nut into the slot of the mouthpiece.</li>
<li>Slide the mouthpiece onto the mouthpiece mount.</li>
<li>Install and tighten the M3 screw to secure the mouthpiece.</li>
<li>Finally, connect the pressure sensor to the mouthpiece using the silicone hose.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070937_hu0aef7289ac4c21d02f3162028785ad0d_1080589_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070937_hu0aef7289ac4c21d02f3162028785ad0d_1080589_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070940_hu0aef7289ac4c21d02f3162028785ad0d_1007172_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070940_hu0aef7289ac4c21d02f3162028785ad0d_1007172_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070942_hu0aef7289ac4c21d02f3162028785ad0d_1226880_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070942_hu0aef7289ac4c21d02f3162028785ad0d_1226880_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070945_hu0aef7289ac4c21d02f3162028785ad0d_1053405_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070945_hu0aef7289ac4c21d02f3162028785ad0d_1053405_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070949_hu0aef7289ac4c21d02f3162028785ad0d_1071286_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070949_hu0aef7289ac4c21d02f3162028785ad0d_1071286_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070950_hu0aef7289ac4c21d02f3162028785ad0d_1012309_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070950_hu0aef7289ac4c21d02f3162028785ad0d_1012309_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070952_hu0aef7289ac4c21d02f3162028785ad0d_964054_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070952_hu0aef7289ac4c21d02f3162028785ad0d_964054_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070953_hu0aef7289ac4c21d02f3162028785ad0d_1044203_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070953_hu0aef7289ac4c21d02f3162028785ad0d_1044203_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070955_hu0aef7289ac4c21d02f3162028785ad0d_1112117_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070955_hu0aef7289ac4c21d02f3162028785ad0d_1112117_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070957_hu0aef7289ac4c21d02f3162028785ad0d_1076903_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260724_mouth_mouse_2/images/assembly/P7070957_hu0aef7289ac4c21d02f3162028785ad0d_1076903_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="firmware">Firmware</h2>
<p>I have been trying to publish a new version of the original mouth-operated mouse for several years now. During that time, I actually completed two new hardware designs. The reason I never published them was that I couldn&rsquo;t find the time to write the software the way I wanted.</p>
<p>This time, I wrote the software in a way that I believe is a step in the right direction. It&rsquo;s now structured to be extendable and maintainable. It isn&rsquo;t just a simple Arduino sketch, but it also isn&rsquo;t quite what I ultimately want it to be. It&rsquo;s fully usable, but it&rsquo;s still a work in progress.</p>
<p>The goal is to create a fairly universal firmware that can implement more than just mouse functionality. The firmware should be configurable through profiles to adapt to specific tasks, and it should also be adaptable to different hardware devices.</p>
<p>Since implementing mouse functionality alone isn&rsquo;t particularly challenging, the current firmware is more than sufficient for this project. However, I expect that future devices may make use of much more of its potential.</p>
<p>Currently, the inputs are mapped as follows:</p>
<ul>
<li>Joystick movement controls the mouse cursor. When scroll mode is enabled, joystick movement scrolls the page instead.</li>
<li>Pressing the joystick toggles between &ldquo;cursor mode&rdquo; and &ldquo;scroll mode&rdquo;&quot;.</li>
<li>Pressure sensor inputs emulate the mouse buttons:
<ul>
<li>Sip = Left mouse button</li>
<li>Puff = Right mouse button</li>
</ul>
</li>
</ul>
<h3 id="flashing-the-firmware">Flashing the Firmware</h3>
<p>There are two ways to get the firmware onto the microcontroller. You can use the debug port and a wlink compatible debuger/programmer. For most people it will be easier to just use the integrated USB bootloader. When pressing the pushbutton on the board while powering up the device, it will enter the bootloader. You can then use e.g. a tool like <a href="https://github.com/ch32-rs/wchisp">wchisp</a> to upload the firmware. I also provide a web-based version for flashing the firmware:</p>
<p><a href="/html/wchisp.html">Firmware Flash Tool</a></p>
<h2 id="calibration">Calibration</h2>
<p>Before using the device, perform an initial calibration of the joystick and the pressure sensor. Calibration is done through a serial terminal. You can use a terminal program such as PuTTY or Minicom. If you prefer not to install any software, you can use my web-based terminal instead:</p>
<p><a href="/html/tty.html">Serial Terminal</a></p>
<p>The <code>cal</code> command provides several subcommands for calibration. First, list all available inputs that can be calibrated:</p>
<p><strong><code>cal list</code></strong></p>
<pre tabindex="0"><code>&gt; cal list
0: Joystick x-Axis
1: Joystick y-Axis
2: Pressure Sensor
&gt;
</code></pre><p>To calibrate an input, use the <code>cal start</code> command followed by the input number. The calibration process will guide you through the required steps. If you are not satisfied with the result, simply do not confirm the calibration. The previous calibration will be restored automatically.</p>
<p><strong><code>cal start</code></strong></p>
<pre tabindex="0"><code>&gt; cal start 0
Please don&#39;t operate Joystick x-Axis and leave it in the idle position!
Measuring baseline
Operate Left and leave idle afterwards.
Operate Right and leave idle afterwards.
Please test calibration:        0
Operate both functions (Left and Right) to keep the calibration.
Restoring previous calibration.
Done.
&gt;
</code></pre><p>Repeat this process for all inputs. Once all channels have been calibrated, the device is ready for use.</p>
<p>Finally, store the calibration in persistent memory. If you skip this step, <strong>the calibration will be lost</strong> after the device is power-cycled.</p>
<p><strong><code>cal write</code></strong></p>
<pre tabindex="0"><code>&gt; cal write
Calibration stored successfully!
&gt;
</code></pre><h2 id="project-files">Project files</h2>
<p>The project is split into two repositories on Codeberg. One repository contains the hardware design along with the 3D models. The software is maintained as a separate project because it may be reused for other devices in the future. It is not intended to be used exclusively for the Mouth Operated Mouse II.</p>
<h3 id="hardware-board-and-3d-models">Hardware (Board and 3D-Models)</h3>
<ul>
<li>Repo: <a href="https://codeberg.org/embedded-ideas/MouthOperatedMouse2-HW">https://codeberg.org/embedded-ideas/MouthOperatedMouse2-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/MouthOperatedMouse2-HW/releases">https://codeberg.org/embedded-ideas/MouthOperatedMouse2-HW/releases</a></li>
</ul>
<h3 id="ahid-software">AHID Software</h3>
<ul>
<li>Repo: <a href="https://codeberg.org/embedded-ideas/ahid">https://codeberg.org/embedded-ideas/ahid</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/ahid/releases">https://codeberg.org/embedded-ideas/ahid/releases</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>3D Printed Pressure Sensor</title>
            <link>https://www.embedded-ideas.de/posts/260702_pressure_sensor/</link>
            <pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260702_pressure_sensor/</guid>
            <description>TL;DR Differential air pressure sensor Built using a 3D-printed body and standard strain gauges Material cost below USD 2 (below USD 1 in quantities of 10 or more) Designed for a measurement range of ±10 kPa Tested for detecting sip-and-puff gestures Introduction I recently needed an air pressure sensor for one of my projects. I was looking for something inexpensive and easy to source. The sensor only needed to operate over a range of roughly ±10 kPa relative to atmospheric pressure, and there were no strict accuracy requirements.</description>
            <content type="html"><![CDATA[<p><img alt="Sensor with HX711 PCB" src="/posts/260702_pressure_sensor/images/title.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Differential air pressure sensor</li>
<li>Built using a 3D-printed body and standard strain gauges</li>
<li>Material cost below USD 2 (below USD 1 in quantities of 10 or more)</li>
<li>Designed for a measurement range of ±10 kPa</li>
<li>Tested for detecting sip-and-puff gestures</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I recently needed an air pressure sensor for one of my projects. I was looking for something inexpensive and easy to source. The sensor only needed to operate over a range of roughly ±10 kPa relative to atmospheric pressure, and there were no strict accuracy requirements. Essentially, I needed a sensor capable of detecting the mild vacuum and overpressure generated when a person sips and puffs into a tube.</p>
<p>There are quite a few suitable options available. ST, for example, offers the MPXx5010 sensor family (originally developed by NXP), and there are also sensors from Asian manufacturers such as CFSensor. The problem is that these options tend to be either relatively expensive or difficult to source for one-off builds.</p>
<p>This made me wonder whether it would be possible to build a &ldquo;good enough&rdquo; pressure sensor using only inexpensive, widely available components.</p>
<p>As it turns out, it is&hellip;to some extent.</p>
<p>The resulting sensor will never be as precise or reliable as a commercially manufactured device. Nevertheless, it works surprisingly well for the intended purpose. After an initial calibration, it remains reasonably stable over a typical indoor temperature range and is not particularly sensitive to humidity.</p>
<p><img alt="Sensor assembled in a 3D printed case" src="/posts/260702_pressure_sensor/images/mom_assembly.jpg"></p>
<p>What I will not do in this article is present a scientific analysis of the sensor or provide a complete specification. I expect every sensor to behave somewhat differently due to variations in the construction process, the materials used, and countless other factors that cannot be tightly controlled when building a device like this at home.</p>
<p>Instead, my goal is to show that it is possible to build a simple, low-cost pressure sensor that is perfectly adequate for certain applications. I will describe how I built mine so that others can adapt the design, improve upon it, or build on my code and 3D models for their own projects.</p>
<h2 id="sensor-idea">Sensor Idea</h2>
<p>Building a pressure sensor comes with several challenges, and building one from 3D-printed parts adds even more. My initial idea was to print a hollow body with a thin membrane and attach a strain gauge to the membrane. After several iterations, I concluded that a two-part design would be the best solution:</p>
<p><img alt="Sensor case" src="/posts/260702_pressure_sensor/images/sensor_case.png"></p>
<p>The lower part forms the membrane, which is 0.4 mm thick. A circular wall is printed directly onto the membrane, creating the air chamber and providing a mounting surface for the top cover. The top cover contains the hose connector and two mounting points for screws. It is significantly thicker than the membrane to provide the necessary rigidity. Both parts are bonded together using super glue, creating an airtight seal. I used PLA+ to print the housing, although PETG would likely be a good alternative as well.</p>
<p>For the measurement, I use two strain gauges in a half-bridge configuration. One gauge is mounted in the center of the membrane, where it experiences tensile strain when positive pressure is applied. The second strain gauge is centered on the edge of the membrane, where it experiences compressive strain under the same pressure.</p>
<p><img alt="Strain gauge placement and theory of operation" src="/posts/260702_pressure_sensor/images/sensor_dms.png"></p>
<p>This arrangement offers another important advantage: thermal compensation. Since both strain gauges are mounted on nearly the same surface, they experience the same temperature changes. As a result, their resistances change by approximately the same amount, causing most of the temperature-induced error to cancel out.</p>
<h2 id="sensor-assembly">Sensor Assembly</h2>
<p>Assembling the sensor can be a bit challenging. The most delicate step is attaching the strain gauges to the membrane. I don&rsquo;t think there is a single &ldquo;best&rdquo; method for doing this. Although it is possible to attach the strain gauges first and solder the wires afterward, I would not recommend that approach, as the heat generated during soldering can easily deform or melt parts of the thin membrane.</p>
<p>In the following, I will describe the assembly method that I have found to be the most reliable and easiest to work with.</p>
<p>First, I used two small strips of adhesive tape to fix the strain gauges onto a clean surface at the correct spacing (8.5 mm), while leaving the solder pads exposed.</p>
<p>Next, I added additional tape to the sides to ensure everything stayed in place while soldering the wires to the strain gauges. I used red and black wires for the reference voltage connections and a yellow wire for the signal. The insulation of the signal wire was stripped in a way that allowed it to be connected to both gauges, making the soldering process much easier.</p>
<p>After attaching the wires and cleaning the assembly with IPA, I applied another piece of adhesive tape over the entire assembly and trimmed it to the correct width using an X-Acto knife.</p>
<p>The complete assembly can then be lifted and positioned on the membrane. To do this, first mark the center of the membrane using either the alignment marks on the sides of the case or the provided printable template. Make sure you do not use the center of the strain gauge itself. Instead, use the alignment marks on the gauge.</p>
<p>Lift the gauge assembly using the side of the transfer tape opposite the wires as a hinge. This ensures that the assembly can be returned to exactly the same position after applying the adhesive. Apply a small amount of super glue to the strain gauges, then lower the assembly back onto the membrane. Press the gauges firmly and evenly against the membrane for 15–30 seconds. Once the adhesive has set, carefully remove the transfer tape wherever possible.</p>
<p>Optionally, you can apply a small amount of additional glue to secure the wires to the side of the sensor for improved strain relief.</p>
<p>As a final step, glue the two halves of the sensor together. Apply a small amount of super glue along the wall of the bottom part, then firmly press the top cover into place. Hold it for 15 to 30 seconds, then allow the glue to fully cure.</p>
<p>Your sensor is now ready to use.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/000_hu0aef7289ac4c21d02f3162028785ad0d_1118970_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/000_hu0aef7289ac4c21d02f3162028785ad0d_1118970_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/001_huc8047255c2fbed13d1a7e748660620a3_1258941_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/001_huc8047255c2fbed13d1a7e748660620a3_1258941_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/002_hu44fdca117d45eb42270da54bb938adf8_1256891_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/002_hu44fdca117d45eb42270da54bb938adf8_1256891_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/003_hu0aef7289ac4c21d02f3162028785ad0d_528982_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/003_hu0aef7289ac4c21d02f3162028785ad0d_528982_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/004_hu0aef7289ac4c21d02f3162028785ad0d_571928_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/004_hu0aef7289ac4c21d02f3162028785ad0d_571928_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/005_hu0aef7289ac4c21d02f3162028785ad0d_562428_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/005_hu0aef7289ac4c21d02f3162028785ad0d_562428_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/006_hu5b0689a1a69b21bba38b76f6c4732c8b_48783_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/006_hu5b0689a1a69b21bba38b76f6c4732c8b_48783_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/007_hu0aef7289ac4c21d02f3162028785ad0d_1567988_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/007_hu0aef7289ac4c21d02f3162028785ad0d_1567988_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/008_hu0aef7289ac4c21d02f3162028785ad0d_675017_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/008_hu0aef7289ac4c21d02f3162028785ad0d_675017_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/009_gauge_hu8d0d74a525567b0288f658ef9d39fcf9_108252_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/009_gauge_hu8d0d74a525567b0288f658ef9d39fcf9_108252_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/010_hu0aef7289ac4c21d02f3162028785ad0d_765198_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/010_hu0aef7289ac4c21d02f3162028785ad0d_765198_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/011_hu0aef7289ac4c21d02f3162028785ad0d_650341_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/011_hu0aef7289ac4c21d02f3162028785ad0d_650341_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/012_hu0aef7289ac4c21d02f3162028785ad0d_724466_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/012_hu0aef7289ac4c21d02f3162028785ad0d_724466_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/013_hu0aef7289ac4c21d02f3162028785ad0d_943808_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/assembly/013_hu0aef7289ac4c21d02f3162028785ad0d_943808_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="taking-measurements">Taking Measurements</h2>
<p>We now have two resistors on a membrane whose resistance changes slightly when pressure is applied. To make the sensor useful, we need to measure these tiny resistance changes.</p>
<p>The two strain gauges form one half of a Wheatstone bridge. By adding a second voltage divider and connecting both dividers to the same reference voltage, we complete the bridge. The voltage difference between the two halves is the quantity we are interested in. Ideally, the reference divider remains stable while the voltage across the strain gauge divider changes with the applied pressure.</p>
<p>Because these voltage changes are extremely small, they must be amplified before they can be measured. Since we are interested in the difference between the two bridge outputs, a differential amplifier, more specifically an instrumentation amplifier, is the ideal choice. Finally, the analog signal must be converted into a digital value.</p>
<p>Building such a circuit from discrete components is unnecessarily complicated. Instead, I highly recommend using an off-the-shelf solution such as the HX711 or HX717. These inexpensive ICs integrate everything we need: a stable reference voltage, a differential amplifier, and a high-resolution analog-to-digital converter. The following example shows how to connect the sensor to an HX717. R1 and R2 represent the strain gauges on the sensor.</p>
<p><img alt="Example schematic for HX717" src="/posts/260702_pressure_sensor/images/schematic_hx717.png"></p>
<p>Congratulations! We now have a digital representation of the applied pressure. But is it useful yet? Probably not. The raw value is not calibrated and has no meaningful reference point. Instead, we simply get an integer that does not directly correspond to any physical quantity.</p>
<p>Calibration is therefore an essential step and brings us to the software side of the project. First, we need to establish a reference point for zero pressure, followed by one or more calibration points that define the measurement range.</p>
<p>At first glance, it might seem sufficient to measure the sensor with no pressure applied to determine the zero point. In practice, however, the zero value drifts depending on the previously applied load. After positive pressure, the resting value settles slightly higher than it does after negative pressure. As a result, the sensor effectively has two different zero points, one for positive measurements and one for negative measurements.</p>
<p>A practical solution is to treat all values between these two zero points as zero. Measurements above the positive zero point use that value as their reference, while measurements below the negative zero point use the negative reference. The measured value can then be linearly interpolated between the corresponding zero point and the calibrated maximum or minimum, allowing the result to be expressed as a more intuitive range, such as ±100%.</p>
<p>I did not calibrate the sensor against any specific physical reference value, so I cannot make any claims about its absolute accuracy or linearity. Instead, I calibrated it based on my own ability to perform sip and puff gestures.</p>
<p>If you have access to equipment capable of generating a stable pressure or vacuum and can perform some measurements, I would be very interested in the results, especially regarding the sensor&rsquo;s linearity.</p>
<p>For my intended use, however, calibrating the sensor to my own sip and puff strength is entirely sufficient ;)</p>
<p>I wrote some code to execute the signal conditioning and the calibration. You will find this in the download section of this post.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>The described sensor works quite well for its intended purpose, and I think it has some potential for DIY projects. I haven&rsquo;t seen anything that uses a similar technique, so I think it is worth writing about and sharing the idea.</p>
<p>Printing the sensor also provides a lot of freedom in terms of its shape and how it can be mounted. This may allow you to build a product with a custom-made sensor that would not have been possible using a commercial one. You could even integrate the sensor directly into the enclosure of a product.</p>
<p>If you use this idea in one of your own projects, I would be happy to hear about it.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/P1010868_hu0aef7289ac4c21d02f3162028785ad0d_1534874_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/P1010868_hu0aef7289ac4c21d02f3162028785ad0d_1534874_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_095747195_hub8627f719c1cf9c86cd7824df096f87d_1492642_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_095747195_hub8627f719c1cf9c86cd7824df096f87d_1492642_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_095838226_hu57521cffb677e72bce403b5cca739c9c_1419119_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_095838226_hu57521cffb677e72bce403b5cca739c9c_1419119_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_100755331_hu12196796f15317aca379bebaf87a0b61_1456575_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_100755331_hu12196796f15317aca379bebaf87a0b61_1456575_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_101550237_hud3ea3395414466fefd0b4043bb16ae31_1840030_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260702_pressure_sensor/images/ideas/PXL_20260630_101550237_hud3ea3395414466fefd0b4043bb16ae31_1840030_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h2 id="project-files">Project files</h2>
<p>DOWNLOAD: <a href="/posts/260702_pressure_sensor/files/pressure_sensor_1_0.zip">Code, STL and SCAD files</a></p>
]]></content>
        </item>
        
        <item>
            <title>Running multiple HX717 from a single clock</title>
            <link>https://www.embedded-ideas.de/posts/260513_multi_hx717/</link>
            <pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260513_multi_hx717/</guid>
            <description>I recently ran into a problem that might be interesting for others. I wanted to use multiple HX717 load cell ADCs in one of my projects. These chips use a very simple serial protocol: pulses on the clock line shift out the result of the previous conversion, and a new conversion is triggered immediately afterward. The number of additional pulses after the 24-bit result defines the gain and the channel for the next conversion.</description>
            <content type="html"><![CDATA[<p><img alt="Protocol timing diagram from the datasheet" src="/posts/260513_multi_hx717/images/datasheet_protocol.png"></p>
<p>I recently ran into a problem that might be interesting for others. I wanted to use multiple HX717 load cell ADCs in one of my projects. These chips use a very simple serial protocol: pulses on the clock line shift out the result of the previous conversion, and a new conversion is triggered immediately afterward. The number of additional pulses after the 24-bit result defines the gain and the channel for the next conversion.</p>
<p><img alt="Normal data transfer" src="/posts/260513_multi_hx717/images/001_signal_detail.png"></p>
<p>This protocol makes it very easy to connect multiple ADCs to the same clock line while reading data from multiple sensors simultaneously. My approach was to generate the clock using a timer. A second channel of that timer triggers a DMA transfer. All data lines are connected to the same GPIO port, which makes it possible to use DMA to capture all inputs in parallel and store them in memory efficiently.</p>
<p>What I didn&rsquo;t know is that there is an undocumented behavior, or perhaps a feature, built into the protocol. After triggering a conversion, the data line goes low when the result is ready. This allows you to trigger, for example, on a falling edge to start reading the data.</p>
<p>However, what is not documented is what happens if you don&rsquo;t read the data. After approximately 3 ms, the device generates a pulse of about 160 µs, which repeats every 3 ms. You can interpret this as a kind of &ldquo;Hey, I still have data you requested&rdquo; signal. When using a single sensor, this can be helpful if you miss the initial falling edge for some reason. But when using multiple HX717s, this behavior becomes problematic.</p>
<p><img alt="Reminder pulses after result is ready" src="/posts/260513_multi_hx717/images/002_signal_detail.png"></p>
<p>Another complication is that conversion time is not constant. I measured conversion times ranging from approximately 500 µs to 3500 µs. This introduces jitter in the first falling edge, meaning each HX717 becomes ready at a slightly different time. As a result, it&rsquo;s not practical to trigger on the falling edge of a single device when multiple devices are used in parallel.</p>
<p>To address this, I initially tried using a fixed timing approach. The driver triggers conversions at a constant frequency to achieve a steady output rate. I used a trigger frequency of 290 Hz, which is below the specified maximum of 320 Hz. However, some conversions occasionally took longer than expected. In a setup with three HX717 devices, this meant that one device could still be busy while the others were already finished.</p>
<p><img alt="Occasional longer conversion time" src="/posts/260513_multi_hx717/images/003_long_conversion.png"></p>
<p>To handle this, I added a check to ensure that all data lines had gone low (indicating &ldquo;data ready&rdquo;) before issuing the next clock sequence. This helped avoid reading incomplete data, but it also exposed the interaction with the periodic &ldquo;reminder&rdquo; pulses, which can interfere with edge-based detection if not handled carefully.</p>
<p>Besides occasionally skipping a conversion, this approach works in most cases, but there is an important edge case.</p>
<p>If a conversion is skipped because another sensor is not ready yet, the timing can align such that the clock pulses are sent exactly during one of those periodic &ldquo;reminder&rdquo; pulses on the data line. And that&rsquo;s where things break down.</p>
<p><img alt="Edge case which leads to the problem" src="/posts/260513_multi_hx717/images/004_edge_case.png"></p>
<p>The device does not handle this situation well.</p>
<p>Initially, I assumed it would simply return the data as usual, since from a protocol perspective the sequence still appears valid. However, that&rsquo;s not what happens. Instead, the device shifts out invalid data and then pulls the data line high for approximately 15 ms. This delays subsequent conversions and introduces corrupted samples, which must be detected and filtered out.</p>
<p><img alt="Unwanted behavior when triggered during reminder pulse" src="/posts/260513_multi_hx717/images/005_error_result.png"></p>
<p>I considered several potential solutions, but ruled them out before implementation:</p>
<ul>
<li>Extending the first high pulse to &gt;160 µs
<ul>
<li>Not viable. The protocol only allows a maximum high time of 50 µs.</li>
<li>Pulses of around 80 µs already trigger a power-down condition.</li>
</ul>
</li>
<li>Adding discrete logic to combine the data signals
<ul>
<li>Would require additional hardware components.</li>
<li>There are still timing scenarios where this approach could run into the same issue.</li>
</ul>
</li>
<li>Polling the state of the data lines
<ul>
<li>Inefficent.</li>
<li>If the state is sampled just before the rising edge of the periodic pulse, it could lead to the same problem.</li>
</ul>
</li>
</ul>
<p>I believe there is no truly clean solution to this problem unless each HX717 runs on its own isolated interface. Since I wanted to operate up to six devices simultaneously in this project, that was not an option due to hardware limitations.</p>
<p>As I don&rsquo;t have strict timing requirements for precise filtering and still had some processing resources available, I settled on the following approach:</p>
<p>I added a falling-edge interrupt for each data signal. The interrupts are disabled while the clock sequence is being sent, and all flags are cleared before re-enabling them. Inside the interrupt handler, I store a timestamp for each device and check whether the time difference between the current timestamp and the stored one is below a threshold of 2.8 ms.</p>
<p>This ensures two things:</p>
<ul>
<li>a) that a falling edge has occurred after the clock sequence, and</li>
<li>b) that there is still some margin before the device triggers its periodic data-line pulse.</li>
</ul>
<p>Based on this, the system only sends the next clock sequence when all devices are within a valid timing window.</p>
<p><img alt="Timing with 5 HX717 connected" src="/posts/260513_multi_hx717/images/006_trigger_below_2_8ms.png"></p>
<p>In theory, this approach could lead to a situation where the system never finds a valid window to send a clock sequence. In practice, however, this is extremely unlikely due to independent clock drift and conversion-time jitter across devices.</p>
<p>In real-world operation, the results are solid. The driver achieves an average sample rate of around <strong>316Hz</strong>, with the lowest observed rate dropping to 232 Hz over a five-minute measurement period.</p>
]]></content>
        </item>
        
        <item>
            <title>The CCGB - An open Gameboy Color IPS mod with integrated video capturing via USB</title>
            <link>https://www.embedded-ideas.de/posts/260416_ccgb_mod/</link>
            <pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260416_ccgb_mod/</guid>
            <description>TL;DR Based on the Open xGB Display Matches original Game Boy Color display size USB UVC video output via USB-C 3x integer scaling (9 pixels per pixel) Supports color intensity control, tinting, and pixel or scanline effects Custom FPCs for simplified assembly and a clean internal layout Introduction This mod was developed as a demo for the Open xGB Display. Since I had not covered the Game Boy Color on this blog before, and because I think the mod turned out quite nicely, I decided to write a separate blog post on how to build it.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/260416_ccgb_mod/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Based on the Open xGB Display</li>
<li>Matches original Game Boy Color display size</li>
<li>USB UVC video output via USB-C</li>
<li>3x integer scaling (9 pixels per pixel)</li>
<li>Supports color intensity control, tinting, and pixel or scanline effects</li>
<li>Custom FPCs for simplified assembly and a clean internal layout</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>This mod was developed as a demo for the <a href="/posts/260413_oxgb_display/">Open xGB Display</a>. Since I had not covered the Game Boy Color on this blog before, and because I think the mod turned out quite nicely, I decided to write a separate blog post on how to build it.</p>
<p>The mod is built around the ER-TFT028A5-4, a modern IPS TFT display with an active width of 43.20 mm, which almost perfectly matches the original Game Boy Color display. It looks great when used with off the shelf lenses.</p>
<p>The display is a relatively recent model with solid technical specifications. It offers a high contrast ratio of <strong>1500:1</strong> and a brightness of <strong>800 cd/m²</strong>.</p>
<p>The 480×640 resolution allows for pixel perfect 3× integer scaling, using 9 pixels per pixel. When applying effects such as horizontal or vertical lines, as well as a pixel effect, most of the pixels remain active. There is also a long term supply promised by buydisplay.com, available until at least 2034.</p>
<p><img alt="Overview" src="/posts/260416_ccgb_mod/images/overview.jpg"></p>
<p>Besides the display, the second main feature is the integrated video capture. The mod includes a custom FPC to connect the USB C port to the Open xGB Display board. It is designed to fit into the upper half of the shell, so you do not need to sacrifice the link port. It can also double as a charging port if you use it as a 5 V supply for a battery charging mod. Two solder pads provide easy access to the USB VBUS.</p>
<p><img alt="USB Port" src="/posts/260416_ccgb_mod/images/usb.jpg"></p>
<p>The connection to the original Game Boy Color hardware is also made via a custom FPC cable, which provides solder pads for directly connecting the buttons and the enable line.</p>
<p>Before you proceed, I highly recommend reading the post about the <a href="/posts/260413_oxgb_display/">Open xGB Display</a> in order to know what you are getting yourself into ;)</p>
<h2 id="what-to-expect--and-what-not-to">What to Expect – and What Not To</h2>
<p>All data and materials are provided &ldquo;as is&rdquo;. If you have questions, I&rsquo;m happy to help when I have the time, however, support is not guaranteed, and responses may be delayed. If you encounter any problems, I would appreciate it if you report them so the project can continue to improve. If you are able to fix an issue yourself, contributions are very welcome!</p>
<p><strong>Disclaimer:</strong> Use of the provided information, files, and build instructions is entirely at your own risk. No guarantee is given regarding accuracy, completeness, or functionality. Any liability for damage to hardware or software, consequential damages, or other claims arising from use is excluded.</p>
<h2 id="settings-and-effects">Settings and Effects</h2>
<p>You can access the device menu via a long press of the Select button. First, the brightness menu will be shown. If you hold it longer, you will enter the settings menu.</p>
<ul>
<li>
<p><strong>Color Intensity</strong></p>
<ul>
<li>Brightness: General brightness value of the image, which manipulates the V value in the HSV model</li>
<li>Saturation: Changes the overall saturation of the image, which manipulates the S value in the HSV model</li>
</ul>
</li>
<li>
<p><strong>Tinting</strong></p>
<ul>
<li>Enable: Enables tinting the image in a single color</li>
<li>Color: Sets the hue value to a fixed value, fixing the H value in the HSV model</li>
</ul>
</li>
<li>
<p><strong>Effects</strong></p>
<ul>
<li>Mode: Horizontal lines, vertical lines, or both, which generate a pixel-like effect</li>
<li>Brightness: Brightness value of the lines, allowing for a generally brighter image compared to using only black</li>
<li>Saturation: Allows desaturating the lines instead of making them darker</li>
</ul>
</li>
<li>
<p><strong>Misc</strong></p>
<ul>
<li>Vertical position: Sets the vertical position to align the image with the lens</li>
</ul>
</li>
</ul>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160876_hu0aef7289ac4c21d02f3162028785ad0d_1074758_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160876_hu0aef7289ac4c21d02f3162028785ad0d_1074758_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160883_hu0aef7289ac4c21d02f3162028785ad0d_1139852_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160883_hu0aef7289ac4c21d02f3162028785ad0d_1139852_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160885_hu0aef7289ac4c21d02f3162028785ad0d_1078777_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160885_hu0aef7289ac4c21d02f3162028785ad0d_1078777_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160887_hu0aef7289ac4c21d02f3162028785ad0d_1119532_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160887_hu0aef7289ac4c21d02f3162028785ad0d_1119532_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160890_hu0aef7289ac4c21d02f3162028785ad0d_1439781_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160890_hu0aef7289ac4c21d02f3162028785ad0d_1439781_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160891_hu0aef7289ac4c21d02f3162028785ad0d_1366569_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160891_hu0aef7289ac4c21d02f3162028785ad0d_1366569_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160892_hu0aef7289ac4c21d02f3162028785ad0d_1345792_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/effects/P4160892_hu0aef7289ac4c21d02f3162028785ad0d_1345792_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="build">Build</h2>
<p>I will not cover how to assemble the PCB. I will assume you have a fully working, fully assembled Open xGB Display PCB at hand. If you need information on how to assemble the board, have a look at <a href="https://www.embedded-ideas.de/posts/250407_hotplate_soldering/">this post</a>. If you need information on how to flash the software, you will find it in <a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/">this post</a>. You will need the following materials for the build:</p>
<ul>
<li>
<p>Parts</p>
<ul>
<li>Open xGB Display PCB</li>
<li>ER-TFT028A5-4 TFT module</li>
<li>GBC FPC adapter</li>
<li>USB FPC adapter</li>
<li>3D printed TFT frame</li>
<li>3D printed USB cover</li>
<li>Game Boy Color shell and lens</li>
</ul>
</li>
<li>
<p>Tools and consumables</p>
<ul>
<li>Double-sided adhesive tape</li>
<li>Files</li>
<li>X-Acto knife</li>
<li>Side cutters</li>
<li>Wires, ~1 to 1.2 mm outer diameter</li>
<li>Thin wires for button connections</li>
<li>3D printed cut template</li>
<li>3D printed display dummy</li>
</ul>
</li>
</ul>
<ol>
<li><strong>TFT cutout:</strong> All modifications are done on the front of the shell. Cut a slot through the display compartment walls on the front. You can use the 3D printed template to get the correct dimensions. The display dummy is also a good way to test the fit without risking the real TFT module. The cutout does not need to be perfect, since it will be covered by the lens anyway.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090908_hu0aef7289ac4c21d02f3162028785ad0d_1788416_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090908_hu0aef7289ac4c21d02f3162028785ad0d_1788416_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090910_hu0aef7289ac4c21d02f3162028785ad0d_1502580_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090910_hu0aef7289ac4c21d02f3162028785ad0d_1502580_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090911_hu0aef7289ac4c21d02f3162028785ad0d_1453424_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090911_hu0aef7289ac4c21d02f3162028785ad0d_1453424_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090914_hu0aef7289ac4c21d02f3162028785ad0d_1655544_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090914_hu0aef7289ac4c21d02f3162028785ad0d_1655544_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090918_hu0aef7289ac4c21d02f3162028785ad0d_1478074_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_tft/P4090918_hu0aef7289ac4c21d02f3162028785ad0d_1478074_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<ol start="2">
<li><strong>USB cutout:</strong> For the USB port, proceed slowly and use a file. File the side wall down to the bottom. Create a cutout for the cable to allow a wider bending radius. Once the connector fits, press it firmly against the shell to leave marks from the rear pins of the connector. Use a 1 mm drill and drill holes where the marks are. Test fit the USB connector and the 3D printed housing.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/1_hu0aef7289ac4c21d02f3162028785ad0d_1448015_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/1_hu0aef7289ac4c21d02f3162028785ad0d_1448015_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/2_hu0aef7289ac4c21d02f3162028785ad0d_1525996_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/2_hu0aef7289ac4c21d02f3162028785ad0d_1525996_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/3_hu0aef7289ac4c21d02f3162028785ad0d_1557820_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/3_hu0aef7289ac4c21d02f3162028785ad0d_1557820_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/4_hu0aef7289ac4c21d02f3162028785ad0d_1575719_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/cutting_usb/4_hu0aef7289ac4c21d02f3162028785ad0d_1575719_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<ol start="3">
<li><strong>PCB assembly:</strong> Glue the PCB to the display. The top edge of the PCB must align with the top edge of the display. Use the adhesive tape provided by the manufacturer and add additional tape in the center of the board to maintain a small gap between the PCB and the metal frame of the TFT module.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/pcb_assembly/1_hu0aef7289ac4c21d02f3162028785ad0d_1600881_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/pcb_assembly/1_hu0aef7289ac4c21d02f3162028785ad0d_1600881_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/pcb_assembly/2_hu0aef7289ac4c21d02f3162028785ad0d_1460377_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/pcb_assembly/2_hu0aef7289ac4c21d02f3162028785ad0d_1460377_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<ol start="4">
<li><strong>Lens installation:</strong> The lens can be glued directly into the case. To prevent dust from getting between the lens and the TFT module, I recommend adding tape on the top and bottom edges of the lens. If there is a slight gap, it can also improve the overall appearance. I used a glass lens with a slightly looser fit compared to the plastic lens that came with the case.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090938_hu0aef7289ac4c21d02f3162028785ad0d_1461425_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090938_hu0aef7289ac4c21d02f3162028785ad0d_1461425_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090940_hu0aef7289ac4c21d02f3162028785ad0d_1434629_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090940_hu0aef7289ac4c21d02f3162028785ad0d_1434629_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090941_hu0aef7289ac4c21d02f3162028785ad0d_1383977_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090941_hu0aef7289ac4c21d02f3162028785ad0d_1383977_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090944_hu0aef7289ac4c21d02f3162028785ad0d_1759176_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/lens/P4090944_hu0aef7289ac4c21d02f3162028785ad0d_1759176_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<ol start="5">
<li><strong>Display installation:</strong> Attach the frame to the module using adhesive tape. Thread the FFC cable of the display through the TFT frame as shown in the picture. This reduces excess cable length and allows for a clean installation. Add two wires for the power supply; they should fit into the slots of the TFT frame. Do not forget to install the USB FPC. You can now add the button membranes, the IR cover, and the power switch slider.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/1_hu0aef7289ac4c21d02f3162028785ad0d_1539863_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/1_hu0aef7289ac4c21d02f3162028785ad0d_1539863_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/2_hu0f315d4c8c177c5775a44584b33d20d4_1904928_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/2_hu0f315d4c8c177c5775a44584b33d20d4_1904928_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/3_hu68b52e4ed0927989a2842635824dd6fa_1745691_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/frame/3_hu68b52e4ed0927989a2842635824dd6fa_1745691_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<ol start="6">
<li><strong>Connecting the GBC PCB:</strong> The custom FPC allows direct connection to the buttons and the power switch. Use small gauge wire to connect to the board. Since Nintendo used fairly large vias back in the day, you can use them as solder points. Make sure to connect the correct points on the board, as there are different PCB revisions. If in doubt, check the CGB CPU and trace the connections to a suitable via.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/P4100952_hu0aef7289ac4c21d02f3162028785ad0d_1554468_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/P4100952_hu0aef7289ac4c21d02f3162028785ad0d_1554468_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/P4100959_hu0aef7289ac4c21d02f3162028785ad0d_1702662_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/P4100959_hu0aef7289ac4c21d02f3162028785ad0d_1702662_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/board_hu253fb666b1a3e10b01a0636d034fed07_1526007_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/board_hu253fb666b1a3e10b01a0636d034fed07_1526007_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/footprint_hu260d3b84efb6ae827bdb537ec60d9664_217206_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/connections/footprint_hu260d3b84efb6ae827bdb537ec60d9664_217206_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<ol start="7">
<li>You can now connect the Game Boy PCB to the display board and screw it in place. As a final step, solder the supply cable to the battery terminals.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/final/P4100964_hu0aef7289ac4c21d02f3162028785ad0d_1608809_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/final/P4100964_hu0aef7289ac4c21d02f3162028785ad0d_1608809_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/final/P4100976_hu8ba754aeb2825451646ae36c264e3d12_1271717_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260416_ccgb_mod/images/build/final/P4100976_hu8ba754aeb2825451646ae36c264e3d12_1271717_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h2 id="thanks">Thanks</h2>
<ul>
<li>Natalie the Nerd
<ul>
<li>Gameboy Color CPU footprint (<a href="https://wiki.nataliethenerd.com/gameboy/gameboycolor">https://wiki.nataliethenerd.com/gameboy/gameboycolor</a>)</li>
<li>Gameboy Color PCB scans (<a href="https://wiki.nataliethenerd.com/gameboy/gameboycolor">https://wiki.nataliethenerd.com/gameboy/gameboycolor</a>)</li>
</ul>
</li>
</ul>
<h2 id="files">Files</h2>
<p>Source code and release binaries are hosted on codeberg.org. Please let me know if anything is missing.</p>
<ul>
<li>
<p>Hardware</p>
<ul>
<li>Open XGB Display
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW">https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW/releases">https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW/releases</a></li>
</ul>
</li>
<li>Debug adapter
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p>Software</p>
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW">https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW/releases">https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW/releases</a></li>
</ul>
</li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>The Open xGB Display – A Development Board for Game Boy Color and Game Boy Advance IPS Mods</title>
            <link>https://www.embedded-ideas.de/posts/260413_oxgb_display/</link>
            <pubDate>Mon, 13 Apr 2026 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260413_oxgb_display/</guid>
            <description>TL;DR Development board for Game Boy Color and Game Boy Advance display mods (RGB TFT replacement system) Modular hardware platform with support for multiple configurations Flexible integration via FPC/FFC adapters for different console layouts Based on RP2350B or RP2354B Optional USB video output via additional CH32V305 coprocessor (UVC support) Fully open source hardware and software All design files and firmware available in the repository Introduction If you have been following the blog, you might be familiar with my previous projects, the Open DMG Display and the Open AGB Display, and maybe also with the recently added USB video output on the Open DMG Display.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/260413_oxgb_display/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Development board for Game Boy Color and Game Boy Advance display mods (RGB TFT replacement system)</li>
<li>Modular hardware platform with support for multiple configurations</li>
<li>Flexible integration via FPC/FFC adapters for different console layouts</li>
<li>Based on RP2350B or RP2354B</li>
<li>Optional USB video output via additional CH32V305 coprocessor (UVC support)</li>
<li>Fully open source hardware and software</li>
<li>All design files and firmware available in the repository</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>If you have been following the blog, you might be familiar with my previous projects, the <a href="/posts/250417_open_dmg_display/">Open DMG Display</a> and the <a href="/posts/250825_openagbdisplay/">Open AGB Display</a>, and maybe also with the recently added <a href="/posts/251116_open_dmg_display_uvc/">USB video output on the Open DMG Display</a>.</p>
<p>I also did a proof-of-concept for <a href="/posts/251030_xgb_to_usb/">video output on the Game Boy Advance</a>, but I didn&rsquo;t implement this into a working mod.</p>
<p>This project brings all of that together. However, instead of another device-specific mod, I wanted to focus on a generic board with reusable code as a blueprint for MCU-based display mods. It can be seen as an invitation for the community to build upon.</p>
<p>Maybe you would like to design a Game Boy Color with a huge display, but you&rsquo;re not familiar with writing firmware or drivers for TFT displays. Or perhaps you are strong in software but don&rsquo;t want to design the circuitry from scratch. This is where the xGB Display helps you jump-start your project.</p>
<p>It offers:</p>
<ul>
<li>A generic board that can be used in multiple different projects</li>
<li>Two example implementations using the board (CGB and AGB)</li>
<li>Support for different displays</li>
<li>Tested components and schematics</li>
</ul>
<h2 id="what-to-expect--and-what-not-to">What to Expect – and What Not To</h2>
<p>I hope this project finds its target audience and continues to mature over time. It is by no means a finished product. I expect bugs in both the software and the hardware, and you should as well when using the provided materials.</p>
<p>All data and materials are provided &ldquo;as is&rdquo;. If you have questions, I&rsquo;m happy to help when I have the time, however, support is not guaranteed, and responses may be delayed. If you encounter any problems, I would appreciate it if you report them so the project can continue to improve. If you are able to fix an issue yourself, contributions are very welcome!</p>
<p><strong>Disclaimer:</strong> Use of the provided information, files, and build instructions is entirely at your own risk. No guarantee is given regarding accuracy, completeness, or functionality. Any liability for damage to hardware or software, consequential damages, or other claims arising from use is excluded.</p>
<h2 id="the-firmware">The Firmware</h2>
<p>The firmware is based on the <a href="/posts/250825_openagbdisplay/">Open AGB Display</a>. It has the same set of features. The relevant changes are:</p>
<ul>
<li>Dynamic configuration capabilities for Game Boy Color and Game Boy Advance signals</li>
<li>Support for multiple TFT modules (see Hardware section for details)</li>
<li>A new module that sends frame data via serial output to the USB video output coprocessor</li>
</ul>
<p>In addition to the main firmware, there is also code running on the CH32V305 coprocessor for video output via USB.</p>
<h3 id="configuration">Configuration</h3>
<p>In order to allow the same firmware to run in different modes on different target hardware, it is crucial to provide configuration information about the underlying hardware and the connected peripherals. This is done using information blocks stored at the end of the flash memory. There are two blocks that are mandatory for running the firmware:</p>
<ul>
<li>The HIB (Hardware Information Block), which holds information about the hardware the firmware is running on
<ul>
<li>Hardware revision</li>
</ul>
</li>
<li>The PIB (Product Information Block), which holds information about the configuration of the hardware
<ul>
<li>Connected peripherals</li>
<li>Product revision</li>
</ul>
</li>
</ul>
<p>Currently, only a minimal amount of information is stored in these blocks. To allow for more information in the future, each block includes a version field. The blocks can be created using a Python script, which you will find in the firmware repository in the <code>scripts</code> subfolder. <strong>The firmware will restart into the bootloader if no valid information blocks are found!</strong></p>
<h3 id="signals-and-timings">Signals and Timings</h3>
<p>Capturing the Game Boy signals is done very similarly to how it is implemented in the <a href="/posts/250825_openagbdisplay/">Open AGB Display</a>. That post already describes the details. The most important takeaway is that the frame timing is driven by the Game Boy&rsquo;s signal, which allows for low latency in combination with the RGB interface on the recommended TFT displays.</p>
<h2 id="the-hardware">The Hardware</h2>
<p>I designed a very small and fairly dense board for this project. It can be used to implement a mod directly or as a basis for designing your own board using the provided design files.</p>
<p>I also designed two types of demo implementations using this board: one for the Game Boy Advance and one for the Game Boy Color. Besides the board itself, you&rsquo;ll also need an FPC adapter cable to connect it to the original Game Boy hardware. Examples of these FPC designs are also provided in the repository.</p>
<p>If you wish to utilize the coprocessor for USB video output, you&rsquo;ll also need an FPC or FFC connection for the USB port. Again, example designs are provided and are intended to fit the demo mods.</p>
<h3 id="the-open-xgb-display-board">The Open xGB Display Board</h3>
<p>I will briefly describe some aspects of the Open xGB PCB, which I hope will help you understand what the hardware offers.</p>
<p><img alt="Comparison between different displays in AGB mode" src="/posts/260413_oxgb_display/images/pcb_overview.png"></p>
<ol>
<li>
<p><strong>Misc connections:</strong> These are mainly intended for implementing user input via buttons. By default, they are used to navigate the menu. They operate at input levels between 0V and 3.3V, where a low level means pressed and a high level means released. They can be directly connected to the Game Boy&rsquo;s input buttons. The default mapping is: 1 for Enter, 2 for Right, and 3 for Left. These connections are also available on the connector to the Game Boy, so it may be more convenient to access them via an FPC.</p>
</li>
<li>
<p><strong>Main MCU (RP2354B):</strong> If you are using the RP2354B, which I would recommend, you do not need external flash. If you have reasons to use the RP2350B, there is still a footprint for external flash memory.</p>
</li>
<li>
<p><strong>Generic xGB connector:</strong> The 24-pin FFC connector is intended to connect the Game Boy display signals to the OXD board. In addition, it carries the general power-enable signal as well as the three misc connections described in (1).</p>
</li>
<li>
<p><strong>USB video coprocessor:</strong> Since the RP235xB only offers a USB FS interface, which is not fast enough for UVC video output, a second microcontroller has been added to the board. It is a small CH32V305 MCU with a USB HS interface. The controller is connected via a serial link that uses two SPI interfaces connected together. It is implemented as a fully independent circuit powered by USB, so it does not consume power unless it is in use. Unfortunately, it does not allow bootloader access, so it must be flashed via a debug probe (which is relatively inexpensive, though).</p>
</li>
<li>
<p><strong>USB and debug connection to the RP235xB:</strong> The 10-pin FFC connector is intended for use with the debug adapter. It provides access to the SWD interface as well as USB for the RP235xB.</p>
</li>
<li>
<p><strong>TFT connector:</strong> The 40-pin FFC connector is intended to connect a TFT module. The pinout supports a range of displays from buydisplay.com (see <a href="/posts/260413_oxgb_display/#tfts">TFTs</a>). If you are using a display with a different pinout or connector, it should not be difficult to reroute this part of the board.</p>
</li>
<li>
<p><strong>Power supplies:</strong> There are two SMPS power supplies for the main circuit (they do not power the coprocessor). One supplies 3.3V for the RP235xB and peripherals. The other is used exclusively for the backlight. The supplies are chosen to operate within the range of two rechargeable AA cells but can also be powered from a 5V supply if required. The backlight supply is a current source regulated via a PWM DAC. This helps prevent flicker caused by on/off cycles. You will also find JP1 in this area. If bridged, the enable line will be tied to the battery, so the device will start directly when power is applied.</p>
</li>
<li>
<p><strong>Supply terminals:</strong> Solder pads for connecting the supply voltage (typically a ~3V battery). In addition to power, you also need to provide a voltage above ~0.7V to the enable line in order to start the OXD. If you do not want to use the enable line, bridge JP1 (see 7).</p>
</li>
</ol>
<h3 id="firmware-flashing-and-debug-adapter">Firmware Flashing and Debug Adapter</h3>
<p>In order to get any firmware onto the Open xGB Display board, you&rsquo;ll need some kind of adapter to connect to the 10-pin FFC connectors. This is also true if you want to do any debugging during development. You could either use a 10-pin FFC-to-pin-header adapter or the debug adapter I created for the Open AGB Display. I will explain the process using this adapter in the following section.</p>
<p><img alt="Comparison between different displays in AGB mode" src="/posts/260413_oxgb_display/images/debug_adapter.jpg"></p>
<p>The debug adapter uses a 10-pin same-side FFC cable to connect to the debug connectors on the OXD board. It provides a JST-SH (1.0 mm pitch) 3-pin connector that is compatible with the <em>Raspberry Pi Pico Debug Probe</em>. It also offers a USB-C port to access USB during development. There is a possibility to power the target from this USB-C port by bridging JP1 and/or JP2, but you have to be careful with this feature. <em>The 5V supply will be directly connected to the supply terminals.</em> If those terminals are connected to the Game Boy, you will supply it with 5V, which <em>might destroy your hardware</em>.</p>
<p><strong>Flashing the RP235xB:</strong> There are two ways to get the firmware onto the RP235xB. The easiest way is to plug the device into a computer via USB and boot into bootloader mode by holding SW1 during power-up. The device will show up as a mass storage device. You can then simply copy the provided UF2 file. Don&rsquo;t forget to provide the <a href="/posts/260413_oxgb_display/#configuration">information block data</a> along with the firmware. You only need to do this once.</p>
<p>If you have a suitable debug adapter at hand and want to compile the code yourself, you can also flash the firmware using SWD.</p>
<p><strong>Flashing the CH32V305:</strong> There is currently only one way to get firmware onto the CH32V305: you must connect a debugger to the chip. I recommend using a WCH-Link and connecting it via a JST-to-pin-header adapter to the debug board. If you bought a Pico Debug Probe, you will already have such an adapter.</p>
<p><img alt="Comparison between different displays in AGB mode" src="/posts/260413_oxgb_display/images/wchlink.jpg"></p>
<p>With the CH32V305, you&rsquo;ll need to connect JP1 and/or JP2 on the debug adapter board in order to power the chip via a connected USB cable. As the WCH-Link uses pin headers and also provides 5V, wiring it up to an FFC adapter is also a good option.</p>
<p>Within the release files you will find a hex file with the firmware. This can be flashed using the <a href="https://github.com/ch32-rs/wlink/releases/tag/v0.1.1">wlink software</a> with the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wlink flash <span style="color:#f92672">[</span>PATH TO RELEASE FILES<span style="color:#f92672">]</span>/xgb2usb.hex
</span></span></code></pre></div><h3 id="tfts">TFTs</h3>
<p>The project currently exclusively uses TFT modules with a parallel RGB interface. This brings some advantages:</p>
<ul>
<li>A bufferless interface, which reduces latency</li>
<li>Full control over frame timing</li>
<li>The ability to let the input signal drive frame timing</li>
<li>Prevention of tearing</li>
</ul>
<p>In order to support as many displays out of the box as possible, I decided to use displays from buydisplay.com (not sponsored). They provide a wide range of displays with RGB interfaces and a consistent pinout.</p>
<p><img alt="Comparison between different displays in CGB mode" src="/posts/260413_oxgb_display/images/comparison/comparison_cgb_mode.png"></p>
<p><img alt="Comparison between different displays in AGB mode" src="/posts/260413_oxgb_display/images/comparison/comparison_agb_mode.png"></p>
<ul>
<li>
<p>Implemented</p>
<ul>
<li><strong>ER-TFT028A5-4</strong>: 2.80&quot;, 1500:1, 480x640, 800 cd/m², 30 mA, 9.00V</li>
<li><strong>ER-TFT040-3</strong>: 4.00&quot;, 800:1, 480x480, 400 cd/m², 30 mA, 15.00V</li>
<li><strong>ER-TFT034-2</strong>: 3.40&quot;, 800:1, 480x480, 550 cd/m², 30 mA, 18.00V</li>
<li><strong>ER-TFT3.95-1</strong>: 3.95&quot;, 800:1, 720x720, 350 cd/m², 30 mA, 15.00V
<ul>
<li>Signal timings need to be optimized, limited support</li>
</ul>
</li>
</ul>
</li>
<li>
<p>Pin compatible</p>
<ul>
<li><strong>ER-TFT3.54-1</strong>: 3.54&quot;, 1000:1, 640x960, 450 cd/m², 30 mA, 15.00V</li>
</ul>
</li>
<li>
<p>Pin compatible but requires backlight supply changes</p>
<ul>
<li><strong>ER-TFT3.53-1</strong>: 3.53&quot;, 1000:1, 480x800, 400 cd/m², 15 mA, 21.00V
<ul>
<li>Backlight current must be set via a different resistor</li>
</ul>
</li>
<li><strong>ER-TFT020-6</strong>: 2.00&quot;, 1000:1, 480x360, 800 cd/m², 90 mA, 3.00V
<ul>
<li>Low backlight voltage, requires a different backlight supply</li>
</ul>
</li>
<li><strong>ER-TFT024-5</strong>: 2.40&quot;, 1000:1, 480x640, 350 cd/m², 60 mA, 3.00V
<ul>
<li>Low backlight voltage, requires a different backlight supply</li>
</ul>
</li>
<li><strong>ER-TFT021-1</strong>: 2.10&quot;, 700:1, 480x480, 300 cd/m², 60 mA, 3.20V
<ul>
<li>Low backlight voltage, requires a different backlight supply (round display)</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>When choosing a display, the most important criteria are size and resolution. Most of the currently supported TFTs have a 480-pixel width, which allows integer scaling for both CGB (160×144) and AGB (240×160). This is especially useful for allowing DMG and CGB games on the Game Boy Advance to be stretched to full width.</p>
<h2 id="how-to-use">How to Use</h2>
<p>In order to provide a better understanding of how this project can be used, I built two mods based on the OXD PCB: one for the Game Boy Advance and one for the Game Boy Color. I won&rsquo;t go into great detail here because the Game Boy Advance variant is essentially a refinement of the Open AGB Display, and I will write another more detailed post about how to build the Game Boy Color version. I will therefore only describe what is required to build something useful with the OXD board.</p>
<h3 id="game-boy-connection-fpc-examples">Game Boy Connection FPC Examples</h3>
<p>In order to connect the board to a Game Boy Color or Game Boy Advance, you&rsquo;ll need to connect the display signals to the 24-pin FFC connector. You could do this using off-the-shelf FFC or FPC cables, which are no longer very expensive. Remember that the misc signals used for the control buttons are also available on the FFC connector, as well as the enable line. It therefore makes sense to include these in an FPC design as well.</p>
<p><img alt="Game Boy connection FFCs front" src="/posts/260413_oxgb_display/images/ffc_gb_f.jpg"></p>
<p>On the left is the connection FPC for the Game Boy Color with its 50-pin display connector. On the right is the 32-pin Game Boy Advance variant. You can see that both cables expose the misc and enable pins via solder pads. This has proven to work quite well if you use thin wires for the connections to the Game Boy PCBs.</p>
<p><img alt="Game Boy connection FFCs back" src="/posts/260413_oxgb_display/images/ffc_gb_b.jpg"></p>
<p>For my mods, I connected left, right, and select for the Game Boy Color, and left shoulder, right shoulder, and select for the Game Boy Advance to the misc connection pads. The enable line is connected to the power switch.</p>
<p><img alt="Installed FPC cable in the GB Advance" src="/posts/260413_oxgb_display/images/agb_gb_fpc_installed.jpg"></p>
<h3 id="usb-fpc-examples">USB FPC Examples</h3>
<p>For the USB connection to the CH32V305, which can be used for video streaming, I also designed FPCs. I used USB-C connectors and additional 5.1 kΩ resistors to enable proper 5V negotiation when connected.</p>
<p><img alt="USB connection FFCs back" src="/posts/260413_oxgb_display/images/ffc_usb_f.jpg"></p>
<p>Both designs include additional pads to connect to the 5V line provided by USB. This can be useful, for example, for connecting a battery charger.</p>
<p><img alt="Installed USB connection FPC on the GB Advance" src="/posts/260413_oxgb_display/images/agb_usb_fpc_installed.jpg"></p>
<h3 id="3d-prints">3D Prints</h3>
<p>In order to fit everything into original or aftermarket cases, I had to design some 3D-printed parts. These mainly include a frame to hold the TFT module and the board, as well as covers for the USB ports. I also found it useful to design templates for cutouts and display alignment.</p>
<p><img alt="3D printed frame installed in AGB" src="/posts/260413_oxgb_display/images/3d_print_frame_agb.jpg"></p>
<h3 id="game-boy-advance">Game Boy Advance</h3>
<p>For the Game Boy Advance, I used the same display module as in the Open AGB Display (ER-TFT034-2). This time, I added an additional frame to provide better side support and to align the OXD board. The case cutouts and custom lens are the same as in the Open AGB Display. On the top, there is a cutout for the USB-C connector.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/01_hu0aef7289ac4c21d02f3162028785ad0d_1569151_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/01_hu0aef7289ac4c21d02f3162028785ad0d_1569151_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/02_hu0aef7289ac4c21d02f3162028785ad0d_1673097_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/02_hu0aef7289ac4c21d02f3162028785ad0d_1673097_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/03_hu0aef7289ac4c21d02f3162028785ad0d_1562856_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/03_hu0aef7289ac4c21d02f3162028785ad0d_1562856_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/04_hu0aef7289ac4c21d02f3162028785ad0d_1696136_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/04_hu0aef7289ac4c21d02f3162028785ad0d_1696136_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/05_hu0aef7289ac4c21d02f3162028785ad0d_1550145_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/05_hu0aef7289ac4c21d02f3162028785ad0d_1550145_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/06_hu0aef7289ac4c21d02f3162028785ad0d_1714583_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/06_hu0aef7289ac4c21d02f3162028785ad0d_1714583_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/07_hu0aef7289ac4c21d02f3162028785ad0d_1571051_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/07_hu0aef7289ac4c21d02f3162028785ad0d_1571051_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/08_hu0aef7289ac4c21d02f3162028785ad0d_1626979_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/08_hu0aef7289ac4c21d02f3162028785ad0d_1626979_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/09_hu0aef7289ac4c21d02f3162028785ad0d_1799535_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/09_hu0aef7289ac4c21d02f3162028785ad0d_1799535_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/10_hu0aef7289ac4c21d02f3162028785ad0d_912719_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260413_oxgb_display/images/gba_mod/10_hu0aef7289ac4c21d02f3162028785ad0d_912719_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="game-boy-color">Game Boy Color</h3>
<p><del>I think the Game Boy Color mod turned out really nicely, and I haven&rsquo;t previously written a post covering it. As mentioned, I will cover the mod in more detail in a separate post. I will link it here as soon as it is published.</del></p>
<p>Please have a look at his post: <a href="/posts/260416_ccgb_mod/">CCGB</a></p>
<p><img alt="Preview of the OXD GBC mod" src="/posts/260413_oxgb_display/images/gbc_preview.jpg"></p>
<h2 id="known-issues">Known Issues</h2>
<ul>
<li>The placement of the USB port on the AGB mod is not ideal because the connector can apply stress to the TFT module.</li>
<li>In AGB mode, the video output occasionally shows a shifted line, resulting in a one-frame glitch. This may be due to a software issue or a limitation of the serial transfer or board signal integrity, and requires further investigation.</li>
</ul>
<h2 id="files">Files</h2>
<p>Source code and release binaries are hosted on codeberg.org. Please let me know if anything is missing.</p>
<ul>
<li>
<p>Hardware</p>
<ul>
<li>Open XGB Display
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW">https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW/releases">https://codeberg.org/embedded-ideas/OpenXgbDisplay-HW/releases</a></li>
</ul>
</li>
<li>Debug adapter
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p>Software</p>
<ul>
<li>Git repository: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW">https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW/releases">https://codeberg.org/embedded-ideas/OpenXgbDisplay-SW/releases</a></li>
</ul>
</li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>The Strainstick - Building a joystick from strain gauges</title>
            <link>https://www.embedded-ideas.de/posts/260305_strainstick/</link>
            <pubDate>Thu, 05 Mar 2026 01:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260305_strainstick/</guid>
            <description>TL;DR Joystick made from PCB and strain gauges Files below Introduction There are many ways to build a two-dimensional control device. In the early days, digital joysticks were common. They provided only left/right/up/down inputs, with diagonal movement represented as a combination of two directions. Today, most devices are analog and based on potentiometers or Hall sensors. Touchpads are also widely used and typically operate capacitively.
In some notebooks, however, you will find another class of control device.</description>
            <content type="html"><![CDATA[<h2 id="tldr">TL;DR</h2>
<ul>
<li>Joystick made from PCB and strain gauges</li>
<li>Files below</li>
</ul>
<p><img alt="Project Overview" src="/posts/260305_strainstick/images/title.JPG"></p>
<h2 id="introduction">Introduction</h2>
<p>There are many ways to build a two-dimensional control device. In the early days, digital joysticks were common. They provided only left/right/up/down inputs, with diagonal movement represented as a combination of two directions. Today, most devices are analog and based on potentiometers or Hall sensors. Touchpads are also widely used and typically operate capacitively.</p>
<p>In some notebooks, however, you will find another class of control device. These often look like small rubber caps, famously a red rubber dot. Such devices measure bending forces. Some implementations work capacitively, but resistive measurement is more common today.</p>
<p>Using a very similar technique, it is possible to build a comparable device from standard FR-4 PCB material. The Strainstick is one such device. The design was inspired by the haptic knob project from <a href="https://www.youtube.com/watch?v=Q76dMggUH1M">scottbez1</a>. It is intended to be used as part of one of my other projects, but I thought it was interesting enough to publish a short post about it.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/back_hu0aef7289ac4c21d02f3162028785ad0d_725384_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/back_hu0aef7289ac4c21d02f3162028785ad0d_725384_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/demo_hu0aef7289ac4c21d02f3162028785ad0d_912506_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/demo_hu0aef7289ac4c21d02f3162028785ad0d_912506_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/title_hu0aef7289ac4c21d02f3162028785ad0d_784340_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/title_hu0aef7289ac4c21d02f3162028785ad0d_784340_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="hardware">Hardware</h2>
<p>The Strainstick uses a 2-layer PCB and is equipped with four very common BF350 strain gauges. To keep things simple, the design uses an ADC with an integrated reference and PGA, the HX717 from AVIA Semiconductors. This chip is very similar to the more famous HX711, but offers higher bandwidth and requires fewer external components while still providing an integrated reference voltage.</p>
<p>The HX717 is a two-channel device, but only one channel is used. Switching between the A and B channels takes approximately four cycles, which would significantly reduce the available bandwidth. Therefore, two chips are used.</p>
<p>Each axis uses one set of strain gauges. This allows a better signal to be obtained (the bending forces compress one gauge and stretch the other) and thermally couples the resulting half-bridge.</p>
<p>I am aware that, instead of strain gauges, it is possible to use SMD resistors. I like the idea, but I wanted a more well-defined device. I would expect differences between manufacturers and possibly reliability issues in the long run. This might be something to test in the future.</p>
<h3 id="attaching-the-strain-gauges">Attaching the strain gauges</h3>
<p>The process of strain gauge attachment isn’t very complicated. You will need:</p>
<ul>
<li>Isopropyl alcohol (for cleaning)</li>
<li>Adhesive tape</li>
<li>Tweezers</li>
<li>Scissors or an X-Acto knife</li>
<li>A cyanoacrylate-based glue (super glue)</li>
</ul>
<p>First, clean the board with IPA. Apply adhesive tape to the areas close to the strain gauges where components need to be attached on the board.</p>
<p>Next, cover the gluing areas with tape in a cross-shaped pattern. Make sure the center of the first tape does not overlap the gluing areas on its sides.</p>
<p>Now, lift the tape from the edges of the board and slide one strain gauge underneath it using tweezers. Ensure it is correctly aligned and fits within the gluing area. Also, make sure the solder pads are on the correct side. Repeat this for the other gauges and perform a final check to ensure everything is positioned correctly.</p>
<p>It’s now time to glue the gauges in place. Lift the tape with the attached gauge one at a time and apply a thin layer of super glue to the gluing area. Lower the tape and press the gauge onto the PCB with your thumb. Hold it in place for about 30 seconds, then proceed to the next gauge.</p>
<p>Depending on the glue and the amount used, you can proceed directly to removing the tape, starting with the first gauge you glued down.</p>
<p>When removing the tape, pull it to the side rather than lifting it straight up.</p>
<p>You are now left with attached strain gauges. Use some wire to connect the gauges to the PCB. Be careful with heat on the gauges, as they can be somewhat sensitive.</p>
<p>Finally, clean the board with IPA. Even after cleaning, you may find some residue from the adhesive tape or super glue on the uncovered areas, but the rest of the board should be clean and ready for assembly.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/1_hu0aef7289ac4c21d02f3162028785ad0d_766166_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/1_hu0aef7289ac4c21d02f3162028785ad0d_766166_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/2_hu0aef7289ac4c21d02f3162028785ad0d_841180_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/2_hu0aef7289ac4c21d02f3162028785ad0d_841180_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/3_hu0aef7289ac4c21d02f3162028785ad0d_856281_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/3_hu0aef7289ac4c21d02f3162028785ad0d_856281_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/4_hu0aef7289ac4c21d02f3162028785ad0d_852861_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/4_hu0aef7289ac4c21d02f3162028785ad0d_852861_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/5_hu0aef7289ac4c21d02f3162028785ad0d_1066779_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/5_hu0aef7289ac4c21d02f3162028785ad0d_1066779_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/6_hu0aef7289ac4c21d02f3162028785ad0d_791114_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/6_hu0aef7289ac4c21d02f3162028785ad0d_791114_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/7_hu0aef7289ac4c21d02f3162028785ad0d_920021_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260305_strainstick/images/gauges/7_hu0aef7289ac4c21d02f3162028785ad0d_920021_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="assembly">Assembly</h3>
<p>The assembly is a straightforward process. There are no particularly complicated components on the board, but I would recommend using some form of magnification. An interactive BOM is included in the released files. As always, I recommend using lead-free solder.</p>
<p>I may create a future version of the board that allows the strain gauges to be mounted on the back of the PCB. This would enable the use of a stencil. For now, however, the board must be soldered by hand.</p>
<h2 id="software">Software</h2>
<p>I created a demo for the device that allows it to act as a mouse. The demo is currently only available as a binary. I plan to publish the source code alongside the mentioned project in the future. If you really want to tinker with the code, feel free to send me an email.</p>
<p>There is an <a href="https://docs.arduino.cc/libraries/hx711-arduino-library/">Arduino library for the HX711</a> which, I believe, should also work for the HX717. This might be a better option if you want to experiment with the device.</p>
<p>The demo runs on the CH32V203 demo board from WCH. You have to connect the Strainstick as follows:</p>
<ul>
<li>Pin 1 &ndash;&gt; 5V</li>
<li>Pin 2 &ndash;&gt; PA2</li>
<li>Pin 3 &ndash;&gt; PA3</li>
<li>Pin 4 &ndash;&gt; PA8</li>
<li>Pin 5 &ndash;&gt; GND</li>
</ul>
<p>You can flash the software using the integrated Bootloader and <a href="https://github.com/ch32-rs/wchisp">WCHISP</a>. Set BOOT0 to high and reboot the board.</p>
<p><img alt="Connected to CH32V203" src="/posts/260305_strainstick/images/demo.JPG"></p>
<h2 id="thanks">Thanks</h2>
<ul>
<li>Thank scottbez1 for the general idea of strain gauges on PCBs</li>
</ul>
<h2 id="project-files">Project files</h2>
<ul>
<li><a href="/posts/260305_strainstick/files/release_1_0/ahid_strain_stick_1_0.zip">KiCAD Files</a></li>
<li><a href="/posts/260305_strainstick/files/release_1_0/ahid_strain_stick_1_0_gbr.zip">Gerbers</a></li>
<li><a href="/posts/260305_strainstick/files/release_1_0/firmware.zip">Test firmware for CH32V203</a></li>
<li><a href="/posts/260305_strainstick/files/release_1_0/ibom.zip">Interactive BOM</a></li>
<li><a href="/posts/260305_strainstick/files/release_1_0/rod.zip">3D printed rod</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>PartNest - Modular Stackable Storage for SMD Parts and Wires</title>
            <link>https://www.embedded-ideas.de/posts/260214_part_nest/</link>
            <pubDate>Sat, 14 Feb 2026 01:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/260214_part_nest/</guid>
            <description>TL;DR See pictures ;) Files below Introduction I already did a take on designing SMD parts containers for SMD tapes. Recently, I came across the problem of storing smaller gauge wires. I thought it would be nice to store them in the same kind of containers I use for my SMD storage. What bothered me about my last design was the amount of time it took to assemble the containers with a rail, and also that the rails themselves are inconvenient to store.</description>
            <content type="html"><![CDATA[<p><img alt="Project Overview" src="/posts/260214_part_nest/images/title.JPG"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>See pictures ;)</li>
<li>Files below</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I already did a take on designing <a href="/posts/250402_smd_storage/">SMD parts containers for SMD tapes</a>. Recently, I came across the problem of storing smaller gauge wires. I thought it would be nice to store them in the same kind of containers I use for my SMD storage. What bothered me about my last design was the amount of time it took to assemble the containers with a rail, and also that the rails themselves are inconvenient to store. So I had the idea of making the containers connect to each other, which also eliminates the need to print a cover for each one. I started experimenting with the dovetail approach I used for my SMD storage tray.</p>
<p><img alt="SMD Containers" src="/posts/260214_part_nest/images/stack.JPG"></p>
<p>After a few iterations, I was quite happy with the results. I ended up designing an SMD parts container that still works like the ones from, for example, <a href="https://www.thingiverse.com/thing:3952021">Robin Reiter</a>, but is easier to print and can be stacked. I also designed a matching storage container for wires. To make handling a bit easier, I created an angled stand and hooks for IKEA Skådis boards, which can be directly attached to the connected containers.</p>
<p><strong>Features</strong></p>
<ul>
<li>Only one non-printable part: a single spring per container</li>
<li>Only one cover per stack (reduces parts and print time)</li>
<li>Label area for writing or printed labels</li>
<li>Fully customizable using the OpenSCAD customizer</li>
<li>Wire container with a rewind mechanism</li>
</ul>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011880_hu0aef7289ac4c21d02f3162028785ad0d_1180408_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011880_hu0aef7289ac4c21d02f3162028785ad0d_1180408_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011882_hu0aef7289ac4c21d02f3162028785ad0d_991107_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011882_hu0aef7289ac4c21d02f3162028785ad0d_991107_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011884_hu0aef7289ac4c21d02f3162028785ad0d_1047940_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011884_hu0aef7289ac4c21d02f3162028785ad0d_1047940_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011892_hu0aef7289ac4c21d02f3162028785ad0d_1124741_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011892_hu0aef7289ac4c21d02f3162028785ad0d_1124741_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011895_hu0aef7289ac4c21d02f3162028785ad0d_939560_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011895_hu0aef7289ac4c21d02f3162028785ad0d_939560_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011896_hu0aef7289ac4c21d02f3162028785ad0d_1111839_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/P1011896_hu0aef7289ac4c21d02f3162028785ad0d_1111839_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/PXL_20260204_162106628_hu3fa13784b718342b8bcc5db6e5ce0f76_2699459_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/features/PXL_20260204_162106628_hu3fa13784b718342b8bcc5db6e5ce0f76_2699459_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h2 id="printing-and-assembly">Printing and Assembly</h2>
<p>The default container size is <strong>60 mm inner diameter</strong>, with a width of <strong>8 mm for the SMD containers</strong> and <strong>9 mm for the wire containers</strong>. You can easily customize these dimensions using the OpenSCAD customizer. I provide STL files for the 60 mm containers with the default widths, along with all matching parts, including the stands and hooks for IKEA Skådis. The rest is up to you.</p>
<p><img alt="SMD Containers" src="/posts/260214_part_nest/images/custom.JPG"></p>
<p>For easier printing, I also added full container sets that include all required parts for one container (except the label inlay).</p>
<ul>
<li><strong>Additional parts</strong>: One 0.3 mm wire spring (4 mm outer diameter, 20 mm length) per container</li>
<li>Layer height: 0.2 mm</li>
<li>Nozzle: 0.4 mm</li>
<li>Smooth print bed</li>
<li>PLA or PLA+ recommended</li>
</ul>
<h3 id="wire-container-assembly">Wire container assembly</h3>
<p>First, screw both parts of the spool together. Set the slider to the lowest position. Insert the spring and push the slider upward. You can compress the spring with a flathead screwdriver to make this easier.</p>
<p>Next, place the gear into its slot and press it down until it clicks into place. Insert the spool with the gear side facing up. The wire should be routed as shown in the picture.</p>
<p>If you want to use a label, simply bend the label insert and slide it into the corresponding slots on top of the container.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011888_hu0aef7289ac4c21d02f3162028785ad0d_954974_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011888_hu0aef7289ac4c21d02f3162028785ad0d_954974_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011889_hu0aef7289ac4c21d02f3162028785ad0d_887815_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011889_hu0aef7289ac4c21d02f3162028785ad0d_887815_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011890_hu0aef7289ac4c21d02f3162028785ad0d_903599_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011890_hu0aef7289ac4c21d02f3162028785ad0d_903599_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011891_hu0aef7289ac4c21d02f3162028785ad0d_903605_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011891_hu0aef7289ac4c21d02f3162028785ad0d_903605_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011892_hu0aef7289ac4c21d02f3162028785ad0d_731828_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011892_hu0aef7289ac4c21d02f3162028785ad0d_731828_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011894_hu0aef7289ac4c21d02f3162028785ad0d_825801_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011894_hu0aef7289ac4c21d02f3162028785ad0d_825801_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011895_hu0aef7289ac4c21d02f3162028785ad0d_1100039_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011895_hu0aef7289ac4c21d02f3162028785ad0d_1100039_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011896_hu0aef7289ac4c21d02f3162028785ad0d_899443_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011896_hu0aef7289ac4c21d02f3162028785ad0d_899443_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011898_hu0aef7289ac4c21d02f3162028785ad0d_894864_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_wire/P1011898_hu0aef7289ac4c21d02f3162028785ad0d_894864_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="smd-container-assembly">SMD container assembly</h3>
<p>The SMD container assembly is very similar. Just make sure the slider is inserted all the way at the bottom.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011899_hu0aef7289ac4c21d02f3162028785ad0d_898370_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011899_hu0aef7289ac4c21d02f3162028785ad0d_898370_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011900_hu0aef7289ac4c21d02f3162028785ad0d_768816_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011900_hu0aef7289ac4c21d02f3162028785ad0d_768816_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011901_hu0aef7289ac4c21d02f3162028785ad0d_832936_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011901_hu0aef7289ac4c21d02f3162028785ad0d_832936_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011902_hu0aef7289ac4c21d02f3162028785ad0d_795584_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/260214_part_nest/images/assemble_smd/P1011902_hu0aef7289ac4c21d02f3162028785ad0d_795584_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="thanks">Thanks</h2>
<ul>
<li><a href="https://www.thingiverse.com/thing:3952021">Robin Reiter</a> and <a href="https://www.printables.com/model/580643-smd-component-tape-magazine-8-12-16mm">Lord Asdi</a> for the idea of the tape holding mechanism</li>
<li><a href="https://github.com/chrisspen/gears">Dr. Jörg Janssen</a> for the gears OpenSCAD library</li>
<li><a href="https://github.com/rcolyer/threads-scad">Ryan A. Colyer</a> for the threads OpenSCAD library</li>
</ul>
<h2 id="project-files">Project files</h2>
<p>DOWNLOAD: <a href="/posts/260214_part_nest/files/partnest.zip">STL and source files</a></p>
]]></content>
        </item>
        
        <item>
            <title>USB video output for the Open DMG Display</title>
            <link>https://www.embedded-ideas.de/posts/251116_open_dmg_display_uvc/</link>
            <pubDate>Sun, 16 Nov 2025 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/251116_open_dmg_display_uvc/</guid>
            <description>TL;DR The Open DMG Display firmware now supports video output via USB Video Class (UVC). Utilizes an MJPEG approach adapted from the GB Interceptor. New firmware available at link. Introduction It has been a while since I published the Open DMG Display. Since then, I’ve tinkered with the display signals of the entire Game Boy lineup, which resulted in an open display for the Game Boy Advance. I don’t know who it was, but someone asked whether it would be possible to add capturing to this device, and that got me thinking about an implementation.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/251116_open_dmg_display_uvc/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>The Open DMG Display firmware now supports video output via USB Video Class (UVC).</li>
<li>Utilizes an MJPEG approach adapted from the GB Interceptor.</li>
<li>New firmware available at <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/releases">link</a>.</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>It has been a while since I published the <a href="/posts/250417_open_dmg_display/">Open DMG Display</a>. Since then, I’ve tinkered with the display signals of the entire Game Boy lineup, which resulted in an <a href="/posts/250825_openagbdisplay/">open display for the Game Boy Advance</a>. I don’t know who it was, but someone asked whether it would be possible to add capturing to this device, and that got me thinking about an implementation.</p>
<p>I remembered the <a href="https://media.ccc.de/v/37c3-11928-reconstructing_game_footage_from_a_game_boy_s_memory_bus">talk by Sebastian Staacks at 37C3 about his GB Interceptor</a>. I came to the conclusion that it wouldn’t be worth trying to implement this directly on the RP2350 (especially after asking Sebastian whether he thought it was possible). So I moved on to experimenting with an ESP32P4, which worked well. Since I also wanted to get familiar with the TinyUSB library, I tried getting capturing to run on a cheap CH32V305, <a href="/posts/251030_xgb_to_usb/">which also worked</a>.</p>
<p>What I totally overlooked was that the GB Interceptor approach could be adapted to the Open DMG Display, something I’m hereby catching up on.</p>
<h2 id="implementation">Implementation</h2>
<p>Until now, the Open DMG Display only used one of the RP2350’s cores, leaving the other free for USB video. The implementation relies heavily on the TinyUSB library for the core USB functionality, while the rest adapts the MJPEG approach from the GB Interceptor.</p>
<p>RAW frames are captured using the existing code. Once a frame is complete, it’s copied into a separate memory region for further processing, which ties USB output to the Game Boy’s frame timing. In 30 FPS mode, every second frame is skipped. Lookup tables convert the 2-bit-per-pixel raw data into 3-bit-per-pixel data as a preliminary step before JPEG encoding.</p>
<p>Unlike Sebastian Staacks’ approach, no PIOs are used, the dedicated core has enough resources to handle everything in software, including JPEG generation via lookup tables.</p>
<p>The adapted method from Sebastian and Ikadzuchi reduces JPEG quantization to the lowest frequencies, keeping mostly luminance. Huffman tables and other parameters are tuned to efficiently encode 3bpp grayscale images using 5 bits per pixel plus JPEG overhead, which includes unused chroma. This allows 30 FPS over a 12 Mbit USB link.</p>
<p>For 60 FPS mode, chroma is skipped entirely, transferring only luminance. This can cause compatibility issues with some software.</p>
<p>For a deeper dive, check out <a href="https://media.ccc.de/v/37c3-11928-reconstructing_game_footage_from_a_game_boy_s_memory_bus">Sebastian’s talk</a>.</p>
<h2 id="usage">Usage</h2>
<p><img alt="Config menu of the Open DMG Display showing options for USB Video output." src="/posts/251116_open_dmg_display_uvc/images/menu.jpg"></p>
<p>The USB video output is disabled by default. To use it, you need to enable it in the menu. Look for “USB Video Mode” and choose between:</p>
<ul>
<li>OFF
<ul>
<li>The system will not initialize the USB port, and the second core will remain inactive.</li>
</ul>
</li>
<li>30fps
<ul>
<li>This mode produces approximately 29.85 FPS. Every second frame is skipped to keep the data rate well below 12 Mbit.</li>
</ul>
</li>
<li>60fps
<ul>
<li>This mode may have compatibility issues. It has been tested with QV4L2 and OBS, only OBS handled the signal correctly.</li>
</ul>
</li>
</ul>
<p>After selecting a mode, <strong>restart the device</strong>. It should now be detected like a webcam or a USB microscope.</p>
<h2 id="thanks">Thanks</h2>
<ul>
<li>Sebastian Staacks for his talk at the 37C3 and the GB Interceptor code (especially the Python scripts)
<ul>
<li><a href="https://media.ccc.de/v/37c3-11928-reconstructing_game_footage_from_a_game_boy_s_memory_bus">https://media.ccc.de/v/37c3-11928-reconstructing_game_footage_from_a_game_boy_s_memory_bus</a></li>
<li><a href="https://github.com/Staacks/gbinterceptor/tree/main/firmware/jpeg">https://github.com/Staacks/gbinterceptor/tree/main/firmware/jpeg</a></li>
</ul>
</li>
<li>Ikadzuchi for suggesting a method on how to efficiently use MJPEG for greyscale images
<ul>
<li><a href="https://github.com/Staacks/gbinterceptor/issues/17">https://github.com/Staacks/gbinterceptor/issues/17</a></li>
</ul>
</li>
<li>The whole team from the TinyUSB library for this awesome piece of software
<ul>
<li><a href="https://www.tinyusb.org">https://www.tinyusb.org</a></li>
</ul>
</li>
</ul>
<h2 id="files">Files</h2>
<ul>
<li>Code: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/">https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/</a></li>
<li>Binaries: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/releases">https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/releases</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>xGB to USB - USB video capturing for Gameboy Advance and Gameboy Color</title>
            <link>https://www.embedded-ideas.de/posts/251030_xgb_to_usb/</link>
            <pubDate>Thu, 30 Oct 2025 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/251030_xgb_to_usb/</guid>
            <description>TL;DR Research project Shows how to capture Gameboy Advance and potentially Gameboy Color display signals using a CH32V305RBT6 Uses TinyUSB library to output the signals via USB (USB Video Class) Code and binaries: https://codeberg.org/embedded-ideas/xgb2usb/ Introduction This project is a proof-of-concept for capturing and outputting display signals from the 2nd and 3rd generation Game Boys using a low-cost, general-purpose microcontroller. It describes how to use a CH32V305 MCU, without any specialized peripherals (other than USB 2.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/251030_xgb_to_usb/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Research project</li>
<li>Shows how to capture Gameboy Advance and potentially Gameboy Color display signals using a CH32V305RBT6</li>
<li>Uses TinyUSB library to output the signals via USB (USB Video Class)</li>
<li>Code and binaries: <a href="https://codeberg.org/embedded-ideas/xgb2usb/">https://codeberg.org/embedded-ideas/xgb2usb/</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>This project is a proof-of-concept for capturing and outputting display signals from the 2nd and 3rd generation Game Boys using a low-cost, general-purpose microcontroller. It describes how to use a CH32V305 MCU, without any specialized peripherals (other than USB 2.0 HS), to capture the Gameboy Advance’s RGB565 display signals at approximately 60 Hz and full resolution, and stream them over USB using the UVC protocol in YUY2 format, all without any additional circuitry, allowing to build a recording/capturing device for the GBA. The code should also work for the Game Boy Color, as the signals are quite similar. There is only a difference in the resolution.</p>
<p>I’ll walk through my thought process and the ideas that led to my solution.</p>
<video preload="metadata" controls width="100%">
    <source
      src="/posts/251030_xgb_to_usb/video/demo1.mp4"
      type="video/mp4"
    >
    Your browser does not support the video element.
  </video>
<h2 id="motivation">Motivation</h2>
<p>Capturing parallel display signals isn’t very complicated when using popular microcontrollers with a wide range of fast parallel peripherals, such as the PIO on the Raspberry Pi Pico or the PARLIO on the ESP32-P4. Traditional interfaces like external memory controllers or camera interfaces can also be used to capture this data.</p>
<p>But what if you want to do the capturing on a very basic microcontroller? I wanted to test whether this would work using a general-purpose controller. I had a WCH CH32V203 lying around, so I decided to start with that. Due to my recent projects, I used the familiar signal from my Game Boy Advance.</p>
<h2 id="project-execution--problem-solving">Project Execution &amp; Problem Solving</h2>
<p>I had the following plan: I wanted to trigger on the VSYNC (start-of-frame) signal using an external interrupt. After this, another external signal interrupt from the pixel clock would trigger a DMA transfer, which moves the contents of a GPIO port input register containing 16 pin states into memory. Not a bad plan, but I was surprised to discover that it isn’t possible to trigger DMA transfers directly from external signals.</p>
<p>A deeper look into the DMA peripheral led me to the capture mode of the timer peripherals. This mode allows an external signal to trigger a DMA channel. Normally, it is intended to transfer the counter register, but there is nothing stopping you from using a GPIO port input register as the source address. And it actually worked.</p>
<p>With this setup, capturing the data became possible, but it was essentially useless because the frame data couldn’t be stored anywhere. A whole frame, 240 by 160 pixels with 2 bytes per pixel, would require 75 KiB of RAM, while the controller only had 20 KiB.</p>
<p>Great! A Frankenstein-like peripheral driver made from a timer, DMA, and basic GPIO, glued together with a few lines of code. Luckily, I also wanted to explore the TinyUSB library’s video capabilities and came across the CH32V305RBT6, which is essentially a CH32V203 with 50 percent more RAM and, most importantly, a high-speed USB port.</p>
<p>TinyUSB includes an implementation for UVC, or USB Video Class, normally used for webcams, and it was used in the Gameboy Interceptor, a Classic Gameboy (DMG-01) capture device by Sebastian Staaks (<a href="https://github.com/Staacks/gbinterceptor)">https://github.com/Staacks/gbinterceptor)</a>. It uses the full-speed USB port of a Pi Pico. However, for the higher resolution and color depth of the Gameboy Advance, a full-speed interface isn’t fast enough. This made the CH32V305 an excellent candidate, especially at a price of 1.50 USD per unit for 10 pieces. Still, there isn’t enough RAM to store a full frame, and TinyUSB only supports transferring complete frames.</p>
<p>After spending some time with the TinyUSB code, I managed to modify the video class driver to support “on-the-fly” data streaming without a frame buffer. I first experimented with generated data and then integrated my capture driver from the CH32V203. I modified it to provide a ring buffer that stores data line by line along with the line index. This allowed the USB video class code to synchronize on the first frame. After that, it retrieves data as quickly as possible. If it is too fast, it waits until new line data is received. With a ring buffer of about 50 lines, this worked quite well.</p>
<p>You can find my changes to the tinyUSB library here: <a href="https://github.com/embedded-ideas/tinyusb">https://github.com/embedded-ideas/tinyusb</a>. I made a pull request so it might end-up in the mainline repo (update: <a href="https://github.com/hathach/tinyusb/pull/3322">it did</a>).</p>
<p>Unfortunately, this was not the end of the challenge. The captured data was RGB565, but the supported video formats were only MJPEG, which we cannot calculate fast enough, and YUV2. YUV2 still requires calculations beyond the CPU’s capabilities. At this point, it was useful that the AGB doesn’t fully use RGB565: the lowest green bit is tied to ground. This means we are effectively dealing with RGB555, or 15-bit data.</p>
<p>This allowed an easy solution: a lookup table. By storing 8-bit YUV values for each possible color, we require 96 KiB, which can be stored in flash memory.</p>
<p>And voilà, it works.</p>
<h2 id="code">Code</h2>
<p>The code is separated into two parts. There is the capture driver (xgb_capture.c) which provides the captured data either as YUV2 or RGB565 data and the code that takes care of the tinyUSB interface (stored in main.c). The other files are taken from the video capture example of the tinyUSB library. They provide the right configuration and the USB descriptors.</p>
<p>You can find the code on codeberg.org: <a href="https://codeberg.org/embedded-ideas/xgb2usb/">https://codeberg.org/embedded-ideas/xgb2usb/</a></p>
<h3 id="build-linux">Build (Linux)</h3>
<p>First you have to prepare the toolchain. Download and extract the archive and add the path to the <em>bin</em> directory to your <em>PATH</em> variable.</p>
<p><a href="https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v15.2.0-1/xpack-riscv-none-elf-gcc-15.2.0-1-linux-x64.tar.gz">https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v15.2.0-1/xpack-riscv-none-elf-gcc-15.2.0-1-linux-x64.tar.gz</a></p>
<h4 id="clone-and-build-the-project">Clone and build the project</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone --recurse-submodules https://codeberg.org/embedded-ideas/xgb2usb.git
</span></span><span style="display:flex;"><span>cd xgb2usb/tinyusb/tools/
</span></span><span style="display:flex;"><span>python get_deps.py ch32v30x
</span></span><span style="display:flex;"><span>cd ../..
</span></span><span style="display:flex;"><span>mkdir build
</span></span><span style="display:flex;"><span>cd build
</span></span><span style="display:flex;"><span>cmake ..
</span></span><span style="display:flex;"><span>make
</span></span></code></pre></div><h4 id="flash-the-binary-to-the-mcu">Flash the binary to the MCU</h4>
<p>The CH32V305 comes with a bootloader. Normally a development board should have a button labeled boot. You have to hold this button while pressing reset or plugin in the device. The MCU should start in bootloader mode which allows us to flash software via the USB. There is a nice tool for this: <a href="https://github.com/ch32-rs/wchisp/releases/tag/v0.3.0">https://github.com/ch32-rs/wchisp/releases/tag/v0.3.0</a></p>
<p>Make sure you added the path to the executable to your <em>PATH</em> variable and run:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wchisp flash xgb2usb.hex
</span></span></code></pre></div><h4 id="testing">Testing</h4>
<p>There are several options to test if the device works. You might consider OBS, QV4L2 or an Android app like &ldquo;USB Camera&rdquo;</p>
<video preload="metadata" controls width="100%">
    <source
      src="/posts/251030_xgb_to_usb/video/demo2.mp4"
      type="video/mp4"
    >
    Your browser does not support the video element.
  </video>
<h2 id="hardware">Hardware</h2>
<p>The code should work fine with every evaluation board which uses a CH32V305RBT6 and an external 8MHz crystal. I used the nanoCH32V305 board which isn&rsquo;t ideal because two of the used inputs are only available via the second USB port data lines, hence I had to use an additional adapter board for A11/12 (see pictures).</p>
<h3 id="connections">Connections</h3>
<table>
<thead>
<tr>
<th>Signal</th>
<th>Gameboy Advance (32-pin connector)</th>
<th>Gameboy Advance (40-pin connector)</th>
<th>CH32V305</th>
</tr>
</thead>
<tbody>
<tr>
<td>VSYNC (SPS)</td>
<td>25</td>
<td>26</td>
<td>PB3</td>
</tr>
<tr>
<td>PCLK (DCK)</td>
<td>2</td>
<td>3</td>
<td>PB8</td>
</tr>
<tr>
<td>LDR1</td>
<td>11</td>
<td>12</td>
<td>PA0</td>
</tr>
<tr>
<td>LDR2</td>
<td>10</td>
<td>11</td>
<td>PA1</td>
</tr>
<tr>
<td>LDR3</td>
<td>9</td>
<td>10</td>
<td>PA2</td>
</tr>
<tr>
<td>LDR4</td>
<td>8</td>
<td>9</td>
<td>PA3</td>
</tr>
<tr>
<td>LDR5</td>
<td>7</td>
<td>8</td>
<td>PA4</td>
</tr>
<tr>
<td>LDG0</td>
<td>17</td>
<td>18</td>
<td>-</td>
</tr>
<tr>
<td>LDG1</td>
<td>16</td>
<td>17</td>
<td>PA5</td>
</tr>
<tr>
<td>LDG2</td>
<td>15</td>
<td>16</td>
<td>PA6</td>
</tr>
<tr>
<td>LDG3</td>
<td>14</td>
<td>15</td>
<td>PA7</td>
</tr>
<tr>
<td>LDG4</td>
<td>13</td>
<td>14</td>
<td>PA8</td>
</tr>
<tr>
<td>LDG5</td>
<td>12</td>
<td>13</td>
<td>PA9</td>
</tr>
<tr>
<td>LDB1</td>
<td>22</td>
<td>23</td>
<td>PA10</td>
</tr>
<tr>
<td>LDB2</td>
<td>21</td>
<td>22</td>
<td>PA11</td>
</tr>
<tr>
<td>LDB3</td>
<td>20</td>
<td>21</td>
<td>PA12</td>
</tr>
<tr>
<td>LDB4</td>
<td>19</td>
<td>20</td>
<td>PA13</td>
</tr>
<tr>
<td>LDB5</td>
<td>18</td>
<td>19</td>
<td>PA14</td>
</tr>
<tr>
<td>GND</td>
<td>32</td>
<td>35</td>
<td>GND</td>
</tr>
</tbody>
</table>
<h2 id="thanks">Thanks</h2>
<ul>
<li>TinyUSB Library for this awesome project
<ul>
<li><a href="https://github.com/hathach/tinyusb">https://github.com/hathach/tinyusb</a></li>
</ul>
</li>
<li>xPack Binary Development Tools for providing a nice way to get an alternative toolchain
<ul>
<li><a href="https://github.com/xpack-dev-tools/">https://github.com/xpack-dev-tools/</a></li>
</ul>
</li>
<li>WCH-ISP for the easy to use flash tool
<ul>
<li><a href="https://github.com/ch32-rs/wchisp/">https://github.com/ch32-rs/wchisp/</a></li>
</ul>
</li>
</ul>
<h2 id="files">Files</h2>
<p>Sourcecode and release binaries are hosted on codeberg.org</p>
<ul>
<li>Sourcecode:  <a href="https://codeberg.org/embedded-ideas/xgb2usb/">https://codeberg.org/embedded-ideas/xgb2usb/</a></li>
<li>Binaries:  <a href="https://codeberg.org/embedded-ideas/xgb2usb/releases">https://codeberg.org/embedded-ideas/xgb2usb/releases</a></li>
</ul>
<h2 id="disclaimer">Disclaimer</h2>
<p>This project is provided for educational and experimental use only.
Use all code, hardware, and instructions at your own risk.</p>
<p>The author assumes no responsibility for damage, data loss, or malfunction resulting from its use.
All trademarks (e.g., Game Boy Advance) belong to their respective owners.
This project is not affiliated with WCH, Nintendo, or any other company.</p>
]]></content>
        </item>
        
        <item>
            <title>Open AGB Display - An Open Source IPS Display Mod for the Game Boy Advance</title>
            <link>https://www.embedded-ideas.de/posts/250825_openagbdisplay/</link>
            <pubDate>Mon, 25 Aug 2025 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250825_openagbdisplay/</guid>
            <description>TL;DR Fully open-source IPS display mod for the Game Boy Advance Based on RP2350B for signal capture + rendering Requires custom PCB, case cuts, and optional custom lens Integer upscaling on 480x480 display resolution (pixel-perfect) Effects support (scanlines, color tweaks, pixelation) Power efficient: ~10-12h on NiMH at 50% brightness Hardware &amp;amp; software files linked below Introduction After designing the Open DMG Display, I became curious whether I had missed anything by never owning a Game Boy Advance.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/250825_openagbdisplay/images/cover.jpg"></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover_hub1caa482ec4272f353c45cb9ba910d48_123288_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover_hub1caa482ec4272f353c45cb9ba910d48_123288_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover2_hubf12942361ec6748d94ae37cea846c03_170003_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover2_hubf12942361ec6748d94ae37cea846c03_170003_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover3_hu4f41aba515712dde5edb4422f0220ab1_76048_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/preview/cover3_hu4f41aba515712dde5edb4422f0220ab1_76048_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h2 id="tldr">TL;DR</h2>
<ul>
<li>Fully open-source IPS display mod for the Game Boy Advance</li>
<li>Based on RP2350B for signal capture + rendering</li>
<li>Requires custom PCB, case cuts, and optional custom lens</li>
<li>Integer upscaling on 480x480 display resolution (pixel-perfect)</li>
<li>Effects support (scanlines, color tweaks, pixelation)</li>
<li>Power efficient: ~10-12h on NiMH at 50% brightness</li>
<li>Hardware &amp; software files linked below</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>After designing the <a href="/posts/250417_open_dmg_display/">Open DMG Display</a>, I became curious whether I had missed anything by never owning a Game Boy Advance. At a recent retro fair in my city, I found a good deal on a standard Game Boy Advance and took it home. I was genuinely surprised by how poor the display quality was. Once again, I couldn’t find any affordable open-source option for a display replacement. I found a nice 480×480 IPS module and already had some RP2350B breakout boards lying around, so I decided to run some experiments to see if I could capture the Game Boy Advance image and display it at full framerate with low latency.</p>
<p>Those experiments eventually escalated into this very project.</p>
<p><img alt="A Game Boy Advance display signal is captured and processed by an RP2350, then sent in RGB565 format to an IPS display module." src="/posts/250825_openagbdisplay/images/test_setup.jpg"></p>
<!--
Lorim Ipsum
![Editing the user palettes CSV](images/calc_userdata.png)
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">

</ul>

-> [Repository on codeberg.org](https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/src/branch/master/scripts) <-
-->
<h2 id="what-to-expect--and-what-not-to">What to Expect – and What Not To</h2>
<p>This is an open project, not a finalized product. All data and materials are provided as is. If you have questions, I’m happy to help when I have the time — however, support is not guaranteed and responses may be delayed. Bugs in the code and potential hardware issues are to be expected. If you encounter any problems, I’d appreciate it if you report them so the project can continue to improve. If you’re able to fix an issue yourself, contributions are very welcome!</p>
<p><strong>Disclaimer</strong>: Use of the provided information, files, and build instructions is entirely at your own risk. No guarantee is given regarding accuracy, completeness, or functionality. Any liability for damage to hardware or software, consequential damages, or other claims arising from use is excluded.</p>
<h2 id="signals-and-timings">Signals and Timings</h2>
<p>In order to understand how this project works, it is essential to first understand the signals we receive from the Game Boy Advance and how we process this data. I will begin with a brief introduction to the Game Boy Advance display signals before explaining how we translate these signals for the TFT.</p>
<h3 id="gameboy-advance-display-signals">Gameboy Advance Display Signals</h3>
<p>If you look at the schematic of the Game Boy Advance, you will see many data lines going to the display. Fortunately, not many of them are relevant for capturing the image data. The most important lines are the DCK, SPL, and SPS lines, along with the 16 data lines (LDRx/LDGx/LDBx).</p>
<p>Regarding the data lines, the Game Boy Advance uses an RGB565 color scheme where the least significant bit of the green channel is tied to ground. This means there is no loss of information if RGB555 is used. In my case, it was easier to use RGB565 to have clean 16-bit data for storage and transport.</p>
<p>The data is transmitted line-by-line from the upper left to the lower right. The start of a frame is indicated by the SPS line, which acts as a vertical synchronization (or start-of-frame) signal. The frame rate directly corresponds to the frequency of this signal.</p>
<p><img alt="GB Advance control signals with measured vsync frequency" src="/posts/250825_openagbdisplay/images/signals/agb_vsyn_framerate.png"></p>
<p>Between two low pulses on the SPS (VSYNC), there are a total of 161 pulses on the SPL (HSYNC) signal, which translates to 161 lines. If you know why there is an additional line, please contact me. In practice, the last line can be ignored.</p>
<p><img alt="GB Advance control signals with measured hsyc pulses within a frame" src="/posts/250825_openagbdisplay/images/signals/agb_frame_measure_hsync.png"></p>
<p>Now let’s take a closer look at a single line. It begins with a high pulse on the SPL (HSYNC) line. The DCK (pixel clock) is only active during the transfer of line data. There are 241 clock cycles within a line, which makes one additional pulse or 241 pixels per row. The first pixel can be ignored. For implementation purposes, the pixel data is valid only when SPL is low (meaning that SPL is high during the first clock pulse).</p>
<p><img alt="GB Advance control signals with measured clock pulses within a line" src="/posts/250825_openagbdisplay/images/signals/agb_line_measure_clk.png"></p>
<p><img alt="HSYNC pulse matched with clock signal" src="/posts/250825_openagbdisplay/images/signals/agb_hsync_pulse.png"></p>
<p>Finally, down at the single-pixel level, the data on the data lines changes on the falling edge of the pixel clock (DCK) and should therefore be latched or captured on the rising edge.</p>
<p><img alt="Single clock cycle with changing data line" src="/posts/250825_openagbdisplay/images/signals/agb_single_pixel.png"></p>
<p>If you want you can download the captures (can be used with Saleae Logic 2): <a href="./files/AGB_Signal_Captures.zip" title="AGB_Signal_Captures.zip">AGB_Signal_Captures.zip</a></p>
<h3 id="tft">TFT</h3>
<p>The TFT uses a non-buffered RGB565 interface, which is quite similar to what I described above. Unfortunately, it differs in ways that prevent us from simply passing the signal through. One major difference is the resolution, meaning we have to handle more data per unit of time. Another difference is in the signal itself. I will not go into detail, but for example, the TFT’s pixel clock must run continuously, whereas the Game Boy signal does not. There are also parameters such as front porches, back porches, and so on.</p>
<p>Therefore, we first buffer part of the frame in the RP2350’s RAM before transferring it to the TFT. More precisely, we capture half of the Game Boy Advance frame before starting the transfer to the display. This approach has two consequences:</p>
<ul>
<li>We get a synchronized signal with the same frame rate as the original.</li>
<li>We introduce a fixed offset to the original signal, also known as latency (or some might call it lag).</li>
</ul>
<p>Since the display controller has no buffer, the signal almost directly drives the TFT’s line and column drivers. However, the display still has a response time, which is a physical characteristic also present in the original Game Boy Advance screen. I do not have the exact figures for the original, but the panel used in this project has a worst-case response time of around 25 ms for a white-to-black transition, which should be relatively rare in most games.</p>
<p>The latency caused by buffering the signal in the RP2350’s RAM measures around 6.5 ms. This is the time between the moment the last pixel of a Game Boy Advance frame is received and the moment the TFT signal reaches the last active line of the display area used for rendering the Game Boy image. This figure assumes that the 240×160 image is scaled to 480×320 and centered on a 480×480 TFT. In this case, 80 pixels at both the top and bottom of the screen remain unused, so the last line containing content would be line 400.</p>
<p><img alt="TFT and Gameboy Signal timings" src="/posts/250825_openagbdisplay/images/signals/agb_tft_frametiming.png"></p>
<p>Signal timings of the Gameboy and the TFT can be downloaded here:  <a href="./files/agb_tft_timings.sal" title="agb_tft_timings.sal">agb_tft_timings.sal</a></p>
<h2 id="capturing-and-rendering">Capturing and Rendering</h2>
<p>The capture driver (agb_capture.c) uses one of the PIO units to capture the full frame and stores the data into a buffer via a DMA channel. This buffer, therefore, holds 16-bit RGB565 pixel values in a linear fashion, starting from the upper-left pixel and ending at the lower-right pixel. It is able to generate a callback after receiving a specified number of lines. For example, we can configure this callback to trigger after receiving 50% of the lines respectively after capturing half of the frame. We use this callback to trigger the other critical driver responsible for generating the display signal: the TFT driver (tft.c). This driver generates a standard RGB interface signal commonly used in modern TFT display controllers. One advantage of this interface is that it is unbuffered, allowing direct control over timing. We leverage this by using the capture driver&rsquo;s callback to initiate a new frame sequence in the TFT driver. Once started, the TFT driver automatically requests the pixel data line by line as it renders the frame. The TFT driver uses its own callback to request this data, effectively acting as the link between the capture driver and the TFT driver. This callback is responsible for transfering the captured image to the TFT display.</p>
<p>In the simplest implementation, this rendering function simply passes the pixel data through to the display, resulting in a 240x160 image displayed on the TFT. Since both systems use the same RGB565 format, the pixel data can be used directly. However, to better utilize the 480x480 display, we can upscale the image to 480x320 using simple integer scaling. While basic, this allows the rendered image to fill the full width of the TFT module.</p>
<p>The rendering function also has significant potential for implementing custom effects and additional functionality, which I will describe in the next chapter.</p>
<h2 id="effects">Effects</h2>
<p>Each pixel’s color is expressed as a 16-bit color value. We have enough RAM to store lookup tables that allow direct mapping from each color to a different value. For example, we can store a slightly more saturated version of each color, resulting in a more vibrant and colorful image. Alternatively, we can fix the hue to a single color and only modify the saturation and brightness, which would produce a single-color tinted image. If green is used, this would make every Game Boy Advance game look more like a high-resolution DMG version.</p>
<p>Since the TFT resolution is twice that of the source image, we have four pixels available for each source pixel. I used this for another class of effect: introducing a second lookup table intended to store a less bright or less saturated version of the values in the first lookup table. Each of the four pixels is linked to one of the two lookup tables. For example, if the two upper pixels are linked to lookup table one and the lower two to lookup table two, this creates a horizontal scanline effect. If the same pattern is applied to the left and right pixels, it produces vertical scanlines. If only the upper-left pixel of the four-pixel block uses values from lookup table one, it results in a kind of pixelation effect.</p>
<p><img alt="Scanline effect" src="/posts/250825_openagbdisplay/images/effect.jpg"></p>
<p>The color adjustments are calculated using the HSV model. The values are computed once and stored in the lookup tables. This approach uses significant RAM but enables real-time rendering of the described effects.</p>
<h2 id="build">Build</h2>
<p>Before you start the build, I recommend using an aftermarket shell to keep the original device intact. You should also print the 3D patterns and the display dummy to make your life easier.</p>
<ul>
<li>TFT Display Module HD34013C40 3.4&quot; 480x480 with 40-pin RGB interface (<a href="https://de.aliexpress.com/item/1005007703060475.html">https://de.aliexpress.com/item/1005007703060475.html</a>)</li>
<li>Assembled <em>Open AGB Display</em> PCB</li>
<li>Pi Pico Debug Adapter for flashing</li>
<li>50mm-150mm FFC, 0.5 pos FFC for connecting the programming adapter</li>
<li>50mm 32- or 40-pin FFC, 0.5mm pitch</li>
<li>3D prints:
<ul>
<li>Cutting patterns</li>
<li>Display dummy</li>
<li>Link port dummy</li>
<li>Bottom spring</li>
</ul>
</li>
<li>Thin double-sided tape</li>
<li>Non-conductive foam</li>
<li>Screen lens without prints to build the custom screen lens (optional)
<ul>
<li>Vinyl film or spray paint</li>
</ul>
</li>
</ul>
<h3 id="case-modification">Case modification</h3>
<p>Start with the upper half of the shell. Use the provided pattern to cut the walls at the correct spot. File down any high points on the case that prevent the display from sitting flat. You can also use a sharp knife for scraping. During this process, use the display dummy to check the fit and protect the actual display.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230006_hu0aef7289ac4c21d02f3162028785ad0d_1044497_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230006_hu0aef7289ac4c21d02f3162028785ad0d_1044497_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230009_hu0aef7289ac4c21d02f3162028785ad0d_603009_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230009_hu0aef7289ac4c21d02f3162028785ad0d_603009_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230011_hu0aef7289ac4c21d02f3162028785ad0d_624553_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230011_hu0aef7289ac4c21d02f3162028785ad0d_624553_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230017_hu0aef7289ac4c21d02f3162028785ad0d_820145_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230017_hu0aef7289ac4c21d02f3162028785ad0d_820145_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230018_hu0aef7289ac4c21d02f3162028785ad0d_773484_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230018_hu0aef7289ac4c21d02f3162028785ad0d_773484_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230022_hu0aef7289ac4c21d02f3162028785ad0d_634709_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230022_hu0aef7289ac4c21d02f3162028785ad0d_634709_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230024_hu0aef7289ac4c21d02f3162028785ad0d_703791_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230024_hu0aef7289ac4c21d02f3162028785ad0d_703791_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230025_hu0aef7289ac4c21d02f3162028785ad0d_710878_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/top_shell/P5230025_hu0aef7289ac4c21d02f3162028785ad0d_710878_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<p>If you want to use the full display area for classic games, you’ll need to cut a new screen opening. A 3D-printable pattern is provided for this as well. Use the pattern to cut a groove first, then remove the excess material with a wire cutter. Finally, file down any burrs for a clean finish.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210188_hu0aef7289ac4c21d02f3162028785ad0d_720076_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210188_hu0aef7289ac4c21d02f3162028785ad0d_720076_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210190_hu0aef7289ac4c21d02f3162028785ad0d_1115559_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210190_hu0aef7289ac4c21d02f3162028785ad0d_1115559_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210191_hu0aef7289ac4c21d02f3162028785ad0d_702205_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210191_hu0aef7289ac4c21d02f3162028785ad0d_702205_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210194_hu0aef7289ac4c21d02f3162028785ad0d_772346_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210194_hu0aef7289ac4c21d02f3162028785ad0d_772346_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210196_hu0aef7289ac4c21d02f3162028785ad0d_721792_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210196_hu0aef7289ac4c21d02f3162028785ad0d_721792_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210198_hu0aef7289ac4c21d02f3162028785ad0d_857072_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210198_hu0aef7289ac4c21d02f3162028785ad0d_857072_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210199_hu0aef7289ac4c21d02f3162028785ad0d_1143333_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/display_cutout/P7210199_hu0aef7289ac4c21d02f3162028785ad0d_1143333_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="pcb-assembly-and-firmware-flashing">PCB assembly and firmware flashing</h3>
<p>You’ll find all information about the required components in the provided BOM. The PCB can be ordered from your preferred supplier. You’ll need to decide whether to place the 32-pin or 40-pin connector for the connection to the AGB PCB. I was only able to test the 32-pin version, so use the 40-pin connector with caution, as it is still untested. A cost-effective method for assembling components onto the PCB is explained in this blog post: <a href="/posts/250407_hotplate_soldering/">Manual Assembly of Modern PCBs Using Low-Cost Tools</a>.</p>
<p>In addition to the main PCB, there is a separate adapter board used for flashing the firmware and/or connecting to the debug interface. You’ll need to assemble this board as well. Connect it to the AGB main board via a 10-pin FFC and power the <em>OpenAGB Display</em> board with an external 3V supply. Alternatively, you can power the Open AGB Display board through the adapter board by bridging the solder jumpers, but be careful not to connect it to the AGB mainboard at the same time.</p>
<p>To flash the firmware, connect the USB-C port of the adapter board to your PC while holding the push button. An external drive should appear in your file system. Copy the provided UF2 file onto this drive. Once the drive disappears, the flashing process is complete.</p>
<h3 id="tft-assembly">TFT assembly</h3>
<p>First, connect the display to the 40-pin connector on the bottom of the Open AGB Display PCB. Clean the back of the TFT with IPA. Apply double-sided tape to the back of the PCB and remove the protective film. Attach the PCB to the back of the TFT, using the display edges for alignment.</p>
<p>Next, solder the wires to the corresponding pads on the board. Use an appropriate wire gauge for the power connections. To avoid confusion, mark the three input wires, either with a permanent marker (as I did) or by using different wire colors. Then insert the 32- or 40-pin FFC into the upper connector and lower the assembly into the case. Make sure to remove the protective film from the display before installation.</p>
<p>Insert the 3D-printed spring at the bottom of the TFT, and place pieces of non-conductive foam on the back of the display. This will keep the TFT pressed firmly against the shell.</p>
<p>Now move on to soldering the AGB mainboard. Begin by removing the link port from the top of the PCB. Connect the wire from pad 3 on the Open AGB Display to TP2. Since the remaining soldering will be done on the back of the AGB mainboard, this is a good time to tidy up the cables and secure the PCB in place with screws. It is also the right moment to connect the FFC between the Open AGB Display board and the AGB PCB. Next, connect the wire from pad 2 to the left shoulder button, and the wire from pad 1 to the right shoulder button. Finally, connect the supply wires to the power switch.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/000_hu0aef7289ac4c21d02f3162028785ad0d_1071739_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/000_hu0aef7289ac4c21d02f3162028785ad0d_1071739_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/001_hu0aef7289ac4c21d02f3162028785ad0d_779932_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/001_hu0aef7289ac4c21d02f3162028785ad0d_779932_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/002_hu0aef7289ac4c21d02f3162028785ad0d_837034_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/002_hu0aef7289ac4c21d02f3162028785ad0d_837034_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/003_hu0aef7289ac4c21d02f3162028785ad0d_1032999_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/003_hu0aef7289ac4c21d02f3162028785ad0d_1032999_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/004_hu0aef7289ac4c21d02f3162028785ad0d_923548_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/004_hu0aef7289ac4c21d02f3162028785ad0d_923548_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/005_hu0aef7289ac4c21d02f3162028785ad0d_1153238_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/005_hu0aef7289ac4c21d02f3162028785ad0d_1153238_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/006_hu0aef7289ac4c21d02f3162028785ad0d_830231_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/006_hu0aef7289ac4c21d02f3162028785ad0d_830231_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/007_hu0aef7289ac4c21d02f3162028785ad0d_1187526_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/007_hu0aef7289ac4c21d02f3162028785ad0d_1187526_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/008_hu0aef7289ac4c21d02f3162028785ad0d_880067_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/008_hu0aef7289ac4c21d02f3162028785ad0d_880067_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/009_hu0aef7289ac4c21d02f3162028785ad0d_878323_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/009_hu0aef7289ac4c21d02f3162028785ad0d_878323_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/010_hu0aef7289ac4c21d02f3162028785ad0d_1197130_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/build/tft/010_hu0aef7289ac4c21d02f3162028785ad0d_1197130_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="custom-lens">Custom Lens</h3>
<p>If you want to take full advantage of the display size, especially when it comes to classic Game Boy games, you&rsquo;ll need to use a custom lens for the screen. Fortunately, there are clear glass and plastic lenses available that do not have any printed graphics.</p>
<p>To achieve a cleaner look, it&rsquo;s a good idea to add a frame that hides the adhesive and the rough edges from the cutouts we previously made.</p>
<p>I tried two methods for creating a frame on the lens. Both use a 3D-printed pattern (included in the project files) to make it easier to mark the transparent area.</p>
<p><strong>Method 1</strong>: Spray Paint</p>
<p>For the first attempt, I used spray paint. I cleaned the glass lens and masked off the area that needed to remain transparent. I applied two coats of black spray paint and removed the masking tape while the paint was still slightly wet. If the paint dries completely, it may peel off when removing the tape. I let the lens dry overnight.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240206_hu0aef7289ac4c21d02f3162028785ad0d_344983_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240206_hu0aef7289ac4c21d02f3162028785ad0d_344983_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240207_hu0aef7289ac4c21d02f3162028785ad0d_573603_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240207_hu0aef7289ac4c21d02f3162028785ad0d_573603_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240209_hu0aef7289ac4c21d02f3162028785ad0d_432703_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240209_hu0aef7289ac4c21d02f3162028785ad0d_432703_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240213_hu0aef7289ac4c21d02f3162028785ad0d_342863_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240213_hu0aef7289ac4c21d02f3162028785ad0d_342863_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240214_hu0aef7289ac4c21d02f3162028785ad0d_356348_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7240214_hu0aef7289ac4c21d02f3162028785ad0d_356348_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7250216_hu0aef7289ac4c21d02f3162028785ad0d_514886_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/spray/P7250216_hu0aef7289ac4c21d02f3162028785ad0d_514886_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<p><strong>Method 2:</strong> Vinyl Film</p>
<p>For the second attempt, I used black vinyl film, typically used with vinyl cutters. I first cleaned the glass lens and covered one side with the film. It is important to be very careful during this step to avoid creating bubbles in the area that will remain on the lens.</p>
<p>Next, I used the 3D-printed pattern to mark the area where the film should be removed, and cut along the marked edges with an X-Acto knife. I then carefully removed the rectangular cutout.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020229_hu0aef7289ac4c21d02f3162028785ad0d_655869_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020229_hu0aef7289ac4c21d02f3162028785ad0d_655869_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020231_hu0aef7289ac4c21d02f3162028785ad0d_670086_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020231_hu0aef7289ac4c21d02f3162028785ad0d_670086_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020234_hu0aef7289ac4c21d02f3162028785ad0d_615397_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020234_hu0aef7289ac4c21d02f3162028785ad0d_615397_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020236_hu0aef7289ac4c21d02f3162028785ad0d_579530_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020236_hu0aef7289ac4c21d02f3162028785ad0d_579530_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020238_hu0aef7289ac4c21d02f3162028785ad0d_664983_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020238_hu0aef7289ac4c21d02f3162028785ad0d_664983_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020240_hu0aef7289ac4c21d02f3162028785ad0d_581385_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020240_hu0aef7289ac4c21d02f3162028785ad0d_581385_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020244_hu0aef7289ac4c21d02f3162028785ad0d_715507_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020244_hu0aef7289ac4c21d02f3162028785ad0d_715507_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020251_hub9f9afffb2ada1f578f332c8edb6b04e_1308839_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250825_openagbdisplay/images/lens/vinyl/P8020251_hub9f9afffb2ada1f578f332c8edb6b04e_1308839_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<p>To assemble the lens into the case, I used double-sided tape for both methods. It can easily be applied along the edges of the black frame and trimmed to the right shape using the lens itself as a guide.</p>
<h2 id="osd-menu-and-settings">OSD Menu and Settings</h2>
<p>Press the Select button for 2 seconds to change the brigthness level. Use the left and right shoulder buttons to change the value.</p>
<p>If you hold Select for 5 seconds, you will enter the settings menu. In this menu, you can:</p>
<ul>
<li>Adjust the color brightness</li>
<li>Apply a tint to the display using a single color</li>
<li>Enable visual effects, such as pixelation or scanlines</li>
<li>View the About section, which shows the current software version</li>
<li>And maybe more in future software revisions</li>
</ul>
<p>This allows you to customize the display to your preference and explore the available effects.</p>
<h2 id="supply-and-power-consumtion">Supply and power consumtion</h2>
<p>The <em>Open AGB Display</em> is powered directly from the battery and does not rely on the AGB’s internal voltage regulators. The board includes two regulators (in addition to the internal regulator of the RP2350). The first is a SEPIC converter that generates the 3.3V rail, accepting input voltages from 1.8V up to 5.5V. The second is a step-up converter that generates 18V for the backlight, operating from 1.8V to 6V.</p>
<p>Both regulators are connected to the battery through the power switch. Since this switch is usually somewhat aged and subject to wear, a voltage drop across it is to be expected. With the backlight fully enabled, the system draws around 400mA at 2.2V. In my measurements, the power switch introduced a voltage drop of about 0.08V, corresponding to roughly 200mΩ resistance. This could be worth revisiting in future revisions.</p>
<p>The regulators have been tested to start up reliably at 2.1V input at the battery terminals, which aligns with the lower discharge voltage of NiMH cells. To reduce current draw, and therefore losses, you may want to consider Li-Ion AA cells with 1.5V nominal voltage. This also brings the regulators closer to their efficiency sweet spot. However, the original AGB regulators may have been optimized for slightly lower voltages, so the measured system power consumption does not provide a clear picture.</p>
<table>
<thead>
<tr>
<th>Brightness</th>
<th>Voltage</th>
<th>Current</th>
<th>Power (W)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>20%</strong></td>
<td>2.2V</td>
<td>178mA</td>
<td>0.392 W</td>
</tr>
<tr>
<td></td>
<td>2.5V</td>
<td>161mA</td>
<td>0.403 W</td>
</tr>
<tr>
<td></td>
<td>3.0V</td>
<td>131mA</td>
<td>0.393 W</td>
</tr>
<tr>
<td><strong>50%</strong></td>
<td>2.2V</td>
<td>234mA</td>
<td>0.515 W</td>
</tr>
<tr>
<td></td>
<td>2.5V</td>
<td>210mA</td>
<td>0.525 W</td>
</tr>
<tr>
<td></td>
<td>3.0V</td>
<td>172mA</td>
<td>0.516 W</td>
</tr>
<tr>
<td><strong>80%</strong></td>
<td>2.2V</td>
<td>406mA</td>
<td>0.894 W</td>
</tr>
<tr>
<td></td>
<td>2.5V</td>
<td>358mA</td>
<td>0.895 W</td>
</tr>
<tr>
<td></td>
<td>3.0V</td>
<td>294mA</td>
<td>0.882 W</td>
</tr>
<tr>
<td><strong>100%</strong></td>
<td>2.2V</td>
<td>418mA</td>
<td>0.920 W</td>
</tr>
<tr>
<td></td>
<td>2.5V</td>
<td>398mA</td>
<td>0.995 W</td>
</tr>
<tr>
<td></td>
<td>3.0V</td>
<td>366mA</td>
<td>1.098 W</td>
</tr>
</tbody>
</table>
<p>(The power consumtion at the time of release with the system running a GBA game)</p>
<p>In practice, 50% brightness feels like a comfortable setting for indoor play. With modern NiMH cells, you can expect around 10–12 hours of runtime from two fully charged batteries, which, in my opinion, is quite reasonable. There may still be potential for software optimizations to reduce power consumption further, but as long as you’re using the maximum backlight setting, the impact of such tweaks will be limited.</p>
<h2 id="thanks">Thanks</h2>
<ul>
<li>
<p>AGB board scans</p>
<ul>
<li>Natalie the Nerd</li>
<li><a href="https://github.com/nataliethenerd/boardscans/tree/main/AGB-CPU-10">https://github.com/nataliethenerd/boardscans/tree/main/AGB-CPU-10</a></li>
<li><a href="https://github.com/nataliethenerd/boardscans/tree/main/AGB-CPU-01">https://github.com/nataliethenerd/boardscans/tree/main/AGB-CPU-01</a></li>
</ul>
</li>
<li>
<p>Graphics Library for the OSD</p>
<ul>
<li>LVGL Graphics Library</li>
<li><a href="https://lvgl.io/">https://lvgl.io/</a></li>
</ul>
</li>
</ul>
<h2 id="files">Files</h2>
<p>Sourcecode and release binaries are hosted on codeberg.org</p>
<ul>
<li>
<p>Hardware</p>
<ul>
<li>Open AGB Display
<ul>
<li>GIT-Repository: <a href="https://codeberg.org/embedded-ideas/OpenAgbDisplay-HW/">https://codeberg.org/embedded-ideas/OpenAgbDisplay-HW/</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenAgbDisplay-HW/releases">https://codeberg.org/embedded-ideas/OpenAgbDisplay-HW/releases</a></li>
</ul>
</li>
<li>Debug adapter
<ul>
<li>GIT-Repository: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases">https://codeberg.org/embedded-ideas/PiPicoFfcDebugAdapter-HW/releases</a></li>
</ul>
</li>
</ul>
</li>
<li>
<p>Software</p>
<ul>
<li>GIT-Repository: <a href="https://codeberg.org/embedded-ideas/OpenAgbDisplay-SW/">https://codeberg.org/embedded-ideas/OpenAgbDisplay-SW/</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenAgbDisplay-SW/releases">https://codeberg.org/embedded-ideas/OpenAgbDisplay-SW/releases</a></li>
</ul>
</li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Real-Time Fractional Scaling for Retro Game Graphics</title>
            <link>https://www.embedded-ideas.de/posts/250615_non-integer_upscaling/</link>
            <pubDate>Sun, 15 Jun 2025 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250615_non-integer_upscaling/</guid>
            <description>TL;DR Fixed fractional factor upscaling method Targeted at real-time frame upscaling Combines nearest-neighbor with local interpolation Well-suited for pixel-based graphics retro game visuals Optimized for resource-constrained embedded systems See accompanying images and example code Introduction I came across the problem of upscaling retro game image/frame data in real-time. While integer upscaling is trivial, fractional upscaling becomes challenging when working with limited resources (e.g., slow floating-point arithmetic). Additionally, the algorithms commonly used for upscaling photos are not well-suited for low-resolution game content or pixel art.</description>
            <content type="html"><![CDATA[<h2 id="tldr">TL;DR</h2>
<ul>
<li>Fixed fractional factor upscaling method</li>
<li>Targeted at real-time frame upscaling</li>
<li>Combines nearest-neighbor with local interpolation</li>
<li>Well-suited for pixel-based graphics retro game visuals</li>
<li>Optimized for resource-constrained embedded systems</li>
<li>See accompanying images and example code</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I came across the problem of upscaling retro game image/frame data in real-time. While integer upscaling is trivial, fractional upscaling becomes challenging when working with limited resources (e.g., slow floating-point arithmetic). Additionally, the algorithms commonly used for upscaling photos are not well-suited for low-resolution game content or pixel art.</p>
<p>The following image demonstrates what happens when you upscale a 160×144 image by a factor of 1.5 using standard methods. The nearest neighbour approach preserves the overall appearance but introduces visual artifacts. In contrast, bilinear interpolation smooths the image, resulting in washed-out colors and a blurry look.</p>
<p><img alt="Upscaling algorithm comparison" src="/posts/250615_non-integer_upscaling/images/overview_legend.png"></p>
<p>There is also a problem when using nearest-neighbor scaling in applications that feature thin lines with high contrast against the background. When these lines move between frames, a flickering effect can occur. I recorded a video to demonstrate this on a real TFT display. The footage was captured at 120 fps and slowed down to 0.25× the original speed. Have a look, for example, at the moving platforms and the background trees.</p>
<video preload="metadata" controls width="100%">
    <source
      src="/posts/250615_non-integer_upscaling/video/demo.mp4"
      type="video/mp4"
    >
    Your browser does not support the video element.
  </video>
<p>What I came up with is somewhat of a hybrid approach. First, the scaled original image is overlaid on the target pixel grid. If a pixel from the original image fully covers a target pixel, we simply use that color. If two or four source pixels intersect within a target pixel, we compute the average of their colors.</p>
<p><img alt="Example for 1.5x upscaling" src="/posts/250615_non-integer_upscaling/images/grid_example_1_5.png"></p>
<p>I’m not sure if this is a known method - so far, I haven’t found any information or a name for it. A fitting description might be something like “nearest neighbour with local bilinear interpolation,” “nearest neighbour with edge averaging,” or “nearest neighbour with edge blurring.” For simplicity, I’ll refer to it as “Edge Smoothing”.</p>
<p>In the following, I will outline an efficient implementation of the proposed method, tailored for resource-constrained systems.</p>
<h2 id="idea-and-implementation">Idea and Implementation</h2>
<p>While experimenting with pixel data, I noticed some interesting properties when using scaling factors expressed as fractions
<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">
<mfrac>
<mi>a</mi>
<mi>b</mi>
</mfrac>
</math>, especially when
<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">
<mi>b</mi>
<mo>=</mo>
<msup>
<mn>2</mn>
<mi>n</mi>
</msup>
</math>, with
<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">
<mi>a</mi>
<mo>,</mo>
<mi>n</mi>
<mo>∈</mo>
<mi>ℕ</mi>
</math>.</p>
<p><math><mfrac>
<mi>a</mi>
<msup>
<mn>2</mn>
<mi>n</mi>
</msup>
</mfrac>
</math> (e.g. factors like 1.5, 1.375, 1.125, 2.75)</p>
<ul>
<li>
<p>The pixel boundaries will meet at <math display="inline"><mi>a</mi></math> respectively <math display="inline"><mi>b</mi></math> when laying the scaled origin pixel grid over the new one. This results in a repeating pattern of <math><mi>a</mi><mo>x</mo><mi>a</mi></math> pixels.</p>
<ul>
<li>This observation is somehow obvious but important for the algorithm</li>
<li>A repeating pattern can allow some pre-calculation</li>
<li>A repeating pattern can save a lot of memory when doing precalculations</li>
</ul>
</li>
<li>
<p>The area covered by a scaled source pixel on a new pixel will always be a fraction in the form of <math display="inline"><mfrac><mn>1</mn><msup><mn>2</mn><mi>x</mi></msup></mfrac></math> when <math><mi>b</mi></math> has been choosen as <math><mi>b</mi><mo>=</mo><msup><mn>2</mn><mi>n</mi></msup></math></p>
<ul>
<li>This allows efficent division by using shifing</li>
<li>and can be used to efficently calculate an average color of overlapping pixels</li>
</ul>
</li>
</ul>
<p>I think a visual representation will be helpful:</p>
<p><img alt="Upscaling 1.5x" src="/posts/250615_non-integer_upscaling/images/upscaling_1_5.png"></p>
<p>The grey pixels represents the source pixels scaled with a factor of 1.5 or</p>
<math display="inline">
<mfrac>
  <mn>3</mn>
  <msup>
    <mn>2</mn>
    <mn>1</mn>
  </msup>
</mfrac>
</math> (a=3, n=1). 
<p>The blue pixels represent the unscaled target pixels. The yellow square marks the repeating pattern. This works the same for other factors but get&rsquo;s a bit messy to show as an example:</p>
<p><img alt="Upscaling 2.75x" src="/posts/250615_non-integer_upscaling/images/upscaling_2_75.png"></p>
<p>With the pattern we are able to precalculate which pixels of the source are relevant for a pixel on the target by just using an offset during runtime. Every <math><mi>a</mi></math> rows respecively cols we are applying the same pattern with a different offset to the source pixels.</p>
<h2 id="example-1">Example 1</h2>
<p>Let’s say we want to upscale a given source graphic from 160×144 px to 240×216 px.</p>
<ul>
<li>The scaling factor is 1.5, or <math><mfrac><mn>3</mn><msup><mn>2</mn><mn>1</mn></msup></mfrac><mi>(</mi><mi>a</mi><mo>=</mo><mn>3</mn><mo>,</mo><mi>n</mi><mo>=</mo><mn>1</mn><mo>)</mo></math> respectively <math><mi>a</mi><mo>=</mo><mn>3</mn><mo>, </mo><mi>b</mi><mo>=</mo><mn>2</mn></math>.</li>
<li>We have a <math><mn>3</mn><mo>x</mo><mn>3</mn></math> repeating pattern.</li>
<li>As most image data comes in a linear buffer, we will work line by line.
<ul>
<li>We are using zero-based indices.</li>
<li>The upper-left pixel is stored at position 0 in a one-dimensional array.</li>
<li>Line <math><mi>y</mi></math> starts at offset <math><mi>width</mi><mo>*</mo><mi>y</mi></math></li>
<li>This concept applies to both the source and the destination.</li>
</ul>
</li>
<li>The pattern is hardcoded to allow for optimization and to avoid unnecessary calculations.</li>
</ul>
<p>Setting a pixel in the target array is done using macros (defines) which assign pixel values based on one, two, or four different pixels relative to the current source pixel offset. In this case, we only use equal distributions of the pixels: 100%, 50%/50%, and 25%/25%/25%/25%.</p>
<p>We apply the first row of our pattern to the first three pixels of the target data. Then we add an offset of <math><mi>b</mi></math> to the source pixel <math><mi>x</mi></math>-offset and repeat the process until the first line of the target data is complete.</p>
<p>After resetting the <math><mi>x</mi></math>-offset, we apply the second row of the pattern to generate our destination data, and then repeat with the third row. By adding an offset of <math><mi>b</mi></math> to the source pixel <math><mi>y</mi></math>-offset, we shift the pattern to match the next three lines.</p>
<p>After repeating this for every row in the target array, we end up with our upscaled frame.</p>
<p>The advantage of carefully choosing the denominator as <math><msup><mn>2</mn><mi>n</mi></msup></math> becomes evident in the <em>mix_2</em> and <em>mix_4</em> functions: we don’t need any floating-point arithmetic.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#75715e">#define SRC_PX(x,y) psSrc[y*uiSrcWidth+x]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define SRC_OFF_X(x) (uiSrcOffsetX + x)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define SRC_OFF_Y(y) (uiSrcOffsetY + y)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define DST_SET_1_100(sx, sy) psDst[uiDstPos++] = SRC_PX(SRC_OFF_X(sx), SRC_OFF_Y(sy))
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define DST_SET_2_50_50(sx0, sy0, sx1, sy1) mix_2(&amp;psDst[uiDstPos++], &amp;SRC_PX(SRC_OFF_X(sx0),SRC_OFF_Y(sy0)), &amp;SRC_PX(SRC_OFF_X(sx1),SRC_OFF_Y(sy1)))
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define DST_SET_4_25_25_25_25(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3) mix_4(&amp;psDst[uiDstPos++], &amp;SRC_PX(SRC_OFF_X(sx0),SRC_OFF_Y(sy0)), &amp;SRC_PX(SRC_OFF_X(sx1),SRC_OFF_Y(sy1)), &amp;SRC_PX(SRC_OFF_X(sx2),SRC_OFF_Y(sy2)), &amp;SRC_PX(SRC_OFF_X(sx3),SRC_OFF_Y(sy3)))
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">mix_2</span>(<span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwDst, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc0, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc1)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">=</span> (((<span style="color:#f92672">*</span>puwSrc0) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc1) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">|=</span> (((((<span style="color:#f92672">*</span>puwSrc0)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>) <span style="color:#f92672">+</span> (((<span style="color:#f92672">*</span>puwSrc1)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&lt;&lt;</span><span style="color:#ae81ff">5</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">|=</span> ((((<span style="color:#f92672">*</span>puwSrc0)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc1)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&lt;&lt;</span><span style="color:#ae81ff">11</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">mix_4</span>(<span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwDst, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc0, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc1, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc2, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwSrc3)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">=</span> (((<span style="color:#f92672">*</span>puwSrc0) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc1) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc2) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc3) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x1F</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">|=</span> (((((<span style="color:#f92672">*</span>puwSrc0)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>) <span style="color:#f92672">+</span> (((<span style="color:#f92672">*</span>puwSrc1)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>) <span style="color:#f92672">+</span> (((<span style="color:#f92672">*</span>puwSrc2)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>) <span style="color:#f92672">+</span> (((<span style="color:#f92672">*</span>puwSrc3)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">5</span>) <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x3F</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>)<span style="color:#f92672">&lt;&lt;</span><span style="color:#ae81ff">5</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">*</span>puwDst <span style="color:#f92672">|=</span> ((((<span style="color:#f92672">*</span>puwSrc0)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc1)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc2)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>) <span style="color:#f92672">+</span> ((<span style="color:#f92672">*</span>puwSrc3)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">11</span>))<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>)<span style="color:#f92672">&lt;&lt;</span><span style="color:#ae81ff">11</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">scale_1_5_rgb565</span>(<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> psSrc, <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> psDst, uint uiSrcWidth, uint uiSrcHeight)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// We expect the destination height and width to be a multiple of 3
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">// so we have to assure the source width and height is a multiple of 2
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">// otherwise we have to add special handling for the last row/column
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#a6e22e">assert</span>(uiSrcWidth<span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">assert</span>(uiSrcHeight<span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  uint uiDstWidth <span style="color:#f92672">=</span> uiSrcWidth <span style="color:#f92672">+</span> (uiSrcWidth<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>  uint uiDstHeight <span style="color:#f92672">=</span> uiSrcHeight <span style="color:#f92672">+</span> (uiSrcHeight<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  uint uiSrcOffsetX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  uint uiSrcOffsetY <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  uint uiDstPos <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  uint uiWidthDiv <span style="color:#f92672">=</span> uiDstWidth <span style="color:#f92672">/</span> <span style="color:#ae81ff">3</span>; <span style="color:#75715e">// a
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (uint uiY <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiY <span style="color:#f92672">&lt;</span> uiDstHeight; uiY<span style="color:#f92672">+=</span><span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Pattern row 0
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    uiSrcOffsetX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> uiWidthDiv; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_1_100</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span> ); 
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_2_50_50</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span> , <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">0</span> ); 
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_1_100</span>( <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">0</span> );
</span></span><span style="display:flex;"><span>      uiSrcOffsetX <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span>; <span style="color:#75715e">// 2^n 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Pattern row 1
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    uiSrcOffsetX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> uiWidthDiv; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_2_50_50</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span> , <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_4_25_25_25_25</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span> , <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span> , <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_2_50_50</span>( <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">0</span> , <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      uiSrcOffsetX <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span>; <span style="color:#75715e">// 2^n 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Pattern row 2
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    uiSrcOffsetX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> uiWidthDiv; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_1_100</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_2_50_50</span>( <span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span> , <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">DST_SET_1_100</span>( <span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span> );
</span></span><span style="display:flex;"><span>      uiSrcOffsetX <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span>; <span style="color:#75715e">// 2^n 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    uiSrcOffsetY <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span>; <span style="color:#75715e">// 2^n
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="example-2">Example 2</h2>
<p>This can be seen more or less as a real-world example. While the first example was used to generate the demo images, this code was used for the demo videos. It includes additional optimizations and is designed to upscale image data in real time (~60 fps), captured from a Game Boy Advance (240×160) running a Game Boy Classic game (160×144). The scaling factor is again 1.5. The code takes into account the offset of the smaller image within the 240×160 display area. Since the TFT driver in this case requests the image line by line, only one line of the image is generated per call.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">tft_line_callback_1_5</span>(uint uiLineCounter, <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> puwLineBuffer)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> auwFrameBuffer <span style="color:#f92672">=</span> <span style="color:#a6e22e">agb_capture_get_framebuffer</span>();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">uint16_t</span><span style="color:#f92672">*</span> psSrc;
</span></span><span style="display:flex;"><span>  uint uiDstPos <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> uint uiSrcOffsetY <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (uiLineCounter <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">216</span>)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    psSrc <span style="color:#f92672">=</span> <span style="color:#f92672">&amp;</span>auwFrameBuffer[<span style="color:#ae81ff">240</span> <span style="color:#f92672">*</span> (<span style="color:#ae81ff">8</span> <span style="color:#f92672">+</span> uiSrcOffsetY) <span style="color:#f92672">+</span> <span style="color:#ae81ff">40</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">switch</span> (uiLineCounter <span style="color:#f92672">%</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">240</span><span style="color:#f92672">/</span><span style="color:#ae81ff">3</span>; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumR0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumG0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumB0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span> ];
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> ((ulSumR0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">|</span> ((ulSumG0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">|</span> (ulSumB0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>];
</span></span><span style="display:flex;"><span>          psSrc <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:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">240</span><span style="color:#f92672">/</span><span style="color:#ae81ff">3</span>; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumR0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumG0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumB0001 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumR1011 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumG1011 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumB1011 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">0</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> ((ulSumR0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">|</span> ((ulSumG0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">|</span> (ulSumB0001<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>              (((ulSumR0001 <span style="color:#f92672">+</span> ulSumR1011)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0xF800</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">|</span> (((ulSumG0001 <span style="color:#f92672">+</span> ulSumG1011)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0x07E0</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">|</span> ((ulSumB0001 <span style="color:#f92672">+</span> ulSumB1011)<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> ((ulSumR1011<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">|</span> ((ulSumG1011<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">|</span> (ulSumB1011<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>          psSrc <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:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (uint uiX <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; uiX <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">240</span><span style="color:#f92672">/</span><span style="color:#ae81ff">3</span>; uiX<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumR0111 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0xF800</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumG0111 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x07E0</span>));
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">uint32_t</span> ulSumB0111 <span style="color:#f92672">=</span> ((<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>) <span style="color:#f92672">+</span> (<span style="color:#66d9ef">uint32_t</span>)(psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>] <span style="color:#f92672">&amp;</span> <span style="color:#ae81ff">0x001F</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> psSrc[<span style="color:#ae81ff">0</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>];
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> ((ulSumR0111<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0xF800</span>) <span style="color:#f92672">|</span> ((ulSumG0111<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">0x07E0</span>) <span style="color:#f92672">|</span> (ulSumB0111<span style="color:#f92672">&gt;&gt;</span><span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>          puwLineBuffer[uiDstPos<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> psSrc[<span style="color:#ae81ff">1</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">*</span><span style="color:#ae81ff">240</span>];
</span></span><span style="display:flex;"><span>          psSrc <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>        uiSrcOffsetY <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memset</span>(puwLineBuffer, <span style="color:#ae81ff">0x00</span>, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">uint16_t</span>)<span style="color:#f92672">*</span><span style="color:#ae81ff">480</span>);
</span></span><span style="display:flex;"><span>    uiSrcOffsetY <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content>
        </item>
        
        <item>
            <title>Custom Palettes and Logo for the Open DMG Display</title>
            <link>https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/</link>
            <pubDate>Sat, 26 Apr 2025 00:00:00 +0000</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/</guid>
            <description>TL;DR CSV user palettes: NAME,C1,C2,C3,C4 (see my_user_palettes.csv) CSV auto palettes: NAME,C1,C2,C3,C4,GAME_ID (see my_auto_palettes.csv) Logo image: Best 160x144 PNG (see my_logo.png) Upload like firmware via USB bootloader Link to the scripts Example calls odd_custom_palette.py my_user_palettes.csv my_user_palettes.bin odd_custom_palette.py -id my_auto_palettes.csv my_auto_palettes.bin odd_custom_logo_generator.py my_logo.png my_logo.bin uf2conv.py -c -b 0x10190000 -f RP2XXX_DATA -o my_auto_palettes.uf2 my_auto_palettes.bin uf2conv.py -c -b 0x101B0000 -f RP2XXX_DATA -o my_user_palettes.uf2 my_user_palettes.bin uf2conv.py -c -b 0x101B8000 -f RP2XXX_DATA -o my_logo.uf2 my_logo.bin Introduction The Open DMG display (hereafter referred to as ODD) comes with basic palettes and a custom logo, which are both directly compiled into the firmware.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/250426_open_dmg_display_customization/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>CSV user palettes: NAME,C1,C2,C3,C4 (see my_user_palettes.csv)</li>
<li>CSV auto palettes: NAME,C1,C2,C3,C4,GAME_ID (see my_auto_palettes.csv)</li>
<li>Logo image: Best 160x144 PNG (see my_logo.png)</li>
<li>Upload like firmware via USB bootloader</li>
<li><a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/src/branch/master/scripts">Link to the scripts</a></li>
<li>Example calls
<ul>
<li><code>odd_custom_palette.py my_user_palettes.csv my_user_palettes.bin</code></li>
<li><code>odd_custom_palette.py -id my_auto_palettes.csv my_auto_palettes.bin</code></li>
<li><code>odd_custom_logo_generator.py my_logo.png my_logo.bin</code></li>
<li><code>uf2conv.py -c -b 0x10190000 -f RP2XXX_DATA -o my_auto_palettes.uf2 my_auto_palettes.bin</code></li>
<li><code>uf2conv.py -c -b 0x101B0000 -f RP2XXX_DATA -o my_user_palettes.uf2 my_user_palettes.bin</code></li>
<li><code>uf2conv.py -c -b 0x101B8000 -f RP2XXX_DATA -o my_logo.uf2 my_logo.bin</code></li>
</ul>
</li>
</ul>
<h2 id="introduction----ok---">Introduction <!-- OK --></h2>
<p>The Open DMG display (hereafter referred to as ODD) comes with basic palettes and a custom logo, which are both directly compiled into the firmware. One way to modify these is by changing the data within the code and recompiling it. However, not everyone is comfortable with this approach. Therefore, the firmware also supports the use of external palettes and logos. To make it easier to create the required external data, I wrote a few Python scripts, which I will introduce in this blog post.</p>
<h2 id="palettes----ok---">Palettes <!-- OK --></h2>
<p>The ODD differentiates between two types of palettes, which are also stored separately. There are user palettes, which are intended to be manually chosen by the user during operation. Additionally, there are automatic palettes, which are automatically chosen when a specific game is detected.</p>
<h3 id="user-palettes----ok---">User palettes <!-- OK --></h3>
<p>The user palettes are simple datasets that consist of a name (using only ASCII characters) and four 24-bit colors. Using the &ldquo;odd_custom_palette.py&rdquo; script, you can generate the binary data that the ODD firmware can read. You can choose between two methods to create a table of personally chosen palettes. The straightforward approach is to create a CSV file and edit it with software like LibreOffice Calc.</p>
<p><img alt="Editing the user palettes CSV" src="/posts/250426_open_dmg_display_customization/images/calc_userdata.png"></p>
<p>The second method is to use GBP files. The script will use the filename as the name of the palette. You can obtain GBP files, for example, from emulators. The script is also capable of processing entire directories. You can store multiple GBP files in one directory and let the script combine them. Additionally, you can generate CSV files from a folder containing GBP files. Let’s clarify this with a few examples:</p>
<p>Creating binary data from a CSV file:<br>
<code>odd_custom_palette.py my_user_palettes.csv my_user_palettes.bin</code></p>
<p>Creating binary data from a folder of GBP and/or CSV files:<br>
<code>odd_custom_palette.py ./my_palettes/ my_user_palettes.bin</code></p>
<p>Creating a CSV table from a folder of GBP and/or CSV files:<br>
<code>odd_custom_palette.py ./my_palettes/ my_user_palettes.csv</code></p>
<h3 id="auto-palettes">Auto palettes</h3>
<p>Auto palettes contain the same data as user palettes but also have an ID field. If the game ID matches the ID field of one of the auto palettes, the ODD firmware will automatically select this palette. The generation process is largely the same, but you must use CSV files only, as GBP files cannot store the ID.</p>
<p><img alt="Editing the auto palettes CSV" src="/posts/250426_open_dmg_display_customization/images/calc_autodata.png"></p>
<p>The same script is used to generate the binary data, but with the <em>-id</em> parameter.</p>
<p>Creating binary data from a CSV file<br>
<code>odd_custom_palette.py -id my_auto_palettes.csv my_auto_palettes.bin</code></p>
<h2 id="custom-logo">Custom logo</h2>
<p>Creating a custom logo is simple. You can design it using your favorite image editor. It&rsquo;s best to start with a 160x144 canvas to get the aspect ratio correct. Save the image as a PNG file. The finished image can then be converted into a format readable by the ODD firmware using the <em>odd_custom_logo_generator.py</em> script.</p>
<p>Converting image to grayscale binary for ODD firmware:<br>
<code>odd_custom_logo_generator.py my_logo.png my_logo.bin</code></p>
<h2 id="writing-the-data-to-the-odd">Writing the data to the ODD</h2>
<p>After creating the different binaries, you need to upload them to the correct positions in the ODD&rsquo;s flash memory. The easiest way to achieve this is by using the same mechanism that is used to upload firmware to the device. To do so, we will need UF2 files, which can be processed via the USB bootloader. I have added the uf2conv.py script by Microsoft to the script folder. It can be used as follows:</p>
<p>Conversion of the auto palette data:<br>
<code>uf2conv.py -c -b 0x10190000 -f RP2XXX_DATA -o my_auto_palettes.uf2 my_auto_palettes.bin</code></p>
<p>Conversion of the user palette data:<br>
<code>uf2conv.py -c -b 0x101B0000 -f RP2XXX_DATA -o my_user_palettes.uf2 my_user_palettes.bin</code></p>
<p>Conversion of the custom logo data:<br>
<code>uf2conv.py -c -b 0x101B8000 -f RP2XXX_DATA -o my_logo.uf2 my_logo.bin</code></p>
<p>You can boot the ODD into the UF2 bootloader by pressing the bootloader button during power-on while the device is connected to a PC. Copy the UF2 files to the RP2350 drive. The firmware should automatically detect the new custom data.</p>
<h2 id="non-volatile-data-area">Non-volatile data area</h2>
<p>The ODD uses a flash memory area to store non-volatile user data. In order to support the upcoming RP2354B chips with integrated 2MB memory the valid total flash memory is limited to 2MB. The first 1.5MB is reserved for the program data. This is followed by 512kB of user data. With respect to the flash and program data offset (0x10180000) The non-volatile memory is organized as follows:</p>
<table>
<thead>
<tr>
<th>address offset</th>
<th>address absolute</th>
<th>description</th>
<th>size</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x00000000</td>
<td>0x10180000</td>
<td>configuration values</td>
<td>64KiB</td>
</tr>
<tr>
<td>0x00010000</td>
<td>0x10190000</td>
<td>automatic palettes</td>
<td>128KiB</td>
</tr>
<tr>
<td>0x00030000</td>
<td>0x101B0000</td>
<td>user palettes</td>
<td>32KiB</td>
</tr>
<tr>
<td>0x00038000</td>
<td>0x101B8000</td>
<td>custom logo</td>
<td>8KiB</td>
</tr>
</tbody>
</table>
<h2 id="pre-generated-palettes-from-thewolfbunny64">Pre-generated palettes from TheWolfBunny64</h2>
<p>When it comes to custom palettes for the Game Boy you will sooner or later find the name <em>TheWolfBunny64</em>. It seems like he started something with his passion for the 4-color limeted handheld. Many people who are publishing their own takes on custom palettes mention him on the demo image or in their comments as a source of inspiration. He recently posted on bsky:</p>
<blockquote>
<p><em>&ldquo;One reason why I made #GameBoy palettes since 2019: to carry on the Game Boy&rsquo;s legacy. Truth told, it gets repetive to play games in the same old four shades of green. Hence why I made holiday palettes like these, to make things a bit more festive. And you can find them on itch and Analogue Pocket.&rdquo;</em></p>
<p>(<a href="https://bsky.app/profile/thewolfbunny64.bsky.social/post/3lkvt2ska2s24">https://bsky.app/profile/thewolfbunny64.bsky.social/post/3lkvt2ska2s24</a>)</p>
</blockquote>
<p>And I really wanted to add &ldquo;&hellip; and on the ODD&rdquo; to his last sentence. I had a short chat with him asking for permission for the use of his material and also started following him on bsky (@thewolfbunny64.bsky.social). He really seems passionate about what he is doing and it looks like he invests a lot of time into it. Maybe you should consider thanking him for his hard work.</p>
<p>Thanks Patrick!</p>
<p>In the following you will find the different palette packs downloadable as directly flashable UF2 files. Enjoy!</p>
<h3 id="palette-packs">Palette Packs</h3>
<h4 id="american-pop-culture-pack">American Pop Culture Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/American_Pop_Culture_Pack.uf2" title="American_Pop_Culture_Pack.uf2">American_Pop_Culture_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Absorbent_and_Yellow_hubd75971c227449f8376a93b8eb72359b_6394_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Absorbent_and_Yellow_hubd75971c227449f8376a93b8eb72359b_6394_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/BMO_Ver._hu6c8bf1827a99f3cb2775c9faf5696e3a_6440_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/BMO_Ver._hu6c8bf1827a99f3cb2775c9faf5696e3a_6440_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Barbie_Pink_hu08437861a5408a7bfecd11e87f715540_6163_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Barbie_Pink_hu08437861a5408a7bfecd11e87f715540_6163_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bedrock_Caveman_Vision_hu7b93260b03a95e6866385441fa0901cf_6621_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bedrock_Caveman_Vision_hu7b93260b03a95e6866385441fa0901cf_6621_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bikini_Bottom_Ver._hu5df12a951711de817419c17341716511_6779_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bikini_Bottom_Ver._hu5df12a951711de817419c17341716511_6779_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Blossom_Pink_hu8eddc5437dc8fa24c3c4c80ca49f131f_6268_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Blossom_Pink_hu8eddc5437dc8fa24c3c4c80ca49f131f_6268_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bubbles_Blue_hu155f69e590f328162844d0214e79882b_6654_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Bubbles_Blue_hu155f69e590f328162844d0214e79882b_6654_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Buttercup_Green_hubcdfbae6d94a6aca241c9ef8403f0662_6668_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Buttercup_Green_hubcdfbae6d94a6aca241c9ef8403f0662_6668_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Danny_Phantom_Silver_hu2a542e0d3bbf621abfd8143222ce4043_6635_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Danny_Phantom_Silver_hu2a542e0d3bbf621abfd8143222ce4043_6635_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Fairly_OddPalette_hu2e5966f74f7b5bd9a917c9301ee0520a_6492_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Fairly_OddPalette_hu2e5966f74f7b5bd9a917c9301ee0520a_6492_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Garfield_Vision_huaee00b0cd0203c69dd1a04a6fd15536b_6772_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Garfield_Vision_huaee00b0cd0203c69dd1a04a6fd15536b_6772_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Hogwarts_Goldius_hu49353c55d5b1f1b04df516660e914514_6438_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Hogwarts_Goldius_hu49353c55d5b1f1b04df516660e914514_6438_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Invincible_Yellow_and_Blue_hub36394662f032db8f6fe7242997d9a7f_6676_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Invincible_Yellow_and_Blue_hub36394662f032db8f6fe7242997d9a7f_6676_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Nick_Orange_hu652683da4592124c9bf14ee00aa6abfa_6013_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Nick_Orange_hu652683da4592124c9bf14ee00aa6abfa_6013_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Ninja_Turtle_Green_hued62c98924e106f1a61ba5551f4f634e_6472_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Ninja_Turtle_Green_hued62c98924e106f1a61ba5551f4f634e_6472_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Optimus_Prime_Palette_hu9c41a3910b4e2f7d254d123bb0fc77fd_6314_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Optimus_Prime_Palette_hu9c41a3910b4e2f7d254d123bb0fc77fd_6314_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Patrick_Star_Pink_huc5fff6b03984064290f1b790fb64fb0d_6631_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Patrick_Star_Pink_huc5fff6b03984064290f1b790fb64fb0d_6631_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Retro_Bogeda_huf98bb305b9d1751db769bc5a0b8ca0af_5995_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Retro_Bogeda_huf98bb305b9d1751db769bc5a0b8ca0af_5995_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Rocket_Portable_Power_hu22f197dc8bcca422e6678c9998bf4167_6552_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Rocket_Portable_Power_hu22f197dc8bcca422e6678c9998bf4167_6552_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Rugrats_Playtime_Palette_hu44766837e3dd64fb1aef5ad01c10b064_6624_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Rugrats_Playtime_Palette_hu44766837e3dd64fb1aef5ad01c10b064_6624_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Sailor_Spinach_Green_hu62df3047b38fdef80c544be8bf21a709_6536_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Sailor_Spinach_Green_hu62df3047b38fdef80c544be8bf21a709_6536_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Scooby-Doo_Mystery_Ver._hud465d20ba1ea1f574871885e63a39339_6821_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Scooby-Doo_Mystery_Ver._hud465d20ba1ea1f574871885e63a39339_6821_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Smurfy_Blue_hud1d8455881d480a973056642d7e90af5_6221_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Smurfy_Blue_hud1d8455881d480a973056642d7e90af5_6221_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/SpongeBob_Yellow_hu6b658bb5d6612880944ab409f5878835_6406_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/SpongeBob_Yellow_hu6b658bb5d6612880944ab409f5878835_6406_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Squidward_Sea_Foam_Green_hu0323b1ee0cbf3a50c8bb4a3065b843de_6649_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Squidward_Sea_Foam_Green_hu0323b1ee0cbf3a50c8bb4a3065b843de_6649_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Swampy_Ogre_Green_hu14cc7776bc46db6c6ea1d50a888739ce_6498_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Swampy_Ogre_Green_hu14cc7776bc46db6c6ea1d50a888739ce_6498_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Timmy_Turner_Pink_hu6a93d01f4453cafb2aa8fcb82240463b_6647_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Timmy_Turner_Pink_hu6a93d01f4453cafb2aa8fcb82240463b_6647_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Universal_Studios_Blue_hu37bf6bd22c49df025f659b4e9b28647b_6594_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/American_Pop_Culture_Pack/Universal_Studios_Blue_hu37bf6bd22c49df025f659b4e9b28647b_6594_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="anime-and-manga-pack">Anime and Manga Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Anime_and_Manga_Pack.uf2" title="Anime_and_Manga_Pack.uf2">Anime_and_Manga_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/ANIMAX_BLUE_hub912ae52202d0ab47d6c33bfde4b0c51_6263_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/ANIMAX_BLUE_hub912ae52202d0ab47d6c33bfde4b0c51_6263_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/All_Might_Hero_Palette_hua5e53798019869a88a4115bd984aa8d5_6646_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/All_Might_Hero_Palette_hua5e53798019869a88a4115bd984aa8d5_6646_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Digivice_Ver._hu57f8d184377e014f0a000587e7c3e0ce_6435_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Digivice_Ver._hu57f8d184377e014f0a000587e7c3e0ce_6435_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Expo_Red_huf06e3f879e6b8cc50c715dbd2ba878d7_6307_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Expo_Red_huf06e3f879e6b8cc50c715dbd2ba878d7_6307_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Expo_Ver._hu87996b76fd29e3583ac477308cac2def_6499_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Anime_Expo_Ver._hu87996b76fd29e3583ac477308cac2def_6499_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Berserk_Blood_hu93986f3fe7676df99a7057b50b5388ec_6103_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Berserk_Blood_hu93986f3fe7676df99a7057b50b5388ec_6103_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Blue_Stripes_Ver._hubfd7210852ab12923eb3daf652d8558f_6410_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Blue_Stripes_Ver._hubfd7210852ab12923eb3daf652d8558f_6410_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Cardcaptor_Pink_hu12d4f30201fc95180f390fe0507ddfac_6693_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Cardcaptor_Pink_hu12d4f30201fc95180f390fe0507ddfac_6693_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Colorful_Horizons_hu844f590da186c4d49389353fb69fe02b_6463_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Colorful_Horizons_hu844f590da186c4d49389353fb69fe02b_6463_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Alpha_Emerald_hud657be5a43de7a33174c144770b9dfd0_6838_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Alpha_Emerald_hud657be5a43de7a33174c144770b9dfd0_6838_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Epsilon_Palette_hu6a4cbf14a2b438372e4ddb30437a0a00_7044_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Epsilon_Palette_hu6a4cbf14a2b438372e4ddb30437a0a00_7044_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Gamma_Palette_hu82633e2d2a5ac08af9813baaad28d183_6514_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Deku_Gamma_Palette_hu82633e2d2a5ac08af9813baaad28d183_6514_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Demon_Slayer_Gold_hufeb1bb4e30faef46d39b8b57934ee9cb_6809_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Demon_Slayer_Gold_hufeb1bb4e30faef46d39b8b57934ee9cb_6809_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Doraemon_Tricolor_hu1f20b288d75156b07456c40de2c57314_6290_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Doraemon_Tricolor_hu1f20b288d75156b07456c40de2c57314_6290_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Dragon_Ball_Orange_hub9944f709cbb97e904e864f5b536306c_6678_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Dragon_Ball_Orange_hub9944f709cbb97e904e864f5b536306c_6678_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Dynamight_Hero_Palette_hue61648b8ffc4ae12e20bf419996845c8_6831_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Dynamight_Hero_Palette_hue61648b8ffc4ae12e20bf419996845c8_6831_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/EVA-01_hubd79b310460892736de5f9adc2e2552c_6129_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/EVA-01_hubd79b310460892736de5f9adc2e2552c_6129_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Eden_Academy_Uniform_hud899b202ef6d5746850c1db5d4edd3ae_6579_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Eden_Academy_Uniform_hud899b202ef6d5746850c1db5d4edd3ae_6579_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Forger_Pretense_Palette_hu7eae4272444ca49cfd5d4baa9a05c7b2_6223_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Forger_Pretense_Palette_hu7eae4272444ca49cfd5d4baa9a05c7b2_6223_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/GOOD_SMILE_VISION_hu3c96a7ffe5196514bbb955a548d4c4dc_6382_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/GOOD_SMILE_VISION_hu3c96a7ffe5196514bbb955a548d4c4dc_6382_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Gear_5_Fever_hu8f3a1aeeec45287d62e0f5d302cf241c_6332_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Gear_5_Fever_hu8f3a1aeeec45287d62e0f5d302cf241c_6332_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Goku_GT_Gi_hu36f2355f3ee8dd67c39e5708abbb4bf7_6355_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Goku_GT_Gi_hu36f2355f3ee8dd67c39e5708abbb4bf7_6355_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Goku_Gi_huc34463040742e20145e4e57c6992e224_6379_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Goku_Gi_huc34463040742e20145e4e57c6992e224_6379_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Grand_Ivory_hu993043555fa29361f6e2ca65cef02aba_6325_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Grand_Ivory_hu993043555fa29361f6e2ca65cef02aba_6325_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Grand_Zeno_Coat_huaa2d78b657924e0985b1aba4c2f5a4db_6724_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Grand_Zeno_Coat_huaa2d78b657924e0985b1aba4c2f5a4db_6724_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Hokage_Orange_hu93efcc5b053e8a0a3cdc0bd243448c59_6532_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Hokage_Orange_hu93efcc5b053e8a0a3cdc0bd243448c59_6532_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/KonoSuba_Sherbet_hu18472797fd7d3ca82cb37a8f7b183ce6_6626_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/KonoSuba_Sherbet_hu18472797fd7d3ca82cb37a8f7b183ce6_6626_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Kuwabara_Blue_hub9b952894a57280d40c327ff13471b7a_6078_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Kuwabara_Blue_hub9b952894a57280d40c327ff13471b7a_6078_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Legendary_Super_Saiyan_hu3c76b48d13a0d4c62d4298333117819b_7074_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Legendary_Super_Saiyan_hu3c76b48d13a0d4c62d4298333117819b_7074_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/LisAni_Orange!_hue8befca027f593ed0c0a0beceff9c0f6_6146_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/LisAni_Orange!_hue8befca027f593ed0c0a0beceff9c0f6_6146_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Orange_Namekian_hu113ebc47689cb02ef1b09bcb16d572c4_6836_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Orange_Namekian_hu113ebc47689cb02ef1b09bcb16d572c4_6836_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Perfect_Majin_Emperor_hu6811d1ae031eeab3019be37ac4a8b48e_7100_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Perfect_Majin_Emperor_hu6811d1ae031eeab3019be37ac4a8b48e_7100_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Perfected_Ultra_Instinct_hue9bcbc243e3f78f3dc370d128ac8e93b_6669_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Perfected_Ultra_Instinct_hue9bcbc243e3f78f3dc370d128ac8e93b_6669_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Precure_Marble_Raspberry_hu8f4194f0f1e2753ec0e17e0c282ed280_6594_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Precure_Marble_Raspberry_hu8f4194f0f1e2753ec0e17e0c282ed280_6594_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Pretty_Guardian_Gold_hu0d6f0d176cbb72cf1217d3c5638bb75e_6673_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Pretty_Guardian_Gold_hu0d6f0d176cbb72cf1217d3c5638bb75e_6673_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Saiyan_Beast_Silver_hu881a7f5fed4d54b22f35e4509159ff7d_6537_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Saiyan_Beast_Silver_hu881a7f5fed4d54b22f35e4509159ff7d_6537_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Shenron_Green_huf7490dd12faa73b7860a8e5a78ae2cac_6258_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Shenron_Green_huf7490dd12faa73b7860a8e5a78ae2cac_6258_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Straw_Hat_Red_hufc2fd986f79be515a4eba8988f706d28_6255_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Straw_Hat_Red_hufc2fd986f79be515a4eba8988f706d28_6255_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_hu65b0c9a447a3efbab8400c4703c8eaae_6907_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_hu65b0c9a447a3efbab8400c4703c8eaae_6907_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_3_hu7c8c594dec98bf2c83025a819382c9c4_6390_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_3_hu7c8c594dec98bf2c83025a819382c9c4_6390_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Blue_hu8deff1b0262fc94d249f263c8a7b75f5_6563_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Blue_hu8deff1b0262fc94d249f263c8a7b75f5_6563_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Blue_Evolved_hue01c835661c86db45d2a13df8b6255f5_6833_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Blue_Evolved_hue01c835661c86db45d2a13df8b6255f5_6833_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_God_hu1b9ae68642829d15e1c91f293bec9fec_6254_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_God_hu1b9ae68642829d15e1c91f293bec9fec_6254_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Rose_hu050d2913cbe864cf89af4c091a6b80f5_6775_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Super_Saiyan_Rose_hu050d2913cbe864cf89af4c091a6b80f5_6775_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Survey_Corps_Uniform_hu55de424ffbd56fc83940d19738e9533d_6592_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Survey_Corps_Uniform_hu55de424ffbd56fc83940d19738e9533d_6592_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Sword_Art_Cyan_hu7b8ccfb52829f3128161f37547b9db22_6386_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Sword_Art_Cyan_hu7b8ccfb52829f3128161f37547b9db22_6386_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Team_Rocket_Uniform_hu6f847be1b7848f1167364e2dbfaed3ea_6530_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Team_Rocket_Uniform_hu6f847be1b7848f1167364e2dbfaed3ea_6530_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Tri_Digivice_Ver._hu69fce662f9b191fe76d054fa383515e1_6715_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Tri_Digivice_Ver._hu69fce662f9b191fe76d054fa383515e1_6715_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/U.A._High_School_Uniform_hu911d4684e5db071c1b04bb319fd838ad_6724_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/U.A._High_School_Uniform_hu911d4684e5db071c1b04bb319fd838ad_6724_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/UTA_VISION_hufca66dee5672fc5ad18062a0b2b30fc4_6593_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/UTA_VISION_hufca66dee5672fc5ad18062a0b2b30fc4_6593_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Ultra_Instinct_Sign_huffdf16efbb768f9b1e38a7357b3bbb6c_6367_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Ultra_Instinct_Sign_huffdf16efbb768f9b1e38a7357b3bbb6c_6367_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Urameshi_Green_hub81f4bde386a776241c3e6b7fced1772_6567_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Urameshi_Green_hub81f4bde386a776241c3e6b7fced1772_6567_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Vegeta_Armor_hu7209fffb710180b327da8cad959f5b3e_6232_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/Vegeta_Armor_hu7209fffb710180b327da8cad959f5b3e_6232_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/animate_vision_hu7051494cd60dcdf086c842279a97718d_6559_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/animate_vision_hu7051494cd60dcdf086c842279a97718d_6559_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/holoblue_hu2693a4a67266601ae3e578ef92cc7a47_6190_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Anime_and_Manga_Pack/holoblue_hu2693a4a67266601ae3e578ef92cc7a47_6190_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="bandai-namco-pack">Bandai Namco Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Bandai_Namco_Pack.uf2" title="Bandai_Namco_Pack.uf2">Bandai_Namco_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/1st_Vision_Pastel_hu5eb45250eb3df6d7b94faee6e0ffa0d4_6454_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/1st_Vision_Pastel_hu5eb45250eb3df6d7b94faee6e0ffa0d4_6454_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765PRO_Pink_huaa03b216fc934134be26f9dff3601cc5_6559_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765PRO_Pink_huaa03b216fc934134be26f9dff3601cc5_6559_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765PRO_TRICOLOR_hudfeb1417d17926855549487235f0961b_6453_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765PRO_TRICOLOR_hudfeb1417d17926855549487235f0961b_6453_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765_Production_Ver._hua261d97c165c41466cfcd655bf309eaf_6755_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/765_Production_Ver._hua261d97c165c41466cfcd655bf309eaf_6755_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/A-RISE_BLUE_hu79f777ce0d387c354d5c4d90976c5b9e_6210_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/A-RISE_BLUE_hu79f777ce0d387c354d5c4d90976c5b9e_6210_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Aqours_Blue_hu8e993025e3fadfc5d16446fc2890af7d_6192_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Aqours_Blue_hu8e993025e3fadfc5d16446fc2890af7d_6192_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Bandai_Namco_Tricolor_hu0e316d16c89f6ffec123b8e395c68cb4_6324_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Bandai_Namco_Tricolor_hu0e316d16c89f6ffec123b8e395c68cb4_6324_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/CINDERELLA_Blue_hu857696ce8aef9cf68b0071c4afee7432_6379_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/CINDERELLA_Blue_hu857696ce8aef9cf68b0071c4afee7432_6379_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Hasunosora_Red_hu38b9bc3696f3cc2ccb1af1c4b95a6211_6052_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Hasunosora_Red_hu38b9bc3696f3cc2ccb1af1c4b95a6211_6052_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/IDOL_WORLD_TRICOLOR!!!_huc0e676b409ec68f91dc0823a9238d8cc_6408_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/IDOL_WORLD_TRICOLOR!!!_huc0e676b409ec68f91dc0823a9238d8cc_6408_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Liella_Purple!_hu3f6ae56279f97959ecab7d4c8ca67492_6787_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Liella_Purple!_hu3f6ae56279f97959ecab7d4c8ca67492_6787_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/MILLION_LIVE_GOLD!_hu71d8ade49b302bdbbdebc1573e85b653_6589_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/MILLION_LIVE_GOLD!_hu71d8ade49b302bdbbdebc1573e85b653_6589_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/MILLION_Yellow!_hu81624ed3aae03221679eac9989f1b870_6172_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/MILLION_Yellow!_hu81624ed3aae03221679eac9989f1b870_6172_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Moonlight_Vision_hu18b3aa623e5e5d9f953625755ad00253_6357_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Moonlight_Vision_hu18b3aa623e5e5d9f953625755ad00253_6357_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Muse_Pink_hu0cc47561c72f1b6c9c67ef3b56a54020_6078_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Muse_Pink_hu0cc47561c72f1b6c9c67ef3b56a54020_6078_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Namco_Idol_Pink_hu36ca7a090b97014b15145459e2488506_6310_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Namco_Idol_Pink_hu36ca7a090b97014b15145459e2488506_6310_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Nijigasaki_Orange_hu3a17635b59a508c2fafcdba60622b5e2_6312_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Nijigasaki_Orange_hu3a17635b59a508c2fafcdba60622b5e2_6312_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/PAC-PALETTE_hufdded06e6d7083b12a7d0183a1f0fd1c_5778_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/PAC-PALETTE_hufdded06e6d7083b12a7d0183a1f0fd1c_5778_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Pac-Man_Vision_huadf769de343b9006c7327fe7865d9c86_6100_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Pac-Man_Vision_huadf769de343b9006c7327fe7865d9c86_6100_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Pac-Man_Yellow_hudc7d7d4cbd4a5c971ca1d755a226583a_6240_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Pac-Man_Yellow_hudc7d7d4cbd4a5c971ca1d755a226583a_6240_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/RADIANT_SMILE_RAMP_hu89619076d85bfa64758a3210656d1d4d_6589_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/RADIANT_SMILE_RAMP_hu89619076d85bfa64758a3210656d1d4d_6589_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/RX-78-2_Gundam_Mode_hu3954198e57808c1de1d75d4df6e2dab2_6704_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/RX-78-2_Gundam_Mode_hu3954198e57808c1de1d75d4df6e2dab2_6704_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Ryuuguu_Sunset_huc2d3785768a16213af64f0f3cf17e758_6330_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Ryuuguu_Sunset_huc2d3785768a16213af64f0f3cf17e758_6330_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/SHINY_Sky_Blue_hu6c1573a31ced3fd2abff7099bcd3f088_6439_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/SHINY_Sky_Blue_hu6c1573a31ced3fd2abff7099bcd3f088_6439_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Saint_Snow_Red_huc5161eba4a3d08717104fb4cf33eada1_6312_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Saint_Snow_Red_huc5161eba4a3d08717104fb4cf33eada1_6312_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/School_Idol_Blue_hu92588315d48fc548df3f0f313963c9a5_6475_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/School_Idol_Blue_hu92588315d48fc548df3f0f313963c9a5_6475_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/School_Idol_Mix_hu79af2564a17fccd3844394343aeb6332_6390_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/School_Idol_Mix_hu79af2564a17fccd3844394343aeb6332_6390_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/SideM_Green_hu0d133de498fb0d8f7ed3ead6a5e6583f_6136_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/SideM_Green_hu0d133de498fb0d8f7ed3ead6a5e6583f_6136_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Sunny_Passion_Paradise_hua3692210f7fd38bc1c193c1bd1321894_6616_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Sunny_Passion_Paradise_hua3692210f7fd38bc1c193c1bd1321894_6616_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Sylvarant_Rose_Pink_hu810603b4f5fec4d77a2b3fa138b49f3a_6499_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Sylvarant_Rose_Pink_hu810603b4f5fec4d77a2b3fa138b49f3a_6499_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Tarnished_Gold_huf7626e4ed400ddc756bc67af2b8f280f_6416_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Tarnished_Gold_huf7626e4ed400ddc756bc67af2b8f280f_6416_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Vulnerable_Blue_hudd7cd102fa495a66880ea3bee16b0b07_6446_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Vulnerable_Blue_hudd7cd102fa495a66880ea3bee16b0b07_6446_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Wind_Ring_Emerald_hu4a284df18ec4e40f01e3b2fc645a6c80_6511_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Bandai_Namco_Pack/Wind_Ring_Emerald_hu4a284df18ec4e40f01e3b2fc645a6c80_6511_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="company-pack">Company Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Company_Pack.uf2" title="Company_Pack.uf2">Company_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Amazon_Vision_hu0d85deb61c8a618ab13ee1fb898548b3_6165_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Amazon_Vision_hu0d85deb61c8a618ab13ee1fb898548b3_6165_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Android_Green_hu83f77b7cd3e4b61c082083bc4f28596d_6318_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Android_Green_hu83f77b7cd3e4b61c082083bc4f28596d_6318_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Apple_Silver_hu64529f2707f2fe006cc204c837bb4538_6119_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Apple_Silver_hu64529f2707f2fe006cc204c837bb4538_6119_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Duolingo_Green_hu8f695e89f25f0648f2aa1a6cd4f17827_6121_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Duolingo_Green_hu8f695e89f25f0648f2aa1a6cd4f17827_6121_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Duracell_Copper_hu23349f963a1093197f791a9a9371e7ca_6409_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Duracell_Copper_hu23349f963a1093197f791a9a9371e7ca_6409_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Blue_hu90c68122a1570411d96f8875baf38b49_6492_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Blue_hu90c68122a1570411d96f8875baf38b49_6492_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Green_huc1ed677c6e1f4467ec4165ba9aa09f51_6234_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Green_huc1ed677c6e1f4467ec4165ba9aa09f51_6234_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Red_hu32bbc9b91895594e185c4b2f84b05f89_6292_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Red_hu32bbc9b91895594e185c4b2f84b05f89_6292_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Yellow_hu7e9355cd433e13171e26c8aeadb794aa_6190_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Google_Yellow_hu7e9355cd433e13171e26c8aeadb794aa_6190_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Spotify_Green_hu02db793ca3e82f45cb4df7647e007432_6201_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Company_Pack/Spotify_Green_hu02db793ca3e82f45cb4df7647e007432_6201_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="food-and-drink-pack">Food and Drink Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Food_and_Drink_Pack.uf2" title="Food_and_Drink_Pack.uf2">Food_and_Drink_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/7-Eleven_Color_Combo_hu2643a779161d2f7d01418124d9887a12_6652_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/7-Eleven_Color_Combo_hu2643a779161d2f7d01418124d9887a12_6652_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baja_Blast_Beach_huc3a8c3da55ab6109bebb044fcda13e73_6448_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baja_Blast_Beach_huc3a8c3da55ab6109bebb044fcda13e73_6448_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baja_Blast_Storm_hu74d3d858506ac4b841ce17fe1985d696_6495_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baja_Blast_Storm_hu74d3d858506ac4b841ce17fe1985d696_6495_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baskin-Robbins_Sundae_hua2f4a45a3c5ac9dd246a9a496bfa1915_6757_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Baskin-Robbins_Sundae_hua2f4a45a3c5ac9dd246a9a496bfa1915_6757_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Burger_King_Color_Combo_hu52953ce9f35e2cf9c6fe5895ee5692fe_6564_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Burger_King_Color_Combo_hu52953ce9f35e2cf9c6fe5895ee5692fe_6564_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Cheeto_Orange_hu1a3192dfac26d23608192bc41b5996f7_6047_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Cheeto_Orange_hu1a3192dfac26d23608192bc41b5996f7_6047_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Circle_K_Color_Combo_hue47263fc2ba4126d40c6386d90ddf05e_6772_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Circle_K_Color_Combo_hue47263fc2ba4126d40c6386d90ddf05e_6772_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Coca-Cola_Vision_hu6c26e118e22a688baf0fe2f4f17aa7d6_6028_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Coca-Cola_Vision_hu6c26e118e22a688baf0fe2f4f17aa7d6_6028_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dew_Green_hudc17c50c2bd60d3dc7eca2024100b6c6_6029_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dew_Green_hudc17c50c2bd60d3dc7eca2024100b6c6_6029_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Domino%27s_Pizza_Vision_hu170d583ef5e9a338ce0fff5346802301_6184_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Domino%27s_Pizza_Vision_hu170d583ef5e9a338ce0fff5346802301_6184_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dr_Pepper_Red_huf0f46e52e1271abba1e6eb2f615b3b87_6154_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dr_Pepper_Red_huf0f46e52e1271abba1e6eb2f615b3b87_6154_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dunkin%27_Vision_hufaaa21b4f58c52fdf58c8420ec68779b_6317_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Dunkin%27_Vision_hufaaa21b4f58c52fdf58c8420ec68779b_6317_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Kentucky_Fried_Red_hud7ee572fb291e3d3471fc8fcbea15bb2_6349_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Kentucky_Fried_Red_hud7ee572fb291e3d3471fc8fcbea15bb2_6349_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Krispy_Kreme_Vision_hu06f6914b8ea9f9b6f66fa26cfde2c965_6603_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Krispy_Kreme_Vision_hu06f6914b8ea9f9b6f66fa26cfde2c965_6603_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Lemon-Lime_Green_huc3b7735e1e90f24342b74e8bae987a3e_6389_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Lemon-Lime_Green_huc3b7735e1e90f24342b74e8bae987a3e_6389_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Mountain_Dew_Ver._huf6cda883448209be774eefed0921946c_6389_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Mountain_Dew_Ver._huf6cda883448209be774eefed0921946c_6389_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/POCARI_SWEAT_BLUE_huc4b89dc60bee97f81fa7e9e0feb7a07f_6176_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/POCARI_SWEAT_BLUE_huc4b89dc60bee97f81fa7e9e0feb7a07f_6176_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Pepsi_Vision_hud850557bca38af74af9646faf1aeeaf9_5952_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Pepsi_Vision_hud850557bca38af74af9646faf1aeeaf9_5952_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Pizza_Hut_Red_hucbd0420fa0749073a65d16bda15b1a2b_6134_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Pizza_Hut_Red_hucbd0420fa0749073a65d16bda15b1a2b_6134_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Sprite_Green_huf91e819bb3f1644661583f707e9dc023_5995_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Food_and_Drink_Pack/Sprite_Green_huf91e819bb3f1644661583f707e9dc023_5995_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="gaming-pack">Gaming Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Gaming_Pack.uf2" title="Gaming_Pack.uf2">Gaming_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/AVGN_Raging_Volcano_hue1952d81ea1fdd262f5828a1667bea4e_6310_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/AVGN_Raging_Volcano_hue1952d81ea1fdd262f5828a1667bea4e_6310_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Blue_Bomber_Vision_huf26851cf292c4850ac778404ab6f9f2e_6266_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Blue_Bomber_Vision_huf26851cf292c4850ac778404ab6f9f2e_6266_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Bobblun_Blue_hu7b59d615b5cb011cd95ee1258c539a7e_6228_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Bobblun_Blue_hu7b59d615b5cb011cd95ee1258c539a7e_6228_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Bubblun_Green_hu3d44ccc4da8f22b1a8ce71afc240fdb3_6262_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Bubblun_Green_hu3d44ccc4da8f22b1a8ce71afc240fdb3_6262_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Chaos_Emerald_Green_hu79fab353f7b061b03d018f799e5fbb86_6477_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Chaos_Emerald_Green_hu79fab353f7b061b03d018f799e5fbb86_6477_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Classic_Blurple_hufe29272e5d19ecb6c4920969da95e734_6419_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Classic_Blurple_hufe29272e5d19ecb6c4920969da95e734_6419_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/DMG_Pea_Green_hu1681e72c04fccb9d1e0c27b00cd464c9_6397_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/DMG_Pea_Green_hu1681e72c04fccb9d1e0c27b00cd464c9_6397_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Ebott_Prologue_huee6824aa4ef52d9551393bb601d55fab_6475_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Ebott_Prologue_huee6824aa4ef52d9551393bb601d55fab_6475_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Game_Grump_Orange_hu2cef8d1c045168c50a46b0d68edc38ba_6422_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Game_Grump_Orange_hu2cef8d1c045168c50a46b0d68edc38ba_6422_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Giga_Kiwi_DMG_hu68592b20343c611c02200954cd268692_6287_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Giga_Kiwi_DMG_hu68592b20343c611c02200954cd268692_6287_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Investigation_Yellow_hudc4043bdf5892b5b4c718ee1bee45c2b_6330_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Investigation_Yellow_hudc4043bdf5892b5b4c718ee1bee45c2b_6330_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Phantom_Red_hud96b19cbdced863952e41f4452b61252_6338_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Phantom_Red_hud96b19cbdced863952e41f4452b61252_6338_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Puyo_Puyo_Green_hu550881aebc74d1959924790e191e9428_6359_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Puyo_Puyo_Green_hu550881aebc74d1959924790e191e9428_6359_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/S.E.E.S._Blue_hu6a7ecd1db57b116c3ef2126c49849a5e_6210_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/S.E.E.S._Blue_hu6a7ecd1db57b116c3ef2126c49849a5e_6210_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/SEGA_Tokyo_Blue_hu5f5ed33a714ef1e513ad47de8aa398d2_6500_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/SEGA_Tokyo_Blue_hu5f5ed33a714ef1e513ad47de8aa398d2_6500_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Scarlett_Green_hubdf3e8d50c6c3dde6a101f29fa1957ec_6326_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Scarlett_Green_hubdf3e8d50c6c3dde6a101f29fa1957ec_6326_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Slime_Blue_hu59c7bac3524f0e8c976b934927fc3c50_6225_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Slime_Blue_hu59c7bac3524f0e8c976b934927fc3c50_6225_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Sonic_Mega_Blue_hua6726d53021b09962a661604b9d9ddf8_6890_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Sonic_Mega_Blue_hua6726d53021b09962a661604b9d9ddf8_6890_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Steam_Gray_hudd9fcd4a9fe14c682d92f5b50d10d15b_6678_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Steam_Gray_hudd9fcd4a9fe14c682d92f5b50d10d15b_6678_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Teyvat_Brown_hu4f8f8c463c32d1ee3539810a57229ba2_6215_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Teyvat_Brown_hu4f8f8c463c32d1ee3539810a57229ba2_6215_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Tropical_Cyber_Space_hua70af887bc1e4f5e828a1138c0a34246_6559_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Tropical_Cyber_Space_hua70af887bc1e4f5e828a1138c0a34246_6559_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Xbox_Green_huf1d36c8e6ebb85e35194d3138cdb8c75_6215_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Gaming_Pack/Xbox_Green_huf1d36c8e6ebb85e35194d3138cdb8c75_6215_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="holiday-pack">Holiday Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Holiday_Pack.uf2" title="Holiday_Pack.uf2">Holiday_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Gold_hufa167ddfcb780e7ba03408d7fa5c8ea7_6636_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Gold_hufa167ddfcb780e7ba03408d7fa5c8ea7_6636_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Silver_hu7f6ebbd8bfc61abfe11e73f654f840de_6747_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Silver_hu7f6ebbd8bfc61abfe11e73f654f840de_6747_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Ver._huf7156dc04319824683e6644cf44b8487_6717_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Christmas_Ver._huf7156dc04319824683e6644cf44b8487_6717_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Classy_Christmas_huddff98db287d6ed1dff86bfc4d284e71_6554_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Classy_Christmas_huddff98db287d6ed1dff86bfc4d284e71_6554_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Clover_Green_hu27982a692f8c10aee0f245abdb79e61f_6417_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Clover_Green_hu27982a692f8c10aee0f245abdb79e61f_6417_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Cupid%27s_Love_Palette_hu3ccd980ac17e17d8542087ba7dcd9c23_6536_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Cupid%27s_Love_Palette_hu3ccd980ac17e17d8542087ba7dcd9c23_6536_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Festive_Christmas_hueb4138595ef3cc8c5e9ee2ec2b70357b_6427_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Festive_Christmas_hueb4138595ef3cc8c5e9ee2ec2b70357b_6427_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Glacial_Winter_Blue_hu01562f0ddebf17e146b6b89ecf2345cd_6462_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Glacial_Winter_Blue_hu01562f0ddebf17e146b6b89ecf2345cd_6462_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Grinchy_Green_huf10947b2cd22d127660895b054f9643c_6272_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Grinchy_Green_huf10947b2cd22d127660895b054f9643c_6272_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Halloween_Ver._huc004cfb2c457aad84dd5eb40b00cccda_6253_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Halloween_Ver._huc004cfb2c457aad84dd5eb40b00cccda_6253_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Haunted_Halloween_hu491afb0fa1ab1d43fcc324770071a826_6363_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Haunted_Halloween_hu491afb0fa1ab1d43fcc324770071a826_6363_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Independence_Boy_hu9223da23af292afc603d2dbf2ac80a03_6140_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Independence_Boy_hu9223da23af292afc603d2dbf2ac80a03_6140_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Irish_Green_huc077a2065f423b67c605b559c912eaf0_6394_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Irish_Green_huc077a2065f423b67c605b559c912eaf0_6394_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Christmas_hu24a9a09ac4608180c6bb3f774430ab62_6196_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Christmas_hu24a9a09ac4608180c6bb3f774430ab62_6196_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Halloween_huafdf8642f16341b1faa1534f31ceb654_6186_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Halloween_huafdf8642f16341b1faa1534f31ceb654_6186_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Valentine%27s_Day_huc6f811075a936ce7c80ce23dcd4a7b7b_6419_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/NES_Valentine%27s_Day_huc6f811075a936ce7c80ce23dcd4a7b7b_6419_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Spooky_Purple_hu5e3d4060e21fd3f7913b679c28fdf619_6310_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Spooky_Purple_hu5e3d4060e21fd3f7913b679c28fdf619_6310_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Winter_Christmas_hua6f11e209d7920b23d66a78059860947_6399_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Holiday_Pack/Winter_Christmas_hua6f11e209d7920b23d66a78059860947_6399_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="japanese-company-pack">Japanese Company Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Japanese_Company_Pack.uf2" title="Japanese_Company_Pack.uf2">Japanese_Company_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/ALSOK_VISION_hu90c6e3bb3855b81c4d75d2bda5c94fc4_6064_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/ALSOK_VISION_hu90c6e3bb3855b81c4d75d2bda5c94fc4_6064_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/ANA_Flight_Blue_hu7497ddb297c07f0ab67d019e4702aec2_6404_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/ANA_Flight_Blue_hu7497ddb297c07f0ab67d019e4702aec2_6404_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/FamilyMart_Vision_huc66afa840d8d7be885611367b2551328_6207_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/FamilyMart_Vision_huc66afa840d8d7be885611367b2551328_6207_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/LAWSON_BLUE_hu238a50f795bccdc6e79c4be7232d192f_6016_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/LAWSON_BLUE_hu238a50f795bccdc6e79c4be7232d192f_6016_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/NHK_Silver_Gray_hu911054f301fb4c09dfe01155cb6e83c4_6309_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/NHK_Silver_Gray_hu911054f301fb4c09dfe01155cb6e83c4_6309_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SAITAMA_SUPER_BLUE_hu8a4a0523d24ec76faf5b1385c8dd629b_6396_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SAITAMA_SUPER_BLUE_hu8a4a0523d24ec76faf5b1385c8dd629b_6396_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SAITAMA_SUPER_GREEN_hu2016863ef4777eeae8c485f643a5350c_6354_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SAITAMA_SUPER_GREEN_hu2016863ef4777eeae8c485f643a5350c_6354_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SEIKO_Timely_Vision_hu120b2158b2d36ce33b2ff6676dd96ddd_6585_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SEIKO_Timely_Vision_hu120b2158b2d36ce33b2ff6676dd96ddd_6585_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SHIBUYA109_PASTEL_hud2ffe1159b0f62a95a3c8c99cf68b9e2_6576_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/SHIBUYA109_PASTEL_hud2ffe1159b0f62a95a3c8c99cf68b9e2_6576_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/Sanrio_Pink_hub2686ba0086949f9d301b30dea6ac91f_6382_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/Sanrio_Pink_hub2686ba0086949f9d301b30dea6ac91f_6382_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/TOKYO_SKYTREE_CLOUDY_BLUE_hubf56e5c55ff13d380d434a9b8cadb699_6556_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Japanese_Company_Pack/TOKYO_SKYTREE_CLOUDY_BLUE_hubf56e5c55ff13d380d434a9b8cadb699_6556_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="j-pop-pack">J-Pop Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/J-Pop_Pack.uf2" title="J-Pop_Pack.uf2">J-Pop_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/AKB48_Pink_hu6e46ef1b617c38159a0544dfefa111af_6258_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/AKB48_Pink_hu6e46ef1b617c38159a0544dfefa111af_6258_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/ATARASHI_GAKKO_PARETTO_hu7459dc521f3701a261396d13cfc224ff_6522_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/ATARASHI_GAKKO_PARETTO_hu7459dc521f3701a261396d13cfc224ff_6522_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/BABYMETAL_KITSUNE_RED_hub5662eb5c741ccbdfdb11ae176cccbb5_6114_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/BABYMETAL_KITSUNE_RED_hub5662eb5c741ccbdfdb11ae176cccbb5_6114_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Hinatazaka46_Blue_hu07179b7570a59fecc2d67b78349b0c81_6365_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Hinatazaka46_Blue_hu07179b7570a59fecc2d67b78349b0c81_6365_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/J-Pop_Idol_Sherbet_hucb4967d77b46bca91cc1355f39f6c626_6490_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/J-Pop_Idol_Sherbet_hucb4967d77b46bca91cc1355f39f6c626_6490_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Miku_Blue_hu2ad0989efeac527468d4e5c3878ab1a8_5966_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Miku_Blue_hu2ad0989efeac527468d4e5c3878ab1a8_5966_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Momoiro_Clover_Z_Palette_hub664295743a4ac8bff57e040af3eb0b4_6696_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Momoiro_Clover_Z_Palette_hub664295743a4ac8bff57e040af3eb0b4_6696_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/NiziU_PrePlay_Palette_hu538a6af54795869724a858df00772cd0_6328_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/NiziU_PrePlay_Palette_hu538a6af54795869724a858df00772cd0_6328_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Nogizaka46_Purple_hub7149519e3ff199e8eae3c52f20c9d81_6744_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/Nogizaka46_Purple_hub7149519e3ff199e8eae3c52f20c9d81_6744_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/ONE_OK_ROCK_RED_hu0b00e642476a61b493c6203dfa06d478_6417_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/ONE_OK_ROCK_RED_hu0b00e642476a61b493c6203dfa06d478_6417_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/YOASOBI_AMARANTH_hud3d5f350ffaab8d5028d16e0900c0f98_6606_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/J-Pop_Pack/YOASOBI_AMARANTH_hud3d5f350ffaab8d5028d16e0900c0f98_6606_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="k-pop-pack">K-Pop Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/K-Pop_Pack.uf2" title="K-Pop_Pack.uf2">K-Pop_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/BANGTAN_ARMY_PURPLE_hud5481748f0b6525f71ed7d4eb9aba34c_6570_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/BANGTAN_ARMY_PURPLE_hud5481748f0b6525f71ed7d4eb9aba34c_6570_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/BLACKPINK_BLINK_PINK_hu801633632f7badb114e4be363ccd1894_6787_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/BLACKPINK_BLINK_PINK_hu801633632f7badb114e4be363ccd1894_6787_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/EXO_ERI_COSMIC_LATTE_hu6c4a97fc2b8e74abc12044b9c1a464d1_6818_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/EXO_ERI_COSMIC_LATTE_hu6c4a97fc2b8e74abc12044b9c1a464d1_6818_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/LA_SSERAFIM_FEARLESS_BLUE_huada5a298354978a51c8b59844ca09b32_6674_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/LA_SSERAFIM_FEARLESS_BLUE_huada5a298354978a51c8b59844ca09b32_6674_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/NTC_NTCZEN_YELLOW_hubce2fc37729aa7205c779da0d07e51bb_6387_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/NTC_NTCZEN_YELLOW_hubce2fc37729aa7205c779da0d07e51bb_6387_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SEVENTEEN_COOL_CARAT_hu484a2692a0198b0e36189d736757d30d_6642_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SEVENTEEN_COOL_CARAT_hu484a2692a0198b0e36189d736757d30d_6642_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SHINee_SHAWOL_GREEN_hu5d50fd98ed2684439784989a1e8b4ee6_6561_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SHINee_SHAWOL_GREEN_hu5d50fd98ed2684439784989a1e8b4ee6_6561_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SNSD_SO-WON_PINK_hu1151f6139ccb13ae06e4dfe636c77d01_6457_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/SNSD_SO-WON_PINK_hu1151f6139ccb13ae06e4dfe636c77d01_6457_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/STRAY_KIDS_STAY_PINK_hu206d4a939523c1b62eaeee7a68d47f0d_6499_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/STRAY_KIDS_STAY_PINK_hu206d4a939523c1b62eaeee7a68d47f0d_6499_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/TROPICAL_TWICE_APRICOT_hu81c7697fe1d1630f1ee9d77e2ad47dc9_6515_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/K-Pop_Pack/TROPICAL_TWICE_APRICOT_hu81c7697fe1d1630f1ee9d77e2ad47dc9_6515_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="legacy-palette-pack">Legacy Palette Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Legacy_Palette_Pack.uf2" title="Legacy_Palette_Pack.uf2">Legacy_Palette_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/3DS_Virtual_Console_Green_hud943c41abc63aae6579cfcc3255502e6_6569_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/3DS_Virtual_Console_Green_hud943c41abc63aae6579cfcc3255502e6_6569_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/3DS_Virtual_Console_Ver._hue743d03be0152f9be32aaa1fe55a0cd6_6665_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/3DS_Virtual_Console_Ver._hue743d03be0152f9be32aaa1fe55a0cd6_6665_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Bill%27s_PC_Screen_hu4de725b603f2c9645a16156a097baf18_6033_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Bill%27s_PC_Screen_hu4de725b603f2c9645a16156a097baf18_6033_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/DMG_Ver._huea994781b47af7aa684b93ea60cce87d_6192_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/DMG_Ver._huea994781b47af7aa684b93ea60cce87d_6192_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Digivice_Ver._hu4ec0d730bcb9d6832f4ca97121785d05_6231_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Digivice_Ver._hu4ec0d730bcb9d6832f4ca97121785d05_6231_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Gamate_Ver._huab245510d0ab54fc98d835b5150b3942_6206_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Gamate_Ver._huab245510d0ab54fc98d835b5150b3942_6206_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/GameKing_Ver._hu3444bb88290484bc1645ffc9b507bdbc_6372_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/GameKing_Ver._hu3444bb88290484bc1645ffc9b507bdbc_6372_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Game_and_Watch_LCD_hu16aa375cb27a0d457d550bc8284374b8_6438_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Game_and_Watch_LCD_hu16aa375cb27a0d457d550bc8284374b8_6438_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Gamebuino_Classic_Ver._hu252e962e6e382a517e41b4f026b4b880_6613_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Gamebuino_Classic_Ver._hu252e962e6e382a517e41b4f026b4b880_6613_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Hartung_Game_Master_Ver._hu6dc6ca5f6f3e650199a40026ef135858_6684_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Hartung_Game_Master_Ver._hu6dc6ca5f6f3e650199a40026ef135858_6684_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Light_Ver._hu117e120a2b56ce29a89860cbcc06e070_6089_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Light_Ver._hu117e120a2b56ce29a89860cbcc06e070_6089_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Link%27s_Awakening_DX_Ver._hu388ed70c410d2df473b548320111c4be_7103_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Link%27s_Awakening_DX_Ver._hu388ed70c410d2df473b548320111c4be_7103_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/MB_Microvision_Ver._hu03b0e5d17ca94e88a79a3b1df86e5b44_6427_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/MB_Microvision_Ver._hu03b0e5d17ca94e88a79a3b1df86e5b44_6427_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Mega_Man_V_Ver._huda294c8834e283deeebd7bae3fdbbb89_6650_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Mega_Man_V_Ver._huda294c8834e283deeebd7bae3fdbbb89_6650_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Neo_Geo_Pocket_Ver._hu7712d523db2b3085e13a075d7558f41c_6280_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Neo_Geo_Pocket_Ver._hu7712d523db2b3085e13a075d7558f41c_6280_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Nokia_3310_Ver._hu8f1c76264116585e521134893a0faf08_6397_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Nokia_3310_Ver._hu8f1c76264116585e521134893a0faf08_6397_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/PocketStation_Ver._hu544d442a5ac2bbc1314215044bbf8df1_6426_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/PocketStation_Ver._hu544d442a5ac2bbc1314215044bbf8df1_6426_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pocket_Tales_Ver._hu783bf97cc70b5edae4824ab37ef7ddaf_6084_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pocket_Tales_Ver._hu783bf97cc70b5edae4824ab37ef7ddaf_6084_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pocket_Ver._huf9f2376068363a57ec042e98c6e34b04_6468_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pocket_Ver._huf9f2376068363a57ec042e98c6e34b04_6468_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_Pinball_Ver._huddbc73d918854ebe5f1a76da28e4ab03_6760_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_Pinball_Ver._huddbc73d918854ebe5f1a76da28e4ab03_6760_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_Ver._hu1eafe15a5786393d02e16217c890dca5_6289_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_Ver._hu1eafe15a5786393d02e16217c890dca5_6289_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_mini_Ver._huf0657aeefdb0101581bd2ac404bc02d3_6517_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Pokemon_mini_Ver._huf0657aeefdb0101581bd2ac404bc02d3_6517_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Poketch_Ver._hu236c41da50f2b556f3749b7b3d490c1a_6211_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Poketch_Ver._hu236c41da50f2b556f3749b7b3d490c1a_6211_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Rocky-Valley_Holiday_hu1e1e1db20bbcdf859f1d7998fab9c69c_6583_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Rocky-Valley_Holiday_hu1e1e1db20bbcdf859f1d7998fab9c69c_6583_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/TI-83_Ver._huad91a5d469a37fe48404184297df558c_6192_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/TI-83_Ver._huad91a5d469a37fe48404184297df558c_6192_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Tamagotchi_Ver._hu5b748a457ddb3e7e01078c5940e37df9_6481_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Tamagotchi_Ver._hu5b748a457ddb3e7e01078c5940e37df9_6481_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Tiger_Game.com_Ver._hu49d54f72d880a09508d8bab928cbf267_6398_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Tiger_Game.com_Ver._hu49d54f72d880a09508d8bab928cbf267_6398_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Timing_Hero_Ver._huac41e35434d2f1558db50e0a5a492882_6361_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Timing_Hero_Ver._huac41e35434d2f1558db50e0a5a492882_6361_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Travel_Wood_hudccf6e8fe743cf077769ed2c34799a55_6287_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Travel_Wood_hudccf6e8fe743cf077769ed2c34799a55_6287_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/VMU_Ver._huc081536fb24386e667cd1b9a75c8ec93_6539_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/VMU_Ver._huc081536fb24386e667cd1b9a75c8ec93_6539_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Virtual_Boy_Ver._hucd637cc2ec9d8229ff16aa4358320be3_5794_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Virtual_Boy_Ver._hucd637cc2ec9d8229ff16aa4358320be3_5794_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Watara_Supervision_Ver._hu56844ceb1f231cc2f8e87728c43d840c_6683_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Watara_Supervision_Ver._hu56844ceb1f231cc2f8e87728c43d840c_6683_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Windows_Classic_Teal_hu35e8d92d8d5ec0bf5e01d306455d01e7_6364_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/Windows_Classic_Teal_hu35e8d92d8d5ec0bf5e01d306455d01e7_6364_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/WonderSwan_Ver._hu99f3076019726f48dae46606007dbff5_6422_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Legacy_Palette_Pack/WonderSwan_Ver._hu99f3076019726f48dae46606007dbff5_6422_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="misc-palette-pack">Misc. Palette Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Misc._Palette_Pack.uf2" title="Misc._Palette_Pack.uf2">Misc._Palette_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Camouflage_Ver._hu231f31ed27c17fb4d278037e5c3c3cec_6385_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Camouflage_Ver._hu231f31ed27c17fb4d278037e5c3c3cec_6385_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Cherry_Blossom_Pink_hud1965debdfec77601fd7ebfa5b7a9879_6562_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Cherry_Blossom_Pink_hud1965debdfec77601fd7ebfa5b7a9879_6562_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Emerald_Green_hu1b2d38ace96c49d0c77e96962d5c3aa7_6366_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Emerald_Green_hu1b2d38ace96c49d0c77e96962d5c3aa7_6366_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Fool%27s_Gold_and_Silver_hu3a592e3a1867f2b2060fcf89d2c13193_6596_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Fool%27s_Gold_and_Silver_hu3a592e3a1867f2b2060fcf89d2c13193_6596_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Glitchy_Blue_huf7b0f6f75983931c68d0155517660d53_6274_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Glitchy_Blue_huf7b0f6f75983931c68d0155517660d53_6274_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Gold,_Silver,_and_Bronze_hu6ff6dbd46f2618140da65f9edf83dee8_6932_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Gold,_Silver,_and_Bronze_hu6ff6dbd46f2618140da65f9edf83dee8_6932_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Golden_Trophy_hu8dfa727755e887862aa22a3927974979_6627_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Golden_Trophy_hu8dfa727755e887862aa22a3927974979_6627_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Greenscale_Ver._hu1a420a4719f84b7942c7cb2b0f7ed6e3_6399_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Greenscale_Ver._hu1a420a4719f84b7942c7cb2b0f7ed6e3_6399_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Leprechaun_Green_hu5c8629fda8b8f3d7a43d939ab6ebfc17_6378_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Leprechaun_Green_hu5c8629fda8b8f3d7a43d939ab6ebfc17_6378_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Nightvision_Green_hu08a68f88f080c5b1a4767af7abe1e165_6409_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Nightvision_Green_hu08a68f88f080c5b1a4767af7abe1e165_6409_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Rising_Sun_Red_huf1cc6ba5f8450668429b3995c0f1e82d_6158_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Rising_Sun_Red_huf1cc6ba5f8450668429b3995c0f1e82d_6158_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Treasure_Gold_hub5afe8aeaba582594c901cde43182b8e_6499_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Treasure_Gold_hub5afe8aeaba582594c901cde43182b8e_6499_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Wild_West_Vision_huba282e8c6f95727353badeec007bdc6a_6468_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Misc._Palette_Pack/Wild_West_Vision_huba282e8c6f95727353badeec007bdc6a_6468_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="nintendo-pack">Nintendo Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Nintendo_Pack.uf2" title="Nintendo_Pack.uf2">Nintendo_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Advanced_Indigo_hu02f5ff90f5012ae7f4a5d3bad91b62cb_6632_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Advanced_Indigo_hu02f5ff90f5012ae7f4a5d3bad91b62cb_6632_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Aegis_Cherry_huad736bb644be0639621bd449e342bf78_6372_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Aegis_Cherry_huad736bb644be0639621bd449e342bf78_6372_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Ancient_Hisuian_Brown_hua087dbd63da09557c32f0c3973f1bc07_6965_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Ancient_Hisuian_Brown_hua087dbd63da09557c32f0c3973f1bc07_6965_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Animal_Crossing_Green_hu6a7cf30bbe1d1aafc6a755ad413a0604_6514_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Animal_Crossing_Green_hu6a7cf30bbe1d1aafc6a755ad413a0604_6514_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Brilliant_Diamond_Blue_hu9c2a364845b4a08293cf874e08252245_6921_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Brilliant_Diamond_Blue_hu9c2a364845b4a08293cf874e08252245_6921_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/COLLECTION_of_SaGa_Ver._hu77163958cdfff85825ef04b72c60f661_6577_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/COLLECTION_of_SaGa_Ver._hu77163958cdfff85825ef04b72c60f661_6577_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Champion%27s_Tunic_huc412c273ca1621a2a3c28dfd496f6f2c_6602_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Champion%27s_Tunic_huc412c273ca1621a2a3c28dfd496f6f2c_6602_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Chozo_Blue_hu73dff194067d3c1ba0c531958e01c9b9_6464_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Chozo_Blue_hu73dff194067d3c1ba0c531958e01c9b9_6464_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DK_Arcade_Blue_hu4ec8a894b191a0f5af0f1513f6c8aa2d_6281_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DK_Arcade_Blue_hu4ec8a894b191a0f5af0f1513f6c8aa2d_6281_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DK_Barrel_Brown_hu56ed29ae73649a973d21013ffc5bf635_6423_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DK_Barrel_Brown_hu56ed29ae73649a973d21013ffc5bf635_6423_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-099_hubd57314c75a60a05cfd890d72f84a270_6556_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-099_hubd57314c75a60a05cfd890d72f84a270_6556_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-GOLD_hucc681c723073db66c536aec6c090259d_6206_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-GOLD_hucc681c723073db66c536aec6c090259d_6206_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-SWITCH_hu2615afa42fc84454c022afeed1b2c033_6268_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/DMG-SWITCH_hu2615afa42fc84454c022afeed1b2c033_6268_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Dream_Land_GB_Ver._hu75fa849cad0d0c77ae7011824c69a81f_6583_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Dream_Land_GB_Ver._hu75fa849cad0d0c77ae7011824c69a81f_6583_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Eevee_Brown_hu4a81e417327673d527bf5d0d8b071b57_6478_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Eevee_Brown_hu4a81e417327673d527bf5d0d8b071b57_6478_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Famicom_Disk_Yellow_hu8dceef3556b6537af7a9a883141b247f_6282_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Famicom_Disk_Yellow_hu8dceef3556b6537af7a9a883141b247f_6282_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Famicom_Frenzy_hu46ad64177f07d844679e0b02f58ebd5d_6720_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Famicom_Frenzy_hu46ad64177f07d844679e0b02f58ebd5d_6720_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Frog_Coin_Green_hu6a12c460f45154bf8a4bcb6ecaf42b87_6154_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Frog_Coin_Green_hu6a12c460f45154bf8a4bcb6ecaf42b87_6154_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Fury_Blue_hu46382312cda76575ad0d339f3d212363_6356_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Fury_Blue_hu46382312cda76575ad0d339f3d212363_6356_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/GameCube_Glimmer_hub7f8f25ef677ebf49487026d138f088e_6656_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/GameCube_Glimmer_hub7f8f25ef677ebf49487026d138f088e_6656_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Golden_Wild_huc65779347ee74bf28a297cf7b216e615_6227_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Golden_Wild_huc65779347ee74bf28a297cf7b216e615_6227_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Goomba_Brown_hu730c6b017d548f062e04faaecf6362b8_6119_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Goomba_Brown_hu730c6b017d548f062e04faaecf6362b8_6119_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Green_Awakening_hu4d4092f3856100b13bb9c7911d9fd8e2_6634_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Green_Awakening_hu4d4092f3856100b13bb9c7911d9fd8e2_6634_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Green_Banana_hu7cef249aec6f0b1f61166451103b784a_6316_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Green_Banana_hu7cef249aec6f0b1f61166451103b784a_6316_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Inkling_Tricolor_hue9599f4337d083268a4bb10c1976df0a_6687_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Inkling_Tricolor_hue9599f4337d083268a4bb10c1976df0a_6687_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/LCD_Clock_Green_hu72507ea1417e50c7e6efe4f134e77690_6463_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/LCD_Clock_Green_hu72507ea1417e50c7e6efe4f134e77690_6463_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Labo_Fawn_hu8315d4a03b0714b714b051f0e6d4248b_6149_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Labo_Fawn_hu8315d4a03b0714b714b051f0e6d4248b_6149_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Mario_Red_huf4d1cb6e74a036b3e7bc8b4c4ccdeedd_5783_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Mario_Red_huf4d1cb6e74a036b3e7bc8b4c4ccdeedd_5783_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Metallic_Paldea_Brass_hud915451343802cb9be2de0f7e2b7a211_6548_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Metallic_Paldea_Brass_hud915451343802cb9be2de0f7e2b7a211_6548_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Blue_hud11f0fdd7668c10d0592fcc3619df556_6117_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Blue_hud11f0fdd7668c10d0592fcc3619df556_6117_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Green_hu5a784221d47d481068353a8b31f88ec0_6007_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Green_hu5a784221d47d481068353a8b31f88ec0_6007_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Orange_hu5f9f67816624d1de6c9606dc4be4bbf4_6346_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Orange_hu5f9f67816624d1de6c9606dc4be4bbf4_6346_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Pink_hua6b512629e2777c5101f329a127aba17_6146_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Pink_hua6b512629e2777c5101f329a127aba17_6146_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Purple_hudd4d47c1a197c625271e8d23f78e191b_6090_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Purple_hudd4d47c1a197c625271e8d23f78e191b_6090_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Red_hua57c7c6bd4cab16a00d623e4acff5129_6142_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Red_hua57c7c6bd4cab16a00d623e4acff5129_6142_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Yellow_hu95b0ca08913b52fcc6fae8d89d27c175_5965_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Neon_Yellow_hu95b0ca08913b52fcc6fae8d89d27c175_5965_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Odyssey_Boy_hu27efb898a0822ccd568f9e37984a2cec_6499_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Odyssey_Boy_hu27efb898a0822ccd568f9e37984a2cec_6499_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Odyssey_Gold_hud250019dcb851d36e89bcb29cc7ee17a_6112_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Odyssey_Gold_hud250019dcb851d36e89bcb29cc7ee17a_6112_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/POCKET_SWITCH_hubb6fbc07c51cfff630ed7aa0e4c22439_6379_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/POCKET_SWITCH_hubb6fbc07c51cfff630ed7aa0e4c22439_6379_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Pikachu_Yellow_hu6c527bc01da29b5a74ba2b6810df436b_6230_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Pikachu_Yellow_hu6c527bc01da29b5a74ba2b6810df436b_6230_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Pokedex_Red_hu69684b2d1816f24dbe8bb1df5ba97e7d_6496_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Pokedex_Red_hu69684b2d1816f24dbe8bb1df5ba97e7d_6496_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Royal_Blue_hu8029bd21ada7b75325ec07c9e5397a79_6338_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Royal_Blue_hu8029bd21ada7b75325ec07c9e5397a79_6338_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Shining_Pearl_Pink_hudcc3e8ceb7abc871ff4b3f3df9358b0c_6755_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Shining_Pearl_Pink_hudcc3e8ceb7abc871ff4b3f3df9358b0c_6755_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Sky_Pop_Ivory_hu23f1269ea177608e1c7122d1e2daabf1_6438_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Sky_Pop_Ivory_hu23f1269ea177608e1c7122d1e2daabf1_6438_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Famicom_Supreme_hu598752be1f89daecc0dc4f4f9a372eaf_6973_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Famicom_Supreme_hu598752be1f89daecc0dc4f4f9a372eaf_6973_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Mushroom_Vision_huac483394a5d8945ea24d093a6ac96c24_6922_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Mushroom_Vision_huac483394a5d8945ea24d093a6ac96c24_6922_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Star_Pink_hud0280266d73adac6eddebf21c42fed97_6590_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Super_Star_Pink_hud0280266d73adac6eddebf21c42fed97_6590_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Superball_Ivory_hud61e1d30b1ac5d6fd75b3401c1ed7a38_6486_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Superball_Ivory_hud61e1d30b1ac5d6fd75b3401c1ed7a38_6486_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Timeless_Gold_and_Red_hu04e88c8527c75cb7c303e1ff17ac7069_6664_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Timeless_Gold_and_Red_hu04e88c8527c75cb7c303e1ff17ac7069_6664_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Ultra_Black_hu85cb7f4ee68f1f0a04961acc9d3784bd_6143_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Ultra_Black_hu85cb7f4ee68f1f0a04961acc9d3784bd_6143_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/WarioWare_MicroBlue_hu7fec166efef6451a3b17aa4b38f89442_6573_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/WarioWare_MicroBlue_hu7fec166efef6451a3b17aa4b38f89442_6573_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Wonder_Purple_huafe95983e505c277ae5ea1433db86f28_6214_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Wonder_Purple_huafe95983e505c277ae5ea1433db86f28_6214_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Yellow_Banana_hu18e213b9efe05f2f55edf82d73db14fd_6342_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Yellow_Banana_hu18e213b9efe05f2f55edf82d73db14fd_6342_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Yoshi_Egg_Green_huf7556583d481af74e9bb0896695a63f8_6317_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Nintendo_Pack/Yoshi_Egg_Green_huf7556583d481af74e9bb0896695a63f8_6317_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="sports-pack">Sports Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Sports_Pack.uf2" title="Sports_Pack.uf2">Sports_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/MLB_Vision_hu37c03d72d1025ad76ef24a79d0928ec6_6207_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/MLB_Vision_hu37c03d72d1025ad76ef24a79d0928ec6_6207_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NASCAR_Ver._hub5c2e3a2bbe154d2d995a0a7ced1f71e_6428_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NASCAR_Ver._hub5c2e3a2bbe154d2d995a0a7ced1f71e_6428_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NBA_Vision_hu3b5950c61811abf35493d83b7ff670b3_6128_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NBA_Vision_hu3b5950c61811abf35493d83b7ff670b3_6128_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NCAA_Blue_hu0fc505c03a88cecf0a94e406d3e09230_6085_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NCAA_Blue_hu0fc505c03a88cecf0a94e406d3e09230_6085_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NFL_Vision_hucad1682bbc29cb20427e4a43c0462fdb_5820_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/NFL_Vision_hucad1682bbc29cb20427e4a43c0462fdb_5820_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Bronze_hu1944b3741da292de45e64f77e2f99ce2_6621_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Bronze_hu1944b3741da292de45e64f77e2f99ce2_6621_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Gold_huc444fe13a654591c1f21d4ffca1b7714_6236_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Gold_huc444fe13a654591c1f21d4ffca1b7714_6236_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Silver_hu1b89e32b8678301fceff34061ee6dc7e_6346_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/Olympic_Silver_hu1b89e32b8678301fceff34061ee6dc7e_6346_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/PGA_Tour_Vision_hu36d52af809375b934de2ae6452e2d96c_6199_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/PGA_Tour_Vision_hu36d52af809375b934de2ae6452e2d96c_6199_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/WWE_White_and_Red_hu15ef906220bed429ef9007374ee1402d_6731_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Sports_Pack/WWE_White_and_Red_hu15ef906220bed429ef9007374ee1402d_6731_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h4 id="traditional-jpn-colors-pack">Traditional JPN Colors Pack</h4>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/Traditional_JPN_Colors_Pack.uf2" title="Traditional_JPN_Colors_Pack.uf2">Traditional_JPN_Colors_Pack.uf2</a></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Aquatic_Iro_hu85dc61bb312ec83eb6fe27f5a2dad41b_6522_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Aquatic_Iro_hu85dc61bb312ec83eb6fe27f5a2dad41b_6522_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Fruity_Orange_huf76bb580734d5a79229de6a23621a489_6443_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Fruity_Orange_huf76bb580734d5a79229de6a23621a489_6443_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Ghostly_Aoi_hu8b4d7b9565a132351e3468564f51665c_6378_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Ghostly_Aoi_hu8b4d7b9565a132351e3468564f51665c_6378_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Golden_Kiiro_hu0e40d090f6cac4bd19625acbc502eaf7_6645_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Golden_Kiiro_hu0e40d090f6cac4bd19625acbc502eaf7_6645_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Lime_Midori_hu42a8074a33a0e3c43447dfa164818889_6545_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Lime_Midori_hu42a8074a33a0e3c43447dfa164818889_6545_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Oni_Aka_hud2987fee40d1181476686d912e2d30a2_6176_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Oni_Aka_hud2987fee40d1181476686d912e2d30a2_6176_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Sakura_Pink_hub1a5a55e69cb11886f73dda06b8895c4_6692_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Sakura_Pink_hub1a5a55e69cb11886f73dda06b8895c4_6692_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Silver_Shiro_hua3f9f092078690784dbf09be29caa4ab_6602_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Silver_Shiro_hua3f9f092078690784dbf09be29caa4ab_6602_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Tea_Midori_hue0a004ff6e0754099d755a15bd746d12_6249_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Tea_Midori_hue0a004ff6e0754099d755a15bd746d12_6249_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Wisteria_Murasaki_hub969e6be47e2aa2fa4de40be03a18770_6652_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250426_open_dmg_display_customization/images/twb64/Traditional_JPN_Colors_Pack/Wisteria_Murasaki_hub969e6be47e2aa2fa4de40be03a18770_6652_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h3 id="full-palette-set-as-csv">Full palette set as CSV</h3>
<p>Author: Patrick Adams (TheWolfBunny64)<br>
Source: <a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a><br>
Download: <a href="./files/TheWolfBunny64_All.csv" title="TheWolfBunny64_All.csv">TheWolfBunny64_All.csv</a></p>
<p>Can be used to create your own selection from the different sets. Just follow the CSV to BIN conversion paragraph.</p>
<h3 id="more-sources-for-palettes">More sources for palettes</h3>
<ul>
<li><a href="https://github.com/davewongillies/openfpga-palettes">https://github.com/davewongillies/openfpga-palettes</a></li>
<li>If you know more let me know</li>
</ul>
<h2 id="link-to-the-python-scripts">Link to the Python Scripts</h2>
<p>-&gt; <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/src/branch/master/scripts">Repository on codeberg.org</a> &lt;-</p>
]]></content>
        </item>
        
        <item>
            <title>Open DMG Display (ODD)</title>
            <link>https://www.embedded-ideas.de/posts/250417_open_dmg_display/</link>
            <pubDate>Thu, 17 Apr 2025 17:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250417_open_dmg_display/</guid>
            <description>TL;DR Fully open-source (GPL licensed) and open hardware (CC-BY-SA licensed) Custom PCB All files available (C code, KiCAD and OpenSCAD) Based on RP2350B or RP235xB when available Features Dimming Palette switching Automatic game detection with palette presets etc. Approx. 20 EUR in parts per unit (for quantities of 5 pcs) Requires minimal modifications to the case Introduction I’ve been thinking about the toys that played an important role during my childhood.</description>
            <content type="html"><![CDATA[<p><img alt="Cover" src="/posts/250417_open_dmg_display/images/cover.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Fully open-source (GPL licensed) and open hardware (CC-BY-SA licensed)</li>
<li>Custom PCB</li>
<li>All files available (C code, KiCAD and OpenSCAD)</li>
<li>Based on RP2350B or RP235xB when available</li>
<li>Features
<ul>
<li>Dimming</li>
<li>Palette switching</li>
<li>Automatic game detection with palette presets</li>
<li>etc.</li>
</ul>
</li>
<li>Approx. 20 EUR in parts per unit (for quantities of 5 pcs)</li>
<li>Requires minimal modifications to the case</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I’ve been thinking about the toys that played an important role during my childhood. Among many others, I had a constant companion that made family reunions bearable: my trusty Game Boy. Unfortunately, I sold my original unit years ago and never used one again. Recently, driven by nostalgia, I bought a model with a broken display on eBay, with the goal of fixing it.</p>
<p>I switched it on, and while there were some lines on the screen, the much bigger issue was that I instantly remembered how poor the LCD was—even back in the day. I did a quick search on how to replace the already broken display with something a bit more modern. While it’s easy to find IPS mods for a DMG, the pricing didn’t seem reasonable.</p>
<p>So, I did the obvious: I started building my own version of such a mod. After spending more money than I would have on any of the available IPS kits, and more time than I originally estimated, I now have exactly what I wanted. To make it easier for others, I&rsquo;m publishing this project here for anyone who might be interested.</p>
<ul>
<li>Features of the Open DMG Display (further called ODD)
<ul>
<li>RP235xB Microcontroller – Affordable, accessible alternative to FPGA solutions.</li>
<li>Custom PCB – Minimal case mod needed.</li>
<li>2-Layer PCB – Cost-effective (ENIG recommended).</li>
<li>3.2&quot; TFT Display – Pixel-perfect, used area matches original size.</li>
<li>Backlight Control – Flicker-free dimming (no PWM).</li>
<li>Multifunction Switch – Replaces contrast wheel; handles UI navigation.</li>
<li>Battery Monitoring – LED, battery warning icon, adjustable settings.</li>
<li>On-Screen Menu</li>
<li>Display Modes - Scanlines and Pixels(experimental)</li>
<li>Game Detection – CRC32-based title screen detection via DMA for auto palette selection</li>
<li>PCB design supports different displays and fast modification.</li>
<li>3D-Printed Frame for the TFT module</li>
<li><em>Update (03.01.2026): Integrated Super Game Boy inspired color plattes for all 32 supported games</em></li>
<li><em>Update (03.01.2026): Integrated Game Boy Color inspired color plattes for all 45 supported games</em></li>
</ul>
</li>
</ul>
<h2 id="what-to-expect--and-what-not-to----ok---">What to Expect – and What Not To <!-- OK --></h2>
<p>This is an open project, not a finalized product. All data and materials are provided as is. If you have questions, I’m happy to help when I have the time — however, support is not guaranteed and responses may be delayed. Bugs in the code and potential hardware issues are to be expected. If you encounter any problems, I’d appreciate it if you report them so the project can continue to improve. If you’re able to fix an issue yourself, contributions are very welcome!</p>
<h2 id="user-interface-----ok---">User interface  <!-- OK --></h2>
<p>The user interface is controlled using the multiswitch, which replaces the contrast wheel of the original LCD board. It can be moved up, moved down, and pressed. There are three different modes:</p>
<ul>
<li>Brightness Adjustment Mode<br>
This is the default mode and allows you to set the display brightness. Simply move the wheel up or down to adjust the brightness level.</li>
<li>Palette Selection Mode<br>
To enter this mode, press the multiswitch briefly. Use the up and down movements to switch between different palettes.</li>
<li>Menu Mode<br>
To access the menu, press and hold the multiswitch (long press). The menu provides access to more advanced features, which will be explained in the following sections.</li>
</ul>
<h3 id="menu----ok---">Menu <!-- OK --></h3>
<ul>
<li>BATT LED DEFAULT
<ul>
<li>ON: The LED will be on when the battery is good</li>
<li>OFF: The LED will be off when the battery is good</li>
</ul>
</li>
<li>BATT LED MODE
<ul>
<li>OFF: LED will always be off</li>
<li>INVERT: Invert the state of the LED when the battery is empty (depending on the BATT LED DEFAULT setting)</li>
<li>PULSE: The LED will start pulsing when empty</li>
<li>BLINK: The LED will start blinking when empty</li>
</ul>
</li>
<li>BATT LED LEVEL
<ul>
<li>Battery LED brightness  (adjustable in three steps)</li>
</ul>
</li>
<li>BATT WARN ON TFT
<ul>
<li>Show an empty battery symbol on the screen when the battery gets empty</li>
</ul>
</li>
<li>BATT TYPE
<ul>
<li>Set battery type dependent thresholds for battery empty detection</li>
</ul>
</li>
<li><del>AUTO PALETTE</del>
<ul>
<li><del>Use automatic game detection and set the palette accordingly</del></li>
</ul>
</li>
<li><em>AUTO PALETTE (changed 03.01.2026)</em>
<ul>
<li>OFF: Disable automatic color palette switching</li>
<li>SGB: Use Super Game Boy–inspired palettes when a supported game is detected</li>
<li>CGB: Use Game Boy Color–inspired palettes when a supported game is detected</li>
<li>USR: Use custom palettes provided by the user (if no custom data is provided, this behaves like OFF)</li>
</ul>
</li>
<li>DISPLAY MODE (experimental)
<ul>
<li>NORMAL: Use four pixels to display one pixel of the game image</li>
<li>LINES: Fill every second line with black (creating a scanline effect)</li>
<li>PIXELS: Only use one pixel for the game image and set the rest to black (creating a pixelated look)</li>
</ul>
</li>
<li>DISPLAY VSYNC
<ul>
<li>GB: Use the driver mode that lets the Game Boy drive the VSYNC (frame timing)</li>
<li>SELF: Use the driver mode that creates the frametiming itself</li>
<li>WARNING! You currently need to restart the device in order to apply the new setting</li>
</ul>
</li>
<li>CUSTOM LOGO
<ul>
<li>If ON: Use the custom logo from NV-Memory. If no valid logo was found, use the demo logo.</li>
</ul>
</li>
<li>SHOW DEBUG INFO
<ul>
<li>Show some data on the screen like battery voltage and the game identifier (<a href="#game-detection">see Game detection</a>)</li>
</ul>
</li>
<li>REBOOT TO BOOTLOADER
<ul>
<li>This will reset the device and start it into the bootloader (same as pressing the <em>USB boot</em> button on startup).</li>
</ul>
</li>
</ul>
<h2 id="implementation-details----ok---">Implementation details <!-- OK --></h2>
<p>I think some aspects of the ODD might be interesting to know, so I explain them briefly.</p>
<h3 id="capturing-the-image-data----ok---">Capturing the image data <!-- OK --></h3>
<p>I wrote a separate blog post about this a while ago. You will find this at <a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/">https://www.embedded-ideas.de/posts/241209_dmg_display_capture/</a></p>
<h3 id="game-detection----ok---">Game detection <!-- OK --></h3>
<p>While searching for suitable color palettes, I came across a repository of palettes for the Super Game Boy. These palettes introduce special 4-color palettes optimized for some of the more popular games. For example, there are custom palettes for Mario games and for Tetris.</p>
<p>The Super Game Boy was able to detect the game and choose the appropriate palette. This was done using the game identification data stored in the game ROM. Unfortunately, the ODD doesn&rsquo;t have access to any memory, so game detection can only be done using the display data.</p>
<p>I came up with the following solution: The DMA controller of the RP235x allows the generation of a CRC32 checksum through its debugging function block (see dma_sniffer functions). This makes it possible to generate a checksum for each captured frame without using any CPU resources. The checksum is constantly monitored until the logo screen&rsquo;s checksum is detected for the first time. We then look for a checksum that is neither the logo screen&rsquo;s nor an empty frame (checksum == 0), and voilà, we have the checksum of the game&rsquo;s title screen.</p>
<p>I tested this method with each game I have on hand, and it looks like this simple approach works like a charm. The final step is to search for the checksum in a table of palettes and activate the corresponding one.</p>
<p>This approach will work for every game as long as it always has the same title screen.</p>
<p><em>Update (03.01.2026): Not only does the Super Game Boy have game-optimized palettes, but the Game Boy Color also offers a variety of color palettes for different games. The ODD has these palettes built in. You can choose between Super Game Boy inspired game palettes, Game Boy Color inspired palettes, or a custom, user-defined palette table.</em></p>
<h3 id="tft-driver-and-vsync-handling----ok---">TFT driver and VSYNC handling <!-- OK --></h3>
<p>The TFT is driven using a parallel RGB interface with 16-bit color (RGB565). This means the signal directly translates to the image on the screen — there’s no frame buffering in RAM like with the more common MCU8080, SPI, or similar interfaces.</p>
<h4 id="pros-and-cons----ok---">Pros and Cons <!-- OK --></h4>
<p>This setup brings some nice advantages, but also a few challenges.</p>
<p>Let’s start with the downsides: Signal generation on the RP2350 is a bit tricky. So far, I haven’t found a clean or elegant solution for a driver. I’ve implemented one which supports two modes of operation (which I’ll explain below), but honestly, I’m not super happy with it in terms of code readability and maintainability. That said, it&rsquo;s working quite well in practice.</p>
<p>Another downside is display initialization. With the RGB interface, it took me some time to get the settings just right to avoid artifacts and flickering. I found <a href="https://tailorpixels.com/quick-understanding-of-the-working-and-phenomenon-of-lcd/">this article</a> that helped explain some of the strange behavior I was seeing. It was a useful starting point — though I’ll admit, I’m far from an expert in this field.</p>
<p>The Upside: Full Display Control - The real advantage of this approach is that you have complete control over the display timing. As long as you stay within acceptable signal margins, the source (here the Game Boy) can effectively control the frame timing of the target display.</p>
<h4 id="driver-mode-1-game-boy-synchronized----ok---">Driver mode 1: Game Boy Synchronized <!-- OK --></h4>
<p>The goal of this mode is to match the Game Boy’s frame timing as closely as possible, without skipping a single frame.</p>
<p>Here’s how it works:</p>
<ul>
<li>The driver is triggered by the capture module after it has captured half of the frame.</li>
<li>It starts a new frame at that moment, transferring the captured data while the rest of the frame gets captured.</li>
<li>This introduces a delay of about 6ms, which I think is acceptable — especially when you compare it to the original Game Boy LCD&rsquo;s refresh behavior.</li>
</ul>
<p><img alt="Synchonization signals of the GB and the TFT" src="/posts/250417_open_dmg_display/images/implementation/tftdrv1_vsync.png"></p>
<p>The Game Boy’s signal isn’t always perfectly consistent. A game can skip clocks to produce visual effects, resulting in frame jitter (longer or shorter frames). Depending on the TFT controller, this can cause flickering.</p>
<p>In my tests, when I stretched the interval between frames to allow for maximum signal jitter from the Game Boy&rsquo;s signal, I did see flicker — so I had to reduce the interval. This worked fine for the displays I used, but I can’t guarantee it will work for every game. Some titles might push the frame length so far that the TFT driver overflows and skips a frame, resulting in visible flicker. (If you find a game that does this, please let me know!)</p>
<p>Another issue: the Game Boy sometimes has blank periods where no frame data is transmitted. The TFT really doesn’t like that. To compensate, the driver detects timeouts and continues displaying the last valid frame while the GB signal is &ldquo;asleep.&rdquo;</p>
<h4 id="driver-mode-2-constant-self-driven----ok---">Driver mode 2: Constant self-driven <!-- OK --></h4>
<p>For good measure, I also added a second mode that runs independently of the Game Boy’s timing. This one simply generates frames at a fixed ~60Hz, always showing the most recently captured GB frame.</p>
<p>This approach ignores GB timing completely, so we lose a frame here and there as we’re sampling a ~55 Hz signal at 60 Hz. You guessed it — Nyquist and Shannon don’t approve <a href="https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem">Sampling Theorem</a>.  Still, for most users and most games, this works just fine.</p>
<p>And if you do run into a compatibility issue or timing problem with the first mode, this can be a solid fallback.</p>
<h3 id="image-overlay-statusbar-menu----ok---">Image overlay (Statusbar, Menu) <!-- OK --></h3>
<p>The menu and other on-screen graphics are implemented as a kind of canvas layered above the actual game image. This canvas uses the lightest (background) and the darkest color of the active palette. It also supports defining areas as either transparent or opaque. The resolution matches the game graphics, ensuring that the interface blends seamlessly with the gameplay. This approach maintains immersion — the additional functionality feels native to the device rather than imposed on top.</p>
<p>I chose this method over using modern graphics libraries like LVGL, etc., as it provides a simpler and more integrated solution. Another benefit is that the canvas can be combined with the game image using basic binary logic operations, making it both lightweight and efficient:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (ui<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>; ui <span style="color:#f92672">&lt;</span> MAIN_WORDS_PER_LINE; ui<span style="color:#f92672">++</span>) <span style="color:#75715e">// Overlay image insertion (for menus etc.)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
</span></span><span style="display:flex;"><span>    ((<span style="color:#66d9ef">uint32_t</span><span style="color:#f92672">*</span>)pucLineData)[ui] <span style="color:#f92672">&amp;=</span> odd_display_aulOverlayMask[uiLine <span style="color:#f92672">*</span> MAIN_WORDS_PER_LINE <span style="color:#f92672">+</span> ui]; <span style="color:#75715e">// Clear DMG screen where mask is set to 0
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    ((<span style="color:#66d9ef">uint32_t</span><span style="color:#f92672">*</span>)pucLineData)[ui] <span style="color:#f92672">|=</span> odd_display_aulOverlay[uiLine <span style="color:#f92672">*</span> MAIN_WORDS_PER_LINE <span style="color:#f92672">+</span> ui];     <span style="color:#75715e">// Add overlay image data
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span></code></pre></div><h2 id="design-choices----ok---">Design choices <!-- OK --></h2>
<p>Some parts of the design might seem a bit odd and need some explanation. I will therefore tell a bit about why I chose to do it this way. Maybe you have a better idea — so we can use this text as a basis for discussion ;)</p>
<h3 id="display-selection----ok---">Display selection <!-- OK --></h3>
<p>It took me quite a while to find a reasonably sized display for this project. The original aspect ratio of the Game Boy isn’t very common these days—especially when you&rsquo;re aiming for a specific resolution that enables pixel-perfect rendering of the DMG’s 160×144px image.</p>
<p>I initially explored various 2.x&quot; displays that closely matched the physical dimensions of the original LCD. Unfortunately, most of them came with a resolution of 160×128px.</p>
<p>Eventually, I abandoned the idea of a landscape-oriented display and started searching for a portrait-oriented alternative. This approach made the search much easier. I settled on using 3.2&quot; screens, which almost perfectly match the original screen size when mounted vertically. The chosen resolution is 320×480px—ideal for mapping the Game Boy&rsquo;s 160px width perfectly when using 4 pixels per pixel. As for the vertical resolution, we do end up with 192 unused pixels, but that’s a trade-off I’m willing to accept.</p>
<p>These types of displays aren’t extremely common, but they’re not hard to find either. In the final design, I added support for two different displays. Both use the HIMAX HX8357-A01 chipset and share the same resolution and physical dimensions. However, they differ in backlight technology, TFT type, and connector.</p>
<p>Why go through all this effort?</p>
<ul>
<li>Sourcing stability: I believe the display is the most likely component to become difficult to source over time. Supporting two display options increases longevity and flexibility.</li>
<li>Flexible routing: The two connector variants allowed me to create a PCB layout that can be easily adapted to support other displays in the future.</li>
<li>Backlight versatility:<br>
There are two common approaches to LED backlighting:
<ul>
<li>Parallel configuration is simpler and often runs off the logic supply (typically 3.3V), which makes it easy to implement. However, it can lead to uneven illumination.</li>
<li>Series configuration eliminates uneven lighting but requires a higher voltage and a more complex boost circuit.</li>
</ul>
</li>
</ul>
<p>To accommodate both types, the board includes support for both backlight circuits: a step-down and a step-up converter, both capable of dimming without using PWM (to avoid backlight flicker). This means you can adapt the board to future display modules without needing a complete redesign.</p>
<p>Currently the board supports the following physical displays</p>
<ul>
<li>
<p>JJY3202-05-Z-A</p>
<ul>
<li>3.2 inch IPS TFT</li>
<li>6 LED backlight (series) ~19.2V</li>
<li>45 pin .3 pitch connector</li>
<li>45.12mm x 67.68mm active area</li>
<li>Ecyberspaces via AliExpress (<a href="https://de.aliexpress.com/item/32632665396.html">https://de.aliexpress.com/item/32632665396.html</a>)</li>
</ul>
</li>
<li>
<p>TT320LHN10A</p>
<ul>
<li><strong>WARNING! The init code for this display isn&rsquo;t ready yet. There might be flicker and/or artefacts when using it. I would currently recommend using the JJY3202-05-Z-A.</strong></li>
<li>3.2 inch IPS TFT</li>
<li>6 LED backlight (parallel) ~3.2V</li>
<li>40 pin .5 pitch connector</li>
<li>45.12mm x 67.45mm</li>
<li>Sources
<ul>
<li>Spring Trend Limited <a href="http://stldisplays.com/">http://stldisplays.com/</a> (OEM)</li>
<li>Shenzhen Toppop Electronic Co.,Ltd  <a href="https://toppoplcd.com/productdetails_5252259.html">https://toppoplcd.com/productdetails_5252259.html</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="pcb----ok---">PCB <!-- OK --></h3>
<p>I have chosen to use a 2-layer PCB to keep the cost down. If you don’t opt for a special surface finish, you could order 5 boards for around 7 EUR. With ENIG (which I recommend for the button contacts), the cost increases to about 23 EUR for 5 pieces. A 4-layer design would at least double these numbers.</p>
<p>The chosen thickness of 1.6mm is required to provide enough clearance for the multi-purpose switch on the left side. The multi-purpose switch would not have fit with the original 1mm PCB thickness of the genuine display.</p>
<h3 id="usb-connector-placement----ok---">USB connector placement <!-- OK --></h3>
<p>The USB connector is not intended for regular use, nor is it meant to be accessed through a cutout in the case. It is designed solely to provide a way to upload the firmware onto the device after it has been built, functioning like an internal flash programmer. If you really want to, you might be able to add a cutout to the DMG shell and use a cable with a long tip.</p>
<h3 id="125mm-pitch-ffc-connector-to-the-gameboy----ok---">1.25mm pitch FFC connector to the gameboy <!-- OK --></h3>
<p>Flat flex cable connectors with a 1.25mm pitch are not very common these days. You can easily find 0.3mm, 0.5mm, and 1.0mm pitch connectors, but 1.25mm connectors are rarely available at a reasonable price point. Therefore, I’ve added solder pads that allow for directly soldering a 1.25mm pitch FFC onto the board. This method is not intended for mass production and is more time-consuming compared to soldering a simple connector. If you&rsquo;re willing to invest, you might consider designing a flex PCB optimized for this use case.</p>
<p>In addition to the solder pads, there is also an extra footprint for a 0.5mm pitch connector, which includes all the relevant signals. This is intended for use with a custom flex PCB adapter that I may design in the future. This connector is currently untested.</p>
<h2 id="assembly">Assembly</h2>
<p>You will need the following parts:</p>
<ul>
<li>PCB and stencil (JLCPCB, PCBWay, multi-cb, etc.)</li>
<li>Components according to BOM (DigiKey, Mouser, LCSC, etc.)</li>
<li>1.25mm pitch FFC cable (AliExpress or eBay)</li>
<li>TFT display (<a href="#display-selection">see display selection</a>)</li>
<li>4x M2 screws with 5mm length (for the display frame)</li>
<li>Display frame top and bottom (3D-printed)</li>
<li>Consider buying an after market Game Boy case in order to not modify your original one (AliExpress, eBay)</li>
</ul>
<h3 id="pcb-assembly----ok---">PCB assembly <!-- OK --></h3>
<p>You’ll need some soldering experience, but it’s not as difficult as you might think. I cover the process of assembling the critical components with basic tools in this post:
<a href="https://www.embedded-ideas.de/posts/250407_hotplate_soldering">Manual Assembly of Modern PCBs Using Low-Cost Tools</a>.</p>
<p>If you’ve ever wanted to get into micro soldering, this project is a great place to start.</p>
<p>I recommend using the provided interactive BOM during assembly — it really helps streamline the process.</p>
<h3 id="ffc-cable-soldering----ok---">FFC Cable Soldering <!-- OK --></h3>
<p>In addition to assembling the PCB, you’ll need to solder the FFC cable to the board. This part is a bit messy. As mentioned, getting connectors with the right pitch can be tricky, so we’ll need to improvise.</p>
<p>You&rsquo;ll need:</p>
<ul>
<li>A 1.25 mm pitch FFC cable (100 mm length; shorter may also work)</li>
<li>Some tape (e.g., Kapton tape)</li>
<li>A hot air tool</li>
<li>Patience</li>
</ul>
<p>Steps:</p>
<ol>
<li>Remove the stiffener from one side of the FFC using hot air (~100 °C).</li>
<li>Carefully lift each individual trace with a knife or sharp tweezers. Doing this on a hotplate makes it easier.<br>
Be careful not to burn yourself and use a safe working temperature.</li>
<li>Once all traces are lifted, trim the excess plastic beneath the traces.</li>
<li>Bend the traces downward slightly so they apply some pressure against the board.</li>
<li>Align the traces with the pads on the board and fix them in place with tape.</li>
<li>Solder the traces, and optionally add strain relief with additional tape.</li>
</ol>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/01_hu0aef7289ac4c21d02f3162028785ad0d_1053964_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/01_hu0aef7289ac4c21d02f3162028785ad0d_1053964_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/02_hu0aef7289ac4c21d02f3162028785ad0d_1000371_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/02_hu0aef7289ac4c21d02f3162028785ad0d_1000371_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/03_hu0aef7289ac4c21d02f3162028785ad0d_978914_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/03_hu0aef7289ac4c21d02f3162028785ad0d_978914_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/04_hu0aef7289ac4c21d02f3162028785ad0d_1054235_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/04_hu0aef7289ac4c21d02f3162028785ad0d_1054235_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/05_hu0aef7289ac4c21d02f3162028785ad0d_1165448_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/05_hu0aef7289ac4c21d02f3162028785ad0d_1165448_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/06_hu0aef7289ac4c21d02f3162028785ad0d_1088768_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/ffc/06_hu0aef7289ac4c21d02f3162028785ad0d_1088768_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h4 id="quick--dirty-method-not-recommended">Quick &amp; Dirty Method (Not Recommended)</h4>
<p>If you&rsquo;re looking to speed things up — and don’t mind the smell of burning mystery plastic — you can skip most of the above and align the FFC directly after removing the stiffener.</p>
<p><strong>Warning: This method will probably burn part of the FFC. Proceed at your own risk.</strong></p>
<p><img alt="Direct soldering without plastic removal" src="/posts/250417_open_dmg_display/images/assembly/ffc_melted.JPG"></p>
<h3 id="display-frame----ok---">Display frame <!-- OK --></h3>
<p>The frame is 3D printed. I used a standard layer height of 0.2 mm with a 0.4 mm nozzle. PETG is a good material choice for printing the frame, though a flexible PLA blend could also work well.</p>
<p>The frame is attached to the PCB using four 5 mm M2 screws. If you have appropriately sized self-tapping screws, those can be a suitable alternative.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/01_hu0aef7289ac4c21d02f3162028785ad0d_2034995_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/01_hu0aef7289ac4c21d02f3162028785ad0d_2034995_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/02_hu1844975e7fa4c62a29b4d1562e19b739_2760973_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/02_hu1844975e7fa4c62a29b4d1562e19b739_2760973_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/03_hu9f02224eba793446ee3fe5573bec6509_416146_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/03_hu9f02224eba793446ee3fe5573bec6509_416146_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/04_hua79fdc643fd103c06dba34deafed9ddc_521720_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/04_hua79fdc643fd103c06dba34deafed9ddc_521720_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/05_hu37b192ba2acabac4a418adb415089cf3_267095_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/05_hu37b192ba2acabac4a418adb415089cf3_267095_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/06_hu8a37d93e774b8e1ed117277a721a5dd3_389091_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/06_hu8a37d93e774b8e1ed117277a721a5dd3_389091_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/07_hu31cd6c583f9912454851e3ea08ed0722_303242_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/display_frame/07_hu31cd6c583f9912454851e3ea08ed0722_303242_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="flashing-the-firmware----ok---">Flashing the firmware <!-- OK --></h3>
<p>Connect the ODD to a PC using a USB cable. While holding down the <em>USB BOOT</em> button, apply power to the board. There are two ways to do this:</p>
<ol>
<li>Recommended: Close jumper JP1 to power the ODD via the USB cable.<br>
<strong>Important: If you choose this method, never switch on the Game Boy while the USB cable is attached!</strong></li>
<li>Leave JP1 open and power the board via the Game Boy mainboard instead.</li>
</ol>
<p>Once connected, a virtual drive will appear on your computer. Simply copy the supplied UF2 file onto the drive — and you&rsquo;re done!</p>
<h3 id="case-preparation-and-board-installation----ok---">Case preparation and board installation <!-- OK --></h3>
<p>Next, remove the protective film from the TFT. Carefully lower the board into the case, making sure the speaker is seated correctly. Pay close attention to the routing of the speaker cables. Use the Phillips screws to secure the board in place.</p>
<p>Note: The ODD PCB is slightly thicker (0.6 mm) than the original PCB. As a result, the back shell may not close perfectly. You’ll need to file down some of the board rests on the back shell. Take your time and check the fit frequently. You may also want to use a caliper to measure your progress for accuracy.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/01_hu1d5bd1c8573274eca360795eed87d3b2_331169_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/01_hu1d5bd1c8573274eca360795eed87d3b2_331169_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/02_hu0aef7289ac4c21d02f3162028785ad0d_1220280_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/02_hu0aef7289ac4c21d02f3162028785ad0d_1220280_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/03_hu0aef7289ac4c21d02f3162028785ad0d_1605753_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/03_hu0aef7289ac4c21d02f3162028785ad0d_1605753_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/04_hu0aef7289ac4c21d02f3162028785ad0d_1660832_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/04_hu0aef7289ac4c21d02f3162028785ad0d_1660832_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/05_hu0aef7289ac4c21d02f3162028785ad0d_1238798_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/05_hu0aef7289ac4c21d02f3162028785ad0d_1238798_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/06_hu0aef7289ac4c21d02f3162028785ad0d_1578514_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/06_hu0aef7289ac4c21d02f3162028785ad0d_1578514_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/07_hua32d2aa3454e41ccc56f6b193e394c13_365126_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/07_hua32d2aa3454e41ccc56f6b193e394c13_365126_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/08_hu0aef7289ac4c21d02f3162028785ad0d_820752_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/08_hu0aef7289ac4c21d02f3162028785ad0d_820752_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/09_hu991038f7de517ea80e543e76348524c2_85900_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/09_hu991038f7de517ea80e543e76348524c2_85900_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/10_hu559e6d957678be02611464150e682c19_140036_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250417_open_dmg_display/images/assembly/case_prep/10_hu559e6d957678be02611464150e682c19_140036_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="unused-circuitry----ok---">Unused circuitry <!-- OK --></h2>
<p>There are some unused, or DNP (Do Not Populate), components on the board. Here’s an explanation of what to do with them:</p>
<ul>
<li>Connector J3
<ul>
<li>Can be used to design a flex PCB as a replacement for the 1.25 mm FFC cable.</li>
<li>UNTESTED!</li>
</ul>
</li>
<li>Op-Amp U4
<ul>
<li>If you’re aiming for the most precise battery measurement in the history of the DMG—or if you want to overclock the ADC—this one’s for you.</li>
</ul>
</li>
<li>Resistors R22, R23
<ul>
<li>I initially thought the negative rail might need some load. That doesn&rsquo;t seem to be the case, so I decided not to use them.</li>
</ul>
</li>
<li>Capacitors C37, C39, C38, C40
<ul>
<li>If you want better compliance, or if you experience noise, you can experiment with these values. They’re intended for decoupling the ODD supply from the Game Boy mainboard.</li>
<li>So far, the regulator caps in combination with the larger electrolytic capacitor have worked fine for me.</li>
</ul>
</li>
</ul>
<h2 id="thanks----ok---">Thanks <!-- OK --></h2>
<p>I used several resources that really helped speed things up:</p>
<ul>
<li>DMG LCD scans
<ul>
<li>bit9 on chipmusic.org</li>
<li><a href="https://chipmusic.org/forums/post/215957/#p215957">https://chipmusic.org/forums/post/215957/#p215957</a></li>
</ul>
</li>
<li>Schematics
<ul>
<li>Gekkio on github</li>
<li><a href="https://github.com/Gekkio/gb-schematics/blob/main/DMG-LCD-06/schematic/DMG-LCD-06.pdf">https://github.com/Gekkio/gb-schematics/blob/main/DMG-LCD-06/schematic/DMG-LCD-06.pdf</a></li>
</ul>
</li>
<li>Color Palettes
<ul>
<li>TheWolfBunny64 (<a href="https://thewolfbunny64.itch.io/game-boy-custom-palettes">https://thewolfbunny64.itch.io/game-boy-custom-palettes</a>)</li>
<li>AdvancedFan2020 (<a href="https://www.deviantart.com/advancedfan2020">https://www.deviantart.com/advancedfan2020</a>)</li>
</ul>
</li>
<li>Font
<ul>
<li>vyznev on fontstruct.com</li>
<li>Pascal Stang via glcd library</li>
</ul>
</li>
<li>PIO
<ul>
<li>A big thank you to the Raspberry Pi team for the PIO units. I believe peripherals like this should have been available years ago!</li>
</ul>
</li>
<li><em>Game Dependent Color Palettes (updated 03.01.2026)</em>
<ul>
<li><em>VIS modding for providing all missing game checksums for the 32 Super Gameboy palettes (<a href="https://github.com/VISmodding">https://github.com/VISmodding</a>)</em></li>
<li><em>VIS modding for providing all game checksums for the 45 Game Boy Color games (<a href="https://github.com/VISmodding">https://github.com/VISmodding</a>)</em></li>
<li><em>R.A.Helllford for providing the palette data (found on <a href="https://github.com/davewongillies/openfpga-palettes">https://github.com/davewongillies/openfpga-palettes</a>)</em></li>
</ul>
</li>
</ul>
<h2 id="files">Files</h2>
<p>Sourcecode and release binaries are hosted on codeberg.org</p>
<ul>
<li>
<p>Hardware</p>
<ul>
<li>GIT-Repository: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-HW/">https://codeberg.org/embedded-ideas/OpenDmgDisplay-HW/</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-HW/releases">https://codeberg.org/embedded-ideas/OpenDmgDisplay-HW/releases</a></li>
</ul>
</li>
<li>
<p>Software</p>
<ul>
<li>GIT-Repository: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/">https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/</a></li>
<li>Releases: <a href="https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/releases">https://codeberg.org/embedded-ideas/OpenDmgDisplay-SW/releases</a></li>
</ul>
</li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Manual Assembly of Modern PCBs Using Low-Cost Tools</title>
            <link>https://www.embedded-ideas.de/posts/250407_hotplate_soldering/</link>
            <pubDate>Mon, 07 Apr 2025 17:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250407_hotplate_soldering/</guid>
            <description>TL;DR I describe the process of assembling a PCB with some somewhat challenging components using only low-cost tools, like a ~10 USD hotplate. The result isn&amp;rsquo;t perfect, but it&amp;rsquo;s still very good for a manually assembled board.
Introduction I think that in electronics, microsoldering has become a necessary skill for professionals and aspiring hobbyists alike. On a professional level, you should be able to make small modifications to a prototype board yourself.</description>
            <content type="html"><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>I describe the process of assembling a PCB with some somewhat challenging components using only low-cost tools, like a ~10 USD hotplate. The result isn&rsquo;t perfect, but it&rsquo;s still very good for a manually assembled board.</p>
<p><img alt="Tool overview" src="/posts/250407_hotplate_soldering/images/overview.JPG"></p>
<h2 id="introduction">Introduction</h2>
<p>I think that in electronics, microsoldering has become a necessary skill for professionals and aspiring hobbyists alike. On a professional level, you should be able to make small modifications to a prototype board yourself. As a hobbyist, you need this skill in order to use modern components on your mostly manually assembled PCBs.</p>
<p>I recently worked a lot with the RP2040 and the RP2350B, which are well known to many people as the Pi Pico and Pi Pico 2, respectively. Maybe you’ve considered a project using one of these chips but changed your mind after discovering that they are only available in a QFN package.</p>
<p>With this post, I’m documenting my assembly process to show that soldering these types of components isn’t as hard as you might think, as long as you’re using the right tools. To make this even more accessible, I limited myself to basic equipment and more affordable consumables. The result may not be perfect, but it is far better than just “working.”</p>
<h2 id="board-and-equipment">Board and equipment</h2>
<p>As an example, I’m using one of my recent prototypes for the Open DMG Display, along with the corresponding <strong>stencil</strong>. The tools are mostly available through sites like AliExpress, eBay, etc.</p>
<p><img alt="Tools" src="/posts/250407_hotplate_soldering/images/tools.JPG"></p>
<ul>
<li><strong>USB-C Mini Hotplate</strong> – 12.99 EUR incl. VAT (<a href="https://de.aliexpress.com/item/1005007060803946.html">Link</a>)
<ul>
<li>These mini hotplates are really cheap compared to a hot air station. When it comes to board assembly, I would absolutely choose one of these over any hot air station for assembling new boards.</li>
</ul>
</li>
<li><strong>Low Temperature Sn42Bi58 Solder Paste OL-3016</strong> – 4.07 EUR incl. VAT (<a href="https://de.aliexpress.com/item/1005006023229246.html">Link</a>)
<ul>
<li>This paste is a bit strange. It’s more like a fluid than a paste, but it is still possible to work with.</li>
</ul>
</li>
<li><strong>Gel Flux OT-338</strong> – 6.39 EUR incl. VAT (<a href="https://de.aliexpress.com/item/1005006472181493.html">Link</a>)
<ul>
<li>Surprisingly good flux.</li>
</ul>
</li>
<li><strong>Pinecil</strong> – 25.99 USD (<a href="https://pine64.com/product/pinecil-smart-mini-portable-soldering-iron/">Link</a>)
<ul>
<li>I have this around for field use and small modifications on the desk.</li>
</ul>
</li>
<li><strong>TS-BC2 TS100 Iron Tip</strong> – ~10 USD
<ul>
<li>The Pinecil comes with a conical tip. Do yourself a favor and get a chisel or beveled tip.</li>
<li>Avoid using the really small ones. It might sound counterintuitive, but it&rsquo;s easier to use a decent tip size.</li>
</ul>
</li>
<li><strong>KELLYSHUN Solder Wick</strong> (came with the paste)</li>
<li><strong>0.5mm Solder Wire with High Sn</strong> (e.g., Sn99.3Cu0.7)
<ul>
<li>I used my usual high-quality solder wire here, but I don’t think this counts as cheating.</li>
</ul>
</li>
<li><strong>Bent Tweezers</strong> – 1.89 EUR incl. VAT (<a href="https://de.aliexpress.com/item/1005004558137618.html">Link</a>)
<ul>
<li>I also use those as a daily driver</li>
</ul>
</li>
<li><strong>Metal Spatula or Old Credit Card</strong></li>
</ul>
<p>Besides the soldering equipment, you will need some sort of magnification. I would not recommend magnifying glasses. If you don&rsquo;t have a lot of money to spend, use a USB camera with some clearance for soldering. I had one from Andonstar, which did a good job: <a href="https://de.aliexpress.com/item/1005008647068869.html">Link</a>. If you want to invest more, buy a proper stereo microscope.</p>
<p>I expect you to have a suitable USB-C power supply for the hotplate and the Pinecil.</p>
<h2 id="the-process">The process</h2>
<p>I&rsquo;m using a hotplate process. In my opinion, this is a much more controlled and much easier process compared to using a cheap hot air station. You don&rsquo;t have to worry about larger ground planes or uneven heating.</p>
<p>I started with the preparation of the PCB. I like to use other boards of the same height to build a temporary frame that holds the board in place. I used Kapton tape for this, but any type of tape works fine. Before aligning the stencil, I give the board a good wipe with some IPA.</p>
<p><img alt="Board preparation" src="/posts/250407_hotplate_soldering/images/01.JPG"></p>
<p>The alignment of the stencil is crucial but doesn&rsquo;t have to be within µm. Make sure the pads are aligned not only locally but also in other places on the board. Check diagonally at the upper left and the lower right. If your board has fiducials, use those.</p>
<p><img alt="Stencil alignment" src="/posts/250407_hotplate_soldering/images/02.JPG"></p>
<p><img alt="Stencil alignment microscope" src="/posts/250407_hotplate_soldering/images/03.JPG"></p>
<p>After the alignment, tape the stencil at the upper corner to create a hinge. I forgot to take a picture of this, but you can see it in the picture with the solder paste.</p>
<p>Apply the perfect amount of solder paste above the area you want to assemble ;) In this example, I only want to assemble a part of the board that has the critical components that can&rsquo;t be soldered with an iron. You also have to take into account that the space on the hotplate is limited.</p>
<p><img alt="Solder paste" src="/posts/250407_hotplate_soldering/images/04.JPG"></p>
<p>As I mentioned, the solder paste I used was quite liquid. I initially took multiple strokes with the spatula, which resulted in a horrible outcome. The paste just spread under the stencil, and the board was completely covered.</p>
<p>If this happens to you, don&rsquo;t worry. Clean everything up with some IPA and try again. On my second attempt, I only used one stroke, which worked quite well.</p>
<p><img alt="Solder paste applied" src="/posts/250407_hotplate_soldering/images/05.JPG"></p>
<p>The result isn&rsquo;t perfect, but you can clearly see the pad shapes even on the small-pitch parts. You shouldn&rsquo;t worry if there&rsquo;s a bit too much paste in those places. The paste will distribute itself as long as it’s roughly in the right place.</p>
<p>It is now time to start the assembly process. I recommend getting everything in place before you start assembling.</p>
<p><img alt="Preparation" src="/posts/250407_hotplate_soldering/images/06.JPG"></p>
<p>First, place the parts you can&rsquo;t solder with an iron. I started with the QFN80 here.</p>
<p><img alt="QFN80 placing" src="/posts/250407_hotplate_soldering/images/placing01.JPG"></p>
<p>I dropped it a bit misaligned and smeared some of the paste around. Normally, this is not a problem. I corrected the alignment and placed the oscillator, the flash, and the 45-pin FFC connector, followed by the other parts whose pads were covered with paste.</p>
<p><img alt="QFN80 alignment" src="/posts/250407_hotplate_soldering/images/placing02.JPG"></p>
<p><img alt="Component placement" src="/posts/250407_hotplate_soldering/images/placing03.JPG"></p>
<p>Now the board is ready for soldering using the hotplate. With the low-temperature paste I used, the following temperature profile was applied:</p>
<ul>
<li>60s at 110°C</li>
<li>150s at 170°C</li>
<li>100s at 220°C</li>
<li>Switch off for cooldown</li>
</ul>
<p>Unfortunately, this needs to be done manually with the hotplate. That&rsquo;s one of the reasons you might consider something like the MHP50 if you do this type of work more often.</p>
<p><img alt="Hotplate" src="/posts/250407_hotplate_soldering/images/soldering01.JPG"></p>
<p>I really like watching this process. The solder paste starts to melt, and shortly after, everything aligns itself. If something doesn’t align properly, you can use the tweezers to gently wiggle it until it sits perfectly.</p>
<p>As expected, my result wasn&rsquo;t perfect but absolutely fine for a hand-assembled board. The only thing that was expected was a lot of bridging on the QFN80 package.</p>
<p><img alt="Soldered PCB" src="/posts/250407_hotplate_soldering/images/soldered01.JPG"></p>
<p><img alt="QFN80 bridging" src="/posts/250407_hotplate_soldering/images/soldered02.JPG"></p>
<p>This is not a problem at all. Just use some flux and drag your iron along the sides of the IC.</p>
<p><img alt="Soldered PCB" src="/posts/250407_hotplate_soldering/images/flux01.JPG"></p>
<p><img alt="QFN80 bridging" src="/posts/250407_hotplate_soldering/images/flux02.JPG"></p>
<p>This is how it looks after some cleanup with IPA.</p>
<p><img alt="QFN80 bridging" src="/posts/250407_hotplate_soldering/images/flux03.JPG"></p>
<p><img alt="Result after reflow" src="/posts/250407_hotplate_soldering/images/flux04.JPG"></p>
<p>The only thing left to do is soldering the components that haven&rsquo;t been covered with the solder paste. Again, you should carefully decide which components you&rsquo;d like to solder with the hotplate, as the area is limited to the size of the heat bed. The used hotplate allows for a 55mm x 55mm area.</p>
<h2 id="result-and-conclusion">Result and conclusion</h2>
<p>The result looks OK overall. It works fine, and I&rsquo;ve seen much worse. There are some misaligned passives, and a few pads had a little too much paste. I was surprised by the cheap flux—it really did a great job. The hotplate also worked much better than I expected. The solder paste was a bit strange and caused some bridging due to its liquid nature (and me dropping components). Working with the Pinecil feels a bit unusual, to be honest. I missed the round shape of my other soldering iron, especially with the beveled tip.</p>
<p>Overall, there is nothing wrong with the tools and consumables. It&rsquo;s quite easy to hand assemble modern components with low-cost equipment. Just give it a try.</p>
<p><img alt="Overview" src="/posts/250407_hotplate_soldering/images/result01.JPG"></p>
<p><img alt="Misaligned" src="/posts/250407_hotplate_soldering/images/result02.JPG"></p>
<p><img alt="To much paste" src="/posts/250407_hotplate_soldering/images/result03.JPG"></p>
]]></content>
        </item>
        
        <item>
            <title>SMD component storage for manual assembly</title>
            <link>https://www.embedded-ideas.de/posts/250402_smd_storage/</link>
            <pubDate>Wed, 02 Apr 2025 01:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250402_smd_storage/</guid>
            <description>TL;DR See pictures ;) Files below Introduction I sometimes work on projects where I need to assemble multiple PCBs or iterate on a project using almost the same components for each prototype. I prefer doing these assemblies manually, as, in my opinion, it speeds up the process when dealing with prototypes. A recurring problem for me is handling components stored in small zipper bags within boxes of components in small zipper bags.</description>
            <content type="html"><![CDATA[<p><img alt="Project Overview" src="/posts/250402_smd_storage/images/promo/00.JPG"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>See pictures ;)</li>
<li>Files below</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I sometimes work on projects where I need to assemble multiple PCBs or iterate on a project using almost the same components for each prototype. I prefer doing these assemblies manually, as, in my opinion, it speeds up the process when dealing with prototypes. A recurring problem for me is handling components stored in small zipper bags within boxes of components in small zipper bags. I often feel like I spend more time searching for parts than placing and soldering them. This becomes especially problematic when the assembly process is fragmented. If I assemble three PCBs one weekend and another three the next, I end up wasting a lot of time just getting everything ready.</p>
<p>For a recent project, I wanted to approach things differently. The components needed to be stored with the project in a way that allows me to start assembling as soon as I pull them out of the drawer. I found a convenient way to store passives on 8mm tape. Several people had published some excellent 3D printable designs for this exact purpose, so I tried out the most promising one. Overall, it worked well, but I wanted a few modifications. Besides the passives, I needed storage for lower-count parts, like ICs, inductors, etc. I envisioned a sort of tray that would allow me to insert component tapes, securing them in a way that prevents them from falling off but still lets me pull them out easily during assembly. Unfortunately, I couldn&rsquo;t find anything pre-made that fit these needs, especially not a storage solution optimized for the specific components I use for my project. So, I decided to design it myself.</p>
<h2 id="parametric-smd-storage-tray">Parametric SMD storage tray</h2>
<p><img alt="SMD Containers" src="/posts/250402_smd_storage/images/tray_promo/00.JPG">
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/00_hu0aef7289ac4c21d02f3162028785ad0d_1354306_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/00_hu0aef7289ac4c21d02f3162028785ad0d_1354306_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/01_hu0aef7289ac4c21d02f3162028785ad0d_1259417_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/01_hu0aef7289ac4c21d02f3162028785ad0d_1259417_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/02_hu0aef7289ac4c21d02f3162028785ad0d_1026483_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_promo/02_hu0aef7289ac4c21d02f3162028785ad0d_1026483_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>
</p>
<p>The goals for this design were to provide a space saving method to store component tapes of different sizes that also lets you directly use the components for assembly. I came up with a design which, at least for me, solves the problem.</p>
<p>It</p>
<ul>
<li>&hellip; is fully parametric</li>
<li>&hellip; is fully 3D printable (no additional parts required)</li>
<li>&hellip; supports labeling (flat surface)</li>
<li>&hellip; supports waterproof markers</li>
<li>&hellip; has an integrated spring mechanism to securely hold the tapes</li>
<li>&hellip; has a cover tape slot</li>
<li>&hellip; makes a satisfying click when correctly assembled</li>
</ul>
<p>To modify the design to suit your needs, you will need to use OpenSCAD (<a href="https://www.openscad.org">https://www.openscad.org</a>). If you&rsquo;re not familiar with it, don’t worry. The only thing you need to do is provide table-like data. You’ll need to describe the dimensions of the tape using seven values, along with an additional parameter to define the tolerance.</p>
<pre tabindex="0"><code>tape([ 12.0, 2.7, 0.5, 1.0, 3.0, 1.0, 3.0], 0.2),
tape([  8.0, 1.3, 0.3, 1.0, 3.5, 1.0, 3.5], 0.2),
tape([    w,   h,  ht, wsl, wsr, wtl, wtr], tolerance),
</code></pre><p>Each line represents one rail on the tray. All values are in mm. The diagram should make things a bit clearer:</p>
<p><img alt="Tape Dimensions" src="/posts/250402_smd_storage/images/tape_dimensions.png"></p>
<p>In addition to the custom dimensions, I’ve also included some generic presets that should fit most 8mm, 12mm, and 16mm tapes. I’ve provided two examples in the SCAD file to help you get started. After editing the dimensions, you will need to compile the model (F6) and export the STL (F7).</p>
<p>For those who don’t want to modify the design, I’ve generated trays with 8x8mm, 8x12mm, and 8x16mm slots, each with a length of 150mm, using the generic presets. If you want to test if your tapes fit the presets, there is also a pre-generated tester model.</p>
<p>Hope you like it!</p>
<h3 id="build">Build</h3>
<h4 id="print-settings">Print settings</h4>
<ul>
<li>Use a flat bed for printing</li>
<li>.2mm layers</li>
<li>.4 nozzle</li>
<li>I had really good results with PLA+</li>
</ul>
<h4 id="assembly">Assembly</h4>
<p>Just slide the two halfs together until you hear a click.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/01_hu0aef7289ac4c21d02f3162028785ad0d_1025022_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/01_hu0aef7289ac4c21d02f3162028785ad0d_1025022_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/02_hu0aef7289ac4c21d02f3162028785ad0d_999417_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/02_hu0aef7289ac4c21d02f3162028785ad0d_999417_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/03_hu0aef7289ac4c21d02f3162028785ad0d_988289_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/03_hu0aef7289ac4c21d02f3162028785ad0d_988289_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/04_hu0aef7289ac4c21d02f3162028785ad0d_963532_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/04_hu0aef7289ac4c21d02f3162028785ad0d_963532_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/05_hu0aef7289ac4c21d02f3162028785ad0d_1012575_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/tray_assembly/05_hu0aef7289ac4c21d02f3162028785ad0d_1012575_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="smd-component-containers-on-a-rail">SMD component containers on a rail</h2>
<p><img alt="SMD Containers" src="/posts/250402_smd_storage/images/container_promo/00.JPG">
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/00_hu1857f2ae3316de2e3e0937184dc667a4_7835409_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/00_hu1857f2ae3316de2e3e0937184dc667a4_7835409_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/01_hu1857f2ae3316de2e3e0937184dc667a4_8070784_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/01_hu1857f2ae3316de2e3e0937184dc667a4_8070784_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/02_hu1857f2ae3316de2e3e0937184dc667a4_7833468_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/02_hu1857f2ae3316de2e3e0937184dc667a4_7833468_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/03_hu0aef7289ac4c21d02f3162028785ad0d_811372_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_promo/03_hu0aef7289ac4c21d02f3162028785ad0d_811372_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>
</p>
<p>The original model was designed by @LordAsdi_1250566 and published on Printables.com (<a href="https://www.printables.com/model/580643-smd-component-tape-magazine-8-12-16mm)">https://www.printables.com/model/580643-smd-component-tape-magazine-8-12-16mm)</a>. He mentioned that he was inspired by Robin Reiter, who had also published a 3D printable design earlier (<a href="https://www.thingiverse.com/thing:3952021)">https://www.thingiverse.com/thing:3952021)</a>, which, in turn, was inspired by Maxint, who may have had the idea in the first place (<a href="https://www.thingiverse.com/thing:2186862)">https://www.thingiverse.com/thing:2186862)</a>. In any case, I made some improvements to the chosen design from my perspective:</p>
<ul>
<li>Container
<ul>
<li>Flat labels (better adhesion)</li>
<li>Snap-in labels (removable)</li>
<li>Parametric version (you can generate any width you like)</li>
<li>Screws instead of clips</li>
</ul>
</li>
<li>Rail
<ul>
<li>Support for weights (optional)</li>
<li>3D printed spring instead of foam</li>
<li>Parametric version (you can generate any width you like)</li>
</ul>
</li>
</ul>
<h3 id="build-1">Build</h3>
<p>Required parts</p>
<ul>
<li>M2.5 x 6mm countersunk screws
<ul>
<li>Metric screws are not ideal for this purpose, but they are working really well here. If you have suitable self-tapping screws, use those.</li>
</ul>
</li>
<li>Cheap 8mm and 10mm round stock
<ul>
<li>Mild steel, nothing fancy</li>
<li>Cut to the length of your rail</li>
</ul>
</li>
<li>Spring (Wire 0.3mm, OD: 4mm, Length=20mm)
<ul>
<li>Maybe 0.4mm wire would be better but I could not test it yet</li>
</ul>
</li>
</ul>
<p>Print settings</p>
<ul>
<li>Use a flat bed for printing</li>
<li>.2mm layers</li>
<li>.4 nozzle</li>
<li>I used PETG (PLA+ might be fine as well)</li>
</ul>
<h4 id="container-assembly">Container assembly</h4>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/00_hu0aef7289ac4c21d02f3162028785ad0d_1220825_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/00_hu0aef7289ac4c21d02f3162028785ad0d_1220825_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/01_hu0aef7289ac4c21d02f3162028785ad0d_1253878_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/01_hu0aef7289ac4c21d02f3162028785ad0d_1253878_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/02_hu0aef7289ac4c21d02f3162028785ad0d_1072076_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/02_hu0aef7289ac4c21d02f3162028785ad0d_1072076_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/03_hu0aef7289ac4c21d02f3162028785ad0d_936535_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/03_hu0aef7289ac4c21d02f3162028785ad0d_936535_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/04_hu0aef7289ac4c21d02f3162028785ad0d_769402_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/04_hu0aef7289ac4c21d02f3162028785ad0d_769402_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/05_hu0aef7289ac4c21d02f3162028785ad0d_1004975_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_assembly/05_hu0aef7289ac4c21d02f3162028785ad0d_1004975_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h4 id="rail-assembly">Rail assembly</h4>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010567_hu0aef7289ac4c21d02f3162028785ad0d_996307_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010567_hu0aef7289ac4c21d02f3162028785ad0d_996307_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010568_hu0aef7289ac4c21d02f3162028785ad0d_702818_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010568_hu0aef7289ac4c21d02f3162028785ad0d_702818_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010574_hu0aef7289ac4c21d02f3162028785ad0d_839663_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010574_hu0aef7289ac4c21d02f3162028785ad0d_839663_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010575_hu0aef7289ac4c21d02f3162028785ad0d_694017_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010575_hu0aef7289ac4c21d02f3162028785ad0d_694017_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010576_hu0aef7289ac4c21d02f3162028785ad0d_686231_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010576_hu0aef7289ac4c21d02f3162028785ad0d_686231_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010577_hu0aef7289ac4c21d02f3162028785ad0d_819464_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010577_hu0aef7289ac4c21d02f3162028785ad0d_819464_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010581_hu0aef7289ac4c21d02f3162028785ad0d_767875_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250402_smd_storage/images/container_rail_assembly/P4010581_hu0aef7289ac4c21d02f3162028785ad0d_767875_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="project-files">Project files</h2>
<p>DOWNLOAD: <a href="/posts/250402_smd_storage/files/tray.zip">SMD Tray files</a></p>
<p>DOWNLOAD: <a href="/posts/250402_smd_storage/files/containers.zip">SMD Containers files</a></p>
]]></content>
        </item>
        
        <item>
            <title>STLINK-V3MINIE Adapter</title>
            <link>https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/</link>
            <pubDate>Fri, 14 Feb 2025 17:21:18 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/</guid>
            <description>TL;DR STLINK-V3MINIE to 2.54mm pin header adapter Target power supply with 5V and 3.3V 3.3V supply is adjustable via resistor divider Current limiting with LED indicator 3D printed case Open hardware: all files available Introduction I really enjoy working with STM32 MCUs and ST&amp;rsquo;s ecosystem, including their debugging adapters. Most of the time, I use the STLINK-V3SET. However, what I don’t like about it is the STDC14 connector with its 1.</description>
            <content type="html"><![CDATA[<p><img alt="Title" src="/posts/250214_stlink-v3minie_adapter/images/title.jpg"></p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>STLINK-V3MINIE to 2.54mm pin header adapter</li>
<li>Target power supply with 5V and 3.3V</li>
<li>3.3V supply is adjustable via resistor divider</li>
<li>Current limiting with LED indicator</li>
<li>3D printed case</li>
<li>Open hardware: all files available</li>
</ul>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-01_hu8e932b73020d9a17cd93823bb0e04e01_1084987_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-01_hu8e932b73020d9a17cd93823bb0e04e01_1084987_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-02_hu03f141fc97ee21d2815aa682c4664ba9_864973_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-02_hu03f141fc97ee21d2815aa682c4664ba9_864973_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-03_hu6e4dd277bbd4abefa802648ac9713caa_668678_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-03_hu6e4dd277bbd4abefa802648ac9713caa_668678_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-04_hua6333a82bc1cdc4291d81448d6aa81e9_673364_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-04_hua6333a82bc1cdc4291d81448d6aa81e9_673364_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-05_hu04cff84f98c83a71a7dc6047e46864b4_986549_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/promo/promo-05_hu04cff84f98c83a71a7dc6047e46864b4_986549_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h2 id="introduction">Introduction</h2>
<p>I really enjoy working with STM32 MCUs and ST&rsquo;s ecosystem, including their debugging adapters. Most of the time, I use the STLINK-V3SET. However, what I don’t like about it is the STDC14 connector with its 1.27mm pitch ribbon cables. Over the last few years, I&rsquo;ve had several issues related to these cables. A broken wire, or even worse, an intermittent contact, caused delays during development. The problem often appeared as a faulty toolchain and was not easy to detect. I have experienced this issue with other debuggers like the Atmel ICE or the PLS UDE, etc.</p>
<p>For my hobby projects, I therefore use a different kind of connection. Most of the time, I have enough space to fit a standard 2.54mm pin header (single row), which is also used on most of ST’s development boards. So far, I have not experienced any major problems with signal integrity. However, when using this approach, I encountered some disadvantages when using the STLINK-V3SET with its 2.54mm adapter board:</p>
<ul>
<li>When using DuPont cables, the STLINK-V3SET gets messy.</li>
<li>The adapter board with the pin headers has a large unprotected area (ESD and short circuit risks).</li>
<li>Micro USB connection.</li>
<li>Unnecessarily large device (when used with the adapter board).</li>
<li>No target power supply options.</li>
</ul>
<h3 id="my-requirements">My requirements</h3>
<p>Therefore I wanted:</p>
<ul>
<li>Smaller footprint</li>
<li>USB-C connection</li>
<li>2.54mm pitch connector only</li>
<li>Target supply option with 5V and 3.3V (up to max. USB current &ndash;&gt; 500mA)</li>
<li>Same compatibility with the ST ecosystem</li>
</ul>
<h2 id="an-stlink-v3minie-based-alternative">An STLINK-V3MINIE based alternative</h2>
<p>ST released the STLINK-V3MINIE debugger as a cheaper alternative to the STLINK-V3SET. It is the first one with a USB-C connector and provides both a STDC14 and a board-edge connector, while being fully compatible with the ST ecosystem.</p>
<p>Around the STLINK-V3MINIE, I designed a small board that connects to the board-edge connector. It offers direct access to the SWD port as well as the internal VCP port, and provides 5V and 3.3V on a 2.54mm pitch pin header. The pin header is separated into three groups (SWD, VCP, and power supply) but can be used with a 2x10 connector to build custom adapters for different projects.</p>
<h3 id="required-materials">Required materials</h3>
<ul>
<li>PCB (Gerbers are included with the project files)</li>
<li>BOM according to the IBOM</li>
<li>2.54mm double-row pin header (2x10)</li>
<li>AVX board-edge connector (009159010061911)</li>
<li>3D printed case</li>
<li>STLINK-V3MINIE</li>
</ul>
<h3 id="assembly">Assembly</h3>
<p>The board is a standard 1.6mm 4-layer PCB. For easy assembly, you should use the “interactive BOM.”</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/pcb/P2120291_hue1f279505bb612ae6792a5aab74fd330_148677_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/pcb/P2120291_hue1f279505bb612ae6792a5aab74fd330_148677_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/pcb/P2120300_hu76d7ae70caa1289f35f9d043928de4ff_91505_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/pcb/P2120300_hu76d7ae70caa1289f35f9d043928de4ff_91505_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<p>Besides the board assembly, there is one other thing to be soldered. You need to add a jumper cable to the STLINK-V3MINIE in order to route the VBUS (+5V) to the adapter board. The following pictures show how I did it, but you might want to do it differently.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper0_hu0c0af1447286980cd6b22894f23d539b_259835_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper0_hu0c0af1447286980cd6b22894f23d539b_259835_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper1_hucdaa892fa4fbe7c372d893539dfabbdf_410553_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper1_hucdaa892fa4fbe7c372d893539dfabbdf_410553_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper2_hu19dbfe28c3175044e2ec9595a6ee8ef3_395415_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper2_hu19dbfe28c3175044e2ec9595a6ee8ef3_395415_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper3_hu7b2c6c0f2eb28c4608e2e2efe638e447_435644_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/jumper/jumper3_hu7b2c6c0f2eb28c4608e2e2efe638e447_435644_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<p>For the case, there are four STL files included in the project files. The bottom part of the case can be printed with or without a cutout for the STDC14 connector of the STLINK-V3MINIE. If you don’t use the connector, you might want to desolder it and use the file without the cutout (mine_adapter_btm_no_con.stl). Otherwise, you should use the default one (mine_adapter_btm.stl). The top part also has two variants. One version has holes for the LEDs to shine through (mine_adapter_top_led_holes.stl). This version should be used if you are using a material that doesn’t allow light to pass through. If you are using a transparent or light material, the other version with minimal material where the LEDs sit is better, as it allows the light to shine through the plastic (mine_adapter_top.stl). You can print with a default layer height of 0.2mm and a standard 0.4mm nozzle. I recommend PETG or PLA+ for some flexibility. Pure PLA might not be the best choice. After printing, you may need to clean up the area around the USB-C connector.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-0_hu6c9de6abbc997c53f50544a2be5d8d12_68725_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-0_hu6c9de6abbc997c53f50544a2be5d8d12_68725_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-1_huf94da9723feaa505ff01971696d61e6b_728802_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-1_huf94da9723feaa505ff01971696d61e6b_728802_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-2_hu7ce53e426aaf1a8d3771d8922617c85b_744890_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/case/case-2_hu7ce53e426aaf1a8d3771d8922617c85b_744890_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<p>Once you have everything together, just connect the adapter board to the STLINK-V3MINIE using the AVX board-edge connector and place it into the top part of the case. The bottom part is held together with clips, so there is no need for screws. Be careful if you didn’t desolder the STDC14 connector in order to avoid breaking the small plastic pieces on the sides.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-0_hu2fb123b64bcd56ed4f18780f7f69a286_786801_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-0_hu2fb123b64bcd56ed4f18780f7f69a286_786801_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-1_hu95fd4a87adce95df0597b32d7474e9aa_920496_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-1_hu95fd4a87adce95df0597b32d7474e9aa_920496_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-2_hue4b9ce286f0c06f8492167861bbe17b2_794515_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-2_hue4b9ce286f0c06f8492167861bbe17b2_794515_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-3_hu765f6403d3a8aa52edb61a9f43de54a5_1068278_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/250214_stlink-v3minie_adapter/images/assembly/assembly-3_hu765f6403d3a8aa52edb61a9f43de54a5_1068278_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="files">Files</h3>
<p>STLINK-V3MINIE Adapter REV 1.0 <a href="./files/minie_adapter_1_0.zip" title="STLINK-V3MINIE adapter rev 1.0 files">DOWNLOAD</a></p>
<h2 id="contact">Contact</h2>
<p>If you have any questions you can send a mail to info &lsquo;at&rsquo; embedded-ideas.de or contact me via mastodon @DerTobi@mastodon.social</p>
]]></content>
        </item>
        
        <item>
            <title>Capturing image data from DMG (GAME BOY classic) display signals</title>
            <link>https://www.embedded-ideas.de/posts/241209_dmg_display_capture/</link>
            <pubDate>Mon, 09 Dec 2024 17:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/241209_dmg_display_capture/</guid>
            <description>Capturing image data from DMG display signals TL;DR Only HSYNC, VSYNC, CLOCK, DATA0 and DATA1 is required Frame starts with rising edge on VSYNC Row begins on rising edge on HSYNC First pulse of row needs to be ignored (occurs while HSYNC is high) First pixel of a row is captured on falling edge of HSYNC Other pixels of a row are captured on falling edge of CLOCK Introduction Capturing the image data from the DMG LCD data lines is actually not very complicated, but there are a few things you need to consider to get it right.</description>
            <content type="html"><![CDATA[<h2 id="capturing-image-data-from-dmg-display-signals">Capturing image data from DMG display signals</h2>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/frame_detail_hu1f51dfe08f2e71922cd459e6667101b7_11658_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/frame_detail_hu1f51dfe08f2e71922cd459e6667101b7_11658_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/frame_overview_hu7cb1a2b907f7c85d9f19c81c65fdd9d9_12880_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/frame_overview_hu7cb1a2b907f7c85d9f19c81c65fdd9d9_12880_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/hsync_falling_timing_hu94aa8eb8b5916d70dce1669a791b39f6_16852_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/hsync_falling_timing_hu94aa8eb8b5916d70dce1669a791b39f6_16852_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/level_shifter_hu3e2460c31d24224f9db29ceb92a51df4_80201_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/level_shifter_hu3e2460c31d24224f9db29ceb92a51df4_80201_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/mario2_title_screen_hu6a5d1ac4848e26c26f078502590a09e4_10652_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/mario2_title_screen_hu6a5d1ac4848e26c26f078502590a09e4_10652_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pixel_clock_measure_hue08dd1a57e9edfc1b673dbb316947505_27421_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pixel_clock_measure_hue08dd1a57e9edfc1b673dbb316947505_27421_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pixel_detail_hu192d7d90f0f32217598578d8a3c62f9b_5657_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pixel_detail_hu192d7d90f0f32217598578d8a3c62f9b_5657_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pulse_random_hudb7ab2261e2d87d60368230905311456_10973_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/pulse_random_hudb7ab2261e2d87d60368230905311456_10973_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/row_overview_hufa0650d085ec170bdc76436cbd854f5d_14847_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241209_dmg_display_capture/images/row_overview_hufa0650d085ec170bdc76436cbd854f5d_14847_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h3 id="tldr">TL;DR</h3>
<ul>
<li>Only HSYNC, VSYNC, CLOCK, DATA0 and DATA1 is required</li>
<li>Frame starts with rising edge on VSYNC</li>
<li>Row begins on rising edge on HSYNC</li>
<li>First pulse of row needs to be ignored (occurs while HSYNC is high)</li>
<li>First pixel of a row is captured on falling edge of HSYNC</li>
<li>Other pixels of a row are captured on falling edge of CLOCK</li>
</ul>
<h3 id="introduction">Introduction</h3>
<p>Capturing the image data from the DMG LCD data lines is actually not very complicated, but there are a few things you need to consider to get it right. Unfortunately, to the best of my knowledge, there is no official documentation for the signals coming from the GAME BOY&rsquo;s CPU to the display board. I spent some time figuring out how it works (or at least how I think it works :) and thought it might be worth writing the results down.</p>
<h3 id="signals">Signals</h3>
<p>There are quite a few signals that are correlated with the display. To capture the image, you will only need VSYNC, HSYNC, CLOCK, and the data lines (DATA0, DATA1).</p>
<table>
<thead>
<tr>
<th style="text-align:left">Signal</th>
<th style="text-align:left">Pin</th>
<th style="text-align:left">Function</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">VSYNC</td>
<td style="text-align:left">12</td>
<td style="text-align:left">Vertical synchronisation (start of frame)</td>
</tr>
<tr>
<td style="text-align:left">ALSIG</td>
<td style="text-align:left">13</td>
<td style="text-align:left">Don&rsquo;t know, don&rsquo;t care</td>
</tr>
<tr>
<td style="text-align:left">CLOCK</td>
<td style="text-align:left">14</td>
<td style="text-align:left">Pixel clock (pixel data on data 0/1 valid)</td>
</tr>
<tr>
<td style="text-align:left">DATA1</td>
<td style="text-align:left">15</td>
<td style="text-align:left">Bit 1 of the 2 bit grayscale value</td>
</tr>
<tr>
<td style="text-align:left">DATA0</td>
<td style="text-align:left">16</td>
<td style="text-align:left">Bit 0 of the 2 bit grayscale value</td>
</tr>
<tr>
<td style="text-align:left">HSYNC</td>
<td style="text-align:left">17</td>
<td style="text-align:left">horizontal synchronisation (start of line)</td>
</tr>
<tr>
<td style="text-align:left">CPL</td>
<td style="text-align:left">18</td>
<td style="text-align:left">Line latch (end of line, optional)</td>
</tr>
<tr>
<td style="text-align:left">CONTROL</td>
<td style="text-align:left">19</td>
<td style="text-align:left">Don&rsquo;t know, don&rsquo;t care</td>
</tr>
</tbody>
</table>
<p>If you&rsquo;re working with, for example, 3.3V logic, you might consider using a level shifter. A generic buffer like the 74LVC541 worked well in my use case.</p>
<p><img alt="74LVC541 used as level shifter from 5V-&gt;3V" src="/posts/241209_dmg_display_capture/images/level_shifter.jpg"></p>
<h3 id="frame-structure">Frame structure</h3>
<p>A frame contains all the data for one full image on the screen. In the case of the DMG, it is used to transfer 160x144 2-bit pixels. The process begins with the first pixel in the upper-left corner and continues horizontally. After 160 pixels, the next line is transferred until 144 lines have been sent to the display.</p>
<p><img alt="Transfer of multiple frames" src="/posts/241209_dmg_display_capture/images/frame_overview.png"></p>
<p>Each frame begins with a rising edge on the VSYNC line. The VSYNC signal stays high during the transfer of the first line and then returns to a low level for the rest of the frame.</p>
<p><img alt="First and second row at the beginning of a frame" src="/posts/241209_dmg_display_capture/images/frame_detail.png"></p>
<p>Within a frame, you will find 144 lines, each initiated with a rising edge on the HSYNC line.</p>
<p><img alt="Full row within a frame" src="/posts/241209_dmg_display_capture/images/row_overview.png"></p>
<p>It seems there is some controversy about how the pixel clock works. I used an approach that I haven&rsquo;t seen elsewhere (please email me if I&rsquo;m wrong).</p>
<p>My first implementation just used the falling edge of the pixel clock (CLOCK line). I measured the pulses of the clock within the frame (160) and the alignment of the pixel data. This led to the obvious conclusion that the pixel data is valid on the falling edge of the clock.</p>
<p><img alt="Measures clock pulses" src="/posts/241209_dmg_display_capture/images/pixel_clock_measure.png"></p>
<p>After a while, I noticed some strange artifacts on the first column of pixels on the screen. Whenever a moving sprite leaves the screen on the right, it shows up pixel-wise on the first column on the left.</p>
<p>I searched for other projects that tried to capture the DMG screen and came across an article by Thomas Spurden (<a href="https://thomas.spurden.name/blog/capturing-gb-lcd/">https://thomas.spurden.name/blog/capturing-gb-lcd/</a> ). He mentions a project by Sven Dahlstrand (<a href="https://github.com/svendahlstrand/game-boy-lcd-sniffing">https://github.com/svendahlstrand/game-boy-lcd-sniffing</a> ) that uses the same approach I did, and an article by Kevin Horton (<a href="http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt">http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt</a> ) which might have served as the signal interpretation blueprint for Thomas&rsquo; project.</p>
<p>Thomas and Kevin both say that the pixel data is valid on the rising edge of the pixel clock. Looking at the signals, this might be possible, but it would also be very strange from a design point of view. We are dealing with old (and cost-optimized) hardware, which might not be able to capture the signal fast enough. Even with modern hardware, it might be challenging to get it right. Additionally, this weakens the signal integrity when it comes to capacitive effects. Looking at the signals, the falling edge provides a nice sampling point at approximately 50%, which seems more likely to be the right approach in my opinion.</p>
<p><img alt="DATA0 and CLOCK measured with 100MS/s" src="/posts/241209_dmg_display_capture/images/pixel_detail.png"></p>
<p>Thomas also mentions that the first pulse on the clock line should be ignored. I think he is correct. The position of the pulse in relation to the data looks a bit random compared to the other pulses. With the rising-edge approach, the capture of the last pixel (which, accordingly, has no pulse on the pixel clock) is done when the row is latched via the CPL signal.</p>
<p><img alt="First pulse of the pixel clock of a row 50MS/s" src="/posts/241209_dmg_display_capture/images/pulse_random.png"></p>
<p>If the data is valid on the rising edge of the pixel clock, we would miss the first pixel when we focus on the falling edge instead. I wasn&rsquo;t happy with this solution, so I did some more analysis on how to capture the first pixel while using the assumption that data is valid on the falling edge.</p>
<p>I used the title screen of Super Mario Land 2 for this. On the far-left column, there is a black line starting from the 15th row. This makes it easy to validate the first pixel of each row.</p>
<p><img alt="Upper left segment of the Super Mario Land 2 title screen" src="/posts/241209_dmg_display_capture/images/mario2_title_screen.jpg"></p>
<p>After some time, I found the pattern that the first pixel data is valid on the falling edge of HSYNC. Measurements also show that the timing is close, if not similar, to the pixel clock. In my opinion, this makes more sense from a design perspective than capturing on the rising edge. The clock line might be disabled if HSYNC is high and triggers the capture mechanism as soon as it returns to low.</p>
<p><img alt="Timings of the signals on falling edge of HSYNC" src="/posts/241209_dmg_display_capture/images/hsync_falling_timing.png"></p>
<p>I re-implemented my solution, which now works as follows:</p>
<ol>
<li>Wait for the rising edge on the VSYNC signal.</li>
<li>Wait for the falling edge on the HSYNC line and capture data lines directly as the first pixel.</li>
<li>Wait for the falling edge on the CLOCK line and capture data as the next pixel.</li>
<li>Repeat step 3 for the next 158 pixels.</li>
<li>Repeat from step 2 for the next 143 lines.</li>
<li>Repeat from step 1.</li>
</ol>
<p>I did some testing with Super Mario Land, Super Mario Land 2, Wario Land, and Pocket Bomberman. Everything looks quite stable. ;)</p>
<p>You can download some of my sample data from the Super Mario Land 2 title screen <a href="/posts/241209_dmg_display_capture/signals_marioland2.sal" title="signal capture title screen">here</a> (50MS/s dumped from Saleae Logic 2).</p>
<p>Please let me know if you find any issues with my approach.</p>
]]></content>
        </item>
        
        <item>
            <title>Retro style CO2 sensing</title>
            <link>https://www.embedded-ideas.de/posts/241016_airghost/</link>
            <pubDate>Wed, 16 Oct 2024 22:30:13 +0200</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/241016_airghost/</guid>
            <description>TL;DR Printable 8-bit ghost shaped CO2 monitoring device Changes color according to CO2 level Works with Arduino Uses Sensirion SCD4x CO2 sensor Based on ESP32-C6 (WiFi, Bluetooth, IEEE802.15.4 capable) Custom PCB All open source / open hardware Files (Board, BOM, Sketch, etc.) Full list of required parts in assembly instructions File download here. Introduction I came across the topic of air quality measurement several times within the last couple of years (mainly on scientific or technical podcasts).</description>
            <content type="html"><![CDATA[<p><img alt="Title" src="/posts/241016_airghost/images/title.jpg"></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/0_hu76a216c68cc08b36c68d3136f99137ca_146689_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/0_hu76a216c68cc08b36c68d3136f99137ca_146689_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/1_hu884b6bed93c6e4a5bd27d1b52f06051d_195913_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/1_hu884b6bed93c6e4a5bd27d1b52f06051d_195913_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/2_hu32c868021e10fcb6c1c4e00d7b6dcc4f_445943_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/2_hu32c868021e10fcb6c1c4e00d7b6dcc4f_445943_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130074_hu1dffb2e8362f1f3fb18fb122c8994bf2_126372_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130074_hu1dffb2e8362f1f3fb18fb122c8994bf2_126372_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130075_hu5966ed2f80b98d8fa83b132201d96dc6_160430_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130075_hu5966ed2f80b98d8fa83b132201d96dc6_160430_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130091_hu564811d94c78beb4ae187e4524e09162_235039_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130091_hu564811d94c78beb4ae187e4524e09162_235039_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130092_hucce130093a858777444c7f2abdb6cb21_194111_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/promo/PA130092_hucce130093a858777444c7f2abdb6cb21_194111_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h2 id="tldr">TL;DR</h2>
<ul>
<li>Printable 8-bit ghost shaped CO<sup>2</sup> monitoring device</li>
<li>Changes color according to CO<sup>2</sup> level</li>
<li>Works with Arduino</li>
<li>Uses Sensirion SCD4x CO<sup>2</sup> sensor</li>
<li>Based on ESP32-C6 (WiFi, Bluetooth, IEEE802.15.4 capable)</li>
<li>Custom PCB</li>
<li>All open source / open hardware</li>
<li>Files (Board, BOM, Sketch, etc.)</li>
<li>Full list of required parts in assembly instructions</li>
<li>File download <a href="./files/AirGhost_REV_1_2.zip" title="Archive inclcuding all required files">here</a>.</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>I came across the topic of air quality measurement several times within the last couple of years (mainly on scientific or technical podcasts). As a developer I&rsquo;m aware of the problem of bad air quality in the office without noticing it. If you&rsquo;re busy problem solving, you might not have time to care about unimportant things like oxygen.</p>
<p>On a second though oxygen might help your brain solving the problem faster and keeps you awake. I came to the conclusion that a simple device which changes it&rsquo;s color from green over yellow to red in order to signalize &ldquo;hey dude, it&rsquo;s time to open the window&rdquo; would be the best for my use case.</p>
<p>I liked the idea that the device should fit nice on a desk and looks somewhat friendly (and maybe a bit nerdy). So an 8-bit ghost was the obvious solution.</p>
<h2 id="hardware">Hardware</h2>
<p>I wanted the device to be reproducible (as christmas presents), so I decided to design a custom PCB. Nothing fancy, just a controller, an LDO, some pixel LEDs and passives. I used four layers because it doesn&rsquo;t cost much more and it speeds up the process. If somebody wants to I&rsquo;m sure it can be reduced to 2-layers.</p>
<p>In order to allow expansion of the functionality and maybe some kind of integration into a smart home setup, the ESP32-C6 seemed like a good fit for the project. It offers the whole range of 2.4GHz standards (WiFi, Bluetooth, 802.15.4 &ndash;&gt; ZigBee, Thread).</p>
<p>I tested some sensors (including VOC sensors) and came to the conclusion that only a real CO<sup>2</sup>-sensor delivers reliable results. The smallest and &ldquo;cheapest&rdquo; solution which is widely available is the Sensirion SCD40. You can get it for around 30$ from DigiKey.</p>
<p>The sensor is attached to the board using spring loaded pins in order to avoid damaging it or heat it up to much in the soldering process. Besides the spring loaded pin option, there is also a header which fits the boards available from ebay or aliexpress. I didn&rsquo;t design any 3D parts for this, so you have to design it yourself.</p>
<p>The device uses 17 WS2812B RGB LEDs which should be driven on a low brightness level in order to avoid heat (and dazzling).</p>
<p>It doesn&rsquo;t take expert level skills to solder the board, but a beginner might run into problems soldering the smaller components and finer pitch parts, especially the USB-C connector.</p>
<h2 id="firmware">Firmware</h2>
<p>I still don&rsquo;t like the Arduino IDE and the &ldquo;Arduino Sketch&rdquo; style of programming. But I get the point that it should be easy for beginners and it allows non programmers to &ldquo;get shit done&rdquo;.</p>
<p>Anyways, I decided to write a basic firmware using Arduino to allow more people to have fun with the project.</p>
<p>The sketch should have enough comments and a sufficient naming scheme to make it understandable. In good Arduino style, a maximum of external libraries have to be imported:</p>
<ul>
<li>Sensirion I2C SCD4x (Sensirion) &ndash;&gt; SCD4x sensor driver</li>
<li>Sensirion Core (Sensirion) &ndash;&gt; Required by Sensirion I2C SCD4x</li>
<li>Adafruit NeoPixel (Adafruit) &ndash;&gt; WS2812 Pixel LED handling</li>
<li>Adafruit Debounce (Adafruit) &ndash;&gt; Button handling</li>
</ul>
<h2 id="assembly-and-programming">Assembly and programming</h2>
<p>Partlist</p>
<ul>
<li>Printables (I used PETG but PLA etc. should be fine as well)
<ul>
<li>1 frontcover (needs to be transparent)</li>
<li>1 backcover</li>
<li>2 eyes</li>
<li>1 sensor holder</li>
<li>1 sensor cover</li>
<li>1 eye conector</li>
<li>1 button cover</li>
</ul>
</li>
<li>Nuts and Bolts
<ul>
<li>3 countersunk M3 x 16mm (e.g. DIN965)</li>
<li>2 M3 x 12mm (any flat headed screw will do)</li>
<li>5 M3 nuts</li>
</ul>
</li>
<li>Populated PCB (see board BOM and assembly pictures for details)</li>
<li>Sensirion SCD4x Sensor (SCD40-D-R2)</li>
</ul>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130059_hu09685639f861251a11c5cecdcea4cd54_120285_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130059_hu09685639f861251a11c5cecdcea4cd54_120285_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130061_hu31bea48ed67f996d6d792d01c703615b_106465_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130061_hu31bea48ed67f996d6d792d01c703615b_106465_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130064_hu424b42cbf4ec9542b37b58befae21bcd_185805_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/parts/PA130064_hu424b42cbf4ec9542b37b58befae21bcd_185805_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="board-assembly">Board assembly</h3>
<p>You can order the board from anywhere you like. Gerbers are provided with the project files. The boards includes a holder for the springs. Before doing anything else you should remove it and put it aside. If you want to connect the ground pad of the ESP module, you should solder it first. I recommend to solder all LEDs and their decoupling caps afterwards. Remaining SMD components can be soldered in a small to large manner. As a last step the spring loaded pin assembly needs to be put together. It&rsquo;s a bit tricky, so take your time. Make sure you dont solder the &ldquo;springy&rdquo; part. I provide some detail pictures as a reference.</p>
<p>For easy assembly you can use the &ldquo;Interactive BOM&rdquo; provided in the download archive.</p>
<p>Remember that you also have to buy the CO<sup>2</sup> sensor: Sensirion SCD40-D-R2 which is seen as an external component and is therefore not part of the BOM.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130031_hu506d4ac8885d017e5faa4980411fe455_73622_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130031_hu506d4ac8885d017e5faa4980411fe455_73622_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130034_hu3e5cb99c24272d2bf5eb88002de1d8e5_126301_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130034_hu3e5cb99c24272d2bf5eb88002de1d8e5_126301_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130038_hue1b936de1c6f7c19e2f5c9eecc5fbef0_124236_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130038_hue1b936de1c6f7c19e2f5c9eecc5fbef0_124236_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130045_hu9b8062cabb9912427d3e429199324d66_107272_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130045_hu9b8062cabb9912427d3e429199324d66_107272_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130052_hu521a4c46e8e1317fee2f5d502fb66312_62693_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130052_hu521a4c46e8e1317fee2f5d502fb66312_62693_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130053_hubeef3452945815c853fb9df465f92273_120755_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130053_hubeef3452945815c853fb9df465f92273_120755_135x120_fill_q80_box_smart1.jpg"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130057_hu5ae287cf17b1df5058cbfa78789cf90e_136693_1980x1080_fit_q75_box.jpg" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/board_assembly/PA130057_hu5ae287cf17b1df5058cbfa78789cf90e_136693_135x120_fill_q80_box_smart1.jpg"/></a></li>
    

</ul>

<h3 id="printing">Printing</h3>
<p>Nothing special about this. I used a .4mm nozzle and a .2mm layer hight with 15% infill. My print was a bit stringy because of the slightly older PETG filament. PLA might be the better option here.</p>
<h3 id="case-assembly">Case assembly</h3>
<p>First screw the sensor to the board and slide the M3 nuts into the front cover. Continue with the eye assembly. Place the board into the case and add the sensor cover and the button cover. Add the back cover and tight it shut with the countersunk screws.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130067_huf0f13ceada5ddacaed774149ed043198_191314_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130067_huf0f13ceada5ddacaed774149ed043198_191314_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130068_huf0d91b86dc3d315b39433689061f2be3_148751_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130068_huf0d91b86dc3d315b39433689061f2be3_148751_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130069_hu1c2991c59bca56c1187b9b0a80a52662_125239_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130069_hu1c2991c59bca56c1187b9b0a80a52662_125239_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130072_huf9502a421b3362be0c04e2d9255e3da4_149278_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130072_huf9502a421b3362be0c04e2d9255e3da4_149278_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130073_hu9f3906380f30ca53a1b75ea71ece9527_175286_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130073_hu9f3906380f30ca53a1b75ea71ece9527_175286_135x120_fill_q80_box_smart1.JPG"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130159_hued1e486a5d471fc9ff401247934084f3_301405_1980x1080_fit_q75_box.JPG" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/case_assembly/PA130159_hued1e486a5d471fc9ff401247934084f3_301405_135x120_fill_q80_box_smart1.JPG"/></a></li>
    

</ul>

<h3 id="compiling-and-flashing">Compiling and flashing</h3>
<p>Download a recent version of the Arduino IDE and install the following libraries (Tools -&gt; Manage Libraries):</p>
<ul>
<li>Sensirion I2C SCD4x (Sensirion) &ndash;&gt; SCD4x sensor driver</li>
<li>Sensirion Core (Sensirion) &ndash;&gt; Required by Sensirion I2C SCD4x</li>
<li>Adafruit NeoPixel (Adafruit) &ndash;&gt; WS2812 Pixel LED handling</li>
<li>Adafruit Debounce (Adafruit) &ndash;&gt; Button handling</li>
</ul>
<p>As well as the board support package (Tools -&gt; Board -&gt; Boards manager)</p>
<ul>
<li>esp32 (Espressif Systems)</li>
</ul>
<p>Select the board &ldquo;esp32 -&gt; ESP32C6 Dev Module&rdquo; and make sure to enable &ldquo;USB CDC On Boot&rdquo; in order to get the println outputs on the serial monitor. It might also be neccessary to install pyserial (serial libraries for python) in order to get the ESP32 tools running.</p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/Arduino_libs_hu52807f1b06bfc3f1e6a51b774779fe27_87131_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/Arduino_libs_hu52807f1b06bfc3f1e6a51b774779fe27_87131_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/Enable_Serial_hu4bbccb215b2a68c7592fb21f08918718_79776_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/Enable_Serial_hu4bbccb215b2a68c7592fb21f08918718_79776_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/esp32_arduino_install_hufc15bd8d907ee9477625831b0e611ffe_141911_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/241016_airghost/images/arduino/esp32_arduino_install_hufc15bd8d907ee9477625831b0e611ffe_141911_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

<h2 id="files">Files</h2>
<p>Please download from the link below. The archive contains all required files to build the project.</p>
<ul>
<li>Schematic</li>
<li>Bill of Materials (BOM)</li>
<li>Gerber files to order the PCB</li>
<li>STL files for printing</li>
<li>OpenSCAD source files</li>
<li>Arduino demo sketch (basic functionality, buttons are not used)</li>
</ul>
<p>AirGhost REV 1.2 <a href="./files/AirGhost_REV_1_2.zip" title="AirGhost rev 1.2 files">DOWNLOAD</a></p>
<h2 id="contact">Contact</h2>
<p>If you have any questions you can send a mail to info &lsquo;at&rsquo; embedded-ideas.de or contact me via mastodon @DerTobi@mastodon.social</p>
]]></content>
        </item>
        
        <item>
            <title>Dual 3.5″ HDD NAS Case for Odroid H2 / H2&#43;</title>
            <link>https://www.embedded-ideas.de/posts/200809_dual_hdd_case_odroid_h2/</link>
            <pubDate>Sun, 09 Aug 2020 17:16:03 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/200809_dual_hdd_case_odroid_h2/</guid>
            <description>Introduction The Odroid H2 and the Odroid H2+ are some of the few single board computers which offer PC like interfaces including 2x SATA, an NVMe slot, 2x 2.5 GBit ethernet (1 GBit for the H2) as well as dual RAM sockets. Besides the interfaces the board is equipped with a powerful, yet energy efficient x86 processor and includes an on board power supply.
In my opinion, the board is the perfect fit for an open source NAS system build.</description>
            <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p><img alt="Case" src="/posts/200809_dual_hdd_case_odroid_h2/images/P1040712-768x796.jpg"></p>
<p>The Odroid H2 and the Odroid H2+ are some of the few single board computers which offer PC like interfaces including 2x SATA, an NVMe slot, 2x 2.5 GBit ethernet (1 GBit for the H2) as well as dual RAM sockets. Besides the interfaces the board is equipped with a powerful, yet energy efficient x86 processor and includes an on board power supply.</p>
<p>In my opinion, the board is the perfect fit for an open source NAS system build. Unfortunately the case which is offered by the manufacturer didn’t meet my requirements.</p>
<p>I therefore built myself a compact and stable case which has the features I want. Maybe it still needs some spit and polish but the result is quite useful for me and maybe for you as well.</p>
<p>Before you start printing, be sure you want to have this case. It will take you a while to get hold of the parts and you will require some grams of filament ;-)</p>
<p><img alt="Case" src="/posts/200809_dual_hdd_case_odroid_h2/images/snapshot03-1024x578.png"></p>
<h2 id="parts">Parts</h2>
<ul>
<li>3D printed parts
<ul>
<li>1x Backplate</li>
<li>1x Fan mounting plate</li>
<li>1x Left side panel</li>
<li>1x Right side panel</li>
<li>1x Top panel</li>
<li>2x HDD rails</li>
<li>4x Feet</li>
<li>1x Button and LED holder</li>
<li>1x Front cover</li>
<li>1x Button inlay (should be printed transparent)</li>
<li>1x Bottom plate with or without maintenance opening</li>
</ul>
</li>
<li>Screws
<ul>
<li>9x M3 16mm</li>
<li>29x M3 12mm</li>
<li>4x Fan screws (normally included with the fan)</li>
<li>8x 6-32 screws for HDD mounting</li>
</ul>
</li>
<li>Intended Hardware
<ul>
<li>Odroid H2 or Odroid H2+ (<a href="https://www.hardkernel.com/shop/odroid-h2plus/">https://www.hardkernel.com/shop/odroid-h2plus/</a>)</li>
<li>RAM (I used 1x Kingston KVR24S17S8/8)</li>
<li>NVMe SSD (e.g. Kingston A2000 250GB SA2000M8/250G)</li>
<li>2x 3.5″ HDD (e.g. Seagate Ironwolf, Toshiba N300, be careful with WD RED –&gt; <a href="https://www.youtube.com/watch?v=aztTf2gI55k">https://www.youtube.com/watch?v=aztTf2gI55k</a> )</li>
<li>2x Odroid SATA cable-set (<a href="https://www.hardkernel.com/shop/sata-data-and-power-cable/">https://www.hardkernel.com/shop/sata-data-and-power-cable/</a>)</li>
<li>92mm PC fan (e.g. bequiet! PURE WINGS 2 92mm)</li>
</ul>
</li>
<li>Additional electronics
<ul>
<li>Temperature controlled fan controller (e.g. <a href="https://de.aliexpress.com/item/33015447685.html">https://de.aliexpress.com/item/33015447685.html</a>)</li>
<li>3mm LED with a suitable current limiting resistor for 3.3V</li>
<li>Pushbutton (I got mine from one of those very handy kits <a href="https://de.aliexpress.com/item/32953981481.html">https://de.aliexpress.com/item/32953981481.html</a>)</li>
<li>Some jumper wires (e.g. <a href="https://de.aliexpress.com/item/32990585262.html">https://de.aliexpress.com/item/32990585262.html</a>)</li>
</ul>
</li>
</ul>
<h2 id="assembly-instructions">Assembly Instructions</h2>
<p>General rules:</p>
<ul>
<li>Use M3 12mm screws if not noted otherwise</li>
<li>Insert M3 nuts into hexagonal holes</li>
<li>Insert M3 nuts in the corresponding slots</li>
</ul>
<p><img alt="Case" src="/posts/200809_dual_hdd_case_odroid_h2/images/snapshot04-e1595172619877-1024x598.png"></p>
<p>You should start by mounting the fan to its mounting plate using the fan screws.</p>
<p><img alt="Case" src="/posts/200809_dual_hdd_case_odroid_h2/images/P1040649-1024x685.jpg"> <img alt="Case" src="/posts/200809_dual_hdd_case_odroid_h2/images/P1040650-1-1024x685.jpg"></p>
<p>Depending on you choice of the bottom plate its a good idea too add the door to it.</p>
<p>After installing the nuts on the bottom, you can screw the fan and the back panel to the bottom plate. And add the feet (use M3 16mm for the feet).</p>
<p>Its time to screw down the Mainboard…</p>
<p>…and add the HDD rails…</p>
<p>…as well as the mount for the pushbutton (use M3 16mm for this).</p>
<p>I used some superglue to keep the push button in place. Don’t forget the current limiting resistor for the LED (@3V3).</p>
<p>Its time to install the remaining hardware. I connected the fan controller board to one of the SATA supply cables…</p>
<p>…and did some cable management. The BIOS battery can be glued to the side of the HDD rail.</p>
<p>Add the button inlay to the front cover.</p>
<p>The top and side covers can be mounted next. It is important to have the side panel with the vents on the right of the case. Do not screw down the side panels on the front. They will be fixed using the front cover.</p>
<p>The front cover is fixed using four M3 16mm screws. You need a screwdriver with a thin shaft in order to be able to screw it down trough the vent slots on the sides.</p>
<p>Done.</p>
<h2 id="files">Files</h2>
<p><a href="/posts/200809_dual_hdd_case_odroid_h2/files/ODROID_H2_NAS_CASE_REV1-0.zip">Download</a>
CC-BY-SA 4.0</p>
]]></content>
        </item>
        
        <item>
            <title>FreeNAS on Odroid H2&#43; – RTL8125B driver installation</title>
            <link>https://www.embedded-ideas.de/posts/200808_freenas_on_odroid_h2/</link>
            <pubDate>Sat, 08 Aug 2020 17:16:03 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/200808_freenas_on_odroid_h2/</guid>
            <description>I wanted to try FreeNAS on my Odroid H2+ NAS system, unfortunately the driver for the Realtek RTL8125B was missing on the FreeBSD OS which is used currently used by FreeNAS.
After reading some post which say something like “There is no way in hell there will be a driver for the RTL8125 unless a big company needs it…”, I came across the following forum topics which pointed me to the actual driver supplied by Realtek.</description>
            <content type="html"><![CDATA[<p>I wanted to try FreeNAS on my Odroid H2+ NAS system, unfortunately the driver for the Realtek RTL8125B was missing on the FreeBSD OS which is used currently used by FreeNAS.</p>
<p>After reading some post which say something like “There is no way in hell there will be a driver for the RTL8125 unless a big company needs it…”, I came across the following forum topics which pointed me to the actual driver supplied by Realtek.</p>
<p><a href="https://www.xigmanas.com/forums/viewtopic.php?t=15326">https://www.xigmanas.com/forums/viewtopic.php?t=15326</a>
<a href="https://forum.netgate.com/topic/135850/official-realtek-driver-binary-1-95-for-2-4-4-release/8">https://forum.netgate.com/topic/135850/official-realtek-driver-binary-1-95-for-2-4-4-release/8</a></p>
<p>Actually I didn’t expected Realtek to provide drivers for FreeBSD but it is available as source for download at:</p>
<p><a href="https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software">https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software</a></p>
<h2 id="compiling-the-driver">Compiling the driver</h2>
<p>Hint: I also provide the binaries for FreeNAS/FreeBSD 11.3. If you don’t want to compile the driver, you can download the binaries and just install it.</p>
<p>As a first attempt I tried to compile the driver directly on my FreeNAS installation. Unfortunately it looks like FreeNAS comes without a build system. As this is my first contact with FreeBSD, I decided to compile the driver on a virtual machine using a fresh FreeBSD 11.3 installation.</p>
<p>You can get the ISO image at <a href="https://download.freebsd.org/ftp/releases/ISO-IMAGES/11.3/FreeBSD-11.3-RELEASE-amd64-dvd1.iso">https://download.freebsd.org/ftp/releases/ISO-IMAGES/11.3/FreeBSD-11.3-RELEASE-amd64-dvd1.iso</a> and install it on e.g. a new VitualBox.</p>
<p>During the installation process you should select to install the “System source tree” in order to be able to compile the system and the driver. If you forgot this step you might consider this blog post: <a href="https://www.jan0sch.de/post/install-freebsd-sources/">https://www.jan0sch.de/post/install-freebsd-sources/</a>. There is nothing else to worry about during the installation. Just follow the process.</p>
<p><img alt="FreeBSD Installer" src="/posts/200808_freenas_on_odroid_h2/images/src_select.png"></p>
<p>The required steps to build the driver are described in the drivers readme.txt. I will describe the steps again as there are some slight changes necessary.</p>
<p>First of all you might want to backup the original files</p>
<pre tabindex="0"><code>cp /usr/src/sys/dev/re/if_re.c /usr/src/sys/dev/re/if_re.c.org
cp /usr/src/sys/modules/Makefile /usr/src/sys/modules/Makefile.org
cp /usr/src/sys/modules/re/Makefile /usr/src/sys/modules/re/Makefile.org
cp /usr/src/sys/amd64/conf/GENERIC /usr/src/sys/amd64/conf/GENERIC.org
</code></pre><p>Now we remove the driver as part of the kernel build. Remove the following lines from /usr/src/sys/amd64/conf/GENERIC respectively /usr/src/sys/modules/Makefile. I used vi for this. If you’re not familiar with vi some hints:</p>
<ul>
<li>dd –&gt; delete line</li>
<li>:wq –&gt; save and exit</li>
<li>:q! –&gt; exit without saving (if you messed up ;-)</li>
</ul>
<pre tabindex="0"><code>vi /usr/src/sys/amd64/conf/GENERIC
delete line --&gt;  device              re

vi /usr/src/sys/modules/Makefile
delete line --&gt;  re \
</code></pre><p>Now the fun part. First we set the build config, then we start the build process. You might consider to get some coffee, this might take a while. After the build we make a reboot.</p>
<pre tabindex="0"><code>cd /usr/src/sys/amd64/conf
/usr/sbin/config GENERIC
cd ../compile/GENERIC

make cleandepend
make depend
make
make install
reboot
</code></pre><p>Now we have the environment to build our driver as a kernel module. First we download the sources from Realtek (or use the link on my webspace). Then we unpack the files to the home dir.</p>
<pre tabindex="0"><code>cd ~
fetch http://www.embedded-ideas.de/files/rtl_bsd_drv_v196.04.tgz
tar -zxvf rtl_bsd_drv_v196.04.tgz
</code></pre><p>Now we copy the files to the right folders…</p>
<pre tabindex="0"><code>cd rtl_bsd_drv_v196.04
cp if_re* /usr/src/sys/dev/re/
cp Makefile /usr/src/sys/modules/re/
</code></pre><p>…and build them.</p>
<pre tabindex="0"><code>cd /usr/src/sys/modules/re
make clean
make
</code></pre><p>Thats it. Copy the if_re.ko onto a USB drive and continue with the installation on FreeNAS.</p>
<p>Update 16.08.20: The build system changed a bit on FreeBSD 12.1. You will find the binaries at /usr/obj/usr/src/amd64.amd64/sys/modules/re. If in doubt, use find / | grep if_re.ko to find the module.</p>
<h2 id="installing-the-rtl8125-driver-on-freenas">Installing the RTL8125 driver on FreeNAS</h2>
<p>As you might not have a working network connection you might consider to copy the driver to a USB stick. If you didn’t wanted to compile it yourself, you can download the binary here :</p>
<p><a href="https://www.embedded-ideas.de/files/if_re-amd64-FreeBSD_11_3.ko">https://www.embedded-ideas.de/files/if_re-amd64-FreeBSD_11_3.ko</a></p>
<p>Update 16.08.20: Binaries for TrueNAS 12 BETA 2 (FreeBSD12.1) untested on my target machine but loadable on a virtual machine: <a href="https://www.embedded-ideas.de/files/if_re-amd64-FreeBSD_12_1.ko">https://www.embedded-ideas.de/files/if_re-amd64-FreeBSD_12_1.ko</a></p>
<p>Please make sure to safe the file on the USB stick as if_re.ko.</p>
<p>On the FreeNAS shell we first have to mount the USB stick. The example expects a FAT32 stick.</p>
<pre tabindex="0"><code>mkdir /mnt/usbstick
mount -t msdosfs /dev/da0s1 /mnt/usbstick
</code></pre><p>Now we have to copy the driver and change the file permissions.</p>
<pre tabindex="0"><code>cd /boot/kernel
cp /mnt/usbstick/if_re.ko ./
chown root:wheel if_re.ko
chmod 0555 if_re.ko
</code></pre><p>In order to load the module on startup we have to add the following line to /boot/loader.conf</p>
<pre tabindex="0"><code>vi /boot/loader.conf
add line --&gt; if_re_load=&#34;YES&#34;
</code></pre><p>Again a hint if you are not familiar with vi:</p>
<ul>
<li>i –&gt; change to insert mode</li>
<li>ESC –&gt; leave the insert mode</li>
<li>:wq –&gt; save and exit</li>
<li>:q! –&gt; exit without saving</li>
</ul>
<p>The driver should be loaded after a reboot. You can check this with</p>
<pre tabindex="0"><code>kldstat
</code></pre><p>if_re.ko should appear in the list. And the network interfaces should be available on FreeNAS.</p>
<p><img alt="Interfaces in FreeNAS" src="/posts/200808_freenas_on_odroid_h2/images/grafik.png"></p>
]]></content>
        </item>
        
        <item>
            <title>A case for DPS size modules</title>
            <link>https://www.embedded-ideas.de/posts/200413_dps_module_case/</link>
            <pubDate>Mon, 13 Apr 2020 17:16:03 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/200413_dps_module_case/</guid>
            <description>It is nice to have a good CV/CC supply in the lab, especially if you want to power-up your prototype for the first time. Unfortunately those supplies are normally big and heavy and you don’t want to carry 9+ kilos from the lab to the living room in order to do some work on the couch.
A while ago I ordered a DPS3005 module to have a useable CV/CC “supply for the kitchen table”.</description>
            <content type="html"><![CDATA[<p><img alt="DPS case" src="/posts/200413_dps_module_case/images/P1040515_small-1024x684.jpg"></p>
<p>It is nice to have a good CV/CC supply in the lab, especially if you want to power-up your prototype for the first time. Unfortunately those supplies are normally big and heavy and you don’t want to carry 9+ kilos from the lab to the living room in order to do some work on the couch.</p>
<p>A while ago I ordered a DPS3005 module to have a useable CV/CC “supply for the kitchen table”. The module itself provides no outstanding performance but is good enough for most scenarios.</p>
<p>In order to add input and output terminals to the module, I designed a small 3D printable case.</p>
<p>Happy printing!</p>
<h2 id="additional-parts">Additional parts</h2>
<ul>
<li>DPSxxxx size module</li>
<li>4x M3 Nut</li>
<li>4x M3 Screw Length: 30-50mm</li>
<li>Input Terminals (Safety or Double 4mm Jacks) and DC-Jack</li>
<li>Output Terminals (Safety or Double 4mm Jacks)</li>
<li>Cable to connect the Terminals to the module (maybe soldering equipment and heat shrink)</li>
</ul>
<p>Example for the safety or isolated terminals:
<img alt="Isolated Terminals" src="/posts/200413_dps_module_case/images/P1040524-scaled-e1595169960162.jpg"></p>
<p>Example for the double screw terminal and the DC-Jack
<img alt="Screw terminals" src="/posts/200413_dps_module_case/images/P1040525-scaled-e1595170030601.jpg"></p>
<p>Modules which (should) fit</p>
<ul>
<li>DPS3003</li>
<li>DPS3005 (tested)</li>
<li>DPS5005</li>
<li>Electronic Load XY-FZ25 (tested)</li>
<li>…maybe others as well</li>
</ul>
<h2 id="files">Files</h2>
<ul>
<li>Left Part (DPS_Case_left_*.stl)
<ul>
<li>with isolated terminals on the front and back (<a href="/posts/200413_dps_module_case/files/DPS_Case_left_f_iso_b_iso.stl">DPS_Case_left_f_iso_b_iso.stl</a>)</li>
<li>with double terminals on the front and back (<a href="/posts/200413_dps_module_case/files/DPS_Case_left_f_dual_b_dual.stl">DPS_Case_left_f_dual_b_dual.stl</a>)</li>
<li>with an isolated terminal on the front and a double terminal on the back (<a href="/posts/200413_dps_module_case/files/DPS_Case_left_f_iso_b_dual.stl">DPS_Case_left_f_iso_b_dual.stl</a>)</li>
<li>with a double terminal on the front and an isolated terminal on the back (<a href="/posts/200413_dps_module_case/files/DPS_Case_left_f_dual_b_iso.stl">DPS_Case_left_f_dual_b_iso.stl</a>)</li>
</ul>
</li>
<li>Right Part (<a href="/posts/200413_dps_module_case/files/DPS_Case_right.stl">DPS_Case_right.stl</a>)</li>
</ul>
<p><a href="/posts/200413_dps_module_case/files/DPS_Module_Case_REV1.zip">DOWNLOAD ALL</a></p>
]]></content>
        </item>
        
        <item>
            <title>OpenWRT Router on Orange Pi R1 with an additional Raspberry Pi Zero for general use</title>
            <link>https://www.embedded-ideas.de/posts/200126_orange_pi_openwrt/</link>
            <pubDate>Sun, 26 Jan 2020 16:00:00 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/200126_orange_pi_openwrt/</guid>
            <description>Introduction For a while I used a Netgear Firewall Router as network switch and internet router. An additional Raspi Zero provided a Pi-hole.
Actually I couldn’t find a good alternative for the crappy Netgear router because most devices today only provide 4 LAN ports and I need at least six. So I ordered an eight port switch and started this little weekend project.
What I wanted was a simple OpenWRT router with one WAN interface and one LAN interface together with an additional Raspi Zero which could be used for other services.</description>
            <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>For a while I used a Netgear Firewall Router as network switch and internet router. An additional Raspi Zero provided a <a href="https://pi-hole.net">Pi-hole</a>.</p>
<p>Actually I couldn’t find a good alternative for the crappy Netgear router because most devices today only provide 4 LAN ports and I need at least six. So I ordered an eight port switch and started this little weekend project.</p>
<p>What I wanted was a simple OpenWRT router with one WAN interface and one LAN interface together with an additional Raspi Zero which could be used for other services. This setup allows to play around with the Raspi Zero without influencing the router. In order to keep cabling to a minimum, I wanted to connect the Pi Zero via a USB network connection.</p>
<h2 id="openwrt-on-the-orange-pi-r1">OpenWRT on the Orange Pi R1</h2>
<p>The OrangePi R1 is officially supported by the OpenWRT project, unfortunately it doesn’t support the additional USB ports of the board. In order to get USB running with the current version (19.07) you have to compile the sources yourself after hacking a kernel patch. I’m not very familiar with modifying the kernel respectively the Device Tree so I took a quick and dirty approach (..and left a message in the forum, hoping someone will submit the hack as a proper patch :-)</p>
<p>For now, the hack will do…</p>
<p>I assume you are running Linux. Download the sources of the OpenWRT 19.07 version from GitHub: <a href="https://github.com/openwrt/openwrt/tree/openwrt-19.07">https://github.com/openwrt/openwrt/tree/openwrt-19.07</a> and get your build environment ready according to <a href="https://openwrt.org/docs/guide-developer/quickstart-build-images">https://openwrt.org/docs/guide-developer/quickstart-build-images</a> within menuconfig your target configuration should look something like this:</p>
<p><img alt="OpenWRT menuconfig" src="/posts/200126_orange_pi_openwrt/images/opi_menuconfig.png"></p>
<p>In addition we need the RNDIS driver which can be activated at Kernel modules–&gt;USB Support–&gt;kmod-usb-net–&gt;kmod-usb-net-rndis. If you need anything else, now is the time.</p>
<p><img alt="OpenWRT menuconfig usb net if" src="/posts/200126_orange_pi_openwrt/images/grafik.png"></p>
<p>Save the build config and open the file target/linux/sunxi/patches-4.14/201-ARM-dts-sun8i-fix-USB-Ethernet-of-Orange-Pi-R1.patch and replace its content with the following:</p>
<pre tabindex="0"><code>From b76dc5927f6442df913f03ed261c5bff18a98df6 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng &lt;icenowy@aosc.io&gt;
Date: Thu, 28 Dec 2017 21:01:56 +0800
Subject: [PATCH] ARM: dts: sun8i: fix USB Ethernet of Orange Pi R1

Orange Pi R1 uses a Realtek RTL8152B USB Ethernet chip, which is easily
seen on the board but not show in the schematics. A regulator for the
power of the RTL8152B chip is hidden, which uses the same pin with the
Wi-Fi regulator on the original Orange Pi Zero.

Add this regulator back to the device tree, and bind it to USB1.

Signed-off-by: Icenowy Zheng &lt;icenowy@aosc.io&gt;
---
 arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts
@@ -49,6 +49,20 @@
 
 	/delete-node/ reg_vcc_wifi;
 
+	/*
+	 * Ths pin of this regulator is the same with the Wi-Fi extra
+	 * regulator on the original Zero. However it&#39;s used for USB
+	 * Ethernet rather than the Wi-Fi now.
+	 */
+	reg_vcc_usb_eth: reg-vcc-usb-ethernet {
+		compatible = &#34;regulator-fixed&#34;;
+		regulator-min-microvolt = &lt;5000000&gt;;
+		regulator-max-microvolt = &lt;5000000&gt;;
+		regulator-name = &#34;vcc-usb-ethernet&#34;;
+		enable-active-high;
+		gpio = &lt;&amp;pio 0 20 GPIO_ACTIVE_HIGH&gt;;
+	};
+
 	aliases {
 		ethernet1 = &amp;rtl8189etv;
 	};
@@ -71,3 +85,23 @@
 		reg = &lt;1&gt;;
 	};
 };
+
+&amp;usbphy {
+	usb1_vbus-supply = &lt;&amp;reg_vcc_usb_eth&gt;;
+};
+
+&amp;ohci2 {
+	status = &#34;okay&#34;;
+};
+
+&amp;ohci3 {
+	status = &#34;okay&#34;;
+};
+
+&amp;ehci2 {
+	status = &#34;okay&#34;;
+};
+
+&amp;ehci3 {
+	status = &#34;okay&#34;;
+};
</code></pre><p>This simply enables the additional USB ports. Save the file and start to compile using make -j. Now its time for a coffee break.</p>
<p>If everything worked you should now find an image for your Orange Pi R1 in bin/targets/sunxi/cortexa7. Dependent on your preferences you can decide to use either openwrt-sunxi-cortexa7-sun8i-h2-plus-orangepi-r1-ext4-sdcard.img.gz or openwrt-sunxi-cortexa7-sun8i-h2-plus-orangepi-r1-squashfs-sdcard.img.gz. Load the contained image to an SD-Card and power up your Orange Pi R1 with it.</p>
<p>It should be possible to connect to OpenWRT using ssh <a href="mailto:root@192.168.1.1">root@192.168.1.1</a> on the connector without the sticker. The other connector needs to be connected to a DHCP enabled net with internet access. First of all we need to install LuCI (<a href="https://openwrt.org/docs/guide-user/luci/luci.essentials">https://openwrt.org/docs/guide-user/luci/luci.essentials</a> for details):</p>
<pre tabindex="0"><code class="language-terminal" data-lang="terminal">opkg update
opkg install luci
opkg install luci-ssl-nginx
</code></pre><p>LuCI should now be available via https://192.168.1.1/.</p>
<h2 id="raspian-installation-and-rndis-setup">Raspian installation and RNDIS setup</h2>
<p>I used Raspbian Buster Lite for my setup, but the following should work on other versions as well.</p>
<p>Obviously, first step is to prepare an SD-Card with the Raspian image. After that we need to activate the ethernet adapter emulation. Open the boot partition and add the following line to the config.txt:</p>
<pre tabindex="0"><code>dtoverlay=dwc2
</code></pre><p>Open the cmdline.txt and add the following text behind rootwait:</p>
<pre tabindex="0"><code>modules-load=dwc2,g_ether
</code></pre><p>The last step in the boot partition is the creation of an empty file named ssh in order to allow console access.</p>
<p>For details you might consider reading <a href="https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget">https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget</a> (even if I doubt their choice for a text editor).</p>
<h2 id="bringing-it-all-together">Bringing it all together</h2>
<p>Connect the Pi Zero to the Orange Pi R1 using the OTG USB port of the Pi Zero (the inner one). If you run dmesg on the Orange Pi it should show something like</p>
<pre tabindex="0"><code>[    8.902193] usb 4-1: New USB device found, idVendor=0525, idProduct=a4a2
[    8.908916] usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[    8.916146] usb 4-1: Product: RNDIS/Ethernet Gadget
[    8.921287] usb 4-1: Manufacturer: Linux 4.19.75+ with 20980000.usb
[    8.930453] cdc_ether 4-1:1.0 usb0: register &#39;cdc_ether&#39; at usb-1c1c000.usb-1, CDC Ethernet Device, xx:xx:xx:xx:xx:xx
</code></pre><p>For the rest we can use LuCI. Open Network–&gt;Interfaces and click on Edit at the br-lan interface. Open the tab Physical Settings and activate usb0 in the drop down box on the bottom.</p>
<p><img alt="LuCI interface configuration" src="/posts/200126_orange_pi_openwrt/images/grafik-1.png"></p>
<p>We now have connected the Pi Zero to the 192.168.1.x network. It should be available via raspberrypi.lan or the IP-lease that it got from OpenWRT (see Network–&gt;DHCP and DNS–&gt;Static Leases).</p>
<p><img alt="LuCI interface configuration" src="/posts/200126_orange_pi_openwrt/images/grafik-4.png"></p>
<p>This should be enough to get you up and running. I highly recommend to set a password for OpenWRT as a next step ;-)</p>
]]></content>
        </item>
        
        <item>
            <title>Unlimited IO that won&#39;t impact&#39; your BOM costs</title>
            <link>https://www.embedded-ideas.de/posts/190602_logic_io/</link>
            <pubDate>Sun, 02 Jun 2019 17:16:03 +0100</pubDate>
            
            <guid>https://www.embedded-ideas.de/posts/190602_logic_io/</guid>
            <description>Today it is often not necessary to add external IO to a micro controller. If you realise a shortage of pins, you can just step up to the next package and get additional pins without any hassle. But what if the package is set for some reason, you want to add new functionality to an existing project or it just makes sense for the board layout? There are many reasons why external IO might be a good solution.</description>
            <content type="html"><![CDATA[<p>Today it is often not necessary to add external IO to a micro controller. If you realise a shortage of pins, you can just step up to the next package and get additional pins without any hassle. But what if the package is set for some reason, you want to add new functionality to an existing project or it just makes sense for the board layout? There are many reasons why external IO might be a good solution. But as always it comes with its pros and cons:</p>
<ul>
<li>Pros
<ul>
<li>Possible extension of existing projects</li>
<li>Often easier routing</li>
<li>IO features like enhanced current capabilities or voltage level shifting</li>
</ul>
</li>
<li>Cons
<ul>
<li>Requires CPU cycles for bus access</li>
<li>Slower access</li>
<li>Higher complexity (no register mapping)</li>
<li>Additional cost/parts</li>
</ul>
</li>
</ul>
<p>I came across this problem several times now and often used the very common Microchip port expanders like the MCP23008. Such a device offers 8 to 16 configurable pins which can be inputs or outputs with pull-up/down resistors. Actually those parts work great but they can be very expensive depending on your project. Another downside is the protocol overhead which you get as a trade-off for the flexibility of those devices. In case you only want to have a fixed number of inputs or outputs the good old 74 series might be a better solution.</p>
<p>I assume it is widely known that the SPI-Bus is ideal for the connection of shift registers to a micro controller. The 74 logic series offers a wide range of such registers. Especially the 74xx595 and the 74xx165 are good candidates for port expansion.</p>
<p><img alt="74HC595 connection to the SPI-Bus" src="/posts/190602_logic_io/images/SPI_CON_74HC595.png"></p>
<p>The 74xx595 is a serial-in parallel-out (SIPO) shift register with an output latch, it offers eight outputs and can be directly connected to a standard SPI bus which is set to CPOL=0 CPHA=0. The only downside is that if you don’t want the outputs to have an unpredictable state before the first transfer, you also have to control the output enable line. In case you only want to control some LEDs you might not care and set the output enable permanently.</p>
<p><img alt="74HC165 connection on the SPI-Bus" src="/posts/190602_logic_io/images/SPI_CON_74HC165_CS_CPOL1.png"></p>
<p>The 74xx165 is a parallel-in serial-out (PISO) shift register with an input latch, it offers eight inputs. Unfortunately it is a bit less compatible to the SPI defacto standards. It is still possible to use it but you need an active high chip enable and invert the SPI clock (CPOL=1 CPHA=0). Unfortunately this makes it also incompatible with the 74xx595. But what if you need inputs and outputs for your project and you don’t want to mess around with two busses, different chip select lines or clock polarity settings?</p>
<p>The solution is quite simple with another part from the 74 series. Just an inverter e.g. 74xx04 on the latch input and on the clock line of the 74xx165 will do the job. Now the PISO also works with a negative chip select and the common CPOL=0 CPHA=0 settings. The 74xx595 and the 74xx165 can co-exist on one SPI bus and even better: you just need one SPI transfer to set the outputs and read the inputs.</p>
<p><img alt="Connecting 74HC595 and 74HC165 on the same SPI-Bus" src="/posts/190602_logic_io/images/combined.png"></p>
<p>Another great feature of this circuit is its expandability. If you need 8 more inputs or outputs, you just add another shift register. For the 74xx595 this can be achieved by connecting the nG, RCLK, nSCLR and SCKL in parallel and the serial output (QHser) with the new chips serial input (SER). The same for the 74xx165: connect SH and CLK in parallel and the serial output (QH) of the new chip to the serial input (SER).</p>
<p>The presented circuit assumes an own bus for the port expansion. If you want to share the bus with other peripherals, you need to get the SPI MISO line in a tri-state if the chip select line is high. This can be achieved with a tri-state buffer like the 74xx125.</p>
<p><img alt="Tri-state MISO for shared bus access" src="/posts/190602_logic_io/images/shared_bus.png"></p>
<p>There are many derivatives of the shift registers and other parts that can be used for the circuits shown above.</p>
<ul>
<li>74HCT595 / 74HCT165 – Only for 5V systems</li>
<li>74HC595 / 74HC165 – OK for 3.3V applications</li>
<li>74LVC595 / 74LVC165 – 3.3V system + 5V tolerant</li>
<li>74LVC2G04 Dual inverter (in case you don’t have space for the 74xx04)</li>
<li>74LVC1G125 – Single tri-state buffer for bus sharing (replaces 74xx125)</li>
<li>TPIC6B595 – High current version of the 74xx595 with open drain outputs</li>
<li>etc.</li>
</ul>
<p>All parts are generic and you can get them from different manufacturers. This allows you to buy all required ICs for as low as 0.20 USD (already @100 qty) from one of the major brands and even cheaper from a no-name brand .</p>
<p>This should be enough information to get you started on the hardware side, but what about the software? Most things on the cons list are software related. Can we get around some of the problems? Maybe! At least we don’t have any protocol overhead. In case of the circuit in the last picture, we transfer 8 bits with which we set the state of 8 outputs and simultaneously read the state of 8 inputs. With the right hardware we can even offload the CPU cycles to the DMA controller and speed up the transfer rate without causing any CPU load. If we reserve a fixed address for the DMA transfer we can even resemble a “register” for the input and output states. In order to use this mechanism it is crucial that the SPI controller supports to set the chip select line in the right way. The controller has to pull the CS line low on the beginning of a transfer and reset it to high after it. Most microcontrollers that I know have this feature but there are exceptions (most of the STM32 controllers).</p>
<p><img alt="Connected 74xx595 and 74xx165 (up-counting of the outputs on 74xx595 and read back via 74xx165). CS and SCK directly connected to 74xx165" src="/posts/190602_logic_io/images/Upcounting_74HC165.png"></p>
<style>
    .image-gallery {overflow: auto; margin-left: -1%!important;}
    .image-gallery li {float: left; display: block; margin: 0 0 1% 1%; width: 19%;}
    .image-gallery li a {text-align: center; text-decoration: none!important; color: #777;}
    .image-gallery li a span {display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; padding: 3px 0;}
    .image-gallery li a img {width: 100%; display: block;}
</style>


<ul class="image-gallery">


    
    
    <li><a href="https://www.embedded-ideas.de/posts/190602_logic_io/images/SPI_CON_74HC165_CS_CPOL1_hubea78550c1d1eeb887885f50e286609e_10686_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/190602_logic_io/images/SPI_CON_74HC165_CS_CPOL1_hubea78550c1d1eeb887885f50e286609e_10686_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/190602_logic_io/images/SPI_CON_74HC595_hu88a92483ff77098e1edf3fae789be574_9942_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/190602_logic_io/images/SPI_CON_74HC595_hu88a92483ff77098e1edf3fae789be574_9942_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/190602_logic_io/images/Upcounting_74HC165_hu5f8bdcd5f6a439c0a9e6a4cc016589cc_30430_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/190602_logic_io/images/Upcounting_74HC165_hu5f8bdcd5f6a439c0a9e6a4cc016589cc_30430_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/190602_logic_io/images/combined_huccd137e8085d207ce4f3f8bd870c3231_15867_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/190602_logic_io/images/combined_huccd137e8085d207ce4f3f8bd870c3231_15867_135x120_fill_q80_box_smart1_3.png"/></a></li>
    
    
    
    <li><a href="https://www.embedded-ideas.de/posts/190602_logic_io/images/shared_bus_hu3c9a2a85b075908531bfcdd7333a45e3_5307_1980x1080_fit_box_3.png" data-lightbox="x"><img src="https://www.embedded-ideas.de/posts/190602_logic_io/images/shared_bus_hu3c9a2a85b075908531bfcdd7333a45e3_5307_135x120_fill_q80_box_smart1_3.png"/></a></li>
    

</ul>

]]></content>
        </item>
        
    </channel>
</rss>
