Wednesday, March 9, 2016

Beaglebone Black switch monitors

Since I've swapped the BeagleBone on my project with a BeagleBone Black, I would like to benefit from the Black's on-board HDMI capabilities and be able to hook up an external monitor when I need to even though my system is presently working with the LCD7 cape. The problem is that there doesn't seem to be any capability for the BBB to "switch monitors" like for Windows PCs. From experimenting, having the LCD7 cape connected to the BBB (which works) prevents the image from being sent to the HDMI port. If I disconnect the BBB from the LCD7 then when the BBB boots it can connect to an HDMI monitor fine. So far what I think I have learned is that the issue has to do with screen resolutions. It has been hinted on some forums that cape HDMI adapters are essentially monitoring the same signals that are used to generate the HDMI on-board the BBB, and there is no way to "switch" between them as a result. It has also been stated that screen resolution can only be set at boot time for reasons that I don't quite follow. The LCD7 has a resolution of 800x480, which is rare for most other monitors. So what seems to be happening is that during boot, the LCD7 is being recognized and the HDMI resolution is being set accordingly, and either the step for retrieving monitor resolutions from devices connected on the HDMI bus is not happening or the connected monitors would show an image if they supported 800x480. If the latter possibility could somehow be verified it would at least prove that the HDMI connections are in fact parallel. In any case, here is the documentation so far of my research into how this works:

Here is a thread which starts off with somebody having a problem with the BBB just outputting an HDMI signal, despite trying mixing various combinations of known good monitors and cables. Somebody asks the question how to force a particular resolution. Gerald has people try different OS releases, which doesn't work for some but for some people it fixes the problem. One guy turned out to have a bad HDMI adapter cable despite initially thinking that his cable was good. It turns out that bad cables are a huge cause of problems with BBB HDMI not working. Some people report having success with using HDMI to DVI adapter cables. There is a discussion of a configuration information called EDID, and forcing the resolution using the uEnv.txt file. There's a fbset command and a xrandr command. It is proposed to troubleshoot the problem by forcing resolution to 640x480@60 which apparently "all displays are required to support." One guy gives a gorgeous example of using xrandr to read info about the connected display, parse-edid to get info on the monitor, ID.txt file to get info on the OS, xrandr to set a new resolution and fbset for something. Then there is a discussion with a guy who has two BBBs with one that isn't working, but his problem is solved by reinstalling his OS on the board that's giving him trouble. Amazingly, this guy gets responses from Robert C. Nelson himself with this issue!
https://groups.google.com/forum/#!topic/beagleboard/0fMTXLPuGS4

A lot of the hints from Gerald and other users on the various google group threads that I've found are (uncharacteristically) well-summarized in this wiki page, which shows how to use xrandr, parse-edid, and how to mdify the uEnv.txt file: http://elinux.org/Beagleboard:BeagleBoneBlack_HDMI

Here is a google group thread where somebody asks exactly the same question that I have about running an LCD cape and HDMI video output at the same time. Except his case is slightly different in that he's trying, optimistically, to design an LCD cape of his own. He is also using Ubuntu which apparently has the HDMI output always on. This is the thread where Gerald mentions that it would work if the monitor and the LCD are the same resolution. Gerald later states that "the HDMI function needs to be disabled to allow something other than 1024x768 to be sent to those pins," which seems to contradict his earlier statement that the HDMI framer and LCD can be run in parallel. Also, the link given by Gerald is to the FAQ which specifically says "The HDMI framer cannot be disabled via SW" and mentions the pins are configured using the Capemanager and mentions a workaround. The workaround seems to require use of the uENV.txt file which can only be edited via USB. Astonishingly, the OP figures out how to disable the HDMI and does something that enables LCD4 firmware. None of which I've been doing when I switch between the LCD7 and the HDMI monitor. Perhaps it's not actually necessary? The OP asks about signal timing and Gerald starts getting snotty for some reason. Other people ask questions I need to know the answer to and Gerald just replies with "search the forum." That is particularly snide considering that the forum tree has "Newbie" in the path. https://groups.google.com/forum/#!topic/beagleboard/-4Q3UnqxY3k

This is the work-around of disabling the onboard HDMI by editing the uEnv.txt file. It also shows checking a configuration file for the capemanager: http://elinux.org/Beagleboard:Weather_Cape_Work-Around

Interestingly, the forum thread from the HDMI question above is a branch of a forum thread tree that starts at beaglebone/hdmi. Promisingly, one of the first threads in the list is LCD as well as HDMI. Here's the topic list, there is so much potential information here: https://groups.google.com/forum/#!categories/beagleboard/hdmi

So, I followed the instructions from the wiki for running xrandr --verbose to get the information on whatever monitor which the BBB is booting to. Strangely the HDMI monitor on my desk seems to support only one resolution: current, min and max are all 1280x720. When using the LCD7, current, min, and max are all 800x480. This may imply that the LCD7 does not support 640x480 as supposedly required.

Looking at the problem a different way, maybe I could find a way to write a script to selectively enable or disable the LCD7 cape so that if it's disabled the HDMI framer finds my monitor. Is there a way to disable a cape from the command line? Hard to say. Here are some links:

