[esp32s3] 800x480 4" ipsディスプレイ 16ビットパラレル接続

# はじめに

<img width="300" alt="4-LCD-800x480-ips-arduino-mega-2560_1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/c2117f58-7dc7-2460-d197-8efe2e7d0f5c.jpeg">

**アリエク**で10US$弱で購入できる 800x480 4インチ ipsディスプレイ[[MAR4018](http://www.lcdwiki.com/4.0inch_Arduino_Display-Mega2560_NT35510)]をESP32-S3で16ビットパラレル接続したのでピンアサインなどをメモしておく。

|おもて|<img width="200" alt="4-LCD-800x480-ips-arduino-mega-2560_2.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/5220e7ae-0c8e-5723-75ba-acf6051f3ec8.jpeg">|
|-|-|
|うら|<img width="200" alt="4-LCD-800x480-ips-arduino-mega-2560_3.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/1bb891a1-2b87-8696-5d77-eff94598dec9.jpeg">|

16ビットパラレル接続の他、8ビットパラレル接続も可能。
タッチパネルにも対応し、SDカードスロットも装備。

5V駆動だが、レベルコンバーターが実装されていて3.3V信号でも扱える。


# オリジナルPCB

30本ほどの配線が必要になるため、ブレッドボードやユニバーサル基板ではなく、専用プリント基板を設計した。レジストはLCDと同じ<b><font color=RED>赤</font></b>。

USB-CからLCDの5Vと、LDOレギュレータ[**AM1117-3.3V**]を通してESP32S3の3.3V電源を供給。

基板上に**RESET**/**BOOT**ボタンとRGBLED[**WS2812C-2020**]を装備。

|基板デザイン|<img width=100" alt="800x480_pcb_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/18e41836-b3fc-714d-5e14-fb1231b5274c.png"> <img width="100" alt="800x480_pcb.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/be183c71-9c2b-0f91-3ace-9eb2f4f4e078.png">|
|-|-|
|実装後|<img width="100" alt="IMG_1894.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/e6dab8a0-d2af-0b40-6848-fa1666ce8b8d.png"> <img width="300" alt="IMG_1895.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/461c144e-cf32-a8ef-68da-eba8aeb79eee.png">|


2層基板だが、部品実装は表面のみ。自作のリフロープレートにて、ESP32s3も含めて、すべての部品を一度にハンダ付けした。一発で問題なく動作してホッとした。

# ピンアサイン

専用PCBを設計する上で配線の取り回しを熟考し次の接続とした。

|PIN#|LCD Pin|ESP32S3|PIN#|LCD Pin|ESP32S3|
|:-:|:-:|:-:|:-:|:-:|:-:|
|1|5V|(5v)|2|5V|(5v)|
|3|DB8|IO2|4|DB9|IO4|
|5|DB10|IO42|6|DB11|IO5|
|7|DB12|IO41|8|DB13|IO6|
|9|DB14|IO40|10|DB15|IO7|
|11|DB7|IO39|12|DB6|IO15|
|13|DB5|IO38|14|DB4|IO16|
|15|DB3|IO37|16|DB2|IO17|
|17|DB1|IO36|18|DB0|IO18|
|19|RS|IO11|20|WR|IO8|
|21|CS|IO10|22|RST|IO9|
|23|NC|-|24|RD|IO12|
|25|T_IRQ|IO13|26|NC|-|
|27|NC|-|28|NC|-|
|29|SD_CS|IO14|30|NC|-|
|31|MISO|IO47|32|MOSI|IO21|
|33|CLK|IO35|34|T_CS|IO48|
|35|GND|GND|36|GND|GND|

IO1をWS2812CのDINに使用
TX/RXとD-/D+を除き、未使用ピンは、ストラップピン（IO3, IO45, IO46）のみ


# デバイス定義

[LovyanGFX](https://github.com/lovyan03/LovyanGFX)のデバイス定義を以下に示す。

```c++:LGFX_NT35510_800x480.h
// https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/2_user_setting/2_user_setting.ino
class LGFX_NT35510_800x480 : public lgfx::LGFX_Device {
  lgfx::Panel_NT35510  _panel_instance;
  lgfx::Bus_Parallel16 _bus_instance;   //16bit Parallelのインスタンス(ESP32s3)
  lgfx::Touch_XPT2046  _touch_instance;

public:
  LGFX_NT35510_800x480(void) {               // バス制御の設定を行います。
    auto cfg = _bus_instance.config();       // バス設定用の構造体を取得します。
    // 16ビットパラレルバスの設定
    cfg.freq_write = 20000000;               // 送信クロック(最大20MHz,80MHzを整数割の値に丸める)
    cfg.pin_wr  =  8;                        // WR を接続しているピン番号
    cfg.pin_rd  = 12;                        // RD を接続しているピン番号
    cfg.pin_rs  = 11;                        // RS(D/C)を接続しているピン番号
    cfg.pin_d0  = 18;                        // D0 を接続しているピン番号
    cfg.pin_d1  = 36;                        // D1 を接続しているピン番号
    cfg.pin_d2  = 17;                        // D2 を接続しているピン番号
    cfg.pin_d3  = 37;                        // D3 を接続しているピン番号
    cfg.pin_d4  = 16;                        // D4 を接続しているピン番号
    cfg.pin_d5  = 38;                        // D5 を接続しているピン番号
    cfg.pin_d6  = 15;                        // D6 を接続しているピン番号s
    cfg.pin_d7  = 39;                        // D7 を接続しているピン番号
    cfg.pin_d8  =  2;                        // D8 を接続しているピン番号
    cfg.pin_d9  =  4;                        // D9 を接続しているピン番号
    cfg.pin_d10 = 42;                        // D10を接続しているピン番号
    cfg.pin_d11 =  5;                        // D11を接続しているピン番号
    cfg.pin_d12 = 41;                        // D12を接続しているピン番号
    cfg.pin_d13 =  6;                        // D13を接続しているピン番号
    cfg.pin_d14 = 40;                        // D14を接続しているピン番号
    cfg.pin_d15 =  7;                        // D15を接続しているピン番号
    _bus_instance.config(cfg);               // 設定値をバスに反映します。
    _panel_instance.setBus(&_bus_instance);  // バスをパネルにセットします。
    {                                        // 表示パネル制御の設定
      auto cfg = _panel_instance.config();   // 表示パネル設定用の構造体を取得します。
      cfg.pin_cs   = 10;                     // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst  =  9;                     // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy = -1;                     // BUSYが接続されているピン番号 (-1 = disable)
      cfg.memory_width = 480;                // ドライバICがサポートしている最大の幅
      cfg.memory_height = 800;               // ドライバICがサポートしている最大の高さ
      cfg.panel_width = 480;                 // 実際に表示可能な幅
      cfg.panel_height = 800;                // 実際に表示可能な高さ
      cfg.offset_x = 0;                      // パネルのX方向オフセット量
      cfg.offset_y = 0;                      // パネルのY方向オフセット量
      cfg.offset_rotation = 0;               // 回転方向の値のオフセット 0~7 (4~7は上下反転)
      cfg.dummy_read_pixel = 8;              // ピクセル読出し前のダミーリードのビット数
      cfg.dummy_read_bits = 1;               // ピクセル以外のデータ読出し前のダミーリードのビット数
      cfg.readable = false;                  // データ読出しが可能な場合 trueに設定
      cfg.invert = false;                    // パネルの明暗が反転してしまう場合 trueに設定
      cfg.rgb_order = true;                  // パネルの赤と青が入れ替わってしまう場合 trueに設定
      cfg.dlen_16bit = true;                 // データ長を16bit単位で送信するパネルの場合trueに設定
      cfg.bus_shared = true;                 // SDカードとバス共有はtrueに設定
      _panel_instance.config(cfg);
    }

    {  // タッチスクリーン制御の設定を行います。（必要なければ削除）
      auto cfg = _touch_instance.config();
      cfg.x_min = 300;          // タッチスクリーンから得られる最小のX値(生の値)
      cfg.x_max = 3800;         // タッチスクリーンから得られる最大のX値(生の値)
      cfg.y_min = 180;          // タッチスクリーンから得られる最小のY値(生の値)
      cfg.y_max = 3900;         // タッチスクリーンから得られる最大のY値(生の値)
      cfg.pin_int = 13;         // INTが接続されているピン番号
      cfg.bus_shared = false;   // 画面と共通のバスを使用している場合 trueを設定
      cfg.offset_rotation = 6;  // 表示とタッチの向きのが一致しない場合の調整 0~7の値で設定
      // SPI接続の場合
      cfg.spi_host = SPI2_HOST;  // 使用するSPIを選択 (HSPI_HOST or VSPI_HOST)
      cfg.freq = 1000000;        // SPIクロックを設定, Max 2.5MHz, 8bit(7bit) mode
      cfg.pin_sclk = 35;         // SCLKが接続されているピン番号, TP CLK
      cfg.pin_mosi = 21;         // MOSIが接続されているピン番号, TP DIN
      cfg.pin_miso = 47;         // MISOが接続されているピン番号, TP DOUT
      cfg.pin_cs   = 48;         // CS  が接続されているピン番号, TP CS
      _touch_instance.config(cfg);
      _panel_instance.setTouch(&_touch_instance);  // タッチスクリーンをパネルにセットします。
    }

    setPanel(&_panel_instance);  // 使用するパネルをセットします。
  }
};
```

# デモ動画

（文末の参考URLに記載した）macsbugさんのブログで公開されていた迷路プログラムを参考にさせて頂きました。

<iframe width="806" height="440" src="https://www.youtube.com/embed/dNdyBw-GrQY?rel=0" title="800x480 4&quot; ipsディスプレイ 16ビットパラレル接続 デモ" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# おわりに

ワイヤレスのサイネージとして使おうかと思います。

<hr>
参考URL：//macsbug.wordpress.com/2022/12/31/mar4018-and-esp32-s3/

https://macsbug.wordpress.com/2022/12/31/mar4018-and-esp32-s3/