FBCP-ILI9341时代已经结束。 FBCP-ILI9341建于Raspberry Pi的视频Despmanx API之上。
但是,Raspberry Pi基金会已将此API弃用了一段时间,最后在Raspberry Pi 5及以后过时了(=不可用)。
后来的Raspberry Pi发行版甚至对于PI0-PI4默认情况下也不再具有dispManx活动性,而是Raspberry Pi已移至较新的KMS驱动程序Compositor堆栈,该堆栈具有不同的抽象来集成SPI显示器驱动程序。其他人正在为与KMS堆栈兼容的PI开发SPI显示驱动程序。前往此Raspberry Pi论坛线程以了解更多信息。
该存储库很高兴被认为是存档/陈旧的,尽管我没有使用GitHub功能进行存档,因为该功能显然也将使问题跟踪器仅阅读。随时继续讨论跟踪器上的问题。
该存储库实现了针对Raspberry Pi A,B,2、3、4和零的某些基于SPI的LCD显示的驱动程序。
这项工作是出于好奇心的动机,在Retomancave YouTube频道上看到了这一系列视频:
在这些视频中,SPI(GPIO)巴士被称为瓶颈。基于SPI的显示器对串行数据总线的更新进行更新,并在总线上每一个时钟周期传输一个位。因此,320x240x16bpp显示屏需要SPI总线时钟速率为73.728MHz,以实现完整的60fps刷新频率。在实践中,很少有SPI LCD控制器可以快速通信,但是被限制为16-50MHz SPI总线时钟速度,限制了最大更新速率。我们可以对此做任何事情吗?
FBCP-ILI9341项目最初是Adafruit 2.8“ 320x240 TFT w/ touch屏幕的显示驱动程序,用于Raspberry Pi显示器,用于使用ILI9341控制器。在该显示器上,FBCP-ILI9341可以实现60fps的更新速率,具体取决于60fps的更新速率正在显示这些视频,以获取驱动程序的示例:
鉴于SPI总线可能会受到带宽的限制,因此FBCP-ILI9341如何以60fps的速度更新?实现这一目标的方法是可以称为自适应显示流更新。与其在每个显示器刷新周期上上传每个像素,不如将屏幕上实际更改的像素提交到显示屏上。这是可行的,因为与许多其他受欢迎的控制器一样,ILI9341控制器具有通信接口功能,允许指定部分屏幕更新,直至子级别,甚至单个像素级别。这允许击败带宽限制:例如,尽管它是一个快速节奏游戏,但平均只有大约46%的屏幕上像素上的46%更改每个渲染框架。某些零件,例如UI几乎在多个帧中保持不变。
其他优化也被用来挤出更多的性能:
#define NO_INTERLACING
在文件config.h
中来禁用此功能很容易禁用此功能)结果是,SPI总线可以保持接近100%的饱和度,即通常的〜94-97%,以最大化总线的利用率,而仅传输几乎可以描述每个新框架所需的最小字节数。
已检查驾驶员在以下系统上工作(至少过去的某个时刻):
尽管并非所有董事会都经过积极测试,因此尤其是在较旧的板上的YMMV。 (欢迎使用错误修复,使用https://elinux.org/rpi_hardwarehistory确定您正在运行的板)
测试了以下LCD显示:
检查以下各节以设置驱动程序。
该驱动程序不会使用Notro/FBTFT FrameBuffer驱动程序,因此如果活动活动,则需要禁用。也就是说,如果您的/boot/config.txt
文件的行看起来像dtoverlay=pitft28r, ...
, dtoverlay=waveshare32b, ...
或dtoverlay=flexfb, ...
,应将其删除。
该程序均未使用默认的SPI驱动程序,因此也应删除诸如dtparam=spi=on
之类的线路= on /boot/config.txt
以免引起冲突。
同样,如果您与触摸控制器相关的DToverlays活动,例如dtoverlay=ads7846,...
或任何具有penirq=
指令的内容,则应将其删除以避免冲突。如果某人想对此进行刺伤,则有可能向FBCP-ILI9341增加触摸支持。
在覆盆子Pi的控制台中运行:
sudo apt-get install cmake
cd ~
git clone https://github.com/juj/fbcp-ili9341.git
cd fbcp-ili9341
mkdir build
cd build
cmake [options] ..
make -j
sudo ./fbcp-ili9341
特别注意两个点..
在Cmake Line上,在这种情况下,该点表示“一个目录”(而不是指“更多的项目”)。
请参阅下一部分,以查看[选项]下输入的内容。
如果您一直在运行现有的fbcp
驱动程序,请确保首先通过sudo pkill fbcp
删除该驱动程序(在SSH提示下运行或连接到HDMI显示屏),这两个无法同时运行。如果/etc/rc.local
or /etc/init.d
包含启动fbcp
条目,则应删除该指令。
通常有两种方法可以配置构建选项,在CMAKE命令行和文件Config.h中。
在CMAKE命令行上,可以配置以下选项:
当使用FBCP-ILI9341已经识别的PI顶部的显示器之一时,您无需指定GPIO PIN分配,但是FBCP-ILI9341代码已经具有这些。通过以下帽子的CMAKE指令之一:
-DADAFRUIT_ILI9341_PITFT=ON
:如果您在Adafruit 2.8“ 320x240 tft w/ touch屏幕上奔跑)raspberry pi(或Adafruit Pitft 2.2” HAT MINI KIT -320x240 2.2旗帜。-DADAFRUIT_HX8357D_PITFT=ON
:如果您有Adafruit Pitft-组装480x320 3.5“ TFT+触摸屏,用于Raspberry Pi显示屏,请添加此行。-DFREEPLAYTECH_WAVESHARE32B=ON
:如果您在自由层CM3或零设备上运行,请传递此标志。 (这不是帽子,但仍然是预配置的销售分配)-DWAVESHARE35B_ILI9486=ON
:如果指定,则针对WaveShare 3.5“ 480x320 ILI9486显示屏。-DTONTEC_MZ61581=ON
:如果您在tontec 3.5“ 320x480 lcd显示屏上运行,请传递此信息。-DPIRATE_AUDIO_ST7789_HAT=ON
:如果指定,则针对海盗音频240x240,1.3英寸IPS LCD lcd display Hat for Raspberry pi for ST7789显示器显示器-DWAVESHARE_ST7789VW_HAT=ON
:如果指定,则针对240x240,1.3英寸IPS LCD显示帽,用于Raspberry Pi,带有ST7789VW显示器控制器。-DWAVESHARE_ST7735S_HAT=ON
:如果指定,则针对128x128、1.44inch lcd显示帽子,用于带有ST7735S显示器控制器的Raspberry Pi。-DKEDEI_V63_MPI3501=ON
:如果指定,则针对kedei 3.5英寸SPI TFTLCD 480*320 16bit/18bit版本6.3 2018/4/9显示带有MPI3501显示器控制器。 如果您直接在PI上连接了电线,而不是从上面列表中使用帽子,则需要使用以下配置指令。除了指定显示外,您还需要告诉FBCP-ILI9341您将连接连接到哪个GPIO引脚。要配置显示控制器,请传递:
-DILI9341=ON
:如果您在任何其他通用ILI9341显示器上运行,或者在WaveShare32b显示屏上显示为独立的,而不是在Freeplaytech CM3/Zero设备上,请传递此标志。-DILI9340=ON
:如果您有ILI9340显示屏,请通过此指令。 ILI9340和ILI9341芯片组非常相似,但是ILI9340不支持ILI9341上的所有功能,它们将被禁用或降级。-DHX8357D=ON
:如果您有HX8357D显示屏,请通过此指令。-DSSD1351=ON
:如果您有SSD1351 OLED显示屏,请使用此。-DST7735R=ON
:如果您有ST7735R显示屏,请使用此。-DST7789=ON
:如果您有ST7789显示器,请使用此。-DST7789VW=ON
:如果您有ST7789VW显示,请使用此。-DST7735S=ON
:如果显示ST7735S,请使用此。-DILI9486=ON
:如果您有ILI9486显示屏,请通过此指令。-DILI9486L=ON
:如果您有ILI9486L显示屏,请通过此指令。请注意,ILI9486和ILI9486L截然不同,相互不兼容的控制器芯片,因此请在此处小心确定您拥有哪一个。 (或只是尝试两者,如果您误认了)-DILI9488=ON
:如果您有ILI9488显示屏,请通过此指令。-DMPI3501=ON
:如果指定了MPI3501显示器控制器的显示。此外,将以下内容传递以自定义您使用的GPIO PIN分配:
-DGPIO_TFT_DATA_CONTROL=number
:指定/覆盖4-Wire SPI通信上的GPIO PIN用于数据/控制(DC)线。该引脚编号在BCM PIN号中指定。如果您的3线SPI显示器没有数据/控制线,请将此值设置为-1 ,即-DGPIO_TFT_DATA_CONTROL=-1
告诉FBCP-ili9341沟通。-DGPIO_TFT_RESET_PIN=number
:指定/覆盖gpio pin用于显示重置行。该引脚编号在BCM PIN号中指定。如果省略,则假定显示屏没有重置销,并且始终为ON。-DGPIO_TFT_BACKLIGHT=number
:指定/覆盖GPIO PIN用于显示背光行。该引脚编号在BCM PIN号中指定。如果省略,则假定显示器没有GPIO控制的背光引脚,并且始终处于打开状态。如果设置此设置,请参见config.h
中的#define BACKLIGHT_CONTROL
选项。FBCP-ILI9341始终使用硬件SPI0端口,因此MISO,MOSI,CLK和CE0引脚始终相同,无法更改。实际上,味o销至少目前尚未使用,因此您可以跳过连接该的。如果您的显示器是一个忽略芯片启用行的盗贼,您也可以忽略连接它,或者如果用力将其连接到地面以简化布线(取决于显示),也可以通过将其连接到地面来摆脱。
为了从显示屏中获得良好的性能,您将使显示屏超过额定速度规格(额定规格的产量约为10fps,具体取决于显示)。因此,您需要明确配置要驱动显示屏的目标速度,因为由于制造差异,每个显示副本都达到了不同的最大速度。 FBCP-ILI9341不会使用“默认速度”。设置速度是通过选项完成的
-DSPI_BUS_CLOCK_DIVISOR=even_number
:设置时钟除数数号,该号码与pi core_freq = ins.un /boot/config.txt
中的选项一起指定显示SPI通信总线的总体速度。 SPI_frequency = core_freq/divisor
。 SPI_BUS_CLOCK_DIVISOR
必须是偶数号码。默认的pi 3b和Zero w core_freq
为400MHz,通常值-DSPI_BUS_CLOCK_DIVISOR=6
似乎是ILI9341显示器可以做到的最好的。如果显示器显示损坏的输出或较小的值以获得更高的带宽,请尝试更大的值。有关调整最大SPI性能的数据点,请参见ILI9341.H和Waveshare35b.h。安全初始值可能是-DSPI_BUS_CLOCK_DIVISOR=30
。 有几个选择可以明确说明您要针对哪个PI板。这些应该为您自动进行自动进行,通常不需要,例如,如果您从另一个系统中为另一个PI板进行了交叉编译,或者想明确,您可以尝试:
-DSINGLE_CORE_BOARD=ON
:如果您在只有一个硬件线程的PI上运行(PI Model A,Pi Model B,Compute Module 1,Pi Zero/Zero/Zero W),则传递此选项。如果不存在,请自动进行。-DARMV6Z=ON
:将此选项传递给ARMV6Z指令集(PI 1A,1A+,1B,1B,1B+,零,零W)。如果不存在,请自动进行。-DARMV7A=ON
:将此选项传递给ARMV7-A指令集(PI 2B <Rev 1.2)。如果不存在,请自动进行。-DARMV8A=ON
:通过此选项专门针对ARMV8-A指令集(PI 2B> = Rev。1.2,3b,3b,3b+,cm3,CM3 Lite,4B,4B,CM4,PI400)。如果不存在,请自动进行。 以下构建选项是所有显示器和PI板的一般性,它们进一步自定义了构建:
-DBACKLIGHT_CONTROL=ON
:如果设置,则启用FBCP-ILI9341可以控制给定背光引脚中的显示背光。屏幕上不活动后,显示屏将入睡。如果没有,则不会触摸背光。-DDISPLAY_CROPPED_INSTEAD_OF_SCALING=ON
:如果设置,源视频框架大于SPI显示视频分辨率,源视频是通过在所有方向上裁剪出来的部分,而不是缩放为fit。-DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON
:当将源视频缩放到SPI显示时,默认情况下按以下纵横比执行缩放,并根据需要添加信箱/支柱。如果设置了这一点,则进行拉伸的破坏纵横比。-DSTATISTICS=number
:指定要在屏幕上显示的叠加统计信息的级别。 0:禁用,1:启用,2:启用和显示帧速率间隔图。默认值为1(启用)。-DUSE_DMA_TRANSFERS=OFF
:如果指定,请使用DMA Transfers(以丢失的CPU使用费用)禁用。如果DMA提出了一些问题,请通过此指令,例如,如果某事看起来不正确,则可以作为故障排除步骤。-DDMA_TX_CHANNEL=<num>
:指定用于SPI发送命令的DMA通道号。如果您发现DMA频道冲突,请更改此操作。-DDMA_RX_CHANNEL=<num>
:指定用于SPI接收命令的DMA通道号。如果您发现DMA频道冲突,请更改此操作。-DDISPLAY_SWAP_BGR=ON
:如果传递此选项,则将红色和蓝色通道逆转(RGB <-> bgr)交换。某些显示器具有相反的颜色面板子像素布局,显示控制器不会自动考虑,因此如果混合了蓝色和红色,请定义此。-DDISPLAY_INVERT_COLORS=ON
:如果传递此选项,则对像素颜色值解释进行反转(白色= 0,黑色= 31/63)。默认值:黑色= 0,白色= 31/63。如果显示图像看起来像实际颜色的颜色负面,则传递此选项。-DDISPLAY_ROTATE_180_DEGREES=ON
:如果设置,则旋转显示180度。这不会影响HDMI输出,仅影响SPI显示输出。-DLOW_BATTERY_PIN=<num>
:指定可以进行轮询以获得电池状态的GPIO引脚。默认情况下,设置此设置时,如果将引脚拉动较低,将显示一个低电池图标(有关对其进行调整的方式,请参见config.h
)。除上述CMAKE指令外,在代码库周围(主要在Config.h)周围,还有各种定义,主要控制着不同的运行时选项。直接编辑这些内容以进一步调整程序的行为。特别是,完成设置后,您可能需要在CMake配置行中使用-DSTATISTICS=0
选项构建。
这是一个完整的示例,说明要构建和运行什么,如果您的Adafruit 2.8“ 320x240 TFT/ touch w/ touch屏幕均用于Raspberry Pi,并带有ILI9341控制器:
cd ~
sudo apt-get install cmake
git clone https://github.com/juj/fbcp-ili9341.git
cd fbcp-ili9341
mkdir build
cd build
cmake -DSPI_BUS_CLOCK_DIVISOR=6 -DADAFRUIT_ILI9341_PITFT=ON ..
make -j
sudo ./fbcp-ili9341
如果以上不起作用,请尝试指定-DSPI_BUS_CLOCK_DIVISOR=8
或=10
以使显示器运行稍慢一点,或者使用-DUSE_DMA_TRANSFERS=OFF
尝试如果DMA可能是问题,则进行故障排除。如果您使用的是与ILI9341相比的另一个显示控制器,则可能需要使用更高的值,例如30或40。更改CMAKE选项时,您可以重新发行CMAKE指令线,而无需重音或重新创建build
目录。但是,您可能需要在更改选项之间手动删除文件cmakecache.txt,以避免记住旧设置。
如果您想从头开始进行完整的重建,则可以rm -rf build
以删除构建目录并重新创建其以从头开始进行清洁重建。该目录的名称或位置没有什么特别的,这只是我通常的惯例。如果您愿意,您也可以在其他目录中与FBCP-ILI9341目录进行构建。
要设置驱动程序以在启动时启动,请在sudo
模式下编辑file /etc/rc.local
sudo /path/to/fbcp-ili9341/build/fbcp-ili9341 &
到最后。记下所需的and &
该行末尾。
例如,如果您使用上面列出的命令行步骤来构建,则文件/etc/rc.local
将接收一行
sudo /home/pi/fbcp-ili9341/build/fbcp-ili9341 &
如果您的Raspberry Pi安装的用户名除默认pi
外,请相应地更改目录以指向用户的主目录。 (使用pwd
在终端中找出当前目录)
systemd
启动显示驱动程序另外,使用所提供的systemd
单元文件,而不是修改/etc/rc.local
,如下所示:
sudo install -m 0644 -t /etc fbcp-ili9341.conf
sudo install -m 0644 -t /etc/systemd/system fbcp-ili9341.service
sudo systemctl daemon-reload
sudo systemctl enable fbcp && sudo systemctl start fbcp
如果默认HDMI输出/dev/fb0
Framebuffer的大小与显示的分辨率不同,则默认情况下,源视频大小将被重新缩放以适合SPI显示屏的大小。 FBCP-ILI9341将在需要时管理设置此重新进行,并由GPU完成,因此性能不应受到太大影响。但是,如果决议不匹配,则小文本可能看起来难以辨认。调整大小将以纵横比保留方式进行,因此,如果纵横比不匹配,则显示在显示屏上的水平或垂直黑色边界。如果您根本不使用HDMI输出,则最好配置HDMI输出以匹配SPI显示大小,以便不需要重新进行重新制定。这可以通过在/boot/config.txt
中设置以下行来完成。
hdmi_group=2
hdmi_mode=87
hdmi_cvt=320 240 60 1 0 0 0
hdmi_force_hotplug=1
如果您的SPI显示器的分辨率与320x240不同,请将320 240
零件更改为EG 480 320
。
这些行暗示本机应用程序有关默认显示模式的应用程序,并让它们渲染到TFT显示的本机分辨率。但是,如果HDMI连接的显示器不支持如此小的分辨率,则可以防止使用HDMI连接器。作为妥协,如果要同时使用HDMI和SPI显示,则可以使用其他一些兼容的分辨率,例如640x480。有关可用选项,请参见Raspberry Pi HDMI文档。
显示屏的刷新速度取决于显示屏连接的SPI总线的时钟速度。由于Raspberry Pi作品上的BCM2835芯片的方式,因此不存在简单的speed=xxx Mhz
选项,该选项可以设置为定义总线速度。取而代之的是,SPI总线速度来自两个单独的参数:BCM2835 SOC的核心频率(in /boot/config.txt
中的core_freq
)和SPI外围CDIV
(时钟分隔线)设置。然后使用公式SPI_speed=core_freq/CDIV
一起计算所得的SPI总线速度。
为了优化显示器以尽可能快地运行,
通过传递指令-DSPI_BUS_CLOCK_DIVISOR=number
来调整CDIV
值。可能8
值是4
2
...
6
请注意,由于CDIV
出现在SPI_speed
公式中的分母中,因此较小的值会导致较高的总线速度,而较高的值则使显示器变慢。最初,当您不知道显示屏可以运行的速度时,请尝试从安全的高设置开始,例如-DSPI_BUS_CLOCK_DIVISOR=30
,然后以较小的数字来找到显示显示可以应对的最大速度。有关不同显示的特定观察到的最大总线速度,请参见README末尾的表。
确保涡轮速度。这对于良好的帧速率至关重要。在Raspberry Pi 3型B上,如果提供足够的功率,则BCM2835核心默认情况下以400MHz运行( 400/CDIV
MHz SPI速度),如果CPU温度不超过热限。如果CPU空转或电压低,则BCM2835核心将恢复到非涡轮增压250MHz状态,从而导致250/CDIV
MHz SPI速度。涡轮速度对性能的这种影响非常重要,因为400MHz与非涡轮增压250MHz的影响占多个带宽的60%。获得60fps的地震,声音或Tyrian通常需要此涡轮频率,但是即使库存为250MHz,例如NES和C64模拟游戏也可能达到60fps。如果由于某种原因即使应喂养足够的功率,也可以通过在file /boot/config.txt
中设置值avoid_warnings=2
来强制启动电压保护。
也许有点违反直觉,核心核心。设置比默认涡轮增压400MHz较小的核心频率可以使用较小的时钟分隔器启用,从而获得较高的SPI总线速度。例如,如果使用默认的core_freq=400
spi CDIV=8
工作(导致SPI BUS SPEED 400MHz/8=50MHz
),但是CDIV=6
不( 400MHz/6=66.67MHz
太多),您可以尝试降低core_freq=360
和设置CDIV=6
以获得360MHz/6=60MHz
的有效SPI总线速度,这是两者之间可能起作用的中间立场。平衡core_freq=
和CDIV
选项使人们可以找到最大的SPI总线速度到显示器可以忍受的最后几个kHz。一个人也可以尝试相反的方向和超频,但这当然会在超频时出现所有问题。底关节确实具有使PI总体运行较慢的缺点,因此这无疑是一个权衡。
另一方面,希望控制允许使用多少CPU时间FBCP-ILI9341。对默认的构建设置进行了调整,以最大化显示刷新速率,以牺牲PI 3B的功耗为代价。在Pi Zero上,相反的情况是,默认情况下,驱动程序优化了用于节省电池的驱动程序,而不是最大显示更新速度。可以控制以下选项以在这两个方面之间取得平衡:
控制CPU使用情况与性能方面的主要选项是#define ALL_TASKS_SHOULD_DMA
在config.h
中。启用此选项将大大减少CPU使用情况。如果该选项被禁用,SPI总线利用率将最大化,但CPU使用率可以高达80%-120%。启用此选项后,CPU的使用通常高达15%-30%。观看视频或玩快速移动的游戏时,最大CPU使用发生。如果屏幕上没有任何变化,则CPU的驱动程序消耗量应非常接近0-5%。默认情况下, #define ALL_TASKS_SHOULD_DMA
启用了Zero的启用,但对于PI 3B而言是禁用的。
CMAKE选项-DUSE_DMA_TRANSFERS=ON
应始终启用以良好的低CPU使用。如果禁用了DMA传输,则驱动程序将以轮询的SPI模式运行,该模式通常使用CPU时间的完整专用单核。如果DMA传输引起问题,请尝试调整DMA发送和接收频道,用于与-DDMA_TX_CHANNEL=<num>
和-DDMA_RX_CHANNEL=<num>
CMAKE选项。
统计覆盖层打印出有关执行状态的相当详细的信息。使用-DSTATISTICS=0
选项以提高性能并减少CPU使用情况。如果要继续打印统计信息,则可以尝试使用#define STATISTICS_REFRESH_INTERVAL <timeInMicroseconds>
选项在config.h中增加间隔。
启用#define USE_GPU_VSYNC
可以减少CPU的消耗,但是由于Raspberrypi/userland#440可能会导致口吃。禁用#defined USE_GPU_VSYNC
会产生较少的口吃,但是由于RaspberryPi/Userland#440,增加了CPU功耗。
选项#define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
可以与#define USE_GPU_VSYNC
结合使用,以尝试在RaspberryPi/userland#440问题之间找到中间立场 - 中度到中度到小stutter,同时又试图掌握很多CPU。尝试尝试启用或禁用此设置。
config.h中有许多#define SAVE_BATTERY_BY_x
选项,所有这些选项都默认为启用。这些应该是安全使用的,而无需折衷。如果您遇到了延迟或与绩效有关的问题,则可以尝试切换这些问题以进行故障排除。
选项#define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE
确实会导致一些额外的CPU使用,因此禁用其会减轻CPU负载。
如果与显示大小相比,SPI显示总线能够非常快速运行,并且在屏幕上更改内容的数量,则可以尝试启用#define UPDATE_FRAMES_IN_SINGLE_RECTANGULAR_DIFF
选项config.h
在公共汽车上发送的字节数。已经观察到这对Pi Zero有很大的影响,因此值得在那里进行检查。
如果SPI Display Bus能够非常非常快速运行(或者您不在乎帧速率,而是仅在CPU使用率较低),则可以尝试在config.h
中启用#define UPDATE_FRAMES_WITHOUT_DIFFING
选项,以放弃自适应的delta扩散选项完全。这将恢复为幼稚的全帧更新,以最低的总体CPU使用。
选项#define RUN_WITH_REALTIME_THREAD_PRIORITY
可以实现在实时过程优先级时运行驱动程序。但是,这可以锁定系统,但仍可用于高级实验。
在display.h
中,有一个选项#define TARGET_FRAME_RATE <number>
。将其设置为较小的价值,例如30,将交易刷新率以减少CPU消费量。
FBCP-ILI9341的一个令人愉悦的方面是,它引入了很少的延迟开销:在119Hz刷新的ILI9341显示屏上,FBCP-ILI9341在GPIO输入中获得像素的响应,以便从GPIO输入中响应屏幕,远低于16.66毫秒。我只有一个120FPS录像机,因此不能轻易地测量延迟的延迟,但是慢动作视频镜头的粗略统计估计表明,这种延迟可能低至2-3毫秒,以〜8.4msecs面板刷新率主导ILI9341。
这并不意味着显示游戏延迟的总体输入将是如此直接。简要测试了NES模拟游戏,这表明总延迟约为60-80毫秒。该延迟是由NES游戏模拟器开销和Linux,Despmanx和GPU渲染以及GPU FrameBuffer快照添加的额外延迟引起的。 (如果您将FBCP-ILI9341作为静态库绕过Despmanx和GPU堆栈,将您的GPIO输入和应用程序逻辑直接链接到FBCP-ILI9341中GPIO输入视频上方)
有趣的是,FBCP-ILI9341比便宜的3.5英寸Kedei HDMI显示器快〜33msecs。我不知道这是否是kedei hdmi显示的结果,专门引入了额外的延迟,或者所有与PI连接的所有HDMI显示延迟开销。
不幸的是,SPI连接的显示器的限制是,在SPI模式下运行时,Vsync线信号在显示器控制器上不可用,因此即使显示屏上的SPI BUS BARSWIDTH足够快,也无法进行Vsync锁定更新。例如,我所拥有的4个ILI9341显示器的运行速度都比75MHz快,因此SPI BUS带宽方面的运行速度所有这些都可以在少于Vsync间隔的情况下更新全帧,但是不可能将更新同步到更新Vsync由于显示控制器没有报告。 (If you do know of a display that does actually expose a vsync clock signal even in SPI mode, you can try implementing support to locking on to it)
You can however choose between two distinct types of tearing artifacts: straight line tearing and diagonal tearing . Whichever looks better is a bit subjective, which is why both options exist. I prefer the straight line tearing artifact, it seems to be less intrusive than the diagonal tearing one. To toggle this, edit the option #define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE
in config.h
. When this option is enabled, fbcp-ili9341 produces straight line tearing, and consumes a tiny few % more CPU power. By default Pi 3B builds with straight line tearing, and Pi Zero with the faster diagonal tearing. Check out the video Latency and tearing test #2: GPIO input to display latency in fbcp-ili9341 and tearing modes to see in slow motion videos how these two tearing modes look like.
Another option that is known to affect how the tearing artifact looks like is the internal panel refresh rate. For ILI9341 displays this refresh rate can be adjusted in ili9341.h
, and this can be set to range between ILI9341_FRAMERATE_61_HZ
and ILI9341_FRAMERATE_119_HZ
(default). Slower refresh rates produce less tearing, but have higher input-to-display latency, whereas higher refresh rates will result in the opposite. Again visually the resulting effect is a bit subjective.
To get tearing free updates, you should use a DPI display, or a good quality HDMI display. Beware that cheap small 3.5" HDMI displays such as KeDei do also tear - that is, even if they are controlled via HDMI, they don't actually seem to implement VSYNC timed internal operation.
Having no vsync is not all bad though, since with the lack of vsync, SPI displays have the opportunity to obtain smoother animation on content that is not updating at 60Hz. It is possible that content on the SPI display will stutter even less than what DPI or HDMI displays on the Pi can currently provide (although I have not been able to test this in detail, except for the KeDei case above).
The main option that affects smoothness of display updates is the #define USE_GPU_VSYNC
line in config.h
. If this is enabled, then the internal Pi GPU HDMI vsync clock is used to drive frames onto the display. The Pi GPU clock runs at a fixed rate that is independent of the content. This rate can be discovered by running tvservice -s
on the Pi console, and is usually 59Hz or 60Hz. If your application renders at this rate, animation will look smooth, but if not, there will be stuttering. For example playing a PAL NES game that updates at 50Hz with HDMI clock set at 60Hz will cause bad microstuttering in video output if #define USE_GPU_VSYNC
is enabled.
If USE_GPU_VSYNC
is disabled, then a busy spinning GPU frame snapshotting thread is used to drive the updates. This will produce smoother animation in content that does not maintain a fixed 60Hz rate. Especially in OpenTyrian, a game that renders at a fixed 36fps and has slowly scrolling scenery, the stuttering caused by USE_GPU_VSYNC
is particularly visible. Running on Pi 3B without USE_GPU_VSYNC
enabled produces visually smoother looking scrolling on an Adafruit 2.8" ILI9341 PiTFT set to update at 119Hz, compared to enabling USE_GPU_VSYNC
on the same setup. Without USE_GPU_VSYNC
, the dedicated frame polling loop thread "finds" the 36Hz update rate of the game, and then pushes pixels to the display at this exact rate. This works nicely since SPI displays disregard vsync - the result is that frames are pushed out to the SPI display immediately as they become available, instead of pulling them at a fixed 60Hz rate like HDMI does.
A drawback is that this kind of polling consumes more CPU time than the vsync option. The extra overhead is around +34% of CPU usage compared to the vsync method. It also requires using a background thread, and because of this, it is not feasible to be used on a single core Pi Zero. If this polling was unnecessary, this mode would also work on a Pi Zero, and without the added +34% CPU overhead on Pi 3B. See the Known Issues section below for more details.
There are two other main options that affect frame delivery timings, #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
and #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES
. Check out the video fbcp-ili9341 frame delivery smoothness test on Pi 3B and Adafruit ILI9341 at 119Hz for a detailed side by side comparison of these different modes. The conclusions drawn from the four tested scenarios in the video are:
1. vc_dispmanx_vsync_callback() (top left) , set #define USE_GPU_VSYNC
and unset #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
:
This mode uses the DispmanX HDMI vsync signal callback to drive frames to the display.
优点:
缺点:
2. vc_dispmanx_vsync_callback() + self synchronization (top right) , set #define USE_GPU_VSYNC
and #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
:
This mode uses the GPU vsync signal, but also aims to find and synchronize to the edge trigger when content is producing frames. This is the default build mode on Pi Zero.
优点:
缺点:
3. gpu polling thread + sleep heuristic (bottom left) , unset #define USE_GPU_VSYNC
and set #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES
:
This mode runs a dedicated background thread that drives frames from the GPU to the SPI display. This is the default build mode on Pi 3B.
优点:
缺点:
4. gpu polling thread without sleeping (bottom right) , unset #define USE_GPU_VSYNC
and unset #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES
:
This mode runs the dedicated GPU thread as fast as possible, without attempting to sleep CPU.
优点:
缺点:
Be aware of the following limitations:
vc_dispmanx_snapshot()
API, and the obtained pixels are then routed on to the SPI-based display. This kind of polling is performed, since there does not exist an event-based mechanism to get new frames from the GPU as they are produced. The result is inefficient and can easily cause stuttering, since different applications produce frames at different paces. Ideally the code would ask the VideoCore API to receive finished frames in callback notifications immediately after they are rendered , but this kind of functionality does not exist in the current GPU driver stack. In the absence of such event delivery mechanism, the code has to resort to polling snapshots of the display framebuffer using carefully timed heuristics to balance between keeping latency and stuttering low, while not causing excessive power consumption. These heuristics keep continuously guessing the update rate of the animation on screen, and they have been tuned to ensure that CPU usage goes down to 0% when there is no detected activity on screen, but it is certainly not perfect. This GPU limitation is discussed at raspberrypi/userland#440. If you'd like to see fbcp-ili9341 operation reduce latency, stuttering and power consumption, please throw a (kind!) comment or a thumbs up emoji in that bug thread to share that you care about this, and perhaps Raspberry Pi engineers might pick the improvement up on the development roadmap. If this issue is resolved, all of the #define USE_GPU_VSYNC
, #define SAVE_BATTERY_BY_PREDICTING_FRAME_ARRIVAL_TIMES
and #define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
hacks from the previous section could be deleted from the driver, hopefully leading to a best of all worlds scenario without drawbacks. /boot/config.txt
and configure all applications to never change that at runtime. 400/250=+60%
as well. Therefore when choosing the SPI CDIV
value to use, one has to pick one that works for both idle and turbo clock speeds. Conversely, the BCM core reverts to non-turbo speed when there is only light CPU load active, and this slows down the display, so if an application is graphically intensive but light on CPU, the SPI display bus does not get a chance to run at maximum speeds. A way to work around this is to force the BCM core to always stay in its turbo state with force_turbo=1
option in /boot/config.txt
, but this has an unfortunate effect of causing the ARM CPU to always run in turbo speed as well, consuming excessive amounts of power. At the time of writing, there does not yet exist a good solution to have both power saving and good performance. This limitation is being discussed in more detail at raspberrypi/firmware#992. For more known issues and limitations, check out the bug tracker, especially the entries marked retired , for items that are beyond current scope.
By default fbcp-ili9341 builds with a statistics overlay enabled. See the video fbcp-ili9341 ported to ILI9486 WaveShare 3.5" (B) SpotPear 320x480 SPI display to find details on what each field means. Build with CMake option -DSTATISTICS=0
to disable displaying the statistics. You can also try building with CMake option -DSTATISTICS=2
to show a more detailed frame delivery timings histogram view, see screenshot and video above.
The fbcp
part in the name means framebuffer copy ; specifically for the ILI9341 controller. fbcp-ili9341 is not actually a framebuffer copying driver, it does not create a secondary framebuffer that it would copy bytes across to from the primary framebuffer. It is also no longer a driver only for the ILI9341 controller. A more appropriate name might be userland-raspi-spi-display-driver or something like that, but the original name stuck.
Yes, it does, although not quite as well as on Pi 3B. If you'd like it to run better on a Pi Zero, leave a thumbs up at raspberrypi/userland#440 - hard problems are difficult to justify prioritizing unless it is known that many people care about them.
Edit the file config.h
and comment out the line #define DISPLAY_OUTPUT_LANDSCAPE
. This will make the display output in portrait mode, effectively rotating it by 90 degrees. Note that this only affects the pixel memory reading mode of the display. It is not possible to change the panel scan order to run between landscape and portrait, the SPI displays typically always scan in portrait mode. The result is that it will change the panel vsync tearing mode from "straight line tearing" over to "diagonal tearing" (see the section About Tearing above).
If you do not want to have diagonal tearing, but would prefer straight line tearing, then additionally enable the option #define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE
in config.h
. That will restore straight line tearing, but it will also increase overall CPU consumption.
Enable the option #define DISPLAY_ROTATE_180_DEGREES
in config.h
. This should rotate the SPI display to show up the other way around, while keeping the HDMI connected display orientation unchanged. Another option is to utilize a /boot/config.txt
option display_rotate=2, which rotates both the SPI output and the HDMI output.
Note that the setting DISPLAY_ROTATE_180_DEGREES
only affects the pixel memory reading mode of the display. It is not possible to flip the panel scan to run inverted by 180 degrees. This means that adjusting these settings will also have effects of changing the visual appearance of the vsync tearing artifact. If you have the ability to mount the display 180 degrees around in your project, it is recommended to do that instead of using the DISPLAY_ROTATE_180_DEGREES
option.
Edit the file config.h
in a text editor (a command line one such as pico
, vim
, nano
, or SSH map the drive to your host), and find the appropriate line in the file. Add comment lines //
in front of that text to disable the option, or remove the //
characters to enable it.
After having edited and saved the file, reissue make -j
in the build directory and restart fbcp-ili9341.
Some options are passed to the build from the CMake configuration script. You can run with make VERBOSE=1
to see which configuration items the CMake build is passing. See the above Configuring Build Options section to customize the CMake configure items. For example, to remove the statistics overlay, pass -DSTATISTICS=0
directive to CMake.
Building requires CMake to be installed on the Pi: try sudo apt-get install cmake
.
Try deleting CMakeCache.txt between changing CMake settings.
Yes, both work fine. For linux command line terminal, the /dev/tty1
console should be set to output to Linux framebuffer 0 ( /dev/fb0
). This is the default mode of operation and there do not exist other framebuffers in a default distribution of Raspbian, but if you have manually messed with the con2fbmap
command in your installation, you may have inadvertently changed this configuration. Run con2fbmap 1
to see which framebuffer the /dev/tty1
console is outputting to, it should print console 1 is mapped to framebuffer 0
. Type con2fbmap 1 0
to reset console 1 back to outputting to framebuffer 0.
Likewise, the X windowing system should be configured to render to framebuffer 0. This is by default the case. The target framebuffer for X windowing service is usually configured via the FRAMEBUFFER
environment variable before launching X. If X is not working by default, you can try overriding the framebuffer by launching X with FRAMEBUFFER=/dev/fb0 startx
instead of just running startx
.
I don't know, I don't currently have any to test. Perhaps the code does need some model specific configuration, or perhaps it might work out of the box. I only have Pi 3B, Pi 3B+, Pi Zero W and a Pi 3 Compute Module based systems to experiment on. Pi 2 B has been reported to work by users (#17).
If the display controller is one of the currently tested ones (see the list above), and it is wired up to run using 4-line SPI, then it should work. Pay attention to configure the Data/Control
GPIO pin number correctly, and also specify the Reset
GPIO pin number if the device has one.
If the display controller is not one of the tested ones, it may still work if it is similar to one of the existing ones. For example, ILI9340 and ILI9341 are practically the same controller. You can just try with a specific one to see how it goes.
If fbcp-ili9341 does not support your display controller, you will have to write support for it. fbcp-ili9341 does not have a "generic SPI TFT driver routine" that might work across multiple devices, but needs specific code for each. If you have the spec sheet available, you can ask for advice, but please do not request to add support to a display controller "blind", that is not possible.
也许。 This is a more recent experimental feature that may not be as stable, and there are some limitations, but 3-wire ("9-bit") SPI display support is now available. If you have a 3-wire SPI display, ie one that does not have a Data/Control (DC) GPIO pin to connect, configure it via CMake with directive -DGPIO_TFT_DATA_CONTROL=-1
to tell fbcp-ili9341 that it should be driving the display with 3-wire protocol.
Current limitations of 3-wire communication are:
ALL_TASKS_SHOULD_DMA
is currently not supported, there is an issue with DMA chaining that prevents this from being enabled. As result, CPU usage on 3-wire displays will be slightly higher than on 4-wire displays.OFFLOAD_PIXEL_COPY_TO_DMA_CPP
is currently not supported. As a result, 3-wire displays may not work that well on single core Pis like Pi Zero.No. Those are completely different technologies altogether. It should be possible to port the driver algorithm to work on I2C however, if someone is interested.
At the moment one cannot utilize the XPT2046/ADS7846 touch controllers while running fbcp-ili9341, so touch is mutually incompatible with this driver. In order for fbcp-ili9341 to function, you will need to remove all dtoverlay
s in /boot/config.txt
related to touch.
I have done close to everything possible to my displays - cut power in middle of operation, sent random data and command bytes, set their operating voltage commands and clock timings to arbitrary high and low values, tested unspecified and reserved command fields, and driven the displays dozens of MHz faster than they managed to keep up with, and I have not yet done permanent damage to any of my displays or Pis.
Easiest way to do permanent damage is to fail at wiring, eg drive 5 volts if your display requires 3.3v, or short a connection, or something similar.
The one thing that fbcp-ili9341 stays clear off is that it does not program the non-volatile memory areas of any of the displays. Therefore a hard power off on a display should clear all performed initialization and reset the display to its initial state at next power on.
That being said, if it breaks, you'll get to purchase a new shiny one to replace it.
Yes, fbcp-ili9341 shows the output of the HDMI display on the SPI screen, and both can be attached at the same time. A HDMI display does not have to be connected however, although fbcp-ili9341 operation will still be affected by whatever HDMI display mode is configured. Check out tvservice -s
on the command line to check what the current DispmanX HDMI output mode is.
At the moment fbcp-ili9341 has been developed to only display the contents of the main DispmanX GPU framebuffer over to the SPI display. That is, the SPI display will show the same picture as the HDMI output does. There is no technical restriction that requires this though, so if you know C/C++ well, it should be a manageable project to turn fbcp-ili9341 to operate as an offscreen display library to show a completely separate (non-GPU-accelerated) image than what the main HDMI display outputs. For example you could have two different outputs, eg a HUD overlay, a dashboard for network statistics, weather, temps, etc. showing on the SPI while having the main Raspberry Pi desktop on the HDMI.
In this kind of mode, you would probably strip the DispmanX bits out of fbcp-ili9341, and recast it as a static library that you would link to in your drawing application, and instead of snapshotting frames, you can then programmatically write to a framebuffer in memory from your C/C++ code.
Unfortunately there are a number of things to go wrong that all result in a white screen. This is probably the hardest part to diagnose.一些想法:
This suggests that the power line or the backlight line might not be properly connected. Or if the backlight connects to a GPIO pin on the Pi (and not a voltage pin), then it may be that the pin is not in correct state for the backlight to turn on. Most of the LCD TFT displays I have immediately light up their backlight when they receive power. The Tontec one has a backlight GPIO pin that boots up high but must be pulled low to activate the backlight. OLED displays on the other hand seem to stay all black even after they do get power, while waiting for their initialization to be performed, so for OLEDs it may be normal for nothing to show up on the screen immediately after boot.
If the backlight connects to a GPIO pin, you may need to define -DGPIO_TFT_BACKLIGHT=<pin>
in CMake command line or config.h
, and edit config.h
to enable #define BACKLIGHT_CONTROL
.
fbcp-ili9341 runs a clear screen command at low speed as first thing after init, so if that goes through, it is a good sign. Try increasing -DSPI_BUS_CLOCK_DIVISOR=
CMake option to a higher number to see if the display driving rate was too fast. Or try disabling DMA with -DUSE_DMA_TRANSFERS=OFF
to see if this might be a DMA conflict.
This suggests same as above, increase SPI bus divisor or troubleshoot disabling DMA. If DMA is detected to be the culprit, try changing up the DMA channels. Double check that /boot/config.txt
does not have any dtoverlay
s regarding other SPI display drivers or touch screen controllers, and that it does NOT have a dtparam=spi=on
line in it - fbcp-ili9341 does not use the Linux kernel SPI driver.
Make sure other fbcp
programs are not running, or that another copy of fbcp-ili9341
is not running on the background.
This is likely caused by the program resizing the video resolution at runtime, which breaks DispmanX. See raspberrypi/userland#461 for more details.
Check that the Pi is powered off of a power supply that can keep up with the voltage, and the low voltage icon is not showing up. (remove any avoid_warnings=1/2
directive from /boot/config.txt
if that was used to get rid of warnings overlay, to check that voltage is good) It has been observed that if there is not enough power supplied, the display can be the first to starve, while the Pi might keep on running fine. Try removing turbo settings or lowering the clock speed if you have overclocked to verify that the display crash is not power usage related.
Also try lowering SPI bus speed to a safe lower value, eg half of the maximum speed that the display was able to manage.
Double check the Data/Command (D/C) GPIO pin physically, and in CMake command line. Whenever fbcp-ili9341 refers to pin numbers, they are always specified in BCM pin numbers. Try setting a higher -DSPI_BUS_CLOCK_DIVISOR=
value to CMake. Make sure no other fbcp
programs or SPI drivers or dtoverlays are enabled.
If the color channels are mixed (red is blue, blue is red, green is green) like shown on the left image, pass the CMake option -DDISPLAY_SWAP_BGR=ON
to the build.
If the color intensities look wrong (white is black, black is white, color looks like a negative image) like seen in the middle image, pass the CMake option -DDISPLAY_INVERT_COLORS=ON
to the build.
If the colors looks off in some other fashion, it is possible that the display is just being driven at a too high SPI bus speed, in which case try making the display run slower by choosing a higher -DSPI_BUS_CLOCK_DIVISOR=
option to CMake. Especially on ILI9486 displays it has been observed that the colors on the display can become distorted if the display is run too fast beyond its maximum capability.
fbcp-ili9341 needs a few megabytes of GPU memory to function if DMA transfers are enabled. The gpu_mem boot config option dictates how much of the Pi's memory area is allocated to the GPU. By default this is 64MB, which has been observed to not leave enough memory for fbcp-ili9341 if HDMI is run at 1080p. If this error happens, try increasing GPU memory to eg 128MB by adding a line gpu_mem=128
in /boot/config.txt
.
As the number of supported displays, Raspberry Pi device models, Raspbian/Retropie/Lakka OS versions, accompanied C++ compiler versions and fbcp-ili9341 build options have grown in number, there is a combinatorial explosion of all possible build modes that one can put the codebase through, so it is not easy to keep every possible combo tested all the time. Something may have regressed or gotten outdated. Stay calm, and report a bug.
You can also try looking through the commit history to find changes related to your configuration combo, to see if there's a mention of a known good commit in time that should work for your case. If you get an odd compiler error on cmake
or make
lines, those will usually be very easy to fix, as they are most of the time a result of some configurational oversight.
First, make sure the display is a 4-wire SPI and not a 3-wire one. A display is 4-wire SPI if it has a Data/Control (DC) GPIO line that needs connecting. Sometimes the D/C pin is labeled RS (Register Select). Support for 3-wire SPI displays does exist, but it is experimental and not nearly as well tested as 4-wire displays.
Second is the consideration about display speed. Below is a performance chart of the different displays I have tested. Note that these are sample sizes of one, I don't know how much sample variance there exists. Also I don't know if it is likely that there exists big differences between displays with same controller from different manufacturers. At least the different ILI9341 displays that I have are all quite consistent on performance, whether they are from Adafruit or WaveShare or from BuyDisplay.com.
小贩 | 尺寸 | 解决 | 控制器 | Rated SPI Bus Speed | Obtained Bus Speed | 帧速率 |
---|---|---|---|---|---|---|
Adafruit PiTFT | 2.8” | 240x320 | ILI9341 | 10MHz | 294MHz/4=73.50MHz | 59.81 fps |
Adafruit PiTFT | 2.2” | 240x320 | ILI9340 | 15.15MHz | 338MHz/4=84.50MHz | 68.76 fps |
Adafruit PiTFT | 3.5” | 320x480 | HX8357D | 15.15MHz | 314MHz/6=52.33MHz | 21.29 fps |
Adafruit OLED | 1.27" | 128x96 | SSD1351 | 20MHz | 360MHz/20=18.00MHz | 91.55 fps |
Waveshare RPi LCD (B) IPS | 3.5” | 320x480 | ILI9486 | 15.15MHz | 255MHz/8=31.88MHz | 12.97 fps |
maithoga TFT LCD | 3.5” | 320x480 | ILI9486L | 15.15MHz | 400MHz/8=50.00MHz | 13.56 fps* |
BuyDisplay.com SPI TFT copy #1 | 3.2” | 240x320 | ILI9341 | 10MHz | 310MHz/4=77.50MHz | 63.07 fps |
BuyDisplay.com SPI TFT copy #2 | 3.2” | 240x320 | ILI9341 | 10MHz | 300MHz/4=75.00MHz | 61.03 fps |
Arduino A000096 LCD | 1.77" | 128x160 | ST7735R | 15.15MHz | 355MHz/6=59.16MHz | 180.56 fps |
Tontec MZ61581-PI-EXT 2016.1.28 | 3.5” | 320x480 | MZ61581 | 128MHz | 280MHz/2=140.00MHz | 56.97 fps |
Adafruit 240x240 Wide Angle TFT | 1.54" | 240x240 | ST7789 | ? | 340MHz/4=85.00MHz | 92.23 fps |
WaveShare 240x240 Display HAT | 1.3” | 240x240 | ST7789VW | 62.5MHz | 338MHz/4=84.50MHz | 91.69 fps |
WaveShare 128x128 Display HAT | 1.44" | 128x128 | ST7735S | 15.15MHz | (未经测试) | (未经测试) |
KeDei v6.3 | 3.5” | 320x480 | MPI3501 | ? | 400MHz/12=33.333MHz | 4.8fps ** |
In this list, Rated SPI Bus Speed is the maximum clock speed that the display controller is rated to run at. The Obtained Bus Speed column lists the fastest SPI bus speed that was achieved in practice, and the core_freq
BCM Core speed and SPI Clock Divider CDIV
setting that was used to achieve that rate. Note how most display controllers can generally be driven much faster than what they are officially rated at in their spec sheets.
The Frame Rate column shows the worst case frame rate when full screen updates are being performed. This occurs for example when watching fullscreen video (that is not a flat colored cartoon). Because fbcp-ili9341 only sends over the pixels that have changed, displays such as HX8357D and ILI9486 can still be used to play many games at 60fps. Retro games work especially well.
All the ILI9341 displays work nice and super fast at ~70-80MHz. My WaveShare 3.5" 320x480 ILI9486 display runs really slow compared to its pixel resolution, ~32MHz only. See fbcp-ili9341 ported to ILI9486 WaveShare 3.5" (B) SpotPear 320x480 SPI display for a video of this display in action. Adafruit's 320x480 3.5" HX8357D PiTFTs is ~64% faster in comparison.
The ILI9486L controller based maithoga display runs a bit faster than ILI9486 WaveShare, 50MHz versus 31.88MHz, ie +56.8% bandwidth increase. However fps-wise maithoga reaches only 13.56 vs WaveShare 12.97 fps, because the bandwidth advantage is fully lost in pixel format differences: ILI9486L requires transmitting 24 bits per each pixel (R6G6B6 mode), whereas ILI9486 supports 16 bits per pixel R5G6B5 mode. This is reflected in the above chart refresh rate for the maithoga display (marked with a star).
If manufacturing variances turn out not to be high between copies, and you'd like to have a bigger 320x480 display instead of a 240x320 one, then it is recommended to avoid ILI9486, they indeed are slow.
The KeDei v6.3 display with MPI3501 controller takes the crown of being horrible, in all aspects imaginable. It is able to run at 33.33 MHz, but due to technical design limitations of the display (see #40), effective bus speed is halved, and only about 72% utilization of the remaining bus rate is achieved. DMA cannot be used, so CPU usage will be off the charts. Even though fbcp-ili9341 supports this display, level of support is expected to be poor, because the hardware design is a closed secret without open documentation publicly available from the manufacturer. Stay clear of KeDei or MPI3501 displays.
The Tontec MZ61581 controller based 320x480 3.5" display on the other hand can be driven insanely fast at up to 140MHz! These seem to be quite hard to come by though and they are expensive. Tontec seems to have gone out of business and for example the domain itontec.com from which the supplied instructions sheet asks to download original drivers from is no longer registered. I was able to find one from eBay for testing.
Search around, or ask the manufacturer of the display what the maximum SPI bus speed is for the device. This is the most important aspect to getting good frame rates, but unfortunately most web links never state the SPI speed rating, or they state it ridiculously low like in the spec sheets. Try and buy to see, or ask in some community forums from people who already have a particular display to find out what SPI bus speed it can achieve.
One might think that since Pi Zero is slower than a Pi 3, the SPI bus speed might not matter as much when running on a Pi Zero, but the effect is rather the opposite. To get good framerates on a Pi Zero, it should be paired with a display with as high SPI bus speed capability as possible. This is because the higher the SPI bus speed is, the more autonomously a DMA controller can drive it without CPU intervention. For the same reason, the interlacing technique does not (currently at least) perform well on a Pi Zero, so it is disabled there by default. ILI9341s run well on Pi Zero, ILI9486 on the other hand is quite difficult to combine with a Pi Zero.
Ultimately, it should be noted that parallel displays (DPI) are the proper method for getting fast framerates easily. SPI displays should only be preferred if display form factor is important and a desired product might only exist as SPI and not as DPI, or the number of GPIO pins that are available on the Pi is scarce that sacrificing dozens of pins to RGB data is not可行的。
Hardware-wise, there are six different ways to connect displays to the Pi. Here are the pros and cons of each:
Displays are generally manufactured to utilize one specific interfacing method, with the exception that some displays have a both I²C and SPI modes that can be configured via soldering.
Fbcp-ili9341 driver is about interfacing with SPI displays. If your display utilizes some other connection mechanism, fbcp-ili9341 will not apply.
Software-wise, there are two possible alternatives to fbcp-ili9341:
The following links proved helpful when writing this:
If you would like to help push Raspberry Pi SPI display support further, there are always more things to do in the project. Here is a list of ideas and TODOs for recognized work items to contribute, roughly rated in order of increasing difficulty.
top
/ htop
, or with a power meter off the wall and report the results.SPI_3WIRE_PROTOCOL
+ ALL_TASKS_SHOULD_DMA
to work together, or 3) fix up SPI_3WIRE_PROTOCOL
+ OFFLOAD_PIXEL_COPY_TO_DMA_CPP
to work together.ALL_TASKS_SHOULD_DMA
mode to be always superior in performance and CPU usage so that the non- ALL_TASKS_SHOULD_DMA
path can be dropped from the codebase. (probably requires the above chaining to function efficiently)This driver is licensed under the MIT License. See LICENSE.txt. In nonlegal terms, it's yours for both free and commercial projects, DIY packages, kickstarters, Etsys and Ebays, and you don't owe back a dime. Feel free to apply and derive as you wish.
If you found fbcp-ili9341 useful, it makes me happy to hear back about the projects it found a home in. If you did a build or a project where fbcp-ili9341 worked out, it'd be great to see a video or some photos or read about your experiences.
I hope you build something you enjoy!
Best way to discuss the driver is to open a GitHub issue. You may also be able to find me over at sudomod.com Discord channel.