ILI9341(SPI)をRaspBerryPiのコンソールとして使う


fbtft+flexfbを使えば、SPI接続のTFTモジュールをコンソールとして使うことができます。
flexfbについては、こちらに 詳しい解説が有ります。

今までfbtft+flexfbを使うには、カーネルのコンパイルが必要と思い込んでいましたが、
OSAKANA TAROさんのこちらの ページで、最近のカーネルでは、コンパイルは必要ないことが分かりました。
そこで、ILI9341の2.4インチTFT/2.8インチTFTを、RaspberryPiとOrangePiのコンソールにしてみまし た。





RaspberryPi(Raspbian)とOrangePi(Armbian)では少し手順が違います。
今回はRaspberryPi(Raspbian)の手順を紹介します。

まずはお試しで、コンソールとして使えるかどうか試してみます。
RaspberryとTFTの結線は、以下の様になります。
ILI9341 TFT Rpi(Pin#)
MISO N/C
LED 3.3V(※1)
SCK SCLK(23)
MOSI MOSI(19)
D/C GPIO2(03)(※2)
RES GPIO3(05)(※2)
CS CS0(24)
GND GND
VCC 3.3V

(※1)バックライトが明るすぎるときは100Ω程度の抵抗を挟んで下さい
(※2)このピンは変更できますが、変更した場合、モジュールロード時に指定するgpiosパラメータが変わります。

最初に raspi-config を使ってSPIを有効にします。

次に、fbtft_deviceモジュールを読み込みます。
D/CはGPIO2、RESETはGPIO3を使うので、[gpios=dc:2,reset:3]となります。(ここがキモです)
sudo modprobe fbtft_device name=flexfb gpios=dc:2,reset:3 speed=3200000

dmesgには以下のように表示されます。
[   99.193056] fbtft: module is from the staging directory, the quality is unknown, you have been warned.
[   99.200957] fbtft_device: module is from the staging directory, the quality is unknown, you have been warned.
[   99.206008] spidev spi0.0: spidev spi0.0 500kHz 8 bits mode=0x00
[   99.206047] spidev spi0.1: spidev spi0.1 500kHz 8 bits mode=0x00
[   99.206109] bcm2708_fb soc:fb: soc:fb id=-1 pdata? no
[   99.206185] spidev spi0.0: Deleting spi0.0
[   99.208527] fbtft_device: GPIOS used by 'flexfb':
[   99.208560] fbtft_device: 'dc' = GPIO2
[   99.208572] fbtft_device: 'reset' = GPIO3
[   99.208599] spidev spi0.1: spidev spi0.1 500kHz 8 bits mode=0x00
[   99.208624] spi spi0.0: flexfb spi0.0 3200kHz 8 bits mode=0x00

次に、flexfbモジュールを読み込みます。
sudo modprobe flexfb width=320 height=240 buswidth=8 init=\
-1,0x01,-2,5,\
-1,0x28,\
-1,0x36,0x38,\
-1,0x3A,0x55,\
-1,0x11,-2,120,\
-1,0x29,-2,20,\
-3

initパラメータの構文はこち らに解説が有りますが、モジュールに対する初期化シーケンスを表しています。
こ ちらがfbtftに組み込まれているILI9341の初期化コードです。
static int init_display(struct fbtft_par *par)
{
    fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);

    par->fbtftops.reset(par);

    /* startup sequence for MI0283QT-9A */
    write_reg(par, 0x01); /* software reset */
    mdelay(5);
    write_reg(par, 0x28); /* display off */
    /* --------------------------------------------------------- */
    write_reg(par, 0xCF, 0x00, 0x83, 0x30);
    write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81);
    write_reg(par, 0xE8, 0x85, 0x01, 0x79);
    write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02);
    write_reg(par, 0xF7, 0x20);
    write_reg(par, 0xEA, 0x00, 0x00);
    /* ------------power control-------------------------------- */
    write_reg(par, 0xC0, 0x26);
    write_reg(par, 0xC1, 0x11);
    /* ------------VCOM --------- */
    write_reg(par, 0xC5, 0x35, 0x3E);
    write_reg(par, 0xC7, 0xBE);
    /* ------------memory access control------------------------ */
    write_reg(par, 0x3A, 0x55); /* 16bit pixel */
    /* ------------frame rate----------------------------------- */
    write_reg(par, 0xB1, 0x00, 0x1B);
    /* ------------Gamma---------------------------------------- */
    /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */
    write_reg(par, 0x26, 0x01);
    /* ------------display-------------------------------------- */
    write_reg(par, 0xB7, 0x07); /* entry mode set */
    write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
    write_reg(par, 0x11); /* sleep out */
    mdelay(100);
    write_reg(par, 0x29); /* display on */
    mdelay(20);

    return 0;
}

