Raspberry Pi Zero(W, WH)でPiTFTを使う


PiZero W + 2.4インチPiTFT

PiTFTは[Adafruitさんのチュートリアル](https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/easy-install-2)にあるインストールスクリプトを走らせると使えるようになりますが、カーネルを入れ替えてしまうため、他に独自に使いたいカーネルモジュールがあると共存が難しくなります。
これらに頼らず、Device Tree等を自分で設定しきれば最新のインストールイメージでも使えるようになるので、その手法を紹介します。

2.2インチ、2.4インチ、2.8インチ、3.5インチ(いずれもResistive Touchscreen)で動作確認を取りました。2.8インチのCapacitive Touchscreenは描画は確認しましたが、タッチスクリーンのドライバを動作確認がとりきれておらず、本稿の対象外です。


# 事前準備
PiZero(W)とPiTFTを用意します。

## PiTFT
いろんなサイズが出ていますが、現時点のオススメは[2.4インチ](https://www.adafruit.com/product/2455)です。理由は2つ。

### 横幅がジャストサイズ

上側2つの穴でネジ止めがしっかりできる上に、コンパクトなケースが設計できます。2.2インチも同じ横幅ですが、タッチスクリーンがないので、ボタン操作を前提でプログラムを書く必要があります。

![PiTFT-02.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/aaa996e9-c12a-6b36-666f-3bef2c0f2eea.jpeg)
斜めから

### 高さを抑えるのが容易

他のGPIOピンが横向きで使用できるので、背の低いピンヘッダ、ピンソケットでPiZeroとPiTFTを接続すれば、割とジャストの高さまで持って行けます。

![PiTFT-05.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/4fc76735-5cb2-bccb-ee72-17f95be55ace.jpeg)
横向きのGPIOピンにGPSをUART経由で接続しています

画像の2.4インチPiTFTは、別途購入した[秋月のロープロファイルピンヘッダ7.7mm](http://akizukidenshi.com/catalog/g/gC-10460/)とそれに合う[ピンソケット5.7mm](http://akizukidenshi.com/catalog/g/gC-02907/)を使っています。

2.4インチ、2.2インチは諸々の半田付けが必要なKitとして用意されているので、余分なコネクタを取り除く腕さえあれば直接接続する([AdafruitさんのPiGRRL Zeroチュートリアル](https://learn.adafruit.com/pigrrl-zero/pitft-to-pi-zero))等、さらなる調整ができます。

しかし、2.8インチ以上は、スルーされたピンが縦向きに付いているのと、それに合わせて背の高いピンヘッダ等やスイッチが予めついてしまっているので、PiZero(W)では使いにくいかと思います。

![PiTFT-03.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/d698160b-72c0-f84f-d6f7-df4d79950a09.jpeg)
左: 2.8インチ(Capacitive), 右: 3.5インチ(Resistive)

![PiTFT-04.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/709f614c-39f8-146a-34c1-402715f462ee.jpeg)
無理して外側のピンソケットを取り外しても直ちに使えない形状。(ピンボケしてます)


# PiTFTの認識

`raspi-config`でI2CとSPIをオンにしておいてください。
また、エディタはvimを使用していますので、適宜読み替えてください。

## 画面

何も設定せずにPiTFTを接続すると電源投入後、画面は白色になりますが、下記の設定が有効になると電源投入後、黒色になります。
また、HDMI用の/dev/fb0に加え、PiTFT用の/dev/fb1が出現します。

```
$ sudo vim /boot/config.txt

#以下は設定済みのはず(I2CとSPI)
dtparam=i2c_arm=on
dtparam=spi=on

#以下を追加
dtoverlay=pitft28-resistive,rotate=270,speed=32000000,fps=20
```

dtoverlayの設定値は下記スクリプト参照になりますが、以下の値になると思います。
https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper

|設定値|説明|
|-------|----|
|pitft22|PiTFT 2.2インチ (タッチスクリーンなしです)|
|pitft28-resistive|PiTFT 2.4, 2.8, 3.2インチ (解像度320x240のResistive Touchscreen)|
|pitft28-capacitive|PiTFT 2.8インチ (解像度320x240のCapacitive Touchscreen)|
|pitft35-resistive|PiTFT 3.5インチ (解像度480x320のResistive Touchscreen)|

また、rotateは画面の向きなので0、90、180、270のどれかに適宜変更してください。270は冒頭の写真にあるように、PiTFT2.4インチのボタンが下に来る向きになります。

## タッチスクリーン

### Resistive Touchscreen

/dev/input/event0で認識できます。

```
$ cat /dev/input/event0
```

PiTFTを適当に触ると何かしら出力されます。

### Capacitive Touchscreen

最新のカーネル4.9より、ドライバがft6236からedt-ft5x06に変わったようで、動かしきれていません。（反応はするのですが）


# コンソールの描画

コンソールを出力させます。Xが描画されればよいという場合は行わなくても構いません。

```
$ sudo vim /boot/cmdline.txt

#末尾にスペースを入れ、以下を追加。
#新しい行ではなく、1行目の最後に追加になります。
fbcon=map:10 fbcon=font:VGA8x8
```

fbcon=font:VGA8x8は小さなフォントを指定するために使っています。指定しなくても可能ですが、起動画面等で端が切れやすくなります。

![PiTFT-06.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/0a9b1f46-b289-eb33-2079-110eb2e7f0ea.jpeg)
fbcon=font:VGA8x8なし。行間がちょっと間延びした感じ。

![PiTFT-07.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/8e4a91de-f1b3-dbc5-f696-539b6efc63ef.jpeg)
fbcon=font:VGA8x8あり。行数は上記の倍以上になり、だいぶ詰め込んでいる感じ。

### さらにフォントを見やすくしたい場合

下記のコマンドでさらに設定可能です。
(/boot/cmdline.txtに記述した fbcon=font:VGA8x8 の設定は見なくなります)

```
$ sudo dpkg-reconfigure console-setup

UTF-8 -> Guess optimal character set -> Terminus -> 6x12 (framebuffer only)
```

こうなります。
![PiTFT-08.jpg](https://qiita-image-store.s3.amazonaws.com/0/100741/b36becef-8235-71d8-17c8-cb4500ac86b6.jpeg)


### 画面をブラックアウトさせない

下記コマンドで設定できます。blankオプションの後ろの数字は分単位で、0にするとブラックアウト無効になります。

```
$ sudo sh -c "TERM=linux setterm -blank 0 > /dev/tty0"
```

毎起動時に有効にしたい場合、

```
$ sudo vim /etc/rc.local

#最後にある`exit 0`の手前に記載
setterm -blank 0
```

設定値の確認は下記コマンドで行えますが、秒単位の数字が帰ってきます。

```
$ cat /sys/module/kernel/parameters/consoleblank
0
```

## タッチスクリーンの調整 (コンソール)

まず、下記を予めインストールします。

```
(tslibではなくlibts0)
$ sudo apt-get install evtest libts0 libts-bin
```

次にAdafruitさんのキャリブレーション用スクリプトを使います。
/etc/pointercalに正しい値を設定することが目標です。
しかしながら、2.8インチ用resistive(28r)の値が一部変なので修正します。

```
$ wget https://raw.githubusercontent.com/adafruit/PiTFT_Extras/master/pitft_touch_cal.py
$ vim pitft_touch_cal.py
#本プログラムはpython2用と古く、python3用に書き直す必要あり。後日掲載予定。

#0度用と270度用の最後にあるパラメータ'6553636'を'65536'に直す

#修正前
CAL_CONFIG['28r']['pointercal']['0']   = '4315 -49 -889068 18 5873 -1043172 6553636'
CAL_CONFIG['28r']['pointercal']['90']  = '-30 -5902 22077792 4360 -105 -1038814 65536'
CAL_CONFIG['28r']['pointercal']['180'] = '-4228 73 16353030 -60 -5888 22004262 65536'
CAL_CONFIG['28r']['pointercal']['270'] = '-69 5859 -829540 -4306 3 16564590 6553636'

#修正後
CAL_CONFIG['28r']['pointercal']['0']   = '4315 -49 -889068 18 5873 -1043172 65536'
CAL_CONFIG['28r']['pointercal']['90']  = '-30 -5902 22077792 4360 -105 -1038814 65536'
CAL_CONFIG['28r']['pointercal']['180'] = '-4228 73 16353030 -60 -5888 22004262 65536'
CAL_CONFIG['28r']['pointercal']['270'] = '-69 5859 -829540 -4306 3 16564590 65536'

$ sudo python2 pitft_touch_cal.py -t 28r -r 270

#実行例

---------------------------------
USING DISPLAY: 28r

---------------------------------
USING ROTATION: 270

---------------------------------
CURRENT CONFIGURATION

Current /etc/pointercal configuration:
-345 5756 517404 -4173 -38 16523678 65536 320 240 0

Current /etc/X11/xorg.conf.d/99-calibration.conf configuration:
Section "InputClass"
    Identifier      "calibration"
    MatchProduct    "stmpe-ts"
    Option  "Calibration"   "287 3739 3817 207"
    Option  "SwapAxes"      "1"
EndSection

---------------------------------
NEW CONFIGURATION

New /etc/pointercal configuration:
-69 5859 -829540 -4306 3 16564590 65536

New /etc/X11/xorg.conf.d/99-calibration.conf configuration:
Section "InputClass"
    Identifier      "calibration"
    MatchProduct    "stmpe-ts"
    Option  "Calibration"   "287 3739 3817 207"
    Option  "SwapAxes"      "1"
EndSection

Update current configuration to new configuration? [y/N]: y  # <-入力
---------------------------------

Updated /etc/pointercal
Updated /etc/X11/xorg.conf.d/99-calibration.conf 
```

動作確認をします。タッチした箇所にポインタが追従すればOKです。

```
$ sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/event0 ts_test
```

手動でキャリブレーションしたい場合は、以下のコマンドで実施します。

```
$ sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/event0 ts_calibrate
```

# X Window Systemの描画

Xを使わない場合は行わなくても構いません。
(Xを介さず直接描画するアプリを作っている場合等)

## 画面表示
PiTFTは/dev/fb1に対応するので(/dev/fb0はHDMI)、こちらにXを描画するように変更します。
raspi-configを使って、コンソール起動に変更後、デスクトップ起動に戻すと、勝手に設定ファイルが更新され/dev/fb0への起動に戻してしまうので、注意が必要です。

```

$ sudo vim /usr/share/X11/xorg.conf.d/99-fbturbo.conf

#/dev/fb0 を /dev/fb1 に変更
Section "Device"
        Identifier      "Allwinner A10/A13 FBDEV"
        Driver          "fbturbo"
        #Option          "fbdev" "/dev/fb0"
        Option          "fbdev" "/dev/fb1"
        Option          "SwapbuffersWait" "true"
EndSection
```

2021/11よりリリースされたRaspberry Pi OS bullseyeの場合、ディスプレイドライバーが標準でkmsになっているので、レガシードライバに戻します。
どうやら、この設定が有効な場合、起動時に /usr/share/X11/xorg.conf.d/99-fbturbo.conf を /usr/share/X11/xorg.conf.d/99-fbturbo.~ にリネームしてしまうようです。

```
$ sudo vim /boot/config.txt

# 以下をコメントアウト
#dtoverlay=vc4-kms-v3d
#max_framebuffers=2
```

## タッチスクリーンの調整 (X Window System)

こちらも[Adafruitさんのチュートリアル](https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/resistive-touchscreen-manual-install-calibrate)を辿ればできますが、最近のインストールイメージ(RASPBIAN JESSIE WITH DESKTOP以降)では、input周りが変更になったためxserver-xorg-input-evdevをインストールする必要があります。(公式FAQの最後の方に追加されて記載)
https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/help-faq#faq-20

```
$ sudo apt-get install xserver-xorg-input-evdev
```

/usr/share/X11/xorg.conf.d/ 下で新しく10-evdev.conf が作成されているはずです。また、40-libinput.confをリネームか削除してください。

```
$ cd /usr/share/X11/xorg.conf.d/
$ sudo mv 40-libinput.conf 40-libinput.conf~
```

コンソール編同様、Adafruitさんのキャリブレーションスクリプトを用います。
/etc/X11/xorg.conf.d/99-calibration.confに正しい値を反映させることが目標です。

```
$ wget https://raw.githubusercontent.com/adafruit/PiTFT_Extras/master/pitft_touch_cal.py
$ sudo python2 pitft_touch_cal.py

#実行例はコンソール編と同じなので省略
```