LilyGo [H698] T-Keyboard S3のArduino使い方

# はじめに
個人用のテンプレートです
LilyGo　[H698]T-Keyboard S3をArduinoで使うためのテンプレートです。
※多分ディスコンです。日本で流通している[H743]T-Keyboard S3 Proではありません。(LCDのCSの取り扱いが異なります。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/3ea00345-9a39-80d0-5b7b-06fb983ea873.png)

Display付きキーが４つ付いています。(一番右はメカニカルキーのカチカチ音がします）
Qwiic端子は1つ付いています。

# 比較
|項目|T-Display S3(H698)|備考|
|:-:|:-:|:-:|
|CPU|ESP32S3R8||
|解像度|128x128 x4||
|Flash|16MB||
|PS-RAM|8MB||
|Wireless protocol|2.4g Wi-Fi 6, Bluetooth 5 (LE), 802.15.4||
|Onboard function|Kwy1(10), Key2(9), Key3(46), Key4(3), Neopixel(11)||
|LCD Driver Chip|GC9107||

https://github.com/Xinyuan-LilyGO/T-Keyboard-S3

# Arduinoの準備
1. githubのトップページから"Code"->"Download ZIP"でファイルをダウンロードして展開します。
2. Arduinoの"File"-->"Prefarence"でArduinoのホームディレクトリを探します。
2. 展開した中のlibrariesのフォルダの中身をArduinoのホームディレクトリのlibrariesフォルダに移します。
("pin_config.h"は、他のモデルと被るので、複数のLilyGo製品を扱うのであればファイル名を変更が望ましそう)
自分の環境ではLVGL v9がすでにはいいていたのでLVLGはコピーしませんでした。

# Arduinoのサンプル・実行
ここではGithubのKeyboardを少し変更して、画像を表示してみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/de7fac4b-1e0b-e0af-a99e-82c5c704248f.png)

https://github.com/Xinyuan-LilyGO/T-Keyboard-S3/tree/main/examples/Keyboard

## 画像の用意
128x128の画像を4つ用意します。ここでは"IMG_A","IMG_B","IMG_C","IMG_D"としています。
自分は、WindowsのPaintで作りました。
1. サイズ変更で128x128ピクセルにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/d6b6e098-4bcb-a84d-af44-adb54e09130b.png)
1. 画像を書きます
1. 保存します。PNG形式にしました。(IMG_A.png, IMG_B.png, IMG_C.png, IMG_D.png)

## 画像の変換
参考
https://learn.adafruit.com/steampunk-cameo-necklace/bitmaps-and-code

変換プログラム(lcd-image-converter)をダウンロードし、展開して実行します。 
https://sourceforge.net/projects/lcd-image-converter/files/

File-->Open　形式をImagesにし、画像を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/e570df67-5149-1eda-d2ce-4e0c1e9a5a84.png)

Option-->Conversion　を開き　Presetを"Color R8G8B8"に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/5a408acb-10f8-ed4a-726c-be02cdf340fb.png)

BlockSizeは8bitにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/d8484032-9ee9-517b-d859-db9ebfa0794d.png)

File-->Convert　でHeaderファイルで保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/105ebbd0-3694-4874-28ea-5a537f7edf3d.png)

## サンプルスケッチの作成
1. Arduino IDEを立ち上げます。
2. 新規でスケッチを作成します。
2. 保存します。ここではT-Keyboard_S3にしました。
2. Arduinoのホームフォルダにスケッチと同名のフォルダが出来たので、そこに画像変換した*.hファイルを移動します。少し待つとタブが増えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/7b177e1c-f4a6-6e20-ae0a-218cc713a876.png)
イメージデータは"image_data_ファイル名"となります。
最後の2行（const tImageの宣言）はエラーになるのでコメントにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/ce429946-40ad-d667-4a72-8fc162fe1775.png)


setup関数内のT_Keyboard_S3_Key_InitializationはT-Keyboard_S3_Driveライブラリで定義してあってPinModeや割込みの設定をしています。
画像表示の部分は追加する必要があります。

