FBCP-ILI9341の時代は終わりました。 FBCP-ILI9341は、Raspberry PiのVideocore Dispmanx APIの上に構築されました。
ただし、このAPIはしばらくの間、Raspberry Pi Foundationによって非難されており、最終的にRaspberry Pi 5以降で時代遅れ(=利用できません)。
後のRaspberry Piディストリビューションは、PI0-PI4でもデフォルトでDispManxがアクティブになっていませんが、代わりにRaspberry PiはSPIディスプレイドライバーを統合するための異なる抽象化を備えた新しいKMSドライバーコンポジタースタックに移動しました。他の人は、KMSスタックと互換性のあるPIのSPIディスプレイドライバーを開発しています。このRaspberry Piフォーラムスレッドにアクセスして、詳細をご覧ください。
このリポジトリは、アーカイブ/古くなっていると見なされるのに適していますが、GitHub機能を使用してアーカイブしているわけではありません。その機能は明らかにトラッカーの読み取り専用になるからです。トラッカーで問題について話し合い続けてください。
このリポジトリは、Raspberry Pi A、B、2、3、4およびゼロの特定のSPIベースのLCDディスプレイのドライバーを実装します。
この作品は、Retromancave YouTubeチャンネルでこの一連のビデオを見た後、好奇心によって動機付けられました。
これらのビデオでは、SPI(GPIO)バスはボトルネックと呼ばれています。 SPIベースのディスプレイは、シリアルデータバスで更新され、バスのクロックごとに1ビットを送信します。したがって、320x240x16bpp表示が必要なため、60fpsの完全な更新周波数を達成するには、73.728MHzのSPIバス時計レートが必要です。多くのSPI LCDコントローラーは実際にこれを迅速に通信することはできませんが、16-50MHz SPIバスクロック速度などに制約されており、最大更新レートを大幅に上限しています。これについて何かできますか?
FBCP-ILI9341プロジェクトは、ILI9341コントローラーを利用するRaspberry PIディスプレイ用のAdafruit 2.8 "320x240 TFT W/ TAUCHスクリーンのディスプレイドライバーとして始まりました。それが表示されています。
SPIバスが帯域幅に非常に制約される可能性があることを考えると、なぜFBCP-ILI9341は最大60fpsで更新できるように思われるのでしょうか?これが達成される方法は、Adaptive Display Streamの更新と呼ばれるものです。各ディスプレイリフレッシュサイクルで各ピクセルをアップロードする代わりに、実際に変更された画面上のピクセルのみがディスプレイに送信されます。これは、他の多くの一般的なコントローラーと同様に、ILI9341コントローラーには、部分的な画面の更新を指定できる通信インターフェイス関数を備えているため、サブレクタングルまたは個々のピクセルレベルまでさえあります。これにより、帯域幅の制限を打ち負かすことができます。たとえば、Quakeでは、ペーシングゲームが速いにもかかわらず、レンダリングされた各フレームの画面変更のすべてのピクセルの平均しかわずか46%です。 UIなどの一部の部分は、複数のフレームにわたって実質的に一定のままです。
他の最適化も利用され、さらに多くのパフォーマンスを絞り出す:
config.h
で行#define NO_INTERLACING
を開始することでこれを無効にするのは簡単です)その結果、SPIバスは、バスの使用率を最大化するために、通常の〜94〜97%に通常100%飽和状態に保つことができます。
ドライバーは、次のシステムで(少なくとも過去のある時点で)作業するようにチェックされています。
すべてのボードが積極的にテストされているわけではないため、特に古いボードではYMMVです。 (バグ修正歓迎、https://elinux.org/rpi_hardwarehistoryを使用して、実行しているボードを特定してください)
次のLCDディスプレイがテストされています。
ドライバーをセットアップするには、次のセクションを確認してください。
このドライバーはNotro/FBTFT FrameBufferドライバーを使用していないため、アクティブな場合は無効にする必要があります。つまり、 /boot/config.txt
ファイルにはdtoverlay=pitft28r, ...
、 dtoverlay=waveshare32b, ...
またはdtoverlay=flexfb, ...
、dtoverlay = waveshare32bなどのように見える行がある場合です。
このプログラムはどちらもデフォルトのSPIドライバーを使用していないため、 dtparam=spi=on
/boot/config.txt
も削除する必要があります。
同様に、 dtoverlay=ads7846,...
またはpenirq=
指示のあるものなど、タッチコントローラーに関連するDtoverlaysアクティブがある場合は、競合を避けるために削除する必要があります。誰かがそれを刺したい場合は、FBCP-ILI9341にタッチサポートを追加することが可能です。
RaspberryPiのコンソールで実行してください:
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
特に2つのドットに注意してください..
この場合、「1つのディレクトリを上にする」を示すcmakeラインに(「より多くのアイテムがここに行く」と言及するのではなく)。
次のセクションを参照して、 [オプション]の下に入力するものを確認してください。
既存のfbcp
ドライバーを実行している場合は、最初にsudo pkill fbcp
介してEGを削除してください(SSHプロンプトで実行中またはHDMIディスプレイに接続しているとき)、これら2つは同時に実行できません。 /etc/rc.local
または/etc/init.d
Bootでfbcp
起動するためのエントリが含まれている場合、その指令を削除する必要があります。
通常、CMakeコマンドラインとファイルconfig.hでビルドオプションを構成する2つの方法があります。
cmakeコマンドラインでは、次のオプションを構成できます。
FBCP-ILI9341によって既に認識されているPIの上にスタックするディスプレイのいずれかを使用する場合、GPIO PIN割り当てを指定する必要はありませんが、FBCP-ILI9341コードにはすでにあります。帽子の次のCmakeディレクティブのいずれかを渡します。
-DADAFRUIT_ILI9341_PITFT=ON
:adafruit 2.8 "320x240 tft w/ raspberry pi(またはadafruit pitft 2.2" hat mini kit -320x240 2.2 "tft -tft-互換性のないタッチディスプレイ)のタッチスクリーンでadafruit 2.8" 320x240 tft w/ touchスクリーンで実行している場合、これを通過します。フラグ。-DADAFRUIT_HX8357D_PITFT=ON
:adafruit pitftを持っている場合-480x320 3.5 "Tft+タッチスクリーンをRaspberry Piディスプレイ用に組み立てて、このラインを追加します。-DFREEPLAYTECH_WAVESHARE32B=ON
:Freeplay CM3またはZeroデバイスで実行している場合は、このフラグを渡します。 (これは帽子ではありませんが、それでも事前に設定されたピンの割り当てです)-DWAVESHARE35B_ILI9486=ON
:指定されている場合、Waveshare 3.5 "480x320 ILI9486ディスプレイをターゲットにします。-DTONTEC_MZ61581=ON
:Tontec 3.5 "320x480 LCDディスプレイで実行している場合は、これを渡します。-DPIRATE_AUDIO_ST7789_HAT=ON
:指定されている場合、海賊オーディオ240x240、1.3inch ips lcd display hat for raspberry pi with st7789ディスプレイコントローラーをターゲット-DWAVESHARE_ST7789VW_HAT=ON
:指定されている場合、ST7789VWディスプレイコントローラーを備えたRaspberry PIの240x240、1.3inch IPS LCDディスプレイハットをターゲットにします。-DWAVESHARE_ST7735S_HAT=ON
:指定されている場合、ST7735Sディスプレイコントローラーを備えたRaspberry PIの128x128、1.44inch LCDディスプレイハットをターゲットにします。-DKEDEI_V63_MPI3501=ON
:指定されている場合、Kedei 3.5インチSPI TFTLCD 480*320をターゲットにします。 上記のリストから帽子を使用する代わりに、PIにワイヤを直接接続する場合は、以下の構成ディレクティブを使用する必要があります。ディスプレイを指定することに加えて、接続を配線したGPIOピンをFBCP-ILI9341に伝える必要があります。ディスプレイコントローラーを構成するには、次の1つを渡します。
-DILI9341=ON
:他の汎用ILI9341ディスプレイ、またはフリープレイテックCM3/ゼロデバイスではなくスタンドアロンであるWaveshare32Bディスプレイで実行している場合は、このフラグを渡します。-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ピンの割り当てをカスタマイズします。
-DGPIO_TFT_DATA_CONTROL=number
:4線SPI通信でデータ/コントロール(DC)ラインに使用するGPIOピンを指定/オーバーライドします。このピン番号は、BCMピン番号で指定されています。データ/コントロールラインがない3線SPIディスプレイがある場合は、この値を-1 、IE -DGPIO_TFT_DATA_CONTROL=-1
に設定して、FBCP-ILI9341に3ワイヤ( "9ビット")SPIをターゲットにします。コミュニケーション。-DGPIO_TFT_RESET_PIN=number
:表示リセットラインに使用するgpioピンを指定/オーバーライドします。このピン番号は、BCMピン番号で指定されています。省略した場合、ディスプレイにはリセットピンがなく、常にオンになっていると想定されています。-DGPIO_TFT_BACKLIGHT=number
:ディスプレイバックライトラインに使用するgpioピンを指定/オーバーライドします。このピン番号は、BCMピン番号で指定されています。省略した場合、ディスプレイにはGPIO制御のバックライトピンがなく、常にオンになっていると想定されています。これを設定する場合は、 config.h
の#define BACKLIGHT_CONTROL
オプションも参照してください。FBCP-ILI9341は常にハードウェアSPI0ポートを使用しているため、MISO、MOSI、CLK、CE0ピンは常に同じであり、変更できません。味oピンは実際には(少なくとも現時点では)使用されていないため、それを接続するだけでスキップできます。ディスプレイがチップイネーブルラインを無視する不正なものである場合、それを接続することも省略したり、配線を簡素化するのが難しい場合(ディスプレイに応じて)接続して地面に接続することで逃げることもできます。
ディスプレイから優れたパフォーマンスを発揮するために、レーティングされた速度仕様をはるかに上回るディスプレイを駆動します(定格仕様は、ディスプレイに応じて約10fpsを生成します)。このため、製造バリアルのために各ディスプレイコピーが異なる最大速度に達するため、ディスプレイを駆動するターゲット速度を明示的に構成する必要があります。 FBCP-ILI9341が使用する「デフォルト速度」はありません。速度の設定は、オプションを介して実行されます
-DSPI_BUS_CLOCK_DIVISOR=even_number
:/boot /boot/config.txt
boot /core_freq =オプションとともにクロックディバイザー番号を設定します。 SPI_frequency = core_freq/divisor
。 SPI_BUS_CLOCK_DIVISOR
偶数でなければなりません。デフォルトのPI 3Bおよびゼロ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モデルA、PIモデルB、コンピューティングモジュール1、PIゼロ/ゼロW)しかないPIで実行されている場合は、このオプションを渡します。存在しない場合は、自動検出されます。-DARMV6Z=ON
:このオプションを渡して、ARMV6Z命令セット(PI 1A、1A+、1B、1B+、ゼロ、ゼロW)を特別に最適化します。存在しない場合は、自動検出されます。-DARMV7A=ON
:このオプションを渡して、ARMV7-A命令セット(PI 2B <rev 1.2)に特に最適化します。存在しない場合は、自動検出されます。-DARMV8A=ON
:このオプションを渡して、ARMV8-A命令セット(PI 2B> = Rev。1.2、3B、3B+、CM3、CM3 Lite、4B、CM4、PI400)に特に最適化します。存在しない場合は、自動検出されます。 次のビルドオプションは、すべてのディスプレイとPIボードの一般的なものであり、ビルドをさらにカスタマイズします。
-DBACKLIGHT_CONTROL=ON
:設定されている場合、FBCP-ILI9341を有効にして、指定されたバックライトピンのディスプレイバックライトを制御します。ディスプレイは、画面上の非アクティブな期間の後に眠ります。そうでない場合、バックライトは触れられません。-DDISPLAY_CROPPED_INSTEAD_OF_SCALING=ON
:設定され、ソースビデオフレームがSPIディスプレイビデオ解像度よりも大きい場合、ソースビデオは、スケーリングするのではなく、すべての方向に一部を切り取ることにより、SPIディスプレイに表示されます。-DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON
:ソースビデオをSPIディスプレイにスケーリングすると、スケーリングはアスペクト比に続いてデフォルトで実行され、必要に応じてレターボックス/ピラーボックスを追加します。これが設定されている場合、ストレッチングは壊れたアスペクト比が実行されます。-DSTATISTICS=number
:画面上に表示するオーバーレイ統計のレベルを指定します。 0:無効、1:有効、2:有効になり、フレームレート間隔グラフを表示します。デフォルト値は1(有効)です。-DUSE_DMA_TRANSFERS=OFF
:指定されている場合は、DMA転送を使用して(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
:このオプションが渡された場合、ピクセルの色の値の解釈が逆になります(White = 0、Black = 31/63)。デフォルト:Black = 0、White = 31/63。ディスプレイ画像が実際の色のネガティブのように見える場合は、このオプションを渡します。-DDISPLAY_ROTATE_180_DEGREES=ON
:設定されている場合、ディスプレイは180度回転します。これはHDMI出力に影響を及ぼさず、SPI表示出力のみが出力されます。-DLOW_BATTERY_PIN=<num>
:バッテリー状態を取得するためにポーリングできるGPIOピンを指定します。デフォルトでは、これが設定されている場合、ピンが低く引っ張られている場合、低いバッテリーアイコンが表示されます(これを微調整できる方法については、 config.h
参照)。上記のCmakeディレクティブに加えて、コードベースの周りに散らばっているさまざまな定義があります。これは、主にConfig.hで、異なるランタイムオプションを制御します。それらを直接編集して、プログラムの動作をさらに調整します。特に、セットアップを終えた後、CMake構成ラインで-DSTATISTICS=0
オプションで構築することをお勧めします。
ILI9341コントローラーを備えたRaspberry PiのタッチスクリーンW/タッチスクリーンを使用している場合、構築および実行するために入力するものの完全な例を次に示します。
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
を指定して、ディスプレイの実行を少し遅くするか、DMAが問題になる場合は-DUSE_DMA_TRANSFERS=OFF
でトラブルシューティングを試してみてください。 ILI9341よりも別のディスプレイコントローラーを使用している場合、30または40などのはるかに高い値を使用する必要がある場合があります。 Cmakeオプションを変更するときは、 build
ディレクトリを再整理または再作成することなく、CMakeディレクティブラインを再発行できます。ただし、古い設定を覚えておくことを避けるために、オプションの変更の間にファイルcmakecache.txtを手動で削除する必要がある場合があります。
ゼロから完全な再構築を行いたい場合は、 rm -rf build
ビルドディレクトリを削除し、クリーンな再構築をゼロから再作成することができます。このディレクトリの名前や場所について特別なものは何もありません。これは私の通常のコンベンションです。また、FBCP-ILI9341ディレクトリに比べて他のディレクトリでビルドを行うこともできます。
起動時に起動するようにドライバーを設定するには、 sudo
モードでファイル/etc/rc.local
を編集し、行を追加します
sudo /path/to/fbcp-ili9341/build/fbcp-ili9341 &
最後まで。必要なアンパサンド&
その行の終わりに注意してください。
たとえば、上記のコマンドラインの手順を使用してビルドした場合、ファイル/etc/rc.local
を受け取ります
sudo /home/pi/fbcp-ili9341/build/fbcp-ili9341 &
Raspberry PIインストールのユーザー名がデフォルトのpi
以外のものである場合、それに応じてディレクトリを変更して、ユーザーのホームディレクトリを指してください。 ( pwd
使用して、端末の現在のディレクトリを見つけます)
systemd
を使用してディスプレイドライバーを起動しますまたは、 /etc/rc.local
を変更する代わりに、以下のように提供されたsystemd
ユニットファイルを使用します。
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
フレームバッファーのサイズがディスプレイの解像度と異なる場合、ソースビデオサイズはデフォルトで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のコア周波数( core_freq
IN /boot/config.txt
)とSPI周辺CDIV
(クロックディバイダー)設定の2つの個別のパラメーターから派生しています。合わせて、結果のSPIバス速度は、式SPI_speed=core_freq/CDIV
で計算されます。
ディスプレイをできるだけ速く実行するように最適化するには、
cmakeコマンドラインのディレクティブ-DSPI_BUS_CLOCK_DIVISOR=number
を渡して、 CDIV
値を調整します。考えられる8
4
偶数2
...
6
。 CDIV
SPI_speed
の式の分母に表示されるため、値が小さくなるとバスの速度が高くなりますが、値が高いほどディスプレイが遅くなります。最初は、ディスプレイがどれだけ速く実行できるかわからない場合は、 -DSPI_BUS_CLOCK_DIVISOR=30
などの安全な高設定から始めて、ディスプレイが対処できる最大速度を見つけるために、より小さな数字に進みます。さまざまなディスプレイの特定の観測された最大バス速度については、READMEの最後にあるテーブルを参照してください。
ターボスピードを確保します。これは、優れたフレームレートにとって重要です。 Raspberry Pi 3モデルBでは、BCM2835コアは、PIに十分な電力が供給されている場合、CPU温度が熱制限を超えない場合、400MHzでデフォルトで実行されます( 400/CDIV
MHz SPI速度になります)。 CPUがアイドル状態である場合、または電圧が低い場合、BCM2835コアは代わりにターボ250MHzの状態に戻り、 250/CDIV
MHz SPI速度になります。 400MHz対非ターボ250MHzがより帯域幅の +60%に出てくるため、パフォーマンスに対するターボ速度のこの効果は重要です。 Quake、Sonic、またはTyrianで60fpsを取得するには、このターボ周波数が必要になることがよくありますが、Eg NESとC64エミュレートゲームは、ストック250MHzでも60fpsに達することがよくあります。何らかの理由で、十分な電力を供給する必要がある場合でも、何らかの理由で電圧保護がキックする場合、ファイル/boot/config.txt
で値をavoid_warnings=2
ことにより、低電圧が存在する場合、強制的に電圧が存在する場合は、強制されるターボを強制することができます。
おそらく少し直感に反して、コアを下着します。デフォルトのターボ400MHzよりも小さなコア周波数を設定すると、より小さなクロック仕切りを使用して、結果として生じるSPIバス速度が高くなります。たとえば、デフォルトのcore_freq=400
spi CDIV=8
作品(SPIバス速度400MHz/8=50MHz
になります)がある場合、 CDIV=6
そうではありません( 400MHz/6=66.67MHz
多すぎました)、 core_freq=360
を下げてみることができますcore_freq=360
およびCDIV=6
設定して360MHz/6=60MHz
の効果的なSPIバス速度を取得します。 core_freq=
バランスとCDIV
オプションにより、ディスプレイコントローラーが許容できる最後の数kHzまでの最大SPIバス速度を見つけることができます。反対の方向とオーバークロックを試すこともできますが、もちろん、オーバークロックするときに起こるすべての問題があります。下着には、PIの実行が全体的に遅くなるという欠点があるため、これは確かにトレードオフです。
一方、CPU時間FBCP-ILI9341が使用できる量を制御することが望ましいです。デフォルトのビルド設定は、PI 3Bの電力消費を犠牲にしてディスプレイリフレッシュレートを最大化するために調整されています。 Pi Zeroでは、反対が完了します。つまり、デフォルトでは、ドライバーは最大のディスプレイアップデート速度ではなく、バッテリーの節約を最適化します。次のオプションは、これら2つのバランスをとるために制御できます。
CPU使用とパフォーマンスの側面を制御する主なオプションは、 config.h
のオプション#define ALL_TASKS_SHOULD_DMA
です。このオプションを有効にすると、CPUの使用量が大幅に削減されます。このオプションが無効になっている場合、SPIバスの使用率は最大化されますが、CPUの使用量は最大80%〜120%になります。このオプションが有効になっている場合、CPUの使用量は一般に最大約15%〜30%です。最大のCPU使用は、ビデオを視聴したり、速い動きのゲームをプレイするときに発生します。画面に何も変わっていない場合、ドライバーのCPU消費は0〜5%近くに低下するはずです。デフォルトでは、 #define ALL_TASKS_SHOULD_DMA
pi zeroで有効になりますが、pi 3bで無効になります。
cmakeオプション-DUSE_DMA_TRANSFERS=ON
より低いCPU使用のために常に有効にする必要があります。 DMA転送が無効になっている場合、ドライバーはポーリングされたSPIモードで実行され、一般にCPU時間の完全な単一コアを利用します。 DMA転送が問題を引き起こしている場合は、DMA送信を調整して、 -DDMA_TX_CHANNEL=<num>
および-DDMA_RX_CHANNEL=<num>
cmakeオプションを使用してSPI通信に使用するチャネルを受信してみてください。
Statistics Overlayは、実行状態に関する非常に詳細な情報を印刷します。 -DSTATISTICS=0
でオーバーレイを無効にすると、cmakeのオプションがパフォーマンスを向上させ、CPUの使用を削減します。統計を印刷し続けたい場合は、 #define STATISTICS_REFRESH_INTERVAL <timeInMicroseconds>
config.hのオプションで間隔を増やすことができます。
#define USE_GPU_VSYNC
を有効にすると、CPUの消費が削減されますが、raspberrypi/userland#440のため、st音を引き起こす可能性があります。 #defined USE_GPU_VSYNC
の無効化の生成は少なくなりますが、raspberrypi/userland#440のため、CPUの消費電力が増加します。
オプション#define SELF_SYNCHRONIZE_TO_GPU_VSYNC_PRODUCED_NEW_FRAMES
は#define USE_GPU_VSYNC
と併用して使用できます。この設定を有効または無効にして実験してみてください。
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ディスプレイバスが本当に非常に速く実行できる場合(またはフレームレートを気にしないが、CPU使用量がほぼ低い場合) config.h
#define UPDATE_FRAMES_WITHOUT_DIFFING
オプションをconfidive deltaディフェンスを控えることができます完全にオプション。これにより、最小限の全体的なCPU使用量のために、Naive Full Frame Updatesに戻ります。
オプション#define RUN_WITH_REALTIME_THREAD_PRIORITY
を有効にすることができ、ドライバーをリアルタイムプロセスの優先順位で実行することができます。ただし、これはシステムをロックアップできますが、それでも高度な実験に利用できるようになりました。
display.h
には、オプション#define TARGET_FRAME_RATE <number>
があります。これを30などのより少ない値に設定すると、リフレッシュレートを取引してCPUの消費を削減します。
FBCP-ILI9341の心地よい側面は、頭上のレイテンシがほとんどないことです。119HzのリフレッシュILI9341ディスプレイで、FBCP-ILI9341は、GPIO入力から16.66ミリ秒未満の画面への応答としてピクセルを取得します。私は120FPS録音カメラしか持っていないので、それよりも簡単に測定することはできませんが、スローモーションビデオ映像の大まかな統計的推定は、この遅延が2〜3ミリ秒ほど低く、〜8.4msecsパネルのリフレッシュレートによって支配される可能性があることを示唆していますILI9341の。
これは、ゲーム内のレイテンシを表示するための全体的な入力が非常に即時になるという意味ではありません。 RetropieでNESエミュレートされたゲームを簡単にテストすると、約60〜80ミリ秒の合計遅延が示唆されています。このレイテンシは、NESゲームエミュレーターのオーバーヘッドとLinux、DispmanxおよびGPUレンダリング、およびGPU FrameBuffer Snapshottingによって追加される追加のレイテンシによって引き起こされます。 (DispManxとGPUスタックをバイパスし、GPIO入力とアプリケーションのロジックをFBCP-ILI9341に直接リンクする静的ライブラリとしてFBCP-ILI9341を実行した場合、全体的なレイテンシのこの数MSECに到達することができます。上記のGPIO入力ビデオ)
興味深いことに、FBCP-ILI9341は、安価な3.5インチのKedei HDMIディスプレイよりも約33msecsです。これがKedei HDMIディスプレイの結果であるかどうか、またはPIに接続されたすべてのHDMIディスプレイが同様に接続されているかどうかはわかりません。レイテンシーオーバーヘッド。また、SPIがPIのDPI接続ディスプレイとどのように比較されるかです。
残念ながら、SPI接続ディスプレイの制限は、SPIモードで実行されているときにVSYNCライン信号がディスプレイコントローラーで使用できないため、ディスプレイのSPIバスの帯域幅が十分に速かったとしても、VSYNCロックされた更新を実行することはできません。 。たとえば、私が持っている4つのILI9341ディスプレイはすべて75MHzよりも速く実行できます。そのため、SPIバスの帯域幅はすべてVSYNC間隔未満でフルフレームを更新できますが、更新を同期することはできません。 vsync since the display controllers do not report it. (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. Some ideas:
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 | (untested) | (untested) |
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.