上のコードをfbtftの形式に変換するとこのようになります。
ILI9341のデータシートに記載がないパラメータと、デフォルト値のパラメータを省くとfbtftのinitパラメータとなります。
init=\
-1,0x01,\
-2,5,\
-1,0x28,\
-1,0xCF,0x00,0x83,0x30,\
-1,0xED,0x64,0x03,0x12,0x81,\
-1,0xE8,0x85,0x01,0x79,\
-1,0xCB,0x39,0x2c,0x00,0x34,0x02,\
-1,0xF7,0x20,\
-1,0xEA,0x00,0x00,\
-1,0xC0,0x26,\
-1,0xC1,0x11,\
-1,0xC5,0x35,0x3E,\
-1,0xC7,0xBE,\
-1,0x3A,0x55,\
-1,0xB1,0x00,0x1B,\
-1,0x26,0x01,\
-1,0xB7,0x07,\
-1,0xB6,0x0a,0x82,0x27,0x00,\
-1,0x11,\
-2,100,\
-1,0x29,\
-2,20,\
-3

新しいデバイス[/dev/fb1]ができます。fbsetで内容を確認することができます。
pi@raspberrypi:~ $ ls /dev/fb*
/dev/fb0  /dev/fb1
pi@raspberrypi:~ $ fbset -i -fb /dev/fb1

mode "320x240"
    geometry 320 240 320 240 16
    timings 0 0 0 0 0 0 0
    nonstd 1
    rgba 5/11,6/5,5/0,0/0
endmode

Frame buffer device information:
    Name        : flexfb
    Address     : 0
    Size        : 153600
    Type        : PACKED PIXELS
    Visual      : TRUECOLOR
    XPanStep    : 0
    YPanStep    : 0
    YWrapStep   : 0
    LineLength  : 640
    Accelerator : No
pi@raspberrypi:~ $

最後に表示テストです。
con2fbmap 1 1

これでTFTがコンソールになります。

お試しでうまく動いたら、次は起動時にモジュールを読み込むことにします。
以下の2つのファイルを作ります。

@/etc/modules-load.d/fbtft.conf

spi-bcm2835
flexfb
fbtft_device

flexfb と fbtft_device の順番は逆でも構いません。

A/etc/modprobe.d/fbtft.conf

options flexfb width=320 height=240 buswidth=8 init=\
-1,0x01,-2,5,\
-1,0x28,\
-1,0x36,0x38,\
-1,0x3A,0x55,\
-1,0x11,-2,120,\
-1,0x29,-2,20,\
-3
options fbtft_device name=flexfb gpios=dc:2,reset:3 speed=3200000

/boot/cmdline.txt の末尾に[fbcon=map:1]を追加します。

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait fbcon=map:1

再起動すると、起動時のシーケンスがずらずらとTFTに表示され、ログインプロンプトが表示されます。

fbconのパラメータについてはこちらで 紹介されています。
フォントサイズの変更(fbcon=font:<name>)や、縦画面への変更(fbcon=rotate:<n>) が
できると紹介されているページが多いですが、実際に試してみるとこれらの変更は動きませんでした。



縦画面への変更

縦画面への変更はモジュールパラメータを変更します。
sudo modprobe fbtft_device name=flexfb gpios=dc:2,reset:3 speed=3200000 rotate=90

initパラメータは36hのレジスターを変更し、アドレスの使い方を変更しています。
この辺りのことはコントローラのデータシートとの格闘になります。
sudo modprobe flexfb width=320 height=240 buswidth=8 init=\
-1,0x01,-2,5,\
-1,0x28,\
-1,0x36,0x58,\
-1,0x3A,0x55,\
-1,0x11,-2,100,\
-1,0x29,-2,20,\
-3





フォントサイズの変更

FrameBufferのフォントサイズの変更は以下の手順で行います。
sudo dpkg-reconfigure console-setup

これ以降は画面の操作になります。






この画面でフォントを指定します。
OKで直ちにフォントサイズが反映されます。再起動は不要です。
変更した結果は「/etc/default/console-setup」に保存されます。




次回はOrangePi(Armbian)での手順を紹介しま す。