4k with a Raspberry Pi 2 Model B? Yes please!

If you're a Raspberry Pi nerd like me, you'll know that one of the biggest selling features of the newest Raspberry Pi 4 is its ability to natively output to two 4k displays.  This is a huge upgrade over the Pi 3, which only officially outputs 1080p to a single display.

As with many things Pi, it can be hacked into doing things it's not officially spec'd to do.  It is possible to get a Pi 3 to output 4k with some additions to config.txt. Since both the Pi 2 and Pi 3 both share the same GPU chipset, I was wondering if a Pi 2 could also be made to output 4k.

A little bit of Google research took me to this thread which confirmed that is is indeed possible, but with some caveats:

  • You won't get 30 FPS.  Period.  15 fps can be achieved without overclocking, and there are mixed reports that say you need to overclock in order to get above 20.  According to what I've been able to find, the Pi 2 taps out at about 28 FPS as the absolute maximum frame rate you can expect, even when overclocked. 
  • Even though you can set the desktop resolution to 3840x2160, it doesn't appear possible to decode a 4k video file at native resolution.  Given the frame rates you can expect, not sure you'd want to do this anyway.
The low frame rate would be a deal-breaker if I were using my Pi for day-to-day productivity tasks.  But my Kitchen Information Centre project doesn't need blistering framerates... it just displays information passively.

Worth a try?  You bet!

If you read through the thread above you'll find exactly the lines you need to add to config.txt to get this to work.  I first tried 3480x2160@15Hz with the following:

disable_overscan=1
hdmi_ignore_edid=0xa5000080
hdmi_cvt 3840 2160 15
framebuffer_width=3840
framebuffer_height=2160
hdmi_group=2
hdmi_mode=87
hdmi_pixel_freq_limit=400000000
max_framebuffer_width=3840
max_framebuffer_height=2160

This worked.  First try.  No fuss. I'm not going to pretend I understand everything that the above does, but I'm going to guess that this line is the key to exceeding 1080p resolution:

    hdmi_ignore_edid=0xa5000080

I'm actually surprised at how easy this was to do, and even more surprised that this resolution isn't enabled by default.  So I decided to try to get a bit more... could I increase this to 24 FPS without an overclock?  

Further down the thread you'll find this:

disable_overscan=1
framebuffer_width=3840
framebuffer_height=2160
max_framebuffer_width=3840
max_framebuffer_height=2160
hdmi_ignore_edid=0xa5000080
hdmi_pixel_freq_limit=400000000
hdmi_group=2
hdmi_mode=87
hdmi_timings=3840 1 48 32 80 2160 1 3 5 54 0 0 0 24 0 211190000 3
gpu_mem=256

This looks even more cryptic than the 15Hz version, especially the hdmi_timings line. I'm not really sure what these numbers mean, but as above... I just... copied and tried it!

Wouldn't you know it!  This also worked. First try.

Performance

The display looks super sharp.  But i'm not seeing frame rates that appear even close to 15 Hz, let alone 24 Hz.  I'm seeing more like like 5-10 FPS.  Maybe this is where the overclock helps.

I'm also noticing that the increase in resolution is causing other things to slow down.  For example, I'm using LIRC to take input from an InfraRed receiver in order to flip between info pages using a remote control.  There is a significant lag between when I press the button and when I see the display update.  About 1-2 seconds.

In a desktop environment, these limitations would make the Pi unusable. If you're reading this and want to give it a try, I'd say it's likely not worth your time.  But for my needs, the above performance degradations are not show stoppers... My info centre just passively displays info, and I seldom pick up the remote to directly interact.  

Formatting for 4k

Accepting the tradeoffs above, I'm now pushing ahead to format MagicMirror's display to fit 4k resolution.  You'll recall that I made a custom CSS file for the old TV it was connected to, which was native 1366x768 resolution.  If I continue to use that CSS file, it looks like this:


Quite the waste of space, and everything is tiny.  You'll also recall that I tried to use a simple zoom factor to scale down native 1080p to 768p.  And it kinda worked, but it wasn't quite right.  Similarly, I could set a zoom factor of 3 on the above layout and I should get something close.  Here's what that looked like: 



Not bad, but this could be much better... Notice how the left side now looks proportionally too large, and by going from a small 30" TV to a 55" screen size with all that extra screen density, I can afford to make large things much smaller in order to better balance the layout without sacrificing legibility.  So once again, it's time to go fully custom.

Now by rights, I should write the CSS to be resolution independent for 1080p and above... there's no real reason to have one CSS style sheet for 1920x1080, and another for 3480x2160.  CSS offers numerous scalable units and mechanisms so that you never actually need to work in pixels. I plan to do this in the future, but that involves rewriting all of MagicMirror's default CSS to also be resolution independent, before moving on to all of the modules I'll be using.  I REALLY want to see this working in glorious 4k, like, yesterday, so for now I'm just going to tweak all of the pixel values to get this working as fast as possible.

Doing the work on my laptop vs previewing on a TV

It's time consuming and tedious to make changes directly on the Raspberry Pi, so a better way to work is to do all of the CSS work on my laptop first, then upload to the Pi later.  This introduces a new problem: On the Raspberry Pi, each pixel is addressed directly -- 1 logical pixel in the CSS represents 1 physical pixel on the display.  My MacBook, however, uses a Retina display, and while the physical pixel resolution is nearly the same as the TV, MacOS abstracts this so that 1 logical pixel in the CSS represents 4 physical pixels in the display.  Apple intelligently did this so that all of the existing websites and software interfaces didn't all of a sudden become tiny when viewed on their new high density displays.  It's an elegant solution, but in this case, it works against my needs... I need a way to preview my work on my laptop so that it represents what I would see on my TV (ANOTHER reason to go resolution independent!!).

My solution was effectively very low tech... On my laptop, I run MagicMirror in server-only mode, and by running it in my browser, I can set Chrome's zoom level to 50%. 

I go from this (zoom 100%):


...to this (zoom 50%):


Much better!

The added definition means that I don't have to dedicate such a large proportion of the screen to the right-side column, making more room for the content on the right.  I now have room for 7 columns in my weather forecast.  Also notice how much more vertical space I've been able to reclaim... On days when there are multiple games in my scoreboard, sometimes they would overlap the Tube service warnings at the bottom.  Now I have room to comfortably show 4 matches on the screen. If a weather alert is displayed, there's more than enough space to accommodate for it, and everything is clearly readable from a distance. The extra vertical space gives me the ability to show more calendar entries too... before I had room for 6.  Now I can show 9 entries:



This took my a couple of nights to accomplish.  Getting the Pi to output 4k was dead easy.  The bulk of the time was spent in rewriting the CSS for the display.

Stay tuned for part 2 of this endeavour where I take on making MagicMirror -- and consequently my info centre -- resolution independent.

Comments

Popular Posts