Graphical front panel display

Hmm… with the overclocking suggested in this RPi Forum thread

https://www.raspberrypi.org/forums/viewtopic.php?t=249071

I’m finding the Zero W not bad at all. I think it would be a lower-power draw than using the RPi 3. I’ll have to experiment a bit more, but I think it may work out. I’d certainly encourage others to give the Zero a try for this application.

The active update loop is taking ~24% cpu time, performing the 2 JSON-RPC calls and updating the progress bar and elapsed time. Artwork redraw time seems acceptable.

1 Like

Great news! The Zero W with an HDMI or MIPI GPIO display would be a very neat solution!

I’ve got a Pimoroni Hyperpixel 800x480 non-touch display I may well pair up with a Zero W for testing. The Zero definitely draws less current than the Pi 3A+ or the Pi 3B+/Pi 4B.

MagPi power benchmarks were for idle and load :
Pi 4B 3.4W / 7.6W
Pi 3A+ 1.2W / 5.4W
Pi Zero W 0.8W / 1.6W

For “Mark II”, I ended up going with the 4-inch HDMI display driven using an RPi Zero W. I eliminated the overclock settings I mentioned earlier, but did find this thread useful (as I was experiencing some kernel panics):

https://www.raspberrypi.org/forums/viewtopic.php?t=212777

The larger display required re-working the case. With the need to piggy-back the RPi, I also moved the Odroid mounting posts back 12 mm to avoid any mechanical interference. This time around, I used heat-set inserts for all of the screws and mounting posts; that was much simpler than trying to thread directly into plastic! I also created an opening for easier access to the Odroid’s SD card.

The updated case is up on Thingiverse.

4 Likes

What software route are you using for HDMI output from the Pi Zero ? Framebuffer?

Yes, the framebuffer:

https://github.com/mattblovell/kodi_panel/blob/170a46455ca37d1321dcae012c967507c1af3b91/kodi_panel_fb.py#L46

# Use a Linux framebuffer via luma.core.device
device = device.linux_framebuffer("/dev/fb0",bgr=1)

Will have a go with my DPI Hyperpixel display - though I think that is 16-bit (565?) and 480x800 (i.e. it declares itself as portrait to frame buffer devices)

The bit-depth within the framebuffer may be different than the display itself. You should check the file /sys/class/graphics/fb0/bits_per_pixel

The WaveShare display is also natively portrait. I rotate it early in boot so that the console is readable, via the rotate flag in this excerpt from /boot/config.txt:

# Waveshare 4inch IPS HDMI (H) panel
hdmi_group=2
hdmi_mode=87
hdmi_cvt 480 800 60 6
display_hdmi_rotate=3 

The RPi’s boot console scrolls by briefly until the PWM module gets loaded.

Yep - the /sys/class/graphics/fb0/bits_per_pixel value is the one I checked, 16.

Pi DPI displays are seldom 24 bit (3 x 8 bit RGB) and are more often 16 bit (5 x R, 6 x G, 5 x B - aka 565) - though I think the 720x720 Square display I was using is differnet to the 800x480 portrait one I tried just now.

However I’ve dug out an old wave share 800x480 HDMI display (5") which is landscape by default and got the code working on that - until I go to TV Shows or Live/Recorded TV and I get an error. I’ve logged an issue on GitHub (skunge2000)

Looks like that shouldn’t be a problem for the updated luma.core. Several bit depths are supported:

https://github.com/rm-hull/luma.core/blob/13f475bc2c5125c3aebd252ef73c61b3ca7972c0/luma/core/device.py#L212-L221

# Lookup table of (target bit-depth, bgr) -> function, where the
# function takes an RGB image and converts it into a stream of
# bytes for the target bit-depth and RGB/BGR orientation.
image_converters = {
    (16, False): self.__toRGB565,
    (24, False): self.__toRGB,
    (24, True): self.__toBGR,
    (32, False): self.__toRGBA,
    (32, True): self.__toBGRA,
}

It does look like one combination – 16-bit pixels with bgr set to True – is missing, though. You can still give it a try and open an issue against luma.core if blue and red need swapping.

Cheers,
Matt

Yep - to do that I removed the bgr=1 from the frame_buffer set-up in kodi_panel_fb - but ended up with a blank screen.

Hi @noggin,

Is the coloring correct with bgr=1 present or is swapping blue/red needed?

I wouldn’t have expected a totally blank screen. I think luma.core should balk and stop execution if the options call for a pixel converter that it doesn’t have.

You can use any (well, nearly all) of the luma.examples demo programs with linux_framebuffer specified as the display on the command line. You can try with and without BGR as well. I always start with the really basic one:

python3 demo.py --display linux_framebuffer --framebuffer-device /dev/fb0

If you can reproduce the entirely-blank screen with one of those example scripts, you can get rm-hull’s attention.

However I’ve dug out an old wave share 800x480 HDMI display (5") which is landscape by default and got the code working on that - until I go to TV Shows or Live/Recorded TV and I get an error. I’ve logged an issue on GitHub (skunge2000)

Hey, my first issue! :slight_smile:

Is the coloring correct with bgr=1 present or is swapping blue/red needed?

Afraid I get a blank screen - so can’t tell! Black is the same in rgb as brg :wink:

Will try the demos.

Hmm - DPI displays don’t seem to respond to either the HDMI or LCD rotate config.txt options as far as I can tell…

Pimoroni’s display rotate function only works within X…

This seems to be something to do with the new video drivers in Raspberry Pi OS on the 4B.

** EDIT - yes - to get config.txt to rotate on a Pi 4B you have to re-enable the old legacy video drivers in raspi-config which comments out dtoverlay=vc4-fkms-v3d **

** EDIT 2 - and using the older driver the Pimorini display is reported as 32 bits per pixel not 16 bits per pixel - I guess the older driver spoofed 32 bits even though the display is 16 bit, and the new driver is more transparent? **

** EDIT 3 - this now works OOB - I’ve just disabled touch and hardware backlight PWM as neither of these are supported by my display - have spotted an issue which I’ve logged via GitHub with lack of artwork updating **

OK - have had a chance to play now. The Pimoroni 800x480 Hyperpixel display is lovely with this!

I’m a big Teletext / Acorn BBC Micro Model B fan, so have switched my fonts to ‘Bedstead’ which is the old SAA5050 (BBC Micro Mode 7) font. It’s a non-proportional font - but I love it and it’s nice and clear at small sizes, so I was able to reduce the font size a little bit for most fields.

Have added audio and video codec fields and TVShowTitle fields to my default video page and they work nicely too. (Shifted Title down below TVShowTitle)

Need to get to grips with TOML a bit to work out how to check what type of VideoPlayer we are in (TV Shows, Movies, Live TV/Recordings etc.) but this is brilliant!

Thanks so much for working on it - it’s something I’ve wanted for ages.

Need to get to grips with TOML a bit to work out how to check what type of VideoPlayer we are in (TV Shows, Movies, Live TV/Recordings etc.) but this is brilliant!

Thanks so much for working on it - it’s something I’ve wanted for ages.

Me too! Glad you like it.

I think I addressed the issue you opened (“static” portion of display not getting redrawn when switching players). Some investigation may be necessary to figure out what details of video playback are available. We can certainly add further functionality.

Cheers,
Matt

It’d be great to see a photo!

I think a could spend an inordinate amount of time trying to pick a different color scheme or alternate fonts. I sort of threw things together (that were appropriately licensed) to get the display up and working. I’ve gotten used to the 7-segment font for the time display, but I might like something else even better.

OK - three images of work in progress - have been playing around with genre, year, video codec and audio codec - and can’t get the VideoPlayer fields that are part of PVR like ChannelName to work - but fun nonetheless.

If you are a child of the 70s and grew up in Europe, or used a BBC Micro in 80s schools - that font is VERY nostalgic :slight_smile:

Also there is something odd about PVRs and durations in Kodi in general I think…

1 Like

OK - I now realise why I’m not getting PVR fields - I thought that the setup.toml defined the fields that were additionally requested in the InfoLabels call in kodi_panel_display.py - but I see that the setup.toml just defines what is done to render InfoLabels fields requested in kodi_panel_display.py so I have to add the new fields I want to this code.

I may also do a similar video codec mapping to that done to neaten up audio codecs.

**EDIT - Yep - have now got VideoPlayer.ChannelName and VideoPlayer.ChannelNumberLabel displaying - which means watching Live TV gives me the channel logo (which is the default returned artwork for Live TV), programme title (VideoPlayer.Title), channel number (VideoPlayer.ChannelNumberLabel) and channel name (VideoPlayer.ChannelName) on the display.

I guess some way of working out what kind of video player mode you are in - PVR/Live TV or Videos/TVShows/Movies might be useful to have two different display layouts?

When playing TV Shows in the library - VideoPlayer.Title is the name of the episode playing, and VideoPlayer.TVShowTitle is the name of the overall TV Show that episode is part of - so you’d want TVShowTitle displayed above Title.

So in my screen shot from TV Shows - “Dracula (2020)” is the TVShowTitle field and “The Rules of the Beast” is the Title field.

However when playing Video files not in the library or watching Live TV I think VideoPlayer.TVShow is empty, and VideoPlayer.Title contains either the filename, or the name of the currently watched TV show.

So in my screen shot from (Live) TV - TVShowTitle is blank, and Title is “Celebrity Mastermind” (and were they to be rendered ChannelNumberLabel would be “101” and ChannelName would be “BBC One Lon”)

Being able to concatenate the contents of TVShowTitle and Title with a line break between them (if TVShowTitle contains content) and then display them as a single field would solve that without having to have two separate layouts (but it would mean you couldn’t render the Title field differently which you might want to as in TV Shows it’s a secondary field and in Videos/TV it’s a primary field?

I guess a hacky solution would be to display Channel Name and Number in the same position as TVShowTitle on the assumption that Live TV and TV Shows are mutually exclusive in that regard?

Yes, at the moment setup.toml just guides all the location, font, and color choices for rendering the InfoLabels hard-coded into the update_display() function. It would be straightforward to place the list of InfoLabels to retrieve (one list for audio, a separate list for video) into setup.toml itself.

If you can arrive at a heuristic that always works to distinguish the various modes of video playback (are there just 3 modes – Movies, Recorded TV, Live TV?) we could certainly replicate the structure that currently exists to provide for separate layouts. Alternatively, special treatment (e.g., the text field “combo_Title” means to combine TVShowTitle and Title per your description above) for any number of fields is quite straightforward – one just needs to add the relevant tests and actions in the video_text_fields() function.

Right now, the names of all text fields to display (for either audio or video modes) must either correspond directly to a retrieved InfoLabel or to a “special treatment” field. Another possibility would be to make use of string interpolation – have the InfoLabel(s) embedded within the string to be displayed, replaced at the last moment with the InfoLabel contents.

At present, I’ve avoided that via

  • the label functionality (e.g., what’s done for the TrackNumber), although that requires completely independent placement of the string to display when the associated InfoLabel is non-empty, and
  • “special treatment” for items such as the audio codec.

One obstacle with the string interpolation approach is that the text display likely always appears to be non-empty – what should one do if one (or more) of the InfoLabels doesn’t exist, but the string has other text to display?

I don’t currently have any means of playing with LiveTV with Kodi. So, experiment and hack away until you have something you’re happy with.

The only caveat I would add is to keep the touch interrupt (T_IRQ) in mind. Currently, both audio and video screens (if the touch interrupt is enabled) cycle through modes based upon screen presses. Perhaps video just merits being treated differently, with the screens corresponding to different material being played.

Regards,
Matt

OK Matt - quite a lot to think about. I don’t currently have a touch display in use - my displays just sit on the default.

To test whether something is in PVR mode - I guess a non-empty ChannelNumberLabel might be a good check?
To test whether something is a TV Show instead of a file or Movie - check whether TVShowTitle is empty?

I suspect there are four or five video use cases I can think of :

  1. Movies
  2. TV Shows
  3. TV (which is both PVR Live and PVR Recorded TV played via a PVR add-aon)
  4. Videos Files (i.e. stuff not in a library)
  5. Music Videos

I don’t know about Music Videos - and not sure Videos Files needs much work - but the Movies vs TV Shows vs TV (aka PVR) are all potentially different displays

  1. Movies - shows you Movie Title, Year, Genre, Currrent Time, Duration and possibly Audio Codec, Video Codec, Video Resolution ?

  2. TV Shows - shows you TVShow Title, Title (which is episode title), poss Ep Num, Year, Genre, Current Time, Duration, and possibly Audio Codec, Video codec, Video Resolution?

  3. PVR/TV/Recorded TV - Shows you Title (which is the TV show name), poss Ep Num, Year, Genre, Current Time, Duration, ChannelNumberLabel, ChannelName, and possibly audio codec, video codec, video resolution etc. (Artwork returned will be station logo if present)

  4. Files - Probably same as Movies (the Title returned from Kodi will be the filename)

VideoCodec could have a lookup in the same way as audio codec I guess?

(Also current time in PVR is always a bit odd - it just counts up from when you started watching - even if it knows the duration and position within a show on-air)