Graphical front panel display

Just installed your GitHub repo on a WiFi Pi3A+ and a 320x240 TFT (identical to the one in your picture I think). Works really nicely! I decided to go with your TFT solution rather than an OLED as the OLED 128x128 res is probably just a bit too restrictive.

Time to try and learn some Python and JSON-RPC to implement other displays…

Thanks for the hard work you have clearly put into this.

1 Like

@noggin, thanks. Glad it’s working for you!

Don’t forget to checkout out the AUDIO_LAYOUT dictionary:

https://github.com/mattblovell/kodi_panel/blob/8d7d80fa626331c637ac7701a706bd9d3ffd9999/kodi_panel.py#L131-L169

Per one of your earlier suggestions, it should permit for layout, font, and color changes (as well as omitting text fields) with not much programming. (Modifying data structures with some understanding does, in my book, count as programming. :slight_smile: )

Augmenting the existing ADisplay enumerated type (well, class since it’s Python), one can also create entirely new layouts (e.g., a screen showing elapsed time only in some large font). This basic structure – AUDIO_LAYOUT defining what to display and where for audio_screens() – is what I plan on replicating for making movie/video now-playing screens.

1 Like

Now that I have something working, naturally I want to see if I can get it working via some other means! Rather than using luma.lcd to drive the SPI display, I thought I would see if I could use it as a framebuffer device on the RPi. That would then open the door to using DPI-based displays.

Unfortunately, all of the earlier info I found regarding fbtft is somewhat stale, since fbtft_device (a supporting element) was removed from the Linux kernel starting with 5.4. A lot of the information one can find googling around is now outdated. The Linux maintainers file shows fbtft as currently orphaned.

The wiki for fbtft now notes the following:

fbtft will now only work with Device Tree due to the above mentioned disruptive gpio rework.

Not a lot of further information is provided (at least not there).

One part of how things seem like they might work now is tinyDRM:

tinydrm was created because fbtft couldn’t move out of staging due to fbdev being closed to new drivers. This means that the fbtft drivers have to be converted to DRM.

Does anyone know what DRM stands for in this context? I keep thinking Digital Rights Management, but that doesn’t seem right!

One can find a few Device Tree Overlay files nominally for the RPi in tinyDRM’s github:

https://github.com/notro/tinydrm/tree/master/rpi-overlays

Prior to today, I didn’t know how overlays got associated with specific device drivers. That association turns out to be entirely guided by the compatible (string) property that gets specified in the tree. (A nice presentation from Thomas Petazzoni explains matters fairly well.)

The "mi,mi0283qt" that gets referenced in tinyDRM’s rpi-display-overlay.dts looks like it ultimately references this device driver:

drivers/gpu/drm/tiny/mi0283qt.c

The latest Raspberry Pi OS has its own dtoverlay files as well, and its rpi-displays.dt[os] file refers to a different driver:

drivers/gpu/drm/tiny/ili9341.c

In spite of the different names, both drivers are meant to communicate with an ILI9341 controller.
The two files seem pretty similar, with just some very minor differences in the initialization code and some reset differences.

Unfortunately, I was not able to get the native RPi rpi-displays.dto to do much of anything last night. The overlay would load, and a /dev/fb1 file would be created. The display itself was not actually responsive though. (The backlight stayed off, and reconnecting the LED signal to 3.3V just showed an all-white screen, so it had never been properly initialized.)

So, I’ll play some more this weekend and see if I can make any headway. The framebuffer approach definitely seems a bit more complicated.

Cheers,
Matt

In this context, DRM means “Direct Rendering Manager”

1 Like

Thanks, @rho-bot. That makes a lot more sense. :slight_smile:

I managed to get things working! I started with the rpi-display-overlay.dts file from tinyDRM and modified the GPIO connectivity to match what I was using with luma.lcd previously, saving it as tinydrm-rpi-display.dts. The modified file is below.

I then “compiled” the .dts file and copied it over to the /boot/overlays directory:

dtc -@ -Hepapr -I dts -O dtb -o tinydrm-rpi-display.dtbo tinydrm-rpi-display.dts
sudo cp tinydrm-rpi-display.dtbo /boot/overlays

