70歳の挑戦... 8bitパラレルTFTのタッチ機能が使えました

　次の構成でタッチスクリーン機能が使えましたので報告します。

    １．8bitパラレル接続TFT LCD Shield（ILI9488 480x320）
    ２．Arduino UNO 互換機
    ３．Arduino IDE 2.3.2

------------------------------------------------------

【2025/06/04追記】
`Arduino UNO R4`での動作も確認できました。ただし、スケッチ`loop`内の補正を

```
  Y = (p.x+54)*0.8; // exchange x <-> y
  X = (p.y-32)*0.86; // 補正
```
と変更して丁度良い具合でした。

------------------------------------------------------
![Touch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/1923385b-51f4-9fe5-556b-4af8fc45471e.jpeg)


　次のサイトが出来るのではと思わせてくれました。
 （保護されていない通信）

http://www.easyaudiokit.com/bekkan2019/teatime4/ILI9341.html

　さらにこのサイトを見つけ
 
https://www.hnhcart.com/blogs/diy-projects/diy-calculator-using-arduino-uno-and-tft-lcd-touch-screen-shield
 
その掲載プログラムを以下のように変更し試してみました。

    １．#include <SPFD5408_Adafruit_GFX.h>     // Core graphics library
        #include <SPFD5408_Adafruit_TFTLCD.h>  // Hardware-specific library
        #include <SPFD5408_TouchScreen.h>
        ↓
        #include <Arduino_GFX_Library.h>     // Core graphics library
        #include <TouchScreen.h>

    ２．Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
        ↓
        Arduino_DataBus *bus = new Arduino_SWPAR8(A2, A3, A1, A0, 8, 9, 2, 3, 4, 5, 6, 7);
        Arduino_GFX *tft = new Arduino_ILI9488(bus, A4 /*DF_GFX_RST*/, 2/*rotation*/, false /*IPS*/);

元は「 ILI9341」用なのですが表示もタッチ機能も不完全ながら動作しました。さらに、タッチスクリーン座標を入れ替えたり（x<->y）、補正したりなどプログラム本体を細かく直し、やっと使用に耐えるところまで来ました。以下に示します。

```c:TFT_8Para_TouchCal.ino
#include <Arduino_GFX_Library.h>     // Core graphics library
#include <TouchScreen.h>

#define BLACK   0x0000
#define WHITE   0xFFFF
#define RED     0xF800      /* 255,   0,   0 */
#define PINK    0xF81F      // MAGENTA
#define YELLOW  0xFFE0      /* 255, 255,   0 */
#define GREEN   0x07E0      /*   0, 255,   0 */
#define CYAN    0x07FF      /*   0, 255, 255 */
#define BLUE    0x001F      /*   0,   0, 255 */

#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin
#define LCD_RESET A4
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0

#define MINPRESSURE 10
#define MAXPRESSURE 1000

/*____Calibrate TFT LCD_____*/
#define TS_MINX 850
#define TS_MINY 100
#define TS_MAXX 180
#define TS_MAXY 780
/*______End of Calibration______*/

Arduino_DataBus *bus = new Arduino_SWPAR8(A2, A3, A1, A0, 8, 9, 2, 3, 4, 5, 6, 7);
//(14 /*TFT_DC*/, 27 /*TFT_CS*/, 25 /*WR*/, 32 /*RD*/,
// 23 /*D0*/, 19 /*D1*/, 18 /*D2*/, 26 /*D3*/, 21 /*D4*/, 4 /*D5*/, 0 /*D6*/, 2 /*D7*/);
Arduino_GFX *tft = new Arduino_ILI9488(
  bus, A4 /*DF_GFX_RST*/, 2 /*rotation*/, false /*IPS*/);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);  //300 is the sensitivity

String symbol[4][4] = {
  { "7", "8", "9", "/" },
  { "4", "5", "6", "*" },
  { "1", "2", "3", "-" },
  { "C", "0", "=", "+" }
};

int X, Y;
long Num1, Num2, Number;
char action;
boolean result = false;

void setup() {
  Serial.begin(115200);  //Use serial monitor for debugging
  tft->begin();         //Always reset at start
  //tft->setRotation(2);  // the power jack faces "down" - optional
  tft->fillScreen(WHITE);
  draw_BoxNButtons();
}

void loop() {
  TSPoint p = waitTouch();
  Y = (p.x+55)*0.84; // exchange x <-> y
  X = (p.y-74)*0.92; // 補正
  Serial.print(X); Serial.print(','); Serial.println(Y);// + " " + Y);
  tft->fillCircle(Y, X, 5, RED);
  DetectButtons();
  if (result == true)
    CalculateResult();
  DisplayResult();
  delay(500);
}

TSPoint waitTouch() {
  TSPoint p;
  do {
    p = ts.getPoint();
    pinMode(XM, OUTPUT);
    pinMode(YP, OUTPUT);
  } while ((p.z < MINPRESSURE) || (p.z > MAXPRESSURE));
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft->width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft->height());
  ;
  return p;
}
void DetectButtons() {
  // Detecting Buttons on Column 0 ---------------------------------
  if (Y < 50 && Y > 0)
  {
    if (X > 269 && X < 300)  //If cancel Button is pressed
    {
      Serial.println("Cancel");
      Number = Num1 = Num2 = 0;
      result = false;
    }
    if (X > 210 && X < 260)  //If Button 1 is pressed
    {
      Serial.println("1");
      if (Number == 0)
        Number = 1;
      else
        Number = (Number * 10) + 1;  //Pressed twice
    }
    if (X > 160 && X < 205)  //If Button 4 is pressed
    {
      Serial.println("4");
      if (Number == 0)
        Number = 4;
      else
        Number = (Number * 10) + 4;  //Pressed twice
    }
    if (X > 108 && X < 156)  //If Button 7 is pressed
    {
      Serial.println("7");
      if (Number == 0)
        Number = 7;
      else
        Number = (Number * 10) + 7;  //Pressed twice
    }
  }
  // Detecting Buttons on Column 1 --------------------------------
  if (Y < 100 && Y > 55)  
  {
    if (X > 269 && X < 300) {
      Serial.println("0");  //Button 0 is Pressed
      if (Number == 0)
        Number = 0;
      else
        Number = (Number * 10) + 0;  //Pressed twice
    }
    if (X > 214 && X < 256) {
      Serial.println("2");
      if (Number == 0)
        Number = 2;
      else
        Number = (Number * 10) + 2;  //Pressed twice
    }
    if (X > 160 && X < 205) {
      Serial.println("5");
      if (Number == 0)
        Number = 5;
      else
        Number = (Number * 10) + 5;  //Pressed twic
    }
    if (X > 108 && X < 156) {
      Serial.println("8");
      if (Number == 0)
        Number = 8;
      else
        Number = (Number * 10) + 8;  //Pressed twic
    }
  }
  // Detecting Buttons on Column 2 ----------------------------------
  if (Y < 175 && Y > 115)
  {
    if (X > 269 && X < 300) {
      Serial.println("Equal");
      Num2 = Number;
      tft->println('=');
      result = true;
    }
    if (X > 210 && X < 256) {
      Serial.println("3");
      if (Number == 0)
        Number = 3;
      else
        Number = (Number * 10) + 3;  //Pressed twice
    }
    if (X > 160 && X < 205) {
      Serial.println("6");
      if (Number == 0)
        Number = 6;
      else
        Number = (Number * 10) + 6;  //Pressed twice
    }
    if (X > 108 && X < 156) {
      Serial.println("9");
      if (Number == 0)
        Number = 9;
      else
        Number = (Number * 10) + 9;  //Pressed twice
    }
  }
  // Detecting Buttons on Column 3 --------------------------------------
  if (Y < 236 && Y > 182)
  {
    Num1 = Number;
    Number = 0;
    tft->setCursor(200, 20);
    tft->setTextColor(RED);
    if (X > 269 && X < 300) {
      Serial.println("Add");
      action = 1;
      tft->println('+');
    }
    if (X > 214 && X < 256) {
      Serial.println("Sub");
      action = 2;
      tft->println('-');
    }
    if (X > 160 && X < 205) {
      Serial.println("Multi");
      action = 3;
      tft->println('*');
    }
    if (X > 108 && X < 156) {
      Serial.println("Dev");
      action = 4;
      tft->println('/');
    }
    delay(300);
  }
}

void CalculateResult() {
  if (action == 1)
    Number = Num1 + Num2;
  if (action == 2)
    Number = Num1 - Num2;
  if (action == 3)
    Number = Num1 * Num2;
  if (action == 4)
    Number = Num1 / Num2;
}

void DisplayResult() {
  tft->fillRect(0, 0, 310, 80, WHITE);  //clear result box
  tft->setCursor(10, 20);
  tft->setTextSize(4);
  tft->setTextColor(BLACK);
  tft->println(Number);  //update new value
}

void draw_BoxNButtons() {
  //Draw the Result Box
  tft->fillRect(0, 0, 240, 80, CYAN);
  //Draw Column 0
  tft->fillRect(0, 260, 60, 60, RED);
  tft->fillRect(0, 200, 60, 60, BLACK);
  tft->fillRect(0, 140, 60, 60, BLACK);
  tft->fillRect(0, 80, 60, 60, BLACK);
  //Draw Column 2
  tft->fillRect(120, 260, 60, 60, GREEN);
  tft->fillRect(120, 200, 60, 60, BLACK);
  tft->fillRect(120, 140, 60, 60, BLACK);
  tft->fillRect(120, 80, 60, 60, BLACK);
  //Draw Column 1,3
  for (int b = 260; b >= 80; b -= 60) {
    tft->fillRect(180, b, 60, 60, BLUE);
    tft->fillRect(60, b, 60, 60, BLACK);
  }
  //Draw Horizontal Lines
  for (int h = 80; h <= 320; h += 60)
    tft->drawFastHLine(0, h, 240, WHITE);
  //Draw Vertical Lines
  for (int v = 0; v <= 240; v += 60)
    tft->drawFastVLine(v, 80, 240, WHITE);
  //Display keypad lables
  for (int j = 0; j < 4; j++) {
    for (int i = 0; i < 4; i++) {
      tft->setCursor(22 + (60 * i), 100 + (60 * j));
      tft->setTextSize(3);
      tft->setTextColor(WHITE);
      tft->println(symbol[j][i]);
    }
  }
}
```
　カルキュレーターとしての使い勝手はまだイマイチですが、タッチ機能が使えるようになったのに満足です。最後まで見ていただきありがとうございました。