Here are some instructions for modifying uEnv.txt. It seems like it's being done from the command line. But maybe it's through the USB. Must re-re-reread: https://groups.google.com/forum/#!topic/beagleboard/aU__9RGq3xU

Here is another example of setting up uEnv.txt. It's for a completely unrelated example, but still helpful. http://tinkernow.com/2015/01/beaglebone-black-rs232-uart-setup/

Here's a link I've gone through before while trying to get Device Tree working for installing the RTC chip; it shows using overlays to install and deinstall a cape, but in the end it finishes up with editing the uEnv.txt file for permanent installation of a cape. This link also has one a very friendly example of chekcing the capemanager slots file to see what is installed. : https://learn.adafruit.com/introduction-to-the-beaglebone-black-device-tree/exporting-and-unexporting-an-overlay

When I check the slots file with the LCD7 installed, it does not list the virtual HDMI cape for some reason! It shows the LCD7 cape in slot 0 and the eMMC in slot 4 but nothing else. Is the driver for the LCD7 completely deinstalling the HDMI cape at bootup?

Here is perhaps what I was looking for. This is a fairly long forum thread. It starts off with somebody trying to edit uEnv.txt in /boot and not getting the desired result, somebody confirms that it's "the wrong uEnv.txt". They suggest "mounting the FAT partition of the EMMC". Somebody else looks at the environment variables and is interested in what it says about the locations of the uEnv.txt file and the fdt file (which seems to be the device tree setup), and proposes changing the setup to use a different uEnv.txt. The OP finds that the FAT partition can be found through a roundabout method of using fdisk to see all partitions and then picking the one that looks most likely to be the right one and mounting it. Note that the partition name used, mmcblk0p1, is mentioned in several other sources which I haven't had time to list yet. The guy that wants to try changing what file is used at boot time tries a though experiment but in the end he comes up with no answer. https://groups.google.com/forum/#!msg/beagleboard/77IuIt1OCss/O2-kKXHFTmQJ

This is the link that explained why the LCD7 and the HDMI couldn't seem to play together. It turns out that it's because the LCD7 is a touch screen also, and it's apparently set up to use both chip selects on the SPI1 bus which apparently locks out the HDMI interface. I wasn't quite able to figure out from this how the drivers figure out how to not enable the HDMI if the LCD7 is connected, but it confirmed that the two are exclusive and I could never as a result have gotten an HDMI signal at any resolution if the LCD7 is connected. Interestingly, this is a github page which is usually used for code repositories, but this page is set up like a wiki page and is the most exquisitely referenced of any I have ever seen from the BeagleBone community. I should eventually read every link in this page:
https://github.com/notro/fbtft/wiki/BeagleBone-Black

While trying to find the previous link again, I did this google search which unearthed some incredibly juicy looking links about interfacing LCD screens in general that I'd love to get back to again:
https://www.google.com/?gws_rd=ssl#q=beaglebone+black+hdmi+lcd+spi+bus

So, now my idea is to see if there is some way to disable the LCD7 cape without disconnecting it, in such a way that the HDMI interface is allowed to boot up. My first idea was to find whatever Device Tree file is used for the LCD7 cape and either modify it or change its name so it can't be accessed, or maybe modify the main Device Tree files to disable the loading of the LCD7 cape. In the end it didn't work at all; there are no dtbo files for the LCD7 in the appropriate directory and I couldn't find the .dti file for the system (I guess in retrospect it wouldn't have been useful since my system Device Tree was already compiled, duh). The LCD7 seems to be one of the capes that is essentially "built in" to the kernel. However, as a result of all this searching, I read through a lot more very good links about Device Tree and also the Capemanager.

Update 3/10/2016: So, after all that searching, I learned enough to discover that the problem was not as difficult to solve as I had feared. After failing to find a way to disable LCD booting through messing around with .dtb files, I began investigating my options for modifying the uEnv.txt file. Many sources have reported that it is only accessible from the FAT partition over USB, but I had links which showed how to mount that partition into my Linux session so I tried that. I was able to find and mount the partition, but to my surprise, there was no uEnv.txt file there! It had nfs_uEnv.txt and all the html files that come up when you connect the bone as a thumb drive, but no uEnv.txt. A look at nfs_uEnv.txt clearly showed that it didn't have the functions that uEnv.txt does. /boot did have a uEnv.txt file, often described as not the one used for booting, but I tried adding a line to it to disable the LCD cape and boom the BBB rebooted with the LCD disabled and it found the HDMI screen that was connected. So, this file is fairly easy to make a shell script for that switches it between disabling or not disabling the LCD, without requiring any additional partition mounting! I think that the reason why this turned out to be easy after all is that I am running the BBB from SD card; probably when running from eMMC it must use the uEnv.txt file from the FAT partition. Either that or maybe it has a hierarchy of going to the /boot directory if it doesn't find uEnv.txt in the FAT partition, and I got lucky because my particular distro (3.8.13.bone-70) didn't come with that file in that partition.