## スケッチ
```
#include <Arduino.h>
#include <Arduino_GFX_Library.h>
#include "T-Keyboard_S3_Drive.h"
#include "pin_config.h"
#include "FastLED.h"
#include <USB.h>
#include <USBHIDKeyboard.h>

#include "IMG_A.h"
#include "IMG_B.h"
#include "IMG_C.h"
#include "IMG_D.h"


#define KEY1_SET 'a'
#define KEY2_SET 'b'
#define KEY3_SET 'c'
#define KEY4_SET 'd'

#define NUM_LEDS 4
#define DATA_PIN WS2812B_DATA
CRGB leds[NUM_LEDS];

USBHIDKeyboard Keyboard;

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_ESP32SPI(N085_DC, -1, N085_SCLK, N085_MOSI, -1);  // Software SPI
/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_GC9107(bus, N085_RST, 0, true, 128, 128, 2, 1, 0, 0);

uint8_t KEY1_Lock = 0;
uint8_t KEY1_Press_Delay = 0;
uint8_t KEY2_Lock = 0;
uint8_t KEY2_Press_Delay = 0;
uint8_t KEY3_Lock = 0;
uint8_t KEY3_Press_Delay = 0;
uint8_t KEY4_Lock = 0;
uint8_t KEY4_Press_Delay = 0;

void WS2812B_KEY_Loop(void) {
  switch (Key1_Flag) {
    case 0:
      leds[0] = CRGB::Black;
      FastLED.show();

      Keyboard.release(KEY1_SET);
      KEY1_Press_Delay = 0;
      KEY1_Lock = 0;
      break;
    case 1:
      if (KEY1_Lock == 0) {
        leds[0] = CRGB::White;
        FastLED.show();
        Keyboard.press(KEY1_SET);
      }

      if (KEY1_Press_Delay >= 100) {
        KEY1_Press_Delay = 100;
        Keyboard.press(KEY1_SET);
      }
      KEY1_Press_Delay++;
      KEY1_Lock = 1;
      break;

    default:
      break;
  }

  switch (Key2_Flag) {
    case 0:
      leds[1] = CRGB::Black;
      FastLED.show();

      Keyboard.release(KEY2_SET);
      KEY2_Press_Delay = 0;
      KEY2_Lock = 0;
      break;
    case 1:
      if (KEY2_Lock == 0) {
        leds[1] = CRGB::White;
        FastLED.show();
        Keyboard.press(KEY2_SET);
      }

      if (KEY2_Press_Delay >= 100) {
        KEY2_Press_Delay = 100;
        Keyboard.press(KEY2_SET);
      }
      KEY2_Press_Delay++;
      KEY2_Lock = 1;
      break;

    default:
      break;
  }

  switch (Key3_Flag) {
    case 0:
      leds[2] = CRGB::Black;
      FastLED.show();

      Keyboard.release(KEY3_SET);
      KEY3_Press_Delay = 0;
      KEY3_Lock = 0;
      break;
    case 1:
      if (KEY3_Lock == 0) {
        leds[2] = CRGB::White;
        FastLED.show();
        Keyboard.press(KEY3_SET);
      }

      if (KEY3_Press_Delay >= 100) {
        KEY3_Press_Delay = 100;
        Keyboard.press(KEY3_SET);
      }
      KEY3_Press_Delay++;
      KEY3_Lock = 1;
      break;

    default:
      break;
  }

  switch (Key4_Flag) {
    case 0:
      leds[3] = CRGB::Black;
      FastLED.show();

      Keyboard.release(KEY4_SET);
      KEY4_Press_Delay = 0;
      KEY4_Lock = 0;
      break;
    case 1:
      if (KEY4_Lock == 0) {
        leds[3] = CRGB::White;
        FastLED.show();
        Keyboard.press(KEY4_SET);
      }

      if (KEY4_Press_Delay >= 100) {
        KEY4_Press_Delay = 100;
        Keyboard.press(KEY4_SET);
      }
      KEY4_Press_Delay++;
      KEY4_Lock = 1;
      break;

    default:
      break;
  }
}

void setup() {
  T_Keyboard_S3_Key_Initialization();
  pinMode(N085_BL, OUTPUT);

  ledcAttach(N085_BL, 20000, 8);
  ledcWrite(N085_BL, 100);  // brightness 0 - 255

  N085_Screen_Set(N085_Initialize);
  N085_Screen_Set(N085_Screen_ALL);
  gfx->begin();
  gfx->fillScreen(WHITE);

  N085_Screen_Set(N085_Screen_1);
  gfx->draw24bitRGBBitmap(0, 0, image_data_IMG_A, 128, 128);  // RGB

  N085_Screen_Set(N085_Screen_2);
  gfx->draw24bitRGBBitmap(0, 0, image_data_IMG_B, 128, 128);  // RGB

  N085_Screen_Set(N085_Screen_3);
  gfx->draw24bitRGBBitmap(0, 0, image_data_IMG_C, 128, 128);  // RGB

  N085_Screen_Set(N085_Screen_4);
  gfx->draw24bitRGBBitmap(0, 0, image_data_IMG_D, 128, 128);  // RGB

  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  // GRB ordering is typical
  FastLED.setBrightness(50);

  Keyboard.begin();
  USB.begin();
}

void loop() {
  WS2812B_KEY_Loop();
}
```

## 実行
実行時(コンパイル時）の設定は以下の通りです
|Setting|Value|
|:-:|:-:|
|Board|ESP32S3 Dev Module|
|Upload Speed|921600|
|USB Mode|Hardware CDC and JTAG|
|USB CDC On Boot|Enabled|
|USB Firmware MSC On Boot|Disabled|
|USB DFU On Boot|Disabled|
|CPU Frequency|240MHz (WiFi)|
|Flash Mode|QIO 80MHz|
|Flash Size|16MB (128Mb)|
|Core Debug Level|None|
|Partition Scheme|16M Flash (3MB APP/9.9MB FATFS)|
|PSRAM|OPI PSRAM|
|Arduino Runs On|	Core 1|
|Events Run On|Core 1|