Raspberry Pi Picoで静電容量方式タッチパネルを使う

# 経緯
抵抗膜方式タッチパネルはいまいち反応が鈍いので、
[Adafruitの静電容量方式タッチパネル 2090](https://www.adafruit.com/product/2090) を買ってRaspberry Pi Picoで動作確認する。

# 回路
![pico_ada2090_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/fc02b025-b9ec-e05b-7c7c-ad415f5a601c.jpeg)

![P_20230224_204111.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/bafc8636-12fd-0677-3d8b-3a332fea2af9.jpeg)

# プログラム
ボードは[非公式版](https://github.com/earlephilhower/arduino-pico)を利用。
液晶パネルILI9341を動かすライブラリ[TFT_eSPI](https://github.com/Bodmer/TFT_eSPI)を利用。

```c:User_Setup_Select.h
//#include <User_Setup.h>           // Default setup is root library folder
#include <User_Setups/Setup60_RP2040_ILI9341.h>    // Setup file for RP2040 with SPI ILI9341
```

```c:Setup60_RP2040_ILI9341.h
#define ILI9341_DRIVER
#define TFT_MISO  12
#define TFT_MOSI  11
#define TFT_SCLK  10
#define TFT_CS   9
#define TFT_DC   8
#define TFT_RST  15

#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#define SMOOTH_FONT

#define TFT_SPI_PORT 1

#define SPI_FREQUENCY  40000000
#define SPI_READ_FREQUENCY  20000000
```

タッチパネル制御チップ(CST026)を動かすライブラリ[Adafruit_FT6206](https://github.com/adafruit/Adafruit_FT6206_Library)を利用。

```cpp:CapTouchPaint.ino
#include <SPI.h>
#include "TFT_eSPI.h"
#include <Wire.h>
#include <Adafruit_FT6206.h>
Adafruit_FT6206 ctp = Adafruit_FT6206();
TFT_eSPI tft = TFT_eSPI();
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
void setup(void) {
  Wire.setSDA(20);
  Wire.setSCL(21);
  Wire.begin();

  Serial.begin(115200);
  Serial.println(F("Cap Touch Paint!"));

  SPI1.setRX(12);// MISO
  SPI1.setTX(11);// MOSI
  SPI1.setSCK(10);

  tft.begin();
  
  if (! ctp.begin(40)) {  // pass in 'sensitivity' coefficient
    Serial.println("Couldn't start FT6206 touchscreen controller");
    while (1);
  }

  Serial.println("Capacitive touchscreen started");

  tft.fillScreen(TFT_BLACK);

  // make the color selection boxes
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, TFT_RED);
  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, TFT_YELLOW);
  tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, TFT_GREEN);
  tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, TFT_CYAN);
  tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, TFT_BLUE);
  tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, TFT_MAGENTA);

  // select the current color 'red'
  tft.drawRect(0, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
  currentcolor = TFT_RED;
}

void loop() {
  // Wait for a touch
  if (! ctp.touched()) {
    return;
  }

  // Retrieve a point
  TS_Point p = ctp.getPoint();

  // flip it around to match the screen.
  p.x = map(p.x, 0, 240, 240, 0);
  p.y = map(p.y, 0, 320, 320, 0);

  // Print out the remapped (rotated) coordinates
  Serial.print("("); Serial.print(p.x);
  Serial.print(", "); Serial.print(p.y);
  Serial.println(")");

  if (p.y < BOXSIZE) {
    oldcolor = currentcolor;

    if (p.x < BOXSIZE) {
      currentcolor = TFT_RED;
      tft.drawRect(0, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    } else if (p.x < BOXSIZE * 2) {
      currentcolor = TFT_YELLOW;
      tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    } else if (p.x < BOXSIZE * 3) {
      currentcolor = TFT_GREEN;
      tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    } else if (p.x < BOXSIZE * 4) {
      currentcolor = TFT_CYAN;
      tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    } else if (p.x < BOXSIZE * 5) {
      currentcolor = TFT_BLUE;
      tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    } else if (p.x <= BOXSIZE * 6) {
      currentcolor = TFT_MAGENTA;
      tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
    }

    if (oldcolor != currentcolor) {
      if (oldcolor == TFT_RED)
        tft.fillRect(0, 0, BOXSIZE, BOXSIZE, TFT_RED);
      if (oldcolor == TFT_YELLOW)
        tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, TFT_YELLOW);
      if (oldcolor == TFT_GREEN)
        tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, TFT_GREEN);
      if (oldcolor == TFT_CYAN)
        tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, TFT_CYAN);
      if (oldcolor == TFT_BLUE)
        tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, TFT_BLUE);
      if (oldcolor == TFT_MAGENTA)
        tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, TFT_MAGENTA);
    }
  }
  if (((p.y - PENRADIUS) > BOXSIZE) && ((p.y + PENRADIUS) < tft.height())) {
    tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
  }
}
```

# 余談
Adafruit 2090の青基板はEYESPIコネクタ無し、黒基板はEYESPIコネクタ有りのようです。
同じ型番なので注文してもどちらが届くか分かりません。
sdカードスロットが必要無いならパネルのみの[Adafruit 2770](https://www.adafruit.com/product/2770)でも良いと思う。