Jumping down the Raspberry Pi Rabbit Hole
by Cory on May 1, 2020 9:59 PM (Edited May 1, 2020 10:01 PM)
Everything's comin' up Milhouse!
Last weekend I remembered that I bought a tiiiiny 1.8" TFT LCD display from adafruit and I decided to pull it out and see if I can hook it up to the raspberry pi. I tried it, failed, tried again and again, failed again and again, lost sleep, got really annoyed, and then finally got it working! I was surprised actually, because usually my forays into hardware don't really lead anywhere. (But I *FUCKING* got it working this time. That's how much I wanna play videogames in bed, I guess)
If you have the retropie image, you can shutdown EmulationStation (the program that you see above and loads emulators), and switch to the Raspbian console.
The screen is surprisingly sharp and crisp, although in this format all the text is too small to read when playing games.
It's not completely perfect yet. I need to fiddle with the LCD settings as you can see colorful static on the left and bottom edges. And I'm manually loading the LCD kernel module, where I'm supposed to use some configuration file to have it come up during boot. And of course, the next step is to buy a larger LCD display (maybe one with a DSI connector instead of going through SPI/GPIOs?) and do the speakers, and buttons.
The rest of this post will be just notes and tips for anyone trying to do the same thing. Here's the stats:
- I bought a Raspberry Pi 3 Model A+. (I recommend getting a Raspberry Pi 4 if you don't have one, since Retropie very recently released an update to support the newest model. And it can emulate PSP games!)
- I installed a premade Retropie image for the Pi 3. Retropie is the group that wrote a bunch of software for the Raspberry Pi that makes it possible to play old videogames. The retropie image is a bare bones Rasbian (Raspberry Pi Debian linux variant) operating system installation.
- I bought an Adafruit 1.8" TFT LCD display compatible with the ST7735R driver.
So the first step is to solder some pin header onto the LCD display so you can hook up wires or put it into a breadboard. The wiring should be straightforward. The pin assignments are here and a reference to the pin numbering is here.
Once you have it physically connected to the Raspberry Pi, you can turn it on and have it boot up. I enabled wireless, supplied network credentials, and enabled ssh so I could log into the terminal from my home computer. It's way easier this way, trust me.
You need to enable the SPI interface on the Raspberry Pi to talk to the LCD. This can be done by running `sudo raspi-config` while ssh'd and then going to > Interfacing Options > SPI and say "yes" when it asks if you want to enable this. Then reboot. Alternatively, you can ssh into the Pi and browse to /boot/config.txt, do a "sudo vi config.txt" and make sure the line "dtparam=spi=on" is uncommented.
A long time ago, a dude named Notro made LCD drivers for a whole bunch of devices. They were incorporated into the Raspbian kernel a while back so luckily there's no need to download anything.
His driver repo is kind of out of date, but still really useful. Anyway, everything in his repo boils down to this. Just run this command:
sudo modprobe fbtft_device name=adafruit18_green txbuflen=32768 debug=7 rotate=270
The debug parameter is optional, but will print a lot of helpful diagnostic messages to dmesg. Rotate will orient the screen depending on the supplied degree input. You will probably need to do 90 or 270 depending on which side you are holding the screen. All the parameters are described in the driver repo.
If this works, you'll see the screen light up and appear kind of darkish. If this DOESN'T work, you'll see a blank white screen. LIke this:
This part took me a week to solve... =_=
A forum post told me that this means that the initialization sequence was incorrect and the driver isn't initialized properly. HERE'S WHY. The adafruit display comes with colored tabs on the shrink wrap. There's red tabs and green tabs, which dictate the underlying LCD model (and in turn which init sequence you need to use). As you can see, the above picture shows that mine has a green tab.
Which is why I used the "adafruit18_green" device when load the TFT driver module. If you don't have a green tab, you'll need to write "adafruit18".
After you load the module, you can check dmesg to see how the driver initialization went. You should see something like:
# dmesg | less
[ 46.049567] spidev spi0.0: spidev spi0.0 125000kHz 8 bits mode=0x00
[ 46.049584] spidev spi0.1: spidev spi0.1 125000kHz 8 bits mode=0x00
[ 46.049641] bcm2708_fb soc:fb: soc:fb id=-1 pdata? no
[ 46.049697] spidev spi0.0: Deleting spi0.0
[ 46.050549] fbtft_device: GPIOS used by 'adafruit18_green':
[ 46.050560] fbtft_device: 'reset' = GPIO25
[ 46.050566] fbtft_device: 'dc' = GPIO24
[ 46.050575] fbtft_device: 'led' = GPIO18
And do `ls /dev/` and check to make sure the framebuffer 1 is there. (Framebuffer 0 is already made and probably whatever you've hooked up to the HDMI port).
To check if it's working, you can write random data to the framebuffer.
cat /dev/urandom > /dev/fb1
If you got the white screen and it doesn't work, nothing will happen. But if it is working, you'll see colorful static:
Never has static looked so beautiful to me.
Ok so if you're here, you're like 90% of the way there. The last thing you need to do is to download and install fbcp. This is a script someone wrote to copy the contents of framebuffer 0 (going to the HDMI) into framebuffer 1. Just uh... you know, figure out some way to get it onto the raspberry pi. Setup a GitHub ssh key if you want to bother, or maybe just download it on your computer and `scp` it to the pi, I dunno.
Follow the instructions to build fbcp and then run it and you'll see that EmulationStation is now tiny and on the LCD! (Like in the first picture at the top of this post).
Another thing is that if you want to get console output to the LCD screen, you need to shutdown EmulationStation (the easiest way is through the in app menu to Quit > Shutdown EmulationStation) and then run `con2fbmap 1 1` in your ssh session. This redirects the console graphical output to framebuffer 1. And doing that successfully will make your screen look like the second picture at the top of this post.
Where to go from here:
I did the manual kernel module loading approach because I wanted something quick and dirty to see if everything would work. Next is to use the device tree and make an overlay for this display. Unfortunately, I haven't been able to find one and I still don't know enough about device trees to write one myself. I think I'm going to buy a bigger screen and then handle this issue when that one is working instead.
This Thought is part of Emulators
Cory tries to make the perfect handheld emulator