Closed dattasaurabh82 closed 4 years ago
I believe it will always copy the first HDMI display's framebuffer. I have not actually tried out either with two HDMI displays, so not sure how it will behave. Let me know as well.
I hear that on RPi4 one needs to manually enable DispmanX API in raspi-config
by adjusting the OpenGL driver option in the menu settings.. with bad luck that disables dual HDMI output support, but I suppose you'll find out soon enough if that's the case...
To be more precise, if there is only one HDMI connected, then it will always duplicate its framebuffer, possibly scaling it down to the SPI display resolution, in case the original HDMI output resolution is something else. If the two HDMI displays do show up as /dev/fb0
and /dev/fb1
then I presume the second HDMI would be able to operate independently to fbcp-ili9341 operation.
@juj that is my assumption as well. I will get the pi4 today and will post the updates here. BTW I've just started maintaining a small blog post on this here
@juj . So My Pi4 arrived and after configuring the system [ updating, upgrading etc. πͺ ].
I first edited the st7735.cpp
: at line 95, changed SPI_TRANSFER(0x37/*VSCSAD: Vertical Scroll Start Address of RAM*/, 0, 320 - DISPLAY_WIDTH);
to SPI_TRANSFER(0x37, 0, 40); // necessary for my circular 1.3" ST7789V 240x240 TFT
Then added in /boot/config.txt
:
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
[all]
hdmi_group=2
hdmi_mode=87
hdmi_cvt=240 240 60 1 0 0 0
hdmi_force_hotplug=1
Then compiled using command: cmake -DSPI_BUS_CLOCK_DIVISOR=6 -DGPIO_TFT_DATA_CONTROL=25 -DARMV8A=ON -DSTATISTICS=0 -DDISPLAY_CROPPED_INSTEAD_OF_SCALING=ON -DST7789=ON
and then make -j
.
Note: I added this -DDISPLAY_CROPPED_INSTEAD_OF_SCALING=ON
as I need the display to show "original size" texts etc.
Running sudo ./fbcp-ili9341
, showed up the first display as expected on the SPI TFT, but command out-put on the terminal was a bit un-expected:
bcm_host_get_peripheral_address: 0xfe000000, bcm_host_get_peripheral_size: 25165824, bcm_host_get_sdram_address: 0xc0000000
BCM core speed: current: 266666666hz, max turbo: 500000000hz. SPI CDIV: 6, SPI max frequency: 83333333hz
Allocated DMA channel 7
Allocated DMA channel 1
Enabling DMA channels Tx:7 and Rx:1
DMA hardware register file is at ptr: 0xb52e8000, using DMA TX channel: 7 and DMA RX channel: 1
DMA hardware TX channel register file is at ptr: 0xb52e8700, DMA RX channel register file is at ptr: 0xb52e8100
Resetting DMA channels for use
DMA all set up
Initializing display
Creating SPI task thread
InitSPI done
DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE: Swapping width/height to update display in portrait mode to minimize tearing.
Relevant source display area size with overscan cropped away: 240x240.
Source GPU display is 240x240. Output SPI display is 240x240 with a drawable area of 240x240. Applying scaling factor horiz=1.00x & vert=1.00x, xOffset: 0, yOffset: 0, scaledWidth: 240, scaledHeight: 240
Creating dispmanX resource of size 240x240 (aspect ratio=1.000000).
GPU grab rectangle is offset x=0,y=0, size w=240xh=240, aspect ratio=1.000000
DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE: Swapping width/height to update display in portrait mode to minimize tearing.
but in config.h
, around line162, which is: #define DISPLAY_OUTPUT_LANDSCAPE
is not commented out and I didn't pass any build option to rotate anything. π§.. Source GPU display is 240x240 ..
. Well first of all there is no source on HDMI-0 as I didn't connect anything to it. So is it because we asked in /boot/config.txt
to hdmi_force_hotplug=1
, so it created a virtual display!? But then, according to what? In raspi-config->advanced-settings
, for resolution settings, it says (if I remember correctly), something along the lines: .. choose the best resolution based on attached display etc../dev/fb*
, I only still get /dev/fb0
returned. So HDMI-1 is not fb1. Good news is, The 2nd HDMI [HDMI-1] is set to it's connected display's resolution and is separate and not mirrored (but can be set to mirror the first display).
If I fire up the VNC, I see this:
And here is my setup (The PI HAT is what I'm currently designing for a project):
1. It says: `DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE: Swapping width/height to update display in portrait mode to minimize tearing.` but in `config.h`, around line162, which is: `#define DISPLAY_OUTPUT_LANDSCAPE` is not commented out and I didn't pass any build option to rotate anything. π§
All the small SPI display panels are "portrait panels", i.e. their vsync refresh runs in portrait orientation. Well, a 240x240 display is square, so there identifying between portrait vs landscape requires looking at the datasheet of the casing manufacturer. DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE
makes the panel updates occur in the native/natural scan order to minimize this kind of diagonal tearing artifact that would otherwise occur if bytes are uploaded in landscape, but the panel updates in portrait. See "Diagonal Tearing Mode" in https://www.youtube.com/watch?v=EOICdpjiqv8 for what that effect looks like in slow motion. Basically DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE
enables the "Straight line tearing mode", at the expense of some added CPU usage.
2\. `.. Source GPU display is 240x240 ..` . Well first of all there is no source on HDMI-0 as I didn't connect anything to it. So is it because we asked in `/boot/config.txt` to `hdmi_force_hotplug=1`, so it created a virtual display!? But then, according to what? In `raspi-config->advanced-settings`, for _resolution settings_, it says (if I remember correctly), something along the lines: .. choose the best resolution based on attached display etc..
The HDMI output on the Pi is enabled/disabled independent of Linux framebuffer system. tvservice -s
can be used to print out its current status. There will always be a HDMI output/framebuffer on the DispmanX, as long as tvservice -s
says that HDMI is on. I don't know how tvservice -s
works with two HDMI outputs, perhaps it prints two sets of output parameters, or something like that.
The size 240x240 was defined by you by choosing to target ST7789, and by enabling DISPLAY_CROPPED_INSTEAD_OF_SCALING=ON
. You can also try setting hdmi_cvt=240 240 60 1 0 0 0
to get the HDMI output to run in the same resolution as the SPI display is. That way you can pass DISPLAY_CROPPED_INSTEAD_OF_SCALING=OFF
to the build to get pixel-perfect output. (I think it is also possible to go faster than 60hz with a ST7789, but don't exactly remember what the max refresh rate is - check from a datasheet if you find one)
3\. After Quarrying `/dev/fb*` , I only still get `/dev/fb0` returned. So HDMI-1 is not fb1.
That is interesting.. No idea how that is supposed to work on the RPi4!
* **Good news is**, The _2nd HDMI_ [HDMI-1] is set to it's connected display's resolution and is separate and not mirrored (but can be set to mirror the first display).
Most excellent! Hopefully that will run smooth.
@juj, Thank you so much again, for the clarifications and information. Regarding your suggestion on driving ST7789 based displays at a higher rate, I found this: from the pi's documentation on core freq :
Changing core_freq in config.txt is not supported on the Pi 4, any change from the default will almost certainly cause a failure to boot.
You do not need to change core_freq. Changing the refresh rate of ST7789 display is done via a SPI command. For ST7789VW model it is
https://github.com/juj/fbcp-ili9341/blob/662e8db76ba16d86cf6fd09d85240adc19e62735/st7735r.cpp#L101
though for other ST* display models it is not enabled.
To update at e.g. 100hz display rate, one would change
hdmi_cvt=240 240 60 1 0 0 0
to
hdmi_cvt=240 240 100 1 0 0 0
Although I am not sure if the Pi supports refresh rates > 60.
You do not need to change core_freq. Changing the refresh rate of ST7789 display is done via a SPI command. For ST7789VW model it is
https://github.com/juj/fbcp-ili9341/blob/662e8db76ba16d86cf6fd09d85240adc19e62735/st7735r.cpp#L101
though for other ST* display models it is not enabled.
To update at e.g. 100hz display rate, one would change
hdmi_cvt=240 240 60 1 0 0 0
to
hdmi_cvt=240 240 100 1 0 0 0
Although I am not sure if the Pi supports refresh rates > 60.
Cool. Will check and let you know
@juj . So the display runs smooth at 100 Hz. No problem π
It is more of clarification/feature-understanding rather than an issue
Hello. First of all thank you so much for this as it is a very helpful tool to setup SPI TFTs with commonly found TFT chipsets. π
If I understand correctly, it copies over frame data, available at
/dev/fb0
[for default HDMI], with out creating a/dev/fb1
for the SPI display bus which is a huge advantage to run it faster at 60Hz, which basically means it kind of mirrors/copies over the HDMI Frame buffer [ in laymen's over simplified terms, as I'm a noob in this area of display and kernel settings ]My question is, for a raspberry pi4, can I keep the 2nd HDMI
fb
(if there is any) intact and separate from being copied over to SPI. In other words, how can I assign, while compiling, that only copy over the HDMI-0's frame buffer and let the HDMI-1 be as it is? Or am I overthinking it and for Pi4, running latest buster, it will anyways only copy the HDMI-0's frame buffer? πI understood, for proper resolution setting reasons, in
/boot/config.txt
you have suggested to add these settings:I have no way of testing at the moment as my Pi4 is still in transit. Any direction and help would be very much appreciated.