<?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>Raspberry Pi Archives - Krystof.IO</title>
	<atom:link href="https://krystof.io/topics/raspberry-pi/feed/" rel="self" type="application/rss+xml" />
	<link>https://krystof.io/topics/raspberry-pi/</link>
	<description>Numerous hobbies, various ramblings.</description>
	<lastBuildDate>Wed, 05 Oct 2022 11:43:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.15</generator>

<image>
	<url>https://krystof.io/wp-content/uploads/2019/10/cropped-site-icon-low-32x32.jpg</url>
	<title>Raspberry Pi Archives - Krystof.IO</title>
	<link>https://krystof.io/topics/raspberry-pi/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</title>
		<link>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/</link>
					<comments>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Thu, 14 May 2020 16:58:46 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Featured]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1467</guid>

					<description><![CDATA[<p>After my recent move, the streaming and &#8216;workshop/den/laboratory&#8217; setup has been a lot of work from the ground up on the computer system side. I used to have a Raspberry&#8230;</p>
<p>The post <a rel="nofollow" href="https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/">MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>After my recent move, the streaming and &#8216;workshop/den/laboratory&#8217; setup has been a lot of work from the ground up on the computer system side.  I used to have a Raspberry PI 4 used as a remote webcam that covered my old place&#8217;s 3D printing area.  While that worked, I never liked the idea of dedicating a whole Raspberry Pi 4 to that &#8211; I wanted to try a Raspberry Pi Zero W and see if it could handle the load.  Utilizing the popular MJPG-Streamer package, I was able to get that installed and running, though I had a few hiccups which I&#8217;ll reference at the bottom.</p>



<p>The article is a combination of various articles I found on the web, referencing older versions of one part or another, and this is a reference for my setup should I need to rebuild 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"><span class="dashicon dashicons dashicons-info"></span></div><div>This article targets Raspberry PI Bullseye, Version dated 10-30-2021.</div></div>



<h2 class="wp-block-heading" id="h-hardware">Hardware</h2>



<ul><li>Raspberry Pi Zero W &#8211; Purchased one of those <a rel="noreferrer noopener" href="https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4" target="_blank">kits </a>on Amazon and it came with various cases and cables I needed, so I was happy with it.</li><li>Logitech USB Webcam</li><li>Power/HDMI/USB</li><li>Keyboard/Mouse</li></ul>



<h2 class="wp-block-heading" id="h-fresh-raspbian-install">Fresh Raspbian Install</h2>



<p>I&#8217;m utilizing the latest version of Raspbian as of this writing, which was released around February, 2020.  Flashing that to a simple 16 GB Micro SD Card for a blank slate:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="796" height="478" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47.png" alt="" class="wp-image-1472" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47.png 796w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-300x180.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-768x461.png 768w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-585x351.png 585w" sizes="(max-width: 796px) 100vw, 796px" /><figcaption>Always fresh, never frozen</figcaption></figure>



<p>Assuming you&#8217;re relatively familiar with the Pi, here&#8217;s the minimum I&#8217;m generally doing as post boot up task work:</p>



<ul><li>Changing default password</li><li>Setting Up Wifi</li><li>Enabling SSH</li><li>Setting Hostname</li><li>Setting Locale/Internationalization Options</li><li>Rebooting</li></ul>



<p>After that, the obligatory &#8216;update&#8217; install:</p>


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


<p>I can now SSH into the Pi Zero W, disconnect the keyboard, and move along with the install.</p>



<h2 class="wp-block-heading" id="h-build-dependencies">Build Dependencies</h2>



<p>We need to download some things first before we can build mjpg-streamer.  I found some references to articles that pulled from the SVN repo to retrieve and compile, but I ended up getting a large amount of compile errors that look like some library was swapped but the source wasn&#8217;t updated.  It&#8217;s the <code>'redefinition of ‘struct statx_timestamp’'</code> error.</p>



<p>Instead of pulling the SVN version, I&#8217;m going to be pulling the Git repo of mjpg-streamer that was created by <a rel="noreferrer noopener" href="https://github.com/jacksonliam" target="_blank">jacksonliam</a>.  This (<a href="https://github.com/jacksonliam/mjpg-streamer" target="_blank" rel="noreferrer noopener">https://github.com/jacksonliam/mjpg-streamer</a>) is the &#8216;official&#8217; successor to the now abandoned SVN version at <a href="https://sourceforge.net/projects/mjpg-streamer/" target="_blank" rel="noreferrer noopener" class="broken_link">https://sourceforge.net/projects/mjpg-streamer/</a>.</p>



<p>We&#8217;ll now install our dependencies before we download and compile mjpg-streamer code:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install build-essential libjpeg9-dev imagemagick libv4l-dev cmake git -y
</pre></div>


<h2 class="wp-block-heading" id="h-git-make-install">Git, Make, Install</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
mkdir ~/mjpg-streamer
cd ~/mjpg-streamer

git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental

make
sudo make install
</pre></div>


<p>The make install will copy binaries, libraries and the www pages to the /usr/local/ directory structure:</p>



<ul><li><code>/usr/local/bin/mjpg_streamer</code> &#8211; The primary binary</li><li><code>/usr/local/lib/mjpg-streamer/</code> &#8211; The directory of input/output modules</li><li><code>/usr/local/share/mjpg-streamer/www</code> &#8211; The www server interface</li></ul>



<h2 class="wp-block-heading" id="h-test-the-build">Test The Build</h2>



<p>I&#8217;m going to test the build by plugging in a webcam into the Pi Zero W&#8217;s lone USB port.  Executing dmesg shows that it was loaded properly:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91; 1275.662775] usb 1-1: New USB device found, idVendor=046d, idProduct=082d, bcdDevice= 0.11
&#91; 1275.662796] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=1
&#91; 1275.662806] usb 1-1: Product: HD Pro Webcam C920
</pre></div>


<p>Let&#8217;s test by trying to run mjpg-streamer against the input_uvc.so plugin, since I&#8221;m not using a Raspi-Camera, but a USB one instead.  (<strong>See notes at the bottom about Raspberry Pi Bullseye and Raspi-Cameras</strong>).  I&#8217;ll also output using the http plugin.  So my testing command line looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/usr/local/bin/mjpg_streamer -i &quot;input_uvc.so -f 15 -r 640x480&quot; \
 -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
</pre></div>


<p>Executing that line gives us a dump of data &#8211; here&#8217;s the relevant info:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
MJPG Streamer Version: git rev: 5a6e0a2db163e6ae9461552b59079870d0959340
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 15
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
 o: www-folder-path......: /usr/local/share/mjpg-streamer/www/
 o: HTTP TCP port........: 8080
 o: HTTP Listen Address..: (null)
 o: username:password....: disabled
 o: commands.............: enabled
</pre></div>


<p>Our key variables to tweak are <strong>-f for frame rate</strong>, and <strong>-r for resolution</strong>. I&#8217;ll change those later, but for a quick test I head on out to my browser and point it at the www server at http://cam-pi-zero.local:8080/</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="801" height="706" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40.png" alt="" class="wp-image-1477" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40.png 801w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-300x264.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-768x677.png 768w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-585x516.png 585w" sizes="(max-width: 801px) 100vw, 801px" /><figcaption>I always feel like&#8230; somebody&#8217;s watching me&#8230;</figcaption></figure>



<p>Not only do we see the web interface, but a snapshot of the web cam, which was, clearly, laying down on a workbench behind me while I tried this out.</p>



<p>Validating the stream worked (by clicking &#8216;Stream&#8217;) and turning around, I could see myself moving:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="734" height="706" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38.png" alt="" class="wp-image-1478" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38.png 734w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38-300x289.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38-585x563.png 585w" sizes="(max-width: 734px) 100vw, 734px" /><figcaption>Hello you&#8230; come here often?</figcaption></figure>



<p>You can now hit CTRL-C in your SSH window (or terminal) and quit the stream.  After this point, I could delete the build files I downloaded.</p>



<h2 class="wp-block-heading" id="h-tweaking-configuration">Tweaking configuration</h2>



<p>I wanted to run my camera at its intended resolution and at least a frame rate of 30fps.  To do that I modified my command line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#30fps, 1080 HD
/usr/local/bin/mjpg_streamer -i &quot;input_uvc.so -f 30 -r 1920x1080&quot; \
 -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
</pre></div>


<p>I then loaded my own stream up in VLC by opening the direct network path to the stream:</p>



<p>http://cam-pi-zero.local:8080?action=stream</p>



<p>That worked, and I get about a 1-2 second delay from Pi to VLC.  So I wouldn&#8217;t use this with audio feeds unless I was planning on creating a sync delay.  I&#8217;m using this to monitor 3D prints, or watch birds outside, so my use case does <strong>not</strong> demand low latency.  Is it exactly 30 frames per second?  No&#8230;. NO it&#8217;s not.</p>



<p>At 1280&#215;720, it seemed closer, but at 1920&#215;1080, when set at 30fps, it definitely wasn&#8217;t even close.  I&#8217;d guess more like 15.</p>



<p>The PI wasn&#8217;t maxed out on CPU, but it could just be the nature of USB 2.0 at this point.  I&#8217;m not sure how I can tell if it&#8217;s overloaded there or not, but, once again, this is a light monitoring video stream, I don&#8217;t care too much about latency.  It could be WiFi as well.  Someday I may dig in a bit more and find out where the bottleneck is.</p>



<p>I think you could probably choose either 1920&#215;1080 15fps or 1280&#215;720 30fps routes and be okay.</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"><span class="dashicon dashicons dashicons-info"></span></div><div>Be careful about frames and resolution &#8211; Watch your CPU, but also make sure you don&#8217;t see messages about fps being &#8216;coerced&#8217; down or up.  Your mileage may vary, and you may have to tweak format, fps, and resolution settings further, check out the mjpg-streamer headquarters on their git hub page (see references down below).  You can also see the different modes available to your camera by using this command:</div></div>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
v4l2-ctl --list-formats-ext
</pre></div>


<h2 class="wp-block-heading" id="h-running-on-startup">Running On Startup</h2>



<p>I liked<a rel="noreferrer noopener" href="https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/" target="_blank" class="broken_link"> Jacob Salmela</a>&#8216;s script &#8211; all I did was change it for my command line on the stop and restart section for my resolution and frame-rate.  Save the following script by doing a sudo vi:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sudo vi /etc/init.d/livestream.sh
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/bin/sh
# /etc/init.d/livestream.sh
### BEGIN INIT INFO
# Provides:          livestream.sh
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: mjpg_streamer for webcam
# Description:       Streams /dev/video0 to http://IP/?action=stream
### END INIT INFO
f_message(){
        echo &quot;&#91;+] $1&quot;
}

# Carry out specific functions when asked to by the system
case &quot;$1&quot; in
        start)
                f_message &quot;Starting mjpg_streamer&quot;
                /usr/local/bin/mjpg_streamer -b -i &quot;input_uvc.so -f 15 -r 1920x1080&quot; -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
                sleep 2
                f_message &quot;mjpg_streamer started&quot;
                ;;
        stop)
                f_message &quot;Stopping mjpg_streamer…&quot;
                killall mjpg_streamer
                f_message &quot;mjpg_streamer stopped&quot;
                ;;
        restart)
                f_message &quot;Restarting daemon: mjpg_streamer&quot;
                killall mjpg_streamer
                /usr/local/bin/mjpg_streamer -b -i &quot;input_uvc.so -f 15 -r 1920x1080&quot; -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
                sleep 2
                f_message &quot;Restarted daemon: mjpg_streamer&quot;
                ;;
        status)
                pid=`ps -A | grep mjpg_streamer | grep -v &quot;grep&quot; | grep -v mjpg_streamer. | awk ‘{print $1}’ | head -n 1`
                if &#91; -n &quot;$pid&quot; ];
                then
                        f_message &quot;mjpg_streamer is running with pid ${pid}&quot;
                        f_message &quot;mjpg_streamer was started with the following command line&quot;
                        cat /proc/${pid}/cmdline ; echo &quot;&quot;
                else
                        f_message &quot;Could not find mjpg_streamer running&quot;
                fi
                ;;
        *)
                f_message &quot;Usage: $0 {start|stop|status|restart}&quot;
                exit 1
                ;;
esac
exit 0
</pre></div>


<p>Then we enable this on startup by performing:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo chmod 755 /etc/init.d/livestream.sh
sudo update-rc.d livestream.sh defaults
</pre></div>


<p>Now you can reboot your pi, or use commands like &#8216;sudo service livestream start&#8217;   I rebooted my pi, and my fed was running, and running a status command on my service yields:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
pi@cam-pi-zero:~ $ sudo service livestream status
● livestream.service - LSB: mjpg_streamer for webcam
   Loaded: loaded (/etc/init.d/livestream.sh; generated)
   Active: active (running) since Thu 2020-05-14 11:46:09 CDT; 2min 51s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 411 ExecStart=/etc/init.d/livestream.sh start (code=exited, status=0/SUCCESS)
   Memory: 2.2M
   CGroup: /system.slice/livestream.service
           └─416 /usr/local/bin/mjpg_streamer -b -i input_uvc.so -f 15 -r 1920x1080 -o output_http.so

May 14 11:46:07 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: TV-Norm...........: DEFAUL
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: www-folder-path......: /us
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: HTTP TCP port........: 808
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: HTTP Listen Address..: (nu
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: username:password....: dis
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: commands.............: ena
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: starting input plugin inpu
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: starting output plugin: ou
May 14 11:46:09 cam-pi-zero.local livestream.sh&#91;411]: &#91;+] mjpg_streamer started
May 14 11:46:09 cam-pi-zero.local systemd&#91;1]: Started LSB: mjpg_streamer for webcam.

</pre></div>


<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>



<p>Using the Raspberry Pi for video streams is good enough if we&#8217;re looking for low frame rate monitoring without audio.  I&#8217;ve yet to find anything that really gives me the frame rate and audio (regardless of latency) that a standard USB webcam directly into my OBS machine would give.  Maybe if NDI ever makes it on to the raspberry Pi, or if there is ever SLDP support.</p>



<p>Have you tried streaming across the network on a Raspberry Pi with a USB webcam?  Did you fare better than I?  Let me know!</p>



<p>Nevertheless, with that, I&#8217;m done!  I can now embed this into OBS via the VLC media source or anything that can handle an HTTP Motion JPEG video stream.  I won&#8217;t have audio, but that&#8217;s okay for what I&#8217;m using this for.</p>



<h2 class="wp-block-heading" id="h-raspi-cameras-libcamera-is-in-raspivid-is-out-in-bullseye">Raspi-Cameras (libcamera is in, raspivid is out in Bullseye)</h2>



<p>Mjpg-Streamer won&#8217;t have the raspicam input module anymore if you compile on Bullseye, because I believe the headers don&#8217;t exist as the Bullseye version is going the way of libcamera.  While I was able to hack around that and build it, I got HORRIBLE artifacts using a raspberry pi camera with the h264 codec and libcamera.  I tried switching codecs to MJPEG instead of H264 and had less artifacts, but worse frame rate.  So for now I decided to go with gstreamer instead of mjpg-streamer at 1280&#215;720 for a nice 30fps solution.</p>



<p>For me, what worked was to enable the legacy raspi-camera support (so we&#8217;re not using libcamera, we&#8217;re using v4l2).</p>



<p>Here are the rough steps:</p>



<ul><li>Started out with Bullseye, latest install with sudo apt update/sudo apt upgrade executed.</li><li>Edit /boot/config.txt and change the following:<ul><li>start_x=1 //add this line</li><li>gpu_mem=128  //probably no higher</li><li>#camera_auto_detect=1 //Comment this line out</li></ul></li><li>Restart</li><li>Installs:</li></ul>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install gstreamer1.0-tools gstreamer1.0-plugins-base \
     gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
</pre></div>


<p>Then execute this on the command line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/usr/bin/gst-launch-1.0 v4l2src ! video/x-h264,width=1280,height=720,framerate=30/1 ! h264parse config-interval=1 ! matroskamux streamable=true ! tcpserversink host=::0 port=9000 sync=false sync-method=2
</pre></div>


<p>Once that&#8217;s up and running, I ran VLC against it using :network-caching=250 and a URL of tcp://&lt;yourhostname&gt;:9000 and was able to get a decent stream.  That&#8217;s about the extent I&#8217;ve been pushing the raspi-cameras as I typically use the USB side.  I did notice it was nice and fluid, along with less power consumption by a 100 milliamps or so, so I think I&#8217;ll use this as a portable battery powered wireless camera to use around the house on streams.  Hmmm, I may need to look at getting a microphone on here somehow and streaming audio with gstreamer as well.</p>



<h2 class="wp-block-heading" id="h-references">References</h2>



<ul><li><a href="https://einar.slaskete.net/2018/08/16/using-a-raspberry-pi-as-a-surveillance-camera-in-home-assistant/" target="_blank" rel="noreferrer noopener">https://einar.slaskete.net/2018/08/16/using-a-raspberry-pi-as-a-surveillance-camera-in-home-assistant/</a></li><li><a href="https://picamera.readthedocs.io/en/release-1.12/fov.html" target="_blank" rel="noreferrer noopener" class="broken_link">https://picamera.readthedocs.io/en/release-1.12/fov.html</a></li><li><a href="https://qengineering.eu/install-gstreamer-1.18-on-raspberry-pi-4.html" target="_blank" rel="noreferrer noopener" class="broken_link">https://qengineering.eu/install-gstreamer-1.18-on-raspberry-pi-4.html</a></li><li><a rel="noreferrer noopener" href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md" target="_blank" class="broken_link">https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md</a> &#8211; Raspberry Pi Document on WIFI Setup</li><li><a rel="noreferrer noopener" href="https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4" target="_blank">https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4</a> &#8211; The Raspberry Pi Zero W kit I purchased</li><li><a href="https://sourceforge.net/projects/mjpg-streamer" rel="noreferrer noopener" target="_blank" class="broken_link">https://sourceforge.net/projects/mjpg-streamer </a>&#8211; The original source forge project.</li><li><a href="https://github.com/jacksonliam/mjpg-streamer" rel="noreferrer noopener" target="_blank">https://github.com/jacksonliam/mjpg-streamer</a> &#8211; The successor to the abandoned Sourceforge project.</li><li><a href="https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/" class="broken_link">https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/</a> &#8211; Reference for build information</li><li><a href="https://www.acmesystems.it/video_streaming">https://www.acmesystems.it/video_streaming</a> &#8211; Another build reference</li><li><a href="https://qiita.com/xeno14/items/e32e52c688d969d182e2">https://qiita.com/xeno14/items/e32e52c688d969d182e2</a> &#8211; Another build reference</li></ul>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/">MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/feed/</wfw:commentRss>
			<slash:comments>41</slash:comments>
		
		
			</item>
		<item>
		<title>Installing Alternative Python Versions on Raspberry Pi</title>
		<link>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/</link>
					<comments>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sat, 15 Feb 2020 13:42:49 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1408</guid>

					<description><![CDATA[<p>Installing an alternative version of python on the raspberry pi.  This is primarily used when the stock version is lower than the python version you desire.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/">Installing Alternative Python Versions on Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In my <a href="https://krystof.io/series/diorama-64">Commodore 64 Diorama series</a>, I used Python to read shared memory segments that we wrote to from VICE.  However, the version of Python at the time of that Raspbian install was less than the version I needed &#8211; 3.8 or higher.  Here&#8217;s how I installed an alternative version of Python, along with making it the default version and using PIP in a version-specific manner.</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"><span class="dashicon dashicons dashicons-info"></span></div><div>This document is a combination from a few different resources and for Python 3.8.  Ideally later versions would work in a similar fashion.</div></div>



<h2 class="wp-block-heading" id="h-downloading-and-updating">Downloading and Updating</h2>



<p>The obligatory apt update/apt upgrade, along with installing dependencies:</p>


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

sudo apt update
sudo apt upgrade
sudo apt-get install -y build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev tar wget vim

wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz
</pre></div>


<h2 class="wp-block-heading" id="h-compile-and-install">Compile and Install</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
tar zxf Python-3.8.0.tgz
cd Python-3.8.0
./configure --enable-optimizations
make -j 4
sudo make altinstall
</pre></div>


<h2 class="wp-block-heading" id="h-validation">Validation</h2>



<p>Executing this on the command line should work just fine and return the version installed:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
pi@vice-pi:~ $ python3.8 -V
Python 3.8.0
</pre></div>


<h2 class="wp-block-heading" id="h-making-our-install-the-default-version">Making our install the default version</h2>



<p>I prefer to do this by adding the alias to a (potentially new) file .bash_aliases in your home directory by adding this line to the file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
alias python=&#039;/usr/local/bin/python3.8&#039;
</pre></div>


<h2 class="wp-block-heading" id="h-example-pip-updating">Example PIP updating</h2>



<p>Based on some current reading it looks like it&#8217;s a good practice to use the python version specific pip for the version you&#8217;re running instead of assuming any default.  Here&#8217;s the example I used to update the python package manager and installing the RPi.GPIO library.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo python3.8 -m pip install --upgrade pip
sudo python3.8 -m pip install RPi.GPIO
</pre></div>


<h2 class="wp-block-heading" id="h-references">References</h2>



<ul><li><a rel="noreferrer noopener" aria-label="https://www.scivision.dev/compile-install-python-beta-raspberry-pi/ (opens in a new tab)" href="https://www.scivision.dev/compile-install-python-beta-raspberry-pi/" target="_blank">https://www.scivision.dev/compile-install-python-beta-raspberry-pi/</a></li><li><a rel="noreferrer noopener" aria-label="https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/ (opens in a new tab)" href="https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/" target="_blank">https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/</a></li><li><a rel="noreferrer noopener" label="https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/ (opens in a new tab)" href="https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/" target="_blank" class="broken_link">https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/</a></li><li><a href="https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip" target="_blank" rel="noreferrer noopener" label="https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip (opens in a new tab)" class="broken_link">https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip</a></li></ul>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/">Installing Alternative Python Versions on Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<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 loading="lazy" 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" label="Commodore 64&#039;s 320x200 (opens in a new tab)" href="http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm" target="_blank" class="broken_link">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>
		<item>
		<title>Auto mounting a USB drive in a Raspberry Pi</title>
		<link>https://krystof.io/auto-mounting-a-usb-drive-in-a-raspberry-pi/</link>
					<comments>https://krystof.io/auto-mounting-a-usb-drive-in-a-raspberry-pi/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Mon, 30 Dec 2019 03:16:58 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1026</guid>

					<description><![CDATA[<p>This isn't de facto behavior out of the box for a Raspberry Pi - so how do we auto mount USB drives to make access and file copying easier?</p>
<p>The post <a rel="nofollow" href="https://krystof.io/auto-mounting-a-usb-drive-in-a-raspberry-pi/">Auto mounting a USB drive in a Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When I&#8217;m building some retro arcade setups on a Raspberry Pi I&#8217;m often copying over some set of disk images, media files, configuration, or ROMs.  They&#8217;re not always on the same network, and sometimes it&#8217;s just easier to take a keychain thumb drive and copy some files around.  I&#8217;m not always in a windows environment on these boxes, either.  I searched the web for a bit on how to do it and here&#8217;s the information I&#8217;ve compiled in a step by step format.</p>



<h2 class="wp-block-heading" id="h-step-1-install-pmount">Step 1 &#8211; Install pmount</h2>



<p><strong>pmount</strong> is a wrapper around the standard mount program which permits normal users to mount removable devices without a matching /etc/<a href="https://wiki.debian.org/fstab">fstab</a>&nbsp;entry.   This is how we&#8217;ll manage to auto mount our USB drives.</p>


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


<h2 class="wp-block-heading" id="h-step-2-udev-rule">Step 2 &#8211; UDEV Rule</h2>



<p>Udev&nbsp;allows for&nbsp;<em>rules</em>&nbsp;that specify what name is given to a device, regardless of which port it is plugged into.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo vi /etc/udev/rules.d/usbstick.rules
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
ACTION==&quot;add&quot;, KERNEL==&quot;sd&#91;a-z]&#91;0-9]&quot;, TAG+=&quot;systemd&quot;, ENV{SYSTEMD_WANTS}=&quot;usbstick-handler@%k&quot;
</pre></div>


<h2 class="wp-block-heading" id="h-step-3-create-systemd-service">Step 3 &#8211; Create Systemd service</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo vi /lib/systemd/system/usbstick-handler@.service
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;Unit]
Description=Mount USB sticks
BindsTo=dev-%i.device
After=dev-%i.device

&#91;Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/automount %I
ExecStop=/usr/bin/pumount /dev/%I
</pre></div>


<h2 class="wp-block-heading" id="h-step-4-create-mount-script">Step 4 &#8211; Create Mount Script</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo vi /usr/local/bin/automount
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/bin/bash

PART=$1
FS_LABEL=`lsblk -o name,label | grep ${PART} | awk &#039;{print $2}&#039;`

if &#91; -z ${FS_LABEL} ]
then
    /usr/bin/pmount --umask 000 --noatime -w --sync /dev/${PART} /media/${PART}
else
    /usr/bin/pmount --umask 000 --noatime -w --sync /dev/${PART} /media/${FS_LABEL}_${PART}
fi
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo chmod +x /usr/local/bin/automount
</pre></div>


<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"><span class="dashicon dashicons dashicons-info"></span></div><div>Note the &#8211;sync option &#8211; with that enabled above write operations will not utilize caching, so while the write is &#8216;safer&#8217; to prevent data loss, it&#8217;s also a lot slower.  Your mileage may vary.</div></div>



<h2 class="wp-block-heading" id="h-step-5-should-be-working-but-if-not">Step 5 &#8211; Should be working, but if not&#8230;</h2>



<p>You&#8217;ll see your USB drives mounted under /media</p>



<p>Per the comment from James:</p>



<blockquote class="wp-block-quote"><p>And rather than reboot, UDEV should automatically detect new rules[<a href="https://wiki.archlinux.org/title/Udev#Loading_new_rules" target="_blank" rel="noreferrer noopener">2</a>], but if it fails to:</p><p>udevadm control &#8211;reload</p></blockquote>



<p>If that doesn&#8217;t work&#8230; you can always try turning it off and on again 🙂</p>



<h4 class="wp-block-heading" id="h-references">References</h4>



<ul><li><a href="https://linux.die.net/man/1/pmount" class="broken_link">pmount</a></li><li><a href="https://raspberrypi.stackexchange.com/questions/66169/auto-mount-usb-stick-on-plug-in-without-uuid" class="broken_link">Stack Exchange Post</a></li></ul>
<p>The post <a rel="nofollow" href="https://krystof.io/auto-mounting-a-usb-drive-in-a-raspberry-pi/">Auto mounting a USB drive in a Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/auto-mounting-a-usb-drive-in-a-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
	</channel>
</rss>
