Support elecrow 5" hdmi touchscreen display
This is needed for Pi Zero Kiosk/AutoKiosk testing.
This means touchprocessor.c:ts_setup() needs to be able to identify the display. How can I do that more easily than is done now with new displays?
Manufacturer page: https://www.elecrow.com/5-inch-hdmi-800-x-480-capacitive-touch-lcd-display-for-raspberry-pi-pc-sony-ps4.html
Wiki Page: https://www.elecrow.com/wiki/index.php?title=RC050_5_inch_HDMI_800_x_480_Capacitive_Touch_LCD_Display_for_Raspberry_Pi/_PC/_SONY_PS4
hdmi_force_hotplug=1 max_usb_current=1 hdmi_drive=1 hdmi_group=2 hdmi_mode=1 hdmi_mode=87 hdmi_cvt 800 480 60 6 0 0 0 dtoverlay=ads7846,cs=1,penirq=25,penirq_pull=2,- speed=50000,keep_vref_on=0,swapxy=0,pmax=255,xohms=150,xmin=200,xmax=3900, ymin=200,ymax=3900 display_rotate=
This config, via the dtoverlay for ads7846, adds an input device and that apparently is supported by the touchscreen library (libpibox).
piboxLoadDisplayConfig[pibox.c:210] INFO Using an LCD/Touchscreen display loadDisplayConfig[launcher.c:239] INFO Touch screen support enabled. main[launcher.c:1298] INFO display type: Unknown main[launcher.c:1305] INFO Registering imageTouch. piboxTouchRegisterCB[touchProcessor.c:550] INFO Registered a touch ABS callback. piboxLoadDisplayConfig[pibox.c:172] INFO Width 800 Height 480 (800x480) piboxLoadDisplayConfig[pibox.c:193] INFO Screen size is SMALL piboxLoadDisplayConfig[pibox.c:210] INFO Using an LCD/Touchscreen display setupTouchRegions[touchProcessor.c:86] INFO Width / Height: 800 / 480 setupTouchRegions[touchProcessor.c:102] INFO region x.y: 0 / 0 setupTouchRegions[touchProcessor.c:102] INFO region x.y: 266 / 160 setupTouchRegions[touchProcessor.c:102] INFO region x.y: 532 / 320 piboxTouchStartProcessor[touchProcessor.c:474] INFO Started touchProcessor thread. ts_setup[touchProcessor.c:170] INFO Have FT5406 memory based driver, want ADS7846 Touchscreen ts_setup[touchProcessor.c:170] INFO Have ILITEK ILITEK-TP, want ADS7846 Touchscreen ts_setup[touchProcessor.c:170] INFO Have raspberrypi-ts, want ADS7846 Touchscreen ts_setup[touchProcessor.c:170] INFO Have ADS7846 Touchscreen, want ADS7846 Touchscreen ts_setup[touchProcessor.c:173] INFO Using device /dev/input/event3 ts_setup[touchProcessor.c:211] INFO Reading From : ADS7846 Touchscreen (ADS7846 Touchscreen)
So the I need to see if touch events are showing up at all. Maybe it just needs calibration.
This might be a cable problem. The HDMI display has a micro USB port connected to a USB-A connector on an unpowered hub connected to the USB port of the Pi Zero W. This combination might not work. I would need a micro usb to micro usb to test that theory and I don't think I have one.
- % Done changed from 10 to 30
The touchscreen isn't working because the display doesn't register with USB. Everything else looks okay as far as I can tell so I think the problem is the USB hub I'm using. It's a Tusita hub that is said to work with the Pi Zero, and it works fine with a USB-to-Eth cable and a keyboard. It's just not seeing the HDMI display. Removing the keyboard from the Tusita didn't help, either. I need the network cable so can't unplug that one.
So I've ordered a different hub# to see if that works any better.
But wait - it's not the hub. It was the cable. That was one of those stupid charger only cables. Ugh. Found a better cable and now the touchscreen USB is seen and ts_finddevice sees /dev/input/event0 as the touchscreen.
The problem, therefore, is that the touchProcessor thread is using event1:
ts_setup[touchProcessor.c:173] INFO Using device /dev/input/event1
So now I just need to find out why.
One way around this might be to allow a config option to override probing. If TSLIB_TSDEVICE is set in the environment then that can be used instead. So a config option of
Can be picked up by cli.c which calls setenv(TSLIB_TSDEVICE, path, 1) so that the touchscreen library will use that instead of probing. It's a hack for now. I'd still like to know why the probe finds /dev/input/event1 instead of event0.
I found the problem. Running evtest with no arguments lists the input event devices.
# evtest No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0: QDtech MPI5001 /dev/input/event1: ADS7846 Touchscreen
Both are enabled with the ADS7846 driver which is enabled in the config.txt for the elecrow 5in display. However, unlike other ADS7846 devices, this one wants the ODTech MPI5001 device to handle input events.The simple solution is to add ODTech MPI5001 to the ts_name_default array in libpibox:touchscreen.c ahead of the ADS7846 Touchscreen entry. But there are three reasons I don't like this idea.
- The array is static and can't be easily extended.
- Forcing order on the array overly complicates it.
- We can identify which device is running using EDID data and then configure what device name to use from that.
That last item is the kicker - While I can leave the ts_name_default array in place (so things that used to work will still work), I can insert the use of a config file that tells me what device name to search for. That makes extending touchscreen.c much simpler and external to the library itself.
Even easier: ts_setup() includes optional use of the environment variable TSLIB_TSDEVICE. So before that choice is made, we call set_env(TSLIB_TSDEVICE, name). This can be done in a new touchscreen.c function called piboxTouchInit() that parses /etc/ts_device.conf, which simply has the name of the device to use. /etc/ts_device.conf is generated by S15Config from the EDID data by sourcing /etc/ts_devices and taking the value of the EDID Device ID (with spaces converted to underscores) variable. So, something like this.
S15Config runs the following command to get the EDID device ID:
On the Elecrow 5in this produces
which is stored in /etc/pibox.config (and is used to update the firmware config.txt file include file for HDMI displays). It then looks up MPI-MPITEST in /etc/ts_devices and finds this.
The value for MPI-MPITEST, which is the QDTech MPI5001 string, is then stored in /etc/ts_device.conf.
When an app starts and decides it will be a touchscreen, it currently calls piboxTouchRegister(). This will call, automatically and before anything else, piboxTouchInit() to read /etc/ts_device.conf and use it's value, if any, to set the environment variable TSLIB_TSDEVICE.Some rules on the implementation.
- S15Config must clear /etc/ts_device.conf (zero it out but leave it in place) if no match is found the EDID device id.
- /etc/ts_devices is manually updated in the dev platform skeleton tree. It can also be updated manually on a running device.
Note that there is a ads7846.dtbo overlay that we're not specifically loading yet. This could go into a /usr/share/pibox/configs/Display-ads7846.txt config and update the functions:optimizeTouchscreen() init script function to handle setup on firstboot.
Both the Elecrow 5" HDMI and the GeeekPi 5" HDMI use the ads7846, so the same display config works with both. However, psplash is not working on either.
The Elecrow model does use the MPI5001 touch processor so the updates to libpibox:touchprocessor.c are still required.
But the bigger problem is automating things. I need a way to know that the display is the Elecrow model. The tvservice --n doesn't seem to work anymore. I can use tvservice --d /tmp/edid.dat to dump the data and then used edid-decode to print it in human readable format. An even simpler way is to use the command edid-decode < /sys/class/drm/card0-eDP-1/edid, but I need to add Target-Packages->Hardware-Handling->edid-decode to the Buildroot config.
In the latter case I need to look for the edid file under /sys/class/drm/*, which should probably be the same all the time on Raspberry Pi though I'm not clear that it is.
I searched for the edid file on a RPi3 | RPiLCD but it wasn't there. I then added dtoverlay=vc4-fkms-v3d to the display-config.txt and rebooted - the edid file is now there. However, it's now under /sys/class/drm/card0-DSI-1/edid. I then tried adding that overlay to an RPi 2 v1.1 board with an HDMI output and the edid file showed up at /sys/class/drm/card0-HDMI-A-1/edid. The commonality here is that there is only one edid file uder /sys/class/drm as long as two monitors are not connected.
The code for finding the edid is already in tvservice, so using that command to dump the file first is probably easier than trying to write a find-based command to get the edid file. So I'll use tvservice for non-RPiLCD displays and choose the display-config.txt from the output of edid-decode.
- /opt/vc/bin/tvservice -d /tmp/edid.dat
- edid-decode /tmp/edid.dat | grep "Manufacturer" | cut -f2 -d":" | sed 's/ //'
- edid-decode /tmp/edid.dat | grep "Model" | cut -f2 -d":" | sed 's/ //'
The Manufacturer and Model together can be used to select the display config.txt in functions:touchscreenOptimize().This table summarizes the displays that need special display configs.
That's all that's necessary right now since any other HDMI monitors don't need special configuration and the TFT displays are handled separately via the lcdshow package.
- % Done changed from 60 to 80
This is nearly done. I've tested it on
- All three board types (2, 3 and 4)
- 5 display types
- Standard HDMI
- GeeekPi 5" HDMI
- Elecrow 5" HDMI
- 3.5" TFT
- RPi LCD
- 4 PiBox systems
What's left is a chicken/egg problem. The 5" HDMI's need the vc4/v3d overlays to be properly identified, but these are included in the board configs. The board configs are copied in during firstboot but have not been loaded yet. So when firstboot's optimizeTouchscreen() function tries to setup the displays it can't identify the 5" HDMIs yet.
The answer is to move the overlays into config.txt so they're always there. The optimizeTouchscreen() can remove them (if necessary) from config.txt instead of board-config.txt, as can the lcdshow postinst script. The only difference will be that two dtoverlay= entries will be removed, when they are removed.
It would be nice to have overlays loaded dynamically but that won't load the drivers properly. The alternative (which is also possible) is to load the appropriate drivers manually. But I think just stuffing in the overlays in config.txt and removing them during installation/firstboot processing is easier, especially given that it's a one time thing.
Making this last change will require another full round of tests, but I'm pretty sure that's the last round.