2.79inch 142×428 IPS TFT LCD with NV3007 Driver

縦(横?)に長いカラーLCDを探していたところ AliExpress で入手できるのがわかったのだが,どれも例外なくドライバーが NV3007 だった.これは使ったことがなくいつも使っているライブラリ(Lovyan GFX)も現状では NV3007 をサポートしていない.
とはいえ,とりあえずこれ(TFT LCDシリアルスクリーンディスプレイ、カラーnv3007ドライブ、2.79インチ、142×428を購入.

2.79inch 142×428 IPS TFT

NV3007 について調べたところ,描画コマンドはST7789などと同じで何とかなりそうな気がしたので,Lovyan GFX 用にヘッダファイルを作成することにした.ちょっと気楽に構えていたがそんな甘いものではなく初期化はかなり苦労してしまった.
最終的には下記のヘッダでうまく動作した.

/*-----------------------------------------
     Panel_NV3007.hpp
------------------------------------------*/
#pragma once

#include "Panel_LCD.hpp"

namespace lgfx
{
 inline namespace v1
 {
//-----------------------------------------
  struct Panel_NV3007  : public Panel_LCD
  {
    Panel_NV3007(void)
    {
      _cfg.panel_width  = 142;
      _cfg.panel_height = 428;
      _cfg.memory_width  = 168;
      _cfg.memory_height = 428;

      _cfg.offset_x = 12;
      _cfg.offset_y = 0;

      _cfg.dummy_read_pixel = 8;
      _cfg.dummy_read_bits = 1;
    }

    const uint8_t* getInitCommands(uint8_t listno) const override {
      static constexpr uint8_t list0[] = {
	        0xFF, 1, 0xA5,
		0x9A, 1, 0x08,
		0x9B, 1, 0x08,
		0x9C, 1, 0xB0,
		0x9D, 1, 0x16,
		0x9E, 1, 0xC4,
		0x8F, 2, 0x55, 0x04,
		0x84, 1, 0x90,
		0x83, 1, 0x7B,
		0x85, 1, 0x33,

		// ===== Gamma =====
		0x60, 1, 0x00,  0x70, 1, 0x00,
		0x61, 1, 0x02,  0x71, 1, 0x02,
		0x62, 1, 0x04,  0x72, 1, 0x04,
		0x6C, 1, 0x29,  0x7C, 1, 0x29,
		0x6D, 1, 0x31,  0x7D, 1, 0x31,
		0x6E, 1, 0x0F,  0x7E, 1, 0x0F,
		0x66, 1, 0x21,  0x76, 1, 0x21,
		0x68, 1, 0x3A,  0x78, 1, 0x3A,
		0x63, 1, 0x07,  0x73, 1, 0x07,
		0x64, 1, 0x05,  0x74, 1, 0x05,
		0x65, 1, 0x02,  0x75, 1, 0x02,
		0x67, 1, 0x23,  0x77, 1, 0x23,
		0x69, 1, 0x08,  0x79, 1, 0x08,
		0x6A, 1, 0x13,  0x7A, 1, 0x13,
		0x6B, 1, 0x13,  0x7B, 1, 0x13,
		0x6F, 1, 0x00,  0x7F, 1, 0x00,

		// ===== Power =====
		0x50, 1, 0x00,
		0x52, 1, 0xD6,
		0x53, 1, 0x08,
		0x54, 1, 0x08,
		0x55, 1, 0x1E,
		0x56, 1, 0x1C,

		// ===== GOA / Scan =====
		0xA0, 3, 0x2B, 0x24, 0x00,
		0xA1, 1, 0x87,
		0xA2, 1, 0x86,
		0xA5, 1, 0x00,
		0xA6, 1, 0x00,
		0xA7, 1, 0x00,
		0xA8, 1, 0x36,
		0xA9, 1, 0x7E,
		0xAA, 1, 0x7E,

		// ===== Timing =====
		0xB9, 1, 0x85,
		0xBA, 1, 0x84,
		0xBB, 1, 0x83,
		0xBC, 1, 0x82,
		0xBD, 1, 0x81,
		0xBE, 1, 0x80,
		0xBF, 1, 0x01,
		0xC0, 1, 0x02,
		0xC1, 1, 0x00,
		0xC2, 1, 0x00,
		0xC3, 1, 0x00,

		0xC4, 1, 0x33,
		0xC5, 1, 0x7E,
		0xC6, 1, 0x7E,

		0xC8, 2, 0x33, 0x33,
		0xC9, 1, 0x68,
		0xCA, 1, 0x69,
		0xCB, 1, 0x6A,
		0xCC, 1, 0x6B,
		0xCD, 2, 0x33, 0x33,
		0xCE, 1, 0x6C,
		0xCF, 1, 0x6D,
		0xD0, 1, 0x6E,
		0xD1, 1, 0x6F,

		0xAB, 2, 0x03, 0x67,
		0xAC, 2, 0x03, 0x6B,
		0xAD, 2, 0x03, 0x68,
		0xAE, 2, 0x03, 0x6C,

		0xB3, 1, 0x00,
		0xB4, 1, 0x00,
		0xB5, 1, 0x00,
		0xB6, 1, 0x32,
		0xB7, 1, 0x7E,
		0xB8, 1, 0x7E,

		// ===== Panel =====
		0xE0, 1, 0x00,
		0xE1, 2, 0x03, 0x0F,
		0xE2, 1, 0x04,
		0xE3, 1, 0x01,
		0xE4, 1, 0x0E,
		0xE5, 1, 0x01,
		0xE6, 1, 0x19,
		0xE7, 1, 0x10,
		0xE8, 1, 0x10,
		0xEA, 1, 0x12,
		0xEB, 1, 0xD0,
		0xEC, 1, 0x04,
		0xED, 1, 0x07,
		0xEE, 1, 0x07,
		0xEF, 1, 0x09,
		0xF0, 1, 0xD0,
		0xF1, 1, 0x0E,

		0xF9, 1, 0x17,
		0xF2, 4, 0x2C, 0x1B, 0x0B, 0x20,

		0xE9, 1, 0x29,
		0xEC, 1, 0x04,

		0x35, 1, 0x00,
		0x44, 2, 0x00, 0x10,
		0x46, 1, 0x10,

		// exit vendor
		0xFF, 1, 0x00,

		0x3A, 1, 0x05,   //RGB565
		CMD_SLPOUT, 0+CMD_INIT_DELAY, 200,
		0x29, 0+CMD_INIT_DELAY, 150,
		0xFF,0xFF, // end
      };
	  
      switch (listno) {
      case 0: return list0;
      default: return nullptr;
      }
    }
  };
//--------------------------------------------
 }
}

これは,今回購入した N279-1428KIWIG01-C1 という型式のものでしか動作確認できていない.
NV3007 はLCDごとに初期化が異なるらしく,他のLCDで動作するかどうかは不明.

Panel_NV3007.hpp を Lovyan GFX の “panel” フォルダ内に置いて,下記のコードで動作確認できる.

/*
  NV3007_test.ino
    for ESP32
*/
#include <LovyanGFX.hpp>

// 自前で追加した Panel_xxx.hpp は 絶対パスでinclude.
#include "\0_work\Arduino\libraries\LovyanGFX\src\lgfx\v1\panel\Panel_NV3007.hpp"

class LGFX : public lgfx::LGFX_Device
{
  lgfx::Panel_NV3007  _panel_instance;
  lgfx::Bus_SPI         _bus_instance;

public:
  LGFX(void)
  {
    {
      auto cfg = _bus_instance.config();
      cfg.spi_host = VSPI_HOST;  // or SPI2_HOST , SPI3_HOST
      cfg.spi_mode = 0; 
      cfg.freq_write = 20000000;
      cfg.freq_read  = 16000000;
      cfg.spi_3wire  = false;
      cfg.use_lock   = true;
      cfg.dma_channel = SPI_DMA_CH_AUTO;
      
      cfg.pin_sclk = 18;            // SCLK
      cfg.pin_mosi = 23;            // MOSI
      cfg.pin_miso = -1;            // MISO(-1 = disable)
      cfg.pin_dc   = 2;            // D/C
      _bus_instance.config(cfg);
      _panel_instance.setBus(&_bus_instance);
    }

    { 
      auto cfg = _panel_instance.config();
      cfg.pin_cs           =    5;  // CS
      cfg.pin_rst          =    15;  // RST
      cfg.pin_busy         =    -1;  // BUSY

      cfg.offset_rotation  =     3;  // 1 or 3, 1はなぜかNG
      cfg.readable         = false;
      cfg.invert           = false;
      cfg.rgb_order        =  true;
      cfg.dlen_16bit       = false;
      cfg.bus_shared       = false;

      _panel_instance.config(cfg);
    }   
    setPanel(&_panel_instance);
  }
};

LGFX lcd;

void setup() {
  lcd.init();
  lcd.setColorDepth(16);
}

void loop() {
  lcd.fillScreen(TFT_BLACK);
  lcd.setTextColor(TFT_CYAN);
  lcd.setFont(&fonts::Font4);
  lcd.setCursor( 0,  0 );
  lcd.printf( "NV3007 Test" );
  delay(400);

  lcd.fillScreen(TFT_WHITE);
  delay(400);
}

自前で追加した Panel_NV3007.hpp はとりあえずこのファイル内で絶対パス指定で include する必要があるみたい.なにかいい方法があるかもしれないけどとりあえずこれで.
cfg.offset_rotation は 3 限定.上下左右を逆にしようとして 1 に設定すると表示がおかしくなる.今のところLCDの表示方向を配慮して取り付けるようにしないといけない.

動作例1動作例2

コメントを残す