Loading the overlay:

sudo dtoverlay tinydrm-rpi-display

No error messages resulted, dmesg showed some new lines from mi0283qt spi0.0, and there was now a /dev/fb1 file. I got such a new framebuffer file last night, trying the native rpi-display.dtbo file, so I wasn’t too excited yet. The display did light up, though, and there a moment in which the backlight was on but the display had been cleared. That seemed promising.

Per a suggestion from the interwebs, I tried cat /dev/urandom > /dev/fb1. Nothing visually changed.
Upon trying con2fbmap 1 1, though, the backlight turned on and I was greeted with a screenful of noise.

After getting fbi from fbida compiled, I was able to display some meaningful images!

tinyDRM_fb1

So, the ili9341 display is alive – on an RPi – as a framebuffer device. I’ll next play with what changes to kodi_panel are needed to use the framebuffer, rather than luma.lcd.


Modified dts file

*
 * Device Tree overlay for ili9341 display, using luma.lcd wiring
 *
 */

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2708";

	fragment@0 {
		target = <&spi0>;
		__overlay__ {
			status = "okay";

			spidev@0{
				status = "disabled";
			};

			spidev@1{
				status = "disabled";
			};
		};
	};

	fragment@1 {
		target = <&gpio>;
		__overlay__ {
			rpi_display_pins: rpi_display_pins {
				brcm,pins = <18 23 24 25>;
				brcm,function = <1 1 1 0>; /* out out out in */
			};
		};
	};

	fragment@2 {
		target = <&spi0>;
		__overlay__ {
			/* needed to avoid dtc warning */
			#address-cells = <1>;
			#size-cells = <0>;

			rpidisplay: rpi-display@0{
				compatible = "mi,mi0283qt";
				reg = <0>;
				//pinctrl-names = "default";
				//pinctrl-0 = <&rpi_display_pins>;

				spi-max-frequency = <32000000>;
				rotation = <180>;
				reset-gpios = <&gpio 25 0>;
				dc-gpios = <&gpio 24 0>;
				backlight = <&backlight>;
			};

			rpi-display-ts@1 {
				compatible = "ti,ads7846";
				reg = <1>;

				spi-max-frequency = <2000000>;
				interrupts = <16 2>; /* high-to-low edge triggered */
				interrupt-parent = <&gpio>;
				pendown-gpio = <&gpio 16 0>;
				ti,x-plate-ohms = /bits/ 16 <60>;
				ti,pressure-max = /bits/ 16 <255>;
			};
		};
	};

	fragment@3 {
		target-path = "/soc";
		__overlay__ {
			backlight: backlight {
				compatible = "gpio-backlight";
				gpios = <&gpio 18 0>;
			};
		};
	};

/*

Alternative pwm backlight section

	fragment@3 {
		target = <&gpio>;
		__overlay__ {
			// This is necessary on Pi1,2,Z not Pi3
			pinctrl-0 = <&gpioout &alt0>; // Remove i2s_alt0 which claims gpio18
		};
	};

	fragment@4 {
		target = <&pwm>;
		__overlay__ {
			pinctrl-names = "default";
			pinctrl-0 = <&pwm0_gpio18>;
			status = "okay";
		};
	};

	fragment@5 {
		target-path = "/soc";
		__overlay__ {
			backlight: backlight {
				compatible = "pwm-backlight";
				pwms = <&pwm 0 5000000>;
				// These levels need calibration
				brightness-levels = <0 5 10 20 40 60 80 100>;
				default-brightness-level = <7>;
			};
		};
	};
*/

	__overrides__ {
		speed = <&rpidisplay>,"spi-max-frequency:0";
		rotation = <&rpidisplay>,"rotation:0";
		format = <&rpidisplay>,"format";
	};
};
2 Likes

One approach discussed previously, using pygame and libSDL to render on a framebuffer-based display, seems to be in a bit of disarray. The following is a 2019 post regarding woes getting pygame/SDL1.2.x working as one would find on any number of web pages:

Issue using Python3/pygame to output to /dev/fb1 targeting a 2.8" TFT screen

Why not using pygame/SDL1.2.x as instructed in many forums and the adafruit TFT manual?

First, it doesn’t work, at all. I have tried a gazillion versions of libsdl and its dependencies and they all failed consistently. I’ve tried forcing some libsdl versions downgrades, same with pygame version, just to try to get back to what the software was when my TFT screen was released (~2014). Then I aslo tried switching to C and handle SDL2 primitives directly.

Furthermore, SDL1.2 is getting old and I believe it is bad practice to build new code on top of old one. That said, I am still using pygame-1.9.4…

So why not SDL2? Well, they have stopped (or are about to stop) supporting framebuffers. I have not tried their alternative to framebuffers, EGL, as it got more complex the further I digged and it did not look too engaging (so old it felt like necro-browsing). Any fresh help or advice on that would be greatly appreciated BTW.

I thought I would be able to very quickly get WeatherPi_TFT going, but it too depends on just being able to “point” SDL to the framebuffer:

Line 100 in WeatherPiTFT.py:

if config['DISPLAY']['FRAMEBUFFER'] is not False:
    # using the dashboard on a raspberry with TFT displays might make this necessary
    os.putenv('SDL_FBDEV', config['DISPLAY']['FRAMEBUFFER'])
    os.environ["SDL_VIDEODRIVER"] = "fbcon"

A bit of an obstacle there…

I did find lots of interesting things to try on the framebuffer display, based on this Feb 2020 presentation by Nicolas Caramelli (PDF of the slides is available on the page):

Back to the Linux Framebuffer! Linux Framebuffer support in free software
https://archive.fosdem.org/2020/schedule/event/fbdev/

It took me a while to figure out the right incantation for mplayer to get the video sent to /dev/fb1. If anyone wants to try, I had luck with

sudo mplayer -vf scale=320:180 -vo fbdev2:/dev/fb1 <video.mp4>

The right scale to use is a function of the display’s size and the video’s aspect ratio. Video playback was pretty smooth with the SPI interface running at 32 MHz. (I think the C4 might need whatever performance increase awesometic figured out recently.)

I’d still like to figure out how to get WeatherPi_TFT going. Given the much slower speed that it or kodi_panel need for screen updates, I think either would be fine just using python-based copying into the framebuffer.

Cheers,
Matt

I thought I would be able to very quickly get WeatherPi_TFT going, but it too depends on just being able to “point” SDL to the framebuffer

I did have some luck following the advice from the 2018 answer provided in this 2015 stackoverflow thread:

No video mode large enough error in pygame when using 1,8" TFT via a RPi

In particular, I was getting a “No video mode large enough” error from pygame. The advice to take the initial output from

fbset -i -fb /dev/fb1

and add it to the contents in /etc/fb.modes appears to have worked. I can get WeatherPi_TFT displaying there with the “standard” values for the two SDL_* environment variables. (Although starting WeatherPi_TFT also seems to cause X, on the RPi’s HDMI display, to go completely blank.)

I’ve had some success at converting kodi_panel.py to use a framebuffer display. The changes amount to the following, all performed on an RPi3:

  1. Comment out the luma.* imports.

  2. After copying Pytorinox’s framebuffer.py file locally, add
    from framebuffer import Framebuffer

  3. Change USE_BACKLIGHT to False.

  4. Change the Image.new() call to use "RGBA" rather than "RGB".

  5. Instead of invoking the constructors for spi() and ili9341(), instantiate a Framebuffer object:
    fb = Framebuffer(1)
    This example is using /dev/fb1.

  6. Replace all device.display(image) calls with fb.show(image)

That was it!

In order to make use of the existing GPIO approach for the touchscreen interrupt, I did recompile the dtoverlay (added to github in the other/ directory) to comment out the whole ti,ads7846 section. That left GPIO 16 (RPi.GPIO or BCM numbering) free for use by kodi_panel.py.

Without that change, I couldn’t get RPi.GPIO to “attach” an interrupt. With the overlay as originally written, the ads7846 driver does got loaded, but I haven’t figured out how one can get equivalent asynchronous interrupt functionality in Python via that driver. The Python evdev package does see the touchscreen as /dev/input/event3, but I didn’t investigate further (as it looked to require use of Python’s asyncio).

So, sticking with GPIO for the touchscreen interrupt, the only thing I haven’t figured out is how to control the backlight from Python for the tinyDRM mi0283qt driver. The usual advice I’ve found on the web about writing a 1 or 0 to a file down in /sys/class/backlight didn’t seem to accomplish anything.

Cheers,
Matt


Representative diff for framebuffer operation

diff --git a/kodi_panel.py b/kodi_panel.py
index af0cf8e..576e4bb 100644
--- a/kodi_panel.py
+++ b/kodi_panel.py
@@ -21,9 +21,9 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 
-from luma.core.interface.serial import spi
-from luma.core.render import canvas
-from luma.lcd.device import ili9341
+#from luma.core.interface.serial import spi
+#from luma.core.render import canvas
+#from luma.lcd.device import ili9341
@@ -32,6 +32,8 @@ from PIL import Image
 from PIL import ImageDraw
 from PIL import ImageFont
 
+from framebuffer import Framebuffer # pytorinox
+
 from datetime import datetime, timedelta
 from enum import Enum
 import time
@@ -80,7 +83,7 @@ color_progfg  = color7S      # progress bar foreground
 color_artist  = 'yellow'     # artist name
 
 # Pillow objects
-image  = Image.new('RGB', (frame_size), 'black')
+image  = Image.new('RGBA', (frame_size), 'black')
 draw   = ImageDraw.Draw(image)
 
 # Audio/Video codec lookup
@@ -250,7 +253,7 @@ lock = threading.Lock()
 # luma.lcd at all to change backlight state.  Uses with OLED displays
 # should set it to False.
 #
-USE_BACKLIGHT = True
+USE_BACKLIGHT = False
 USE_PWM       = False
 PWM_FREQ      = 362      # frequency, presumably in Hz
 PWM_LEVEL     = 75.0     # float value between 0 and 100
@@ -288,20 +291,24 @@ PWM_LEVEL     = 75.0     # float value between 0 and 100
 # once non-zero reset hold and release times were specified
 # for the device.
 #
-serial = spi(port=0, device=0, gpio_DC=24, gpio_RST=25,
-             reset_hold_time=0.2, reset_release_time=0.2)
+#serial = spi(port=0, device=0, gpio_DC=24, gpio_RST=25,
+#             reset_hold_time=0.2, reset_release_time=0.2)
+#
+# if USE_PWM:
+#     device = ili9341(serial, active_low=False, width=320, height=240,
+#                      bus_speed_hz=32000000,
+#                      gpio_LIGHT=18,
+#                      pwm_frequency=PWM_FREQ
+#     )
+# else:
+#     device = ili9341(serial, active_low=False, width=320, height=240,
+#                      bus_speed_hz=32000000,
+#                      gpio_LIGHT=18
+#     )
+
+
+fb = Framebuffer(1)
 
-if USE_PWM:
-    device = ili9341(serial, active_low=False, width=320, height=240,
-                     bus_speed_hz=32000000,
-                     gpio_LIGHT=18,
-                     pwm_frequency=PWM_FREQ
-    )
-else:
-    device = ili9341(serial, active_low=False, width=320, height=240,
-                     bus_speed_hz=32000000,
-                     gpio_LIGHT=18
-    )
@@ -784,7 +791,7 @@ def update_display():
         audio_screens(image, draw, track_info, prog)
 
     # Output to OLED/LCD display
-    device.display(image)
+    fb.show(image)
     lock.release()
@@ -825,7 +834,9 @@ def main():
         screen_on()
         draw.rectangle([(0,0), (frame_size[0],frame_size[1])], 'black', 'black')
         draw.text(( 5, 5), "Waiting to connect with Kodi...",  fill='white', font=font_main)
-        device.display(image)
+        fb.show(image)
1 Like

So, sticking with GPIO for the touchscreen interrupt, the only thing I haven’t figured out is how to control the backlight from Python for the tinyDRM mi0283qt driver.

Perhaps sticking with direct GPIO control is the best approach. The changes below are working (effectively mimicking with luma.lcd was doing previously).

USE_BACKLIGHT = True
LED_PIN       = 18       # GPIO bin for LED backlight

def screen_on():
    if not USE_BACKLIGHT:
        return
    GPIO.output(LED_PIN, GPIO.HIGH)

def screen_off():
    if not USE_BACKLIGHT:
        return;
    GPIO.output(LED_PIN, GPIO.LOW)

with main() setting things up:

if USE_BACKLIGHT:
    GPIO.setup(LED_PIN, GPIO.OUT)

If you piece together this backlight change with those described in my previous update, the modified kodi_panel.py is now using the ili9341-based display via the Linux framebuffer. That means that it can work with any other display for which a framebuffer / DRM driver is available. The biggest obstacle is just getting the display up and running, with the right kernel modules available and with (on ARM platforms) any dtoverlay necessary to describe the hardware to the kernel.

Once you have a display up and running, modify the resolution, and change layouts within kodi_panel as necessary for the (hopefully increased) space, you’re set.

Now I just need to decide if would be worthwhile to chase down an IPS display! :grin:

(I have not yet investigated permissions settings for the framebuffer /dev/fb file. For these experiments, I’ve been starting up kodi_panel via sudo python3 kodi_panel.py. That likely merits a bit more research if I go fully down this path.)

Oh, and I also think that PWM control over the backlight brightness should be possible. From the little that I’ve experimented, I think RPi.GPIO 18 has hardware-based PWM available (on the RPi.)

One other nagging detail…

I find, after loading the dtoverlay, that I must invoke

con2fbmap 1 1

in order to have the display be “alive”. If I just start up kodi_panel, only backlight activity occurs (that is, the backlight turns on and off per expectations, but the display itself remains all-black). If I run con2fbmap first, then everything behaves correctly. So, it must be doing something to turn on the tinyDRM driver.

Above I describe changes to kodi_panel.py to make use of Pytorinox’s framebuffer.py. In discussing support for other TFT controllers with luma’s rm-hull, I learned that luma.core already has framebuffer support!

rm-hull writes:

An alternative is that if there is already a kernel framebuffer implementation for [the] device (i.e. it exports a /dev/fb0 device), then we can simply use the luma.core.device.linux_framebuffer() pseudo-display right now.

In pondering what other display options might be worth pursuing, I posted the following on LibreELEC’s forum, as I was thinking the options mostly revolved around RPi’s available ports. I haven’t seen much of a response there so far. Realizing that the DSI interface is available on more SBCs than I first thought, perhaps this group has some insights.

The question is what’s worth trying out next – DPI, DSI, or HDMI?

SPI-connected displays, unless one is using a display controller that provides for on-board drawing widgets, seem limited to around 320x240 pixels in resolution.

  • According to this raspberrypi.org page, using the DPI interface does not require any additional drivers, just the passing of options (format, timing, display resolution) via config.txt. Does that mean that a standard LE/CE installation can support a DPI display out-of-the-box? If a DPI display is attached, does that leave the main HDMI display (/dev/fb0 presumably) functional and HW-accelerated for Kodi’s use?

  • MIPI-DSI is available on both RPi and Khadas boards. It would seem to require kernel module support, though, with (from the little I’ve read) a display controller-specific driver. Are any of those even present within the various JeOS’ kernels?

  • How about the RPi4’s second HDMI interface (/dev/fb1)? Can it be active and independent from fb0? I would not be trying to “steer” Kodi to use fb1 or extend Kodi across both displays. (Kodi shouldn’t need to know that fb1 even exists, ideally.) Some of these short discussion threads seem more promising than others:

Regarding DSI, I did find that the linux.arm.conf file for both libreelec-9.2 and current nightly builds has CONFIG_DRM_MIPI_DSI=y. Presumably, CoreELEC follows suit. I don’t know what other drivers might be needed, though.

I’m generally pretty happy with the 3.2-inch SPI display I’m currently using except for its viewing angle. From many perspectives it just becomes a white, washed out glob of light! There seems to be a lot of energy being put into both the Linux kernel and Kodi to “standardize” RPi4 support more than in the past, so I picked one up and ordered a 4-inch IPS HDMI panel to experiment with.

Nevertheless, I am curious what people think regarding display connections for the various SBCs.
Think everything will converge on HDMI or are there still advantages that will keep the others popular? Is having more than a single display (of any size or type) too fringe of a use case to garner much attention?

Regards,
Matt

I think separating the screen from the Kodi platform is still a sensible approach. A Pi Zero W or Pi 3A+ with either an SPI, HDMI or DPI screen (*) connected over the network to your Kodi platform is a really smart solution. It doesn’t have to be physically connected to the Kodi device, and would work whether Kodi was running on Windows, MacOS, Linux or Android/Android TV (or MrMC on tvOS?). That way you can position it where it’s best placed for visibility - with it only requiring a power feed. However this would probably not work if you wanted visualisations on your second display - like waveforms, equalisers etc.

Personally I really love the 720x720 and 800(?)x480 Hyperpixel DPI displays that Pimoroni do (the 720x720 models with or without touch are both gorgeous - and they are popular enough that you can find 3D printed case models to download for some of them), but Waveshare do some neat piggy back HDMI displays that come with the HDMI-HDMI bracket. DPI and HDMI are full-frame rate displays (usually 60Hz refresh) so don’t have the refresh rate issues that some SPI displays have (particularly the larger ones - though there is a replacement for the notro frame buffer driver for the il-based devices that is a bit quicker)

(*) The Pi only supports one model of DSI display - the Pi Foundation 7" touch screen - and that’s a bit big for this use case IMO. There are lots of very nice case solutions for it though.

AIUI DPI displays are really only widely supported on Raspberry Pi - other SBCs haven’t exposed and/or enabled DPI to their GPIOs (It’s a high bandwidth video connection, a bit like a parallel version of HDMI, so isn’t the thing you can bit bang in software at decent resolutions) AIUI all models of Pi allow for both HDMI and DPI to be enabled at the same time, and to carry different video content. For a long time the kernel had some limitations (so only one display could be targeted for X- or similar output - but a newer kernel has removed that limitation AIUI). Not sure how LibreElec handles that though. You could run with X on one output and OMX Video replay on the other from the start - but now I think you can do more with the two outputs.

HDMI is the most standard display standard across SBCs - and you can get lots of different HDMI displays as either bare panels with interface boards, or low cost displays, however they are often quite high resolution and a bit more expensive than the lower res SPI and lower-end DPI displays. There are now experimental builds for the Pi 4B that allow video over HDMI0 and audio over HDMI1 (for 4K video output for those with HD-only AVRs)

1 Like

Reading about RPi’s GPU further, it seems like basically all the display interfaces – HDMI, DSI, and DPI – are handled by the GPU. At the moment, a choice of three drivers is available on the RPi4:

  • legacy. Loaded if no relevant dtoverlay= statement is present in config.txt. Provides distinct fbdev files (/dev/fb*) for each attached display.

  • vc4-fkms-v3d. Sort of a stop-gap approach, presenting DRM/KMS interfaces to the rest of software while still using legacy DispmanX code to drive the GPU. Presents a single, consolidated /dev/fb0 file.

  • vc4-kms-v3d (note the removal of the “f”). Full-blown, mainstream DRM/KMS driver for the Broadcom GPU. Available today if one upgrades to Linux 5.10-based Raspberry Pi OS.

See posts here and here on the Rpi forums.

That certainly simplifies one aspect, but the vc4-kms-v3d “direction” for Raspberry Pi OS seems somewhat like an obstacle of its own (particularly if other SBCs also converge there). Having an application that aims to draw directly on a legacy framebuffer isn’t too useful if the DRM/KMS driver is only presenting a single, unified file for all attached displays.

I think I need to figure out if there’s any (straightforward) way of convincing the [f]kms driver to present per-device framebuffers. Lacking that, it seems like one has to either write a native-DRM/KMS application or just make it X-based. (Just to add to confusion, DRM/KMS has its own version of framebuffers. I think those are somewhat distinct from legacy fbdev files.)

I keep reading statements that DRM/KMS only allows one “master” application as well, which definitely seems like a complication if one is trying to run Kodi on the same SBC.

All of this is a bit off-topic from the usual amlogic focus for CE discussion, but I’m hoping it’s useful for someone. :slight_smile:

This may take a bit to figure out!

Cheers,
Matt

2 Likes

I believe what most people might be interested in if they aren’t exactly watching something or listening to something, would be the weather (current and forecast) and date and time.

1 Like

Yes - current date and time and weather, as would next PVR recording scheduled if people have Live TV configured (if that’s something that is easily available).

Oops! I guess my question (a few posts up) should have been phrased as “pondering what other display connection options might be worth pursuing.” The rest of that post discussed DPI, DSI, and HDMI connections. :slight_smile:

Kodi’s InfoLabels do provide the current weather conditions. I don’t immediately see forecast info available, however. (One could always make use of OpenWeather’s One Call API; it’s just more JSON to process, well that and another server to contact.)

The PVR InfoLabels have several NextRecording* fields.

Currently, I just have the display turn off when no music is playing. (The significant other didn’t want another clock.) A status screen gets shown momentarily upon a touch being detected. One approach would be to replace the call that gets made for that status screen, asking for different InfoLabels.

Additional changes would then follow in status_screen() itself and the STATUS_LAYOUT dictionary.

I’m currently deciding how much effort I should put into playing with an RPi4 and a 4-inch IPS HDMI panel. The small display is working nicely with the Pi’s fkms driver and X. I haven’t figured out how to get the DRM/KMS driver to give me a distinct framebuffer for that display, though, and Kodi (at least the version compiled for Raspberry Pi OS) no longer runs under the Pi’s legacy display driver. (I think Kodi on Linux is an OpenGL ES application these days??)

It feels like I have all the hardware necessary to get a (pretty nice!) 480x800 display going, except there’s an immense software stack (that I don’t understand) in the way!

1 Like

No oops. I read the entire post.

That particular sentence simply had me going like… “hey if nothing is on the display…”, hence I made a quick post about it. I figured it might be something different from blanking the screen when there’s no activity. And it might be a way to turn an old box into a weatherstation.

I’ve had a play with framebuffer.py and my 720x720 non-touch HyperPixel. Have got kodi_panel_fb.py working but had to add a line to framebuffer.py to get it to accept RGBA 32 bits per pixel (which is the format my HyperPixel reports supporting) without a KEY ERROR. Also had to edit it to use fb0 not fb1 (as my HyperPixel is my primary display)

First I tried RGB rather than RGBA in kodi_panel_fb but I got blue instead of black background and distorted colours.

** EDIT - my RGBA edit has got the background as black - but I think my R and B channels are reversed… **

Revised code fragment for framebuffer.py here :

# anything that does not use numpy is hopelessly slow
_CONVERTER = {
    ("RGBA", 16): _converter_rgba_rgb565_numpy,
    ("RGB", 16): _converter_rgb565,
    ("RGB", 24): _converter_no_change,
    ("RGB", 32): _converter_argb,
    ("RGBA", 32): _converter_no_change,
    # note numpy does not work well with mode="1" images as
    # image.tobytes() loses pixel color info
    ("1", 16): _converter_1_rgb565,
    ("1", 24): _converter_1_rgb,
    ("1", 32): _converter_1_argb,
}

My new line is the RGBA 32 converter no change bit before the # note numpy comments.

The IPS screen looks gorgeous :slight_smile:

(This is with a Pi 3A+ connected to the HyperPixel square running WiFi connected to a different device running Kodi)

Also need to work out how to disable a pesky cursor (which I think is caused by the frame buffer also sitting waiting for a login, as the console is also displayed on it - and hitting a keyboard connected to it confirms this)

OK - I doubled every H and V size and font size in the settings to get a larger display - and it looks really nice!
First photo is the original sized version (320x240 on a 720x720 display)

!

Second photo is a quick and dirty 2x scale (so 640x480 on a 720x720 display)

!

Third photo shows the original cover art - and mis-matched colours.

!