<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>LCD Displays Archives - Krystof.IO</title>
	<atom:link href="https://krystof.io/tags/lcd-displays/feed/" rel="self" type="application/rss+xml" />
	<link>https://krystof.io/tags/lcd-displays/</link>
	<description>Numerous hobbies, various ramblings.</description>
	<lastBuildDate>Mon, 31 May 2021 00:45:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.9</generator>

<image>
	<url>https://krystof.io/wp-content/uploads/2019/10/cropped-site-icon-low-32x32.jpg</url>
	<title>LCD Displays Archives - Krystof.IO</title>
	<link>https://krystof.io/tags/lcd-displays/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</title>
		<link>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/</link>
					<comments>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Wed, 15 Jan 2020 16:13:13 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[LCD Displays]]></category>
		<category><![CDATA[Featured]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1126</guid>

					<description><![CDATA[<p>I needed a small display for my Commodore diorama that mirrors the output of my Raspberry Pi - I found one with this 1.3 inch ST7789 driven LCD display.  Trouble was, mirroring this wasn't as straight forward as I would have liked.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/">Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>My Commodore 64 Diorama project was well underway.  After installing VICE on the console of a Raspberry Pi 4, the next step was to make sure I could get a tiny display that would fit some sort of &#8216;tiny monitor&#8217; I&#8217;d have to create further into the project.    I shopped around a few different places, but I ended up really liking two, both available from Adafruit.    Either way, we&#8217;re mirroring the Raspberry Pi to a ST7789 driven LCD display. </p>



<p><a href="https://krystof.io/installing-the-vice-commodore-emulator-for-console-mode-on-a-fresh-raspberry-pi-4/">Previously in the series</a>, we installed VICE on our Raspberry Pi and made sure it worked.  Now we want to mirror the HDMI output to our tiny LCD for the <a href="https://krystof.io/series/diorama-64/">diorama</a>.</p>



<p>Here&#8217;s our video that covers this article at a high level:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display" width="1170" height="658" src="https://www.youtube.com/embed/1zTZgx9ilWU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading" id="h-two-lcds-enter-one-lcd-leaves">Two LCDs enter, One LCD leaves</h2>



<p>The <a rel="noreferrer noopener" aria-label="OLED Breakout Board - 16-bit Color 0.96&quot; w/microSD holder (opens in a new tab)" href="https://www.adafruit.com/product/684" target="_blank">OLED Breakout Board &#8211; 16-bit Color 0.96&#8243; w/microSD holder</a> was a contender.  At about 1/12 scale this would have worked out nicely, though it felt a little &#8216;wide screen&#8217; compared to the monitors I knew of my youth.  I was also concerned with resolution, as it supports  96&#215;64, a far cry from the <a rel="noreferrer noopener" aria-label="Commodore 64's 320x200 (opens in a new tab)" href="http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm" target="_blank">Commodore 64&#8217;s 320&#215;200</a>.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="970" height="728" src="https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display.jpg" alt="" class="wp-image-1130" srcset="https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display.jpg 970w, https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display-300x225.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display-768x576.jpg 768w" sizes="(max-width: 970px) 100vw, 970px" /><figcaption>Image from Adafruit&#8217;s Product Page</figcaption></figure>



<p>The other, and my ultimate winner &#8211; the <a rel="noreferrer noopener" aria-label="Adafruit 1.3&quot; 240x240 Wide Angle TFT LCD Display with MicroSD - ST7789 (opens in a new tab)" href="https://www.adafruit.com/product/4313" target="_blank">Adafruit 1.3&#8243; 240&#215;240 Wide Angle TFT LCD Display with MicroSD &#8211; ST7789</a> at least got me closer with 240&#215;240, though it was a touch larger.  To that end, I&#8217;d try both with the Raspberry Pi and compare.  Once I plugged in the 240&#215;240 display and saw the Commodore 64 Ready screen, I was sold.  Even though you&#8217;d be able to make out what I was playing on the OLED display mirroring my HDMI output, with the 240&#215;240 you can actually read a good amount of text, as well.  <em>We have a winner.</em></p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="970" height="728" src="https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display.jpg" alt="" class="wp-image-1131" srcset="https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display.jpg 970w, https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display-300x225.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display-768x576.jpg 768w" sizes="(max-width: 970px) 100vw, 970px" /><figcaption>Image from Adafruit&#8217;s Product Page</figcaption></figure>



<h2 class="wp-block-heading" id="h-a-couple-of-quests-for-the-chosen-one">A Couple of Quests for the Chosen One</h2>



<p>Adafruit has a great page in terms of how to wire this up to an Arduino and Raspberry Pi located <a rel="noreferrer noopener" aria-label="here (opens in a new tab)" href="https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays?view=all" target="_blank">here</a>. It&#8217;s where I learned that the ST7789 chip is used to drive two different LCD displays &#8211; 240&#215;240 and 320&#215;240.  This becomes important later as I struggle with getting that working on the Raspberry Pi.  Regardless of what display I chose &#8211; I knew I needed to have the following requirements satisfied:</p>



<ul><li>The LCD should mirror HDMI output &#8211; I didn&#8217;t want this to be the primary display, but a <em><strong>mirrored</strong></em> display.</li><li>The LCD screen needed to be in a specific orientation &#8211; <strong><em>pins on the bottom</em></strong> &#8211; so they could more easily hide inside the 3D printed monitor &#8216;bottom&#8217;</li></ul>



<h3 class="wp-block-heading" id="h-wire-before-you-fire">Wire Before You Fire</h3>



<p>The display doesn&#8217;t come with header pins pre-soldered, so after remembering which end of the soldering iron is the hot end, I was able to move forward by placing the display into my breadboard:</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="804" height="226" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55.jpg" alt="" class="wp-image-1149" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55.jpg 804w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55-300x84.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55-768x216.jpg 768w" sizes="(max-width: 804px) 100vw, 804px" /></figure>



<p>I followed the basic Adafruit directions for wiring the ST7789 driven 240&#215;240 display into my Raspberry Pi.  Key points:</p>



<ul><li>This is an SPI mode device.  We&#8217;re using the Raspi&#8217;s SPI0 mode, so that some of the LCD pins need to wire up to specific Raspberry Pi Pins.  More on SPI here.</li><li>We have a choice on the LCD&#8217;s reset pin, we went with a loose default of 24 on the Pi.</li><li>We have a choice on the D/C pin, we went with a loose default of GPIO 25 on the Pi.</li></ul>



<p>Here&#8217;s from Adafruit&#8217;s page specific to our ST7789 driven LCD display: <em><strong>(Editors Note &#8211; If you compare this to Adafruit&#8217;s wiring page, you may notice I swapped my RST and D/C pins &#8211; Adafruit uses 24/25 and I&#8217;m using 25/24 &#8211; It&#8217;s fine as long as you&#8217;re consistent with your physical pins and the command line options you&#8217;ll use later.  Thanks, Thomas!)</strong></em></p>



<ul><li><strong>Vin</strong>&nbsp;connects to the Raspberry Pi&#8217;s&nbsp;<strong>3V</strong>&nbsp;pin</li><li><strong>GND</strong>&nbsp;connects to the Raspberry Pi&#8217;s&nbsp;<strong>ground</strong></li><li><strong>CLK</strong>&nbsp;connects to SPI clock. On the Raspberry Pi, thats&nbsp;<strong>SCLK</strong></li><li><strong>MOSI</strong>&nbsp;connects to SPI MOSI. On the Raspberry Pi, thats also&nbsp;<strong>MOSI</strong></li><li><strong>CS</strong>&nbsp;connects to our SPI Chip Select pin. We&#8217;ll be using&nbsp;<strong>CE0</strong></li><li><strong>RST</strong>&nbsp;connects to our Reset pin. We&#8217;ll be using&nbsp;<strong>GPIO 25</strong>&nbsp;but this can be changed later. </li><li><strong>D/C</strong>&nbsp;connects to our the data/command pin. We&#8217;ll be using&nbsp;<strong>GPIO 24</strong>, but this can be changed later as well.</li></ul>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div><em>&#8220;But I looked at Adafruit&#8217;s page and they reference CS AND D/C as SPI Chip Select?&#8221;</em>  I noticed that too&#8230; and it was confusing to me.  It seems there are variations in how SPI works, and here&#8217;s a simple summary of the same question on Adafruit&#8217;s site:  <a rel="noreferrer noopener" label=" (opens in a new tab)" href="https://forums.adafruit.com/viewtopic.php?f=47&amp;t=51949" target="_blank" class="broken_link">https://forums.adafruit.com/viewtopic.php?f=47&amp;t=51949</a>.  Also, found a great summary here on <a rel="noreferrer noopener" aria-label="particle.io (opens in a new tab)" href="https://community.particle.io/t/ssd1306-via-hardware-spi/8448/4" target="_blank">particle.io</a>:<br><br><em>The DC or D/C pin is needed by some devices to distinguish between commands or data for the controler.<br>Since SPI only pushes out anonymous bitsreams the user code has to “tell” the controler if this will be a command (e.g. D/C LOW) or a data (e.g. D/C HIGH) bitstream. And so D/C is not actually an SPI pin, but this gives you freedom which Core pin to choose.</em><br></div></div>



<hr class="wp-block-separator"/>



<p>Remember that the Raspberry PI has numerous GPIO pins, but GPIO pin 24 doesn&#8217;t mean pin 24 on the pin-out diagram &#8211; always refer to some cheat sheet like this one from <a rel="noreferrer noopener" label="RaspberryPi.org (opens in a new tab)" href="https://www.raspberrypi.org/documentation/usage/gpio/" target="_blank" class="broken_link">RaspberryPi.org</a> shown below.  Also, another great Raspberry Pi pin-out page that&#8217;s interactive is made available by <a rel="noreferrer noopener" aria-label="Gadgetoid (opens in a new tab)" href="https://pinout.xyz/" target="_blank">Gadgetoid</a>.</p>



<div class="wp-block-envira-envira-gallery"><div class="envira-gallery-feed-output"><img class="envira-gallery-feed-image" tabindex="0" src="https://krystof.io/wp-content/uploads/2020/01/GPIO-Pinout-Diagram-2-1024x588.png" title="GPIO-Pinout-Diagram-2" alt="" /></div></div>



<p>Okay, so we&#8217;ve got it wired now, and there&#8217;s a promising backlight barely illuminating the LCD when we turn the PI on.  We&#8217;re one step closer to mirroring our Raspberry Pi to the ST7789 driven LCD Display.  Now what?</p>



<h2 class="wp-block-heading" id="h-lcd-driver-powers-activate-form-of-a-mirrored-display">LCD Driver Powers activate! Form of a mirrored display</h2>



<p>While I could have used Python to draw some Commodore images, screenshots, and other static media on the display, I want to actually mirror the display.  What shows on the HDMI output should show on the LCD, but I need the mirror scaled.  My monitor I&#8217;ll play games on doesn&#8217;t support 320&#215;240 as a resolution, the bare minimum is 800&#215;600 to make it work well enough.  So I searched around the internet and found a couple of solutions that did NOT turn the LCD into the only display or require me to overwrite with a new image.</p>



<p>This is where things might get a little confusing.  Both solutions I&#8217;m presenting here involve taking the HDMI display output and doing a little frame-buffer copy and manipulation magic.</p>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>Keep in mind that as the time of this writing, I&#8217;m using the Raspbian Buster Lite image on a Raspberry Pi 4.  Mileage may vary in the future.</div></div>



<hr class="wp-block-separator"/>



<ol><li>Notro&#8217;s <strong>fbtft</strong> LCD device drivers, which create an LCD frame buffer at /dev/fb1, then utilizing tasanakorn&#8217;s <strong>fbcp</strong> program which copies /dev/fb0 (HDMI output) to /dev/fb1 (LCD output), effectively mirroring the display.</li><li>juj&#8217;s <strong>fbcp-ili9341</strong> display driver that effectively does the same thing as #1, though it doesn&#8217;t technically create it&#8217;s own framebuffer, and it&#8217;s not just for ili9341 displays (it supports my ST7789!)</li></ol>



<p>Which one to use?  Well, if only one works for you, choose that one.  Otherwise, I found that  the second, <strong>fbcp-ili9341</strong> worked the best, but it does utilize a little more CPU, so you may very well want to test both (the Raspberry Pi 4 handled it fine)</p>



<p>The primary issues I had with both of these solutions involved rotation.  My requirements for either solution were to have the header pins aligned with the bottom of the display so I could more easily hide them in the mini-LCD monitor&#8217;s bottom piece.  </p>



<h3 class="wp-block-heading" id="h-option-1-fbtft-and-fbcp">Option 1 &#8211; fbtft and fbcp</h3>



<h4 class="wp-block-heading" id="h-the-journey-to-a-working-lcd-mirror">The Journey to a working LCD mirror</h4>



<p>Notro&#8217;s <a rel="noreferrer noopener" aria-label="fbtft driver (opens in a new tab)" href="https://github.com/notro/fbtft" target="_blank">fbtft driver</a> repo seems to be still a good reference point but may not be forever.  There&#8217;s a lot of discussion around the future of this project, as part of it has been brought into the Linux staging structure, and that it may stay there forever stagnating based on some discussions on the <a rel="noreferrer noopener" aria-label="development page (opens in a new tab)" href="https://github.com/notro/fbtft/wiki/Development" target="_blank">development page</a>.  Nevertheless, it did end up working.</p>



<p>There&#8217;s a lot of good information to sift through on that wiki, but I&#8217;ll keep this page more towards my journey in getting it working.</p>



<p>I saw some references in the staging code base to the ST7789 driver, so it felt promising:</p>



<p><a href="https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c</a></p>



<p>Now, the key here is that if these drivers are effectively already part of my Raspbian install, I should be able to use the Linux modprobe commands to load these modules in.  By looking at other sample modprobe commands I tried this against my Raspberry Pi with the LCD on the breadboard:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Screen mirrors but inverted colors and rotation
sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 gpios=reset:25,dc:24
</pre></div>


<p>The command above loads the <em>fbtft_device</em> module with a custom configuration based on the provided driver <em>fb_st7789v</em>.  Notice that we didn&#8217;t have to declare the standard SPI pins but we need to reference our two custom GPIO pins from the wiring section &#8211; reset and dc.</p>



<p><em>Remember that this command just creates a framebuffer for the LCD at /dev/fb1, it doesn&#8217;t actively mirror the display.  We need the fbcp program for that.</em>  I just run fbcp as a background process and voila.  The LCD came to life &#8230; but it&#8217;s a little off.  (Also, don&#8217;t worry, the full setup steps are at the end)</p>



<p>Here&#8217;s the result when I ran &#8216;htop&#8217;:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-1024x578.jpg" alt="" class="wp-image-1161" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06.jpg 1220w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>I want none of this.</figcaption></figure></div>



<p>If you don&#8217;t know what that <strong>should</strong> look like, I can tell you that display screen is rotated 180 degrees off my desired layout (pins on the bottom), and the screen color is &#8216;negative&#8217;.  It should be a black screen with white text.</p>



<p>Now I&#8217;m off to figure out how to rotate and how to invert the colors.  I dug around the issues page on the wiki and found this reference:</p>



<p><a href="https://github.com/notro/fbtft/issues/425">https://github.com/notro/fbtft/issues/425</a></p>



<p>Github user <a rel="noreferrer noopener" aria-label="tr1p1ea  (opens in a new tab)" href="https://github.com/tr1p1ea" target="_blank">tr1p1ea </a>references an init string argument you can also pass along in the modprobe argument, which probably was setting some ST7789 specific codes I needed to set.</p>



<pre class="wp-block-code"><code>init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3</code></pre>



<p>What is all this crap?  These are initialization parameters you can send directly to your LCD driver chipset.  Notro&#8217;s page has some information there, but understanding the specifics for your LCD require the datasheet.  Nevertheless, I tried it out and we got farther&#8230;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="579" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-1024x579.jpg" alt="" class="wp-image-1167" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-1024x579.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-300x170.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49.jpg 1222w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Okay, color looks good, now let&#8217;s rotate it.</figcaption></figure></div>



<p>The fbtft_device page on the wiki references other parameters &#8211; one of them being rotate:</p>



<pre class="wp-block-code"><code>rotate
Angle to rotate display counter clockwise: 0, 90, 180, 270 </code></pre>



<p>Okay, so we rotate with our updated command &#8211; I figured 180 degrees to start.</p>



<pre class="wp-block-code"><code>sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3</code></pre>



<p>Which now leaves us with something completely different &#8211; I thought I saw rotation but couldn&#8217;t tell easily &#8211; so I ran VICE and saw it fill up only part of the screen!</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="580" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-1024x580.jpg" alt="" class="wp-image-1173" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-1024x580.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-300x170.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-768x435.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31.jpg 1220w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>What fresh hell is this?</figcaption></figure>



<p>During my research on fbtft and fbcp, I ran across that the ST7789 driver chip supported 320&#215;240 <strong><em>and</em></strong> 240&#215;240 displays.  So it looked like to me that my 240&#215;240 lcd was acting as a viewport into the &#8216;opposite end&#8217; of the video ram that stores the 240&#215;240 image as configured by our modprobe command.</p>



<p>I had a rough idea now of what I was looking for &#8211; I need to &#8216;scroll&#8217; up about 320-240 = 80 pixels.  How the **** am I supposed to do this?  At this point I started looking for the ST7789 data sheet so I could see if there was some &#8216;mode&#8217; or related setting.  After perusing this for a while, I found something quite interesting in the <a rel="noreferrer noopener" aria-label="PDF (opens in a new tab)" href="https://www.rhydolabz.com/documents/33/ST7789.pdf" target="_blank">PDF</a>:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="535" height="622" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58.jpg" alt="" class="wp-image-1174" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58.jpg 535w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58-258x300.jpg 258w" sizes="(max-width: 535px) 100vw, 535px" /><figcaption>This looks promising!</figcaption></figure></div>



<p>At this point it looked like I wanted to add to our init string.  Something with instruction 37h, with 2 parameters.  I defaulted the first to zero and the second to the number of pixels I wanted to &#8216;scroll&#8217;.  I wasn&#8217;t sure if my rotation settings &#8216;inverted&#8217; the pixel count so I just started with the difference of 320-240 = 80.  Of course, we&#8217;re dealing with hex, so thats 0x50.  The full piece of the initialization string I inserted after the 0x36 instruction follows:</p>



<pre class="wp-block-preformatted">-1,0x37,0x00,0x50
<strong>-1</strong> (break for new instruction)
<strong>0x37</strong> Instruction for Vertical Scroll Start Address Of RAM
<strong>0x00</strong> First Parameter  (defaulted this to 0)
<strong>0x50</strong> Second Parameter (set this to 80 pixels, converted to hex)</pre>



<p>So now my init string, with the extra 37h instruction added, yielded this result:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="577" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-1024x577.jpg" alt="" class="wp-image-1175" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-1024x577.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-768x433.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06.jpg 1226w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Holy crap, it actually worked.</figcaption></figure></div>



<h4 class="wp-block-heading" id="h-install-instructions-for-option-1-fbtft-and-fbcp">Install Instructions for Option 1 &#8211; fbtft and fbcp</h4>



<p>So, we at least have something working.  That was the entire goal of this first stage &#8211; just get the LCD mirroring the HDMI output of my Raspberry Pi with VICE.  Good to go!  So let&#8217;s finish off option 1 by building the list of instructions.</p>



<p>Since fbtft drivers are already part of Raspbian Buster, all we really need to do is download and copy fbcp, and basing the instructions off that GitHub page: <a rel="noreferrer noopener" aria-label="https://github.com/tasanakorn/rpi-fbcp (opens in a new tab)" href="https://github.com/tasanakorn/rpi-fbcp" target="_blank">https://github.com/tasanakorn/rpi-fbcp</a></p>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>This option is here to best describe the journey &#8211; I ended up going with Option 2 &#8211; FBCP-ILI9341</div></div>



<hr class="wp-block-separator"/>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
mkdir ~/fbcp-src
cd ~/fbcp-src

git clone https://github.com/tasanakorn/rpi-fbcp.git
cd rpi-fbcp/

mkdir build
cd build
cmake ..
make
</pre></div>


<p>After that point, a new <em><strong>fbcp</strong></em> binary now exists in the build directory we just made.</p>



<p>To just test the general execution of these two, I&#8217;ll enter the commands into the shell.  Afterwards I&#8217;d see the LCD activate and mirror the screen properly.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
#start LCD Driver - create fb1 frame buffer
sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x37,0x00,0x50,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3
</pre></div>


<p>Then, we need to run fbcp so it can copy the framebuffer from HDMI (/dev/fb0) to the LCD (/dev/fb1) &#8211; run this from your fbcp&#8217;s build directory you created earlier:</p>



<pre class="wp-block-preformatted">./fbcp &amp;</pre>



<p>What if we want this to run on start up?  There are numerous ways to do that, here&#8217;s a simple one &#8211; pop it into rc.local.  We&#8217;ll cover alternate methods later in the series, this article is just about getting the LCD going.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Copy fbcp and start it up and the fbtft drivers  (run from your fbcp build dir)
sudo cp fbcp /usr/bin 
sudo chmod +x /usr/bin/fbcp

sudo nano /etc/rc.local
</pre></div>


<p>Add the following lines to rc.local before &#8216;exit 0&#8217;.  Remember the sudo modprobe is <em>all one single line</em>.</p>



<pre class="wp-block-code"><code>sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x37,0x00,0x50,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3

#
#Add a little sleep before starting fbcp to allow fbtft to initialize
#(your display might stay blank otherwise)
#
sleep 2

/usr/bin/fbcp &amp;</code></pre>



<p>Reboot and you should see the screen mirror after the boot process initializes some.  If you don&#8217;t have your HDMI output active, VICE may not load (it doesn&#8217;t get a good hook into /dev/fb0) &#8211; so you may need to edit your /boot/config.txt and add:</p>



<pre class="wp-block-code"><code>hdmi_force_hotplug=1</code></pre>



<h3 class="wp-block-heading" id="h-option-2-fbcp-ili9341">Option 2 &#8211; fbcp-ili9341</h3>



<h4 class="wp-block-heading" id="h-a-faster-alternative-to-fbtft-fbcp-that-uses-a-little-more-cpu">A faster alternative to fbtft/fbcp that uses a little more CPU</h4>



<p>I was initially happy with option 1 &#8211; I wasn&#8217;t planning on playing games using the tiny LCD, just mirror it so the diorama looked alive.  However, I still perused a few other search threads and found out about this other option called <strong>fbcp-ili9341</strong>, and while the name may be confusing (it doesn&#8217;t create a framebuffer, and it&#8217;s not just for the ili9341 driver), I was able to get it working with our ST7789 1.3&#8243; LCD display.  </p>



<p><strong>Why did I try it out?</strong> Turns out, SPI doesn&#8217;t have the inherent bandwidth as it stands with libtft and fbcp &#8211; and since I&#8217;m playing games, which inherently implies video as opposed to text, I noticed the refresh rate on the LCD was always a little stuttered while playing C64 games and demos.  Through some optimizations and shortcuts, the author juj has created an alternative that is faster than our option 1, all the way to 60fps.  Ohhhhh yeah.</p>



<p>So here&#8217;s the journey to making that work.  A little easier, and a bit nicer payoff.  This option, while using a little more CPU (Our Raspi has 4 cores, so it&#8217;s not a big deal), is <strong><em>fast</em></strong>.  In fact, it says so on it&#8217;s <a rel="noreferrer noopener" aria-label="GitHub page (opens in a new tab)" href="https://github.com/juj/fbcp-ili9341" target="_blank">GitHub page</a>, so you know it&#8217;s true!</p>



<p>Since the name is also confusing, here&#8217;s <em>why</em> it&#8217;s named the way it is:</p>



<p><em>The&nbsp;<code>fbcp</code>&nbsp;part in the name means&nbsp;framebuffer copy; specifically for the ILI9341 controller. fbcp-ili9341 is not actually a framebuffer copying driver, it does not create a secondary framebuffer that it would copy bytes across to from the primary framebuffer. It is also no longer a driver only for the ILI9341 controller. A more appropriate name might be&nbsp;userland-raspi-spi-display-driver&nbsp;or something like that, but the original name stuck. </em></p>



<p>So I downloaded the source and compiled it, and there&#8217;s effectively just one execution line since this takes the place of fbtft and fbcp &#8211; in fact, you can&#8217;t run both at the same time &#8211; test with Option 1 or Option 2 separately.</p>



<p>The <strong>cmake</strong> command to the build takes a few options in, and I chose these as my initial settings so I could see what it would do:</p>



<pre class="wp-block-preformatted"><strong>-DST7789=ON</strong> 
There's built in support for our chip set, so this was a natural choice.
<strong>-DGPIO_TFT_DATA_CONTROL=24</strong>
Same as option 1 - our custom pin we chose for data control.
<strong>-DGPIO_TFT_RESET_PIN=25</strong>
Same as option 1 - our custom pin for LCD display reset.
<strong>-DSPI_BUS_CLOCK_DIVISOR=30</strong>
My sensible default based on the GitHub page - lower is more responsive but may cause screen artifacts on LCDs.</pre>



<p>Compiling with those options successfully, I now had a fbcp-ili9341 binary to execute.  Survey says&#8230;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-1024x578.jpg" alt="" class="wp-image-1191" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-768x433.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04.jpg 1225w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Rotated 90 degrees off, and looks like some debugging info at the &#8216;top&#8217;.</figcaption></figure></div>



<p>Okay, we can fix this.  Reading up on a reported issue in the project&#8217;s GitHub issues list, I found reference to a couple of items to change in the code:</p>



<pre class="wp-block-preformatted"><strong>define DISPLAY_OUTPUT_LANDSCAPE</strong> - If we comment this out, we'll rotate the display 90 degrees - which way though?  Let's try and find out what happens.</pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="491" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-1024x491.jpg" alt="" class="wp-image-1192" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-1024x491.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-300x144.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-768x369.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45.jpg 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Getting closer&#8230;</figcaption></figure></div>



<p>So we&#8217;re rotated properly, but we&#8217;re reversed.  The text should be on the left.  So we need to reverse the image, not just a simple rotation.  Here&#8217;s the next changes I tried:</p>



<pre class="wp-block-preformatted"><strong>madctl ^= MADCTL_COLUMN_ADDRESS_ORDER_SWAP;</strong>  - Adding this line into another file will mirror image the display - Sold!

<strong>-DSTATISTICS=0</strong> Remove that debug information</pre>



<p>So, we try this change and rebuild, and we now have&#8230;</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-1024x578.jpg" alt="" class="wp-image-1195" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03.jpg 1224w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>The proper orientation, but &#8230; slightly squeezed.  Like an 8-bit orange.</figcaption></figure>



<p>Now we&#8217;re getting there!  We&#8217;re oriented in the right way, and the image reads left to right.  Only thing now is to change the scaling, which is how my research led to this option:</p>



<pre class="wp-block-preformatted"><strong>-DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON</strong> - I expected something like this because our display is 240 wide, so it's scaling 180 on the vertical to maintain aspect ratio.  Let's just make it fill the whole thing so we don't have the black bars of doom.</pre>



<p>And now&#8230;.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="491" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-1024x491.jpg" alt="" class="wp-image-1196" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-1024x491.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-300x144.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-768x369.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22.jpg 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>We&#8217;re done!</figcaption></figure>



<p>So now I&#8217;ve got both options working in the same fashion.  There are differences though, and we&#8217;ll cover that in the next section below, after the &#8216;install instructions&#8217;</p>



<h4 class="wp-block-heading" id="h-install-instructions-for-option-2-fbcp-ili9341">Install Instructions for Option 2 &#8211; fbcp-ili9341</h4>



<p>Our goal is to download fbcp-ili9341, perform some quick modifications to the code, set our options, compile, and execute it.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>If you are running Option 1 on start up of your PI, you should disable that first.  Option 1 and Option 2 are mutually exclusive.</div></div>



<p>If necessary, download the dependencies required:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install cmake
</pre></div>


<p>Then let&#8217;s download our source code:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
mkdir ~/fbcp-ili9341
cd ~/fbcp-ili9341
git clone https://github.com/juj/fbcp-ili9341.git
</pre></div>


<p>This creates and downloads the source to /home/pi/fbcp-ili9341/fbcp-ili9341  (Yeah, it&#8217;s a double directory, I always make my own root directories for compilation work)</p>



<p>Before we compile, we need to make the edits referenced in our previous section on figuring out how Option 2 was going to work.  </p>



<p>Edit your config.h file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano ~/fbcp-ili9341/fbcp-ili9341/config.h
</pre></div>


<p>Comment out the line below (the example is already commented out)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
//#define DISPLAY_OUTPUT_LANDSCAPE
</pre></div>


<p>Next, we&#8217;ll edit our ST7789 (actually it&#8217;s a file that handles a couple of ST-made chips) specific file to do the &#8216;mirroring&#8217; swap.  Edit the following:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano ~/fbcp-ili9341/fbcp-ili9341/st7735r.cpp
</pre></div>


<p>and add the following line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
madctl ^= MADCTL_COLUMN_ADDRESS_ORDER_SWAP;
</pre></div>


<p>somewhere before this line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x36/MADCTL: Memory Access Control/, madctl);
</pre></div>


<p><strong>Optional Gamma Change: </strong>I&#8217;ve also, over time, discovered that I like the screen a little darker, primarily because I have a camera pointed at it at the Twitch stream and it causes some overexposure of the screen compared to the diorama itself.  So you can make the gamma 1.0 by changing this line in the same file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x26/Gamma Curve Select/, 0x04/Gamma curve 3 (2.5x if GS=1, 2.2x otherwise)/);
</pre></div>


<p>Change the 0x04 to 0x08:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x26/Gamma Curve Select/, 0x08/Gamma curve 3 (2.5x if GS=1, 2.2x otherwise)/);
</pre></div>


<p>That&#8217;s it for file editing, let&#8217;s get back to the compile.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd ~/fbcp-ili9341/fbcp-ili9341
mkdir build
cd build
cmake -DST7789=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSPI_BUS_CLOCK_DIVISOR=30 -DSTATISTICS=0 -DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON ..
make -j
</pre></div>


<p>This will create the <strong>fbcp-ili9341</strong> binary in the build directory.  Try it out by running it and hitting CTRL-C when you&#8217;re done.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo ./fbcp-ili9341
</pre></div>


<p>If that works nicely for you, you could also make a quick hack to your /etc/rc.local file and make it boot on startup.  (This is a quick hack)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Copy fbcp-ili9341 and start it up on boot
sudo cp ./fbcp-ili9341 /usr/bin 
sudo chmod +x /usr/bin/fbcp-ili9341

sudo nano /etc/rc.local
</pre></div>


<p>Add the following line to rc.local before &#8216;exit 0&#8217;.  </p>



<pre class="wp-block-code"><code>sudo /usr/bin/fbcp-ili9341 &amp;</code></pre>



<h2 class="wp-block-heading" id="h-comparing-mirroring-options">Comparing Mirroring Options</h2>



<p>You may notice right off the bat that the default initialization of our option 1 vs option 2 have a stark difference in brightness.  I didn&#8217;t investigate further in making the first option brighter, because I was just so happy with option 2 as a whole I never looked back.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="590" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-1024x590.jpg" alt="" class="wp-image-1222" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-1024x590.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-300x173.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-768x443.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03.jpg 1199w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Option 2 may seem almost too bright from the photo, but it&#8217;s actually not bad for me in person.</figcaption></figure>



<p>Option 2, as you can see in the video segment at the beginning of this article, has a much higher frame rate as promised.  While I did try two different arguments to the <strong>SPI_BUS_CLOCK_DIVISOR</strong> option (30 and 8), I really didn&#8217;t see much of a difference in my eyes.  The big difference is between fbtft/fbcp being much slower than fbcp-ili9341.  </p>



<p>What&#8217;s the trade-off?  As you see in the video, there&#8217;s about a 20-40% spike in one of my Pi&#8217;s cores on FBCP-ILI9341 vs regular old FBCP.  Given I&#8217;m using a beefy Raspberry Pi, I detected no issues in game play.  Your mileage may vary.</p>



<p>So we&#8217;ve now got part of our diorama circuitry working &#8211; we successfully mirrored the Raspberry Pi HDMI output to the ST7789 driven LCD display, showing whatever we play on our VICE Commodore emulator&#8217;s HDMI output.  There&#8217;s more to come, though!  Remember those 1541 disk drives that Commodore computers utilized?  Well, we need to make sure that the LEDs we plan on putting in those floppy drives <strong>light up according to activity in VICE</strong>.  To do that, we&#8217;ll need to create a custom VICE build (we&#8217;ll be doing a small bit of C programming) so we can drive LED activity and power LEDs based on whatever VICE is doing.  That will be the next article in the series, coming soon.</p>



<h2 class="wp-block-heading" id="h-references-and-further-reading">References and Further Reading</h2>



<p><strong>SPI &#8211; Serial Peripheral Interface</strong></p>



<p><a rel="noreferrer noopener" aria-label="https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all (opens in a new tab)" href="https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all" target="_blank">https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all</a><br><a rel="noreferrer noopener" aria-label="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface (opens in a new tab)" href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface" target="_blank">https://en.wikipedia.org/wiki/Serial_Peripheral_Interface</a><br><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md" class="broken_link">https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md</a><br><a rel="noreferrer noopener" aria-label="https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices (opens in a new tab)" href="https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices" target="_blank">https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices</a></p>



<p><strong>Option 1 &#8211; FBTFT/FBCP</strong></p>



<p><a href="https://github.com/notro/fbtft" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft</a></p>



<p><a href="https://github.com/notro/fbtft/wiki/Development" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft/wiki/Development</a></p>



<p><a href="https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c</a></p>



<p><a href="https://github.com/notro/fbtft/issues/425" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft/issues/425</a></p>



<p><a href="https://www.rhydolabz.com/documents/33/ST7789.pdf" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://www.rhydolabz.com/documents/33/ST7789.pdf</a></p>



<p><a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://github.com/tasanakorn/rpi-fbcp" target="_blank">https://github.com/tasanakorn/rpi-fbcp</a></p>



<p><strong>Option 2 &#8211; FBCP-ILI9341</strong></p>



<p><a href="https://github.com/juj/fbcp-ili9341">https://github.com/juj/fbcp-ili9341</a></p>



<p><strong>Raspberry Pi GPIO Information</strong></p>



<p><a href="https://www.raspberrypi.org/documentation/usage/gpio/" target="_blank" rel="noreferrer noopener" label=" (opens in a new tab)" class="broken_link">https://www.raspberrypi.org/documentation/usage/gpio/</a></p>



<p><strong>Adafruit</strong></p>



<p><a rel="noreferrer noopener" aria-label=".96&quot; OLED Product Page (opens in a new tab)" href="https://www.adafruit.com/product/684" target="_blank">.96&#8243; OLED Product Page</a> (Not the display I ended up going with for resolution reasons, otherwise it&#8217;s very nice.)</p>



<p><a rel="noreferrer noopener" aria-label="1.3&quot; 240x240 TFT LCD Product Page (opens in a new tab)" href="https://www.adafruit.com/product/4313" target="_blank">1.3&#8243; 240&#215;240 TFT LCD Product Page</a> (My ultimate choice for this diorama)</p>



<p><a href="https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays?view=all">Tutorial/Learning Page for the 1.3&#8243; display</a> (wiring, python, etc.)</p>



<p><strong>VICE</strong></p>



<p><a href="https://csdb.dk/release/?id=179123" target="_blank" rel="noreferrer noopener" aria-label="The Elder Scrollers Demo by Booze Design (opens in a new tab)">The Elder Scrollers Demo by Booze Design</a></p>
<p>The post <a rel="nofollow" href="https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/">Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/feed/</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
		
		<series:name><![CDATA[Diorama 64]]></series:name>
	</item>
	</channel>
</rss>
