fbiego / CST816S

An Arduino library for the Hynitron CST816S capacitive touch screen IC
MIT License
51 stars 24 forks source link

Does it also work with CST816T? #1

Open Fischkopppp opened 2 years ago

Fischkopppp commented 2 years ago

I hope it is ok to write my question under the issue field. Has someone tried this library with CST816T chips? With best regards!

modi12jin commented 2 years ago

CST816T.cpp

#include "CST816T.h"

CST816T::CST816T(int8_t sda_pin, int8_t scl_pin, int8_t rst_pin, int8_t int_pin)
{
    _sda = sda_pin;
    _scl = scl_pin;
    _rst = rst_pin;
    _int = int_pin;
}

void CST816T::begin(void)
{
    // Initialize I2C
    if (_sda != -1 && _scl != -1)
    {
        Wire.begin(_sda, _scl);
    }
    else
    {
        Wire.begin();
    }

    // Int Pin Configuration
    if (_int != -1)
    {
        pinMode(_int, OUTPUT);
        digitalWrite(_int, HIGH); //高电平
        delay(1);
        digitalWrite(_int, LOW); //低电平
        delay(1);
    }

    // Reset Pin Configuration
    if (_rst != -1)
    {
        pinMode(_rst, OUTPUT);
        digitalWrite(_rst, LOW);
        delay(10);
        digitalWrite(_rst, HIGH);
        delay(300);
    }

    // Initialize Touch
    i2c_write(0xFE, 0XFF); //禁止自动进入低功耗模式。
}

bool CST816T::getTouch(uint16_t *x, uint16_t *y, uint8_t *gesture)
{
    bool FingerIndex = false;
    FingerIndex = (bool)i2c_read(0x02);

    *gesture = i2c_read(0x01);
    if (!(*gesture == SlideUp || *gesture == SlideDown))
    {
        *gesture = None;
    }

    uint8_t data[4];
    i2c_read_continuous(0x03,data,4);
    *x = ((data[0] & 0x0f) << 8) | data[1];
    *y = ((data[2] & 0x0f) << 8) | data[3];

    return FingerIndex;
}

uint8_t CST816T::i2c_read(uint8_t addr)
{
    uint8_t rdData;
    uint8_t rdDataCount;
    do
    {
        Wire.beginTransmission(I2C_ADDR_CST816T);
        Wire.write(addr);
        Wire.endTransmission(false); // Restart
        rdDataCount = Wire.requestFrom(I2C_ADDR_CST816T, 1);
    } while (rdDataCount == 0);
    while (Wire.available())
    {
        rdData = Wire.read();
    }
    return rdData;
}

uint8_t CST816T::i2c_read_continuous(uint8_t addr, uint8_t *data, uint32_t length)
{
  Wire.beginTransmission(I2C_ADDR_CST816T);
  Wire.write(addr);
  if ( Wire.endTransmission(true))return -1;
  Wire.requestFrom(I2C_ADDR_CST816T, length);
  for (int i = 0; i < length; i++) {
    *data++ = Wire.read();
  }
  return 0;
}

void CST816T::i2c_write(uint8_t addr, uint8_t data)
{
    Wire.beginTransmission(I2C_ADDR_CST816T);
    Wire.write(addr);
    Wire.write(data);
    Wire.endTransmission();
}

uint8_t CST816T::i2c_write_continuous(uint8_t addr, const uint8_t *data, uint32_t length)
{
  Wire.beginTransmission(I2C_ADDR_CST816T);
  Wire.write(addr);
  for (int i = 0; i < length; i++) {
    Wire.write(*data++);
  }
  if ( Wire.endTransmission(true))return -1;
  return 0;
}

CST816T.h

#ifndef _CST816T_H
#define _CST816T_H

#include <Wire.h>

#define I2C_ADDR_CST816T 0x15

//手势
enum GESTURE
{
    None = 0x00,       //无手势
    SlideDown = 0x01,  //向下滑动
    SlideUp = 0x02,    //向上滑动
    SlideLeft = 0x03,  //向左滑动
    SlideRight = 0x04, //向右滑动
    SingleTap = 0x05,  //单击
    DoubleTap = 0x0B,  //双击
    LongPress = 0x0C   //长按
};

/**************************************************************************/
/*!
    @brief  CST816T I2C CTP controller driver
*/
/**************************************************************************/
class CST816T
{
public:
    CST816T(int8_t sda_pin = -1, int8_t scl_pin = -1, int8_t rst_pin = -1, int8_t int_pin = -1);

    void begin(void);
    bool getTouch(uint16_t *x, uint16_t *y, uint8_t *gesture);

private:
    int8_t _sda, _scl, _rst, _int;

    uint8_t i2c_read(uint8_t addr);
    uint8_t i2c_read_continuous(uint8_t addr, uint8_t *data, uint32_t length);
    void i2c_write(uint8_t addr, uint8_t data);
    uint8_t i2c_write_continuous(uint8_t addr, const uint8_t *data, uint32_t length);
};
#endif

touch_text.ino

#include "CST816T.h"

#define I2C_SDA 8
#define I2C_SCL 9
#define TP_INT 38
#define TP_RST 39

CST816T touch(I2C_SDA, I2C_SCL,TP_RST,TP_INT); 

void setup() {
    Serial.begin(115200); 
    touch.begin(); 
}

bool FingerNum;
uint8_t gesture;
uint16_t touchX,touchY;
void loop() {
    FingerNum=touch.getTouch(&touchX,&touchY,&gesture);
    if(FingerNum){
              Serial.printf("X:%d,Y:%d,gesture:%x\n",touchX,touchY,gesture);
    }

    delay(100);
}

CST816T.zip

modi12jin commented 2 years ago

ESP32S3_ST7789_CST816T_LVGL.ino

#include <lvgl.h>
#include "demos/lv_demos.h"
#include <LovyanGFX.hpp>
#include "CST816T.h"

#define I2C_SDA 8
#define I2C_SCL 9
#define TP_INT 38
#define TP_RST 39

class LGFX : public lgfx::LGFX_Device {

  lgfx::Panel_ST7789 _panel_instance;

  lgfx::Bus_SPI _bus_instance;

public:
  LGFX(void) {
    {
      auto cfg = _bus_instance.config();

      // SPIバスの設定
      cfg.spi_host = SPI2_HOST;  // 使用するSPIを選択  ESP32-S2,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
      // ※ ESP-IDFバージョンアップに伴い、VSPI_HOST , HSPI_HOSTの記述は非推奨になるため、エラーが出る場合は代わりにSPI2_HOST , SPI3_HOSTを使用してください。
      cfg.spi_mode = 0;                   // SPI通信モードを設定 (0 ~ 3)
      cfg.freq_write = 80000000;          // 传输时的SPI时钟(最高80MHz,四舍五入为80MHz除以整数得到的值)
      cfg.freq_read = 20000000;           // 接收时的SPI时钟
      cfg.spi_3wire = true;               // 受信をMOSIピンで行う場合はtrueを設定
      cfg.use_lock = true;                // 使用事务锁时设置为 true
      cfg.dma_channel = SPI_DMA_CH_AUTO;  // 使用するDMAチャンネルを設定 (0=DMA不使用 / 1=1ch / 2=ch / SPI_DMA_CH_AUTO=自動設定)
      // ※ ESP-IDFバージョンアップに伴い、DMAチャンネルはSPI_DMA_CH_AUTO(自動設定)が推奨になりました。1ch,2chの指定は非推奨になります。
      cfg.pin_sclk = 12;  // SPIのSCLKピン番号を設定
      cfg.pin_mosi = 11;  // SPIのCLKピン番号を設定
      cfg.pin_miso = -1;  // SPIのMISOピン番号を設定 (-1 = disable)
      cfg.pin_dc = 6;     // SPIのD/Cピン番号を設定  (-1 = disable)

      _bus_instance.config(cfg);               // 設定値をバスに反映します。
      _panel_instance.setBus(&_bus_instance);  // バスをパネルにセットします。
    }

    {                                       // 表示パネル制御の設定を行います。
      auto cfg = _panel_instance.config();  // 表示パネル設定用の構造体を取得します。

      cfg.pin_cs = 10;    // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst = -1;   // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy = -1;  // BUSYが接続されているピン番号 (-1 = disable)

      // ※ 以下の設定値はパネル毎に一般的な初期値が設定さ BUSYが接続されているピン番号 (-1 = disable)れていますので、不明な項目はコメントアウトして試してみてください。

      cfg.memory_width = 240;    // ドライバICがサポートしている最大の幅
      cfg.memory_height = 280;   // ドライバICがサポートしている最大の高さ
      cfg.panel_width = 240;     // 実際に表示可能な幅
      cfg.panel_height = 280;    // 実際に表示可能な高さ
      cfg.offset_x = 0;          // パネルのX方向オフセット量
      cfg.offset_y = 20;         // パネルの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 = true;         // 如果面板的明暗反转,则设置为 true
      cfg.rgb_order = true;      // 如果面板的红色和蓝色被交换,则设置为 true
      cfg.dlen_16bit = false;    // 对于以 16 位单位发送数据长度的面板,设置为 true
      cfg.bus_shared = false;    // 如果总线与 SD 卡共享,则设置为 true(使用 drawJpgFile 等执行总线控制)

      _panel_instance.config(cfg);
    }

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

// 準備したクラスのインスタンスを作成します。
LGFX tft;
CST816T touch(I2C_SDA, I2C_SCL,TP_RST,TP_INT); 

/*更改为您的屏幕分辨率*/
static const uint32_t screenWidth = 240;
static const uint32_t screenHeight = 280;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[2][screenWidth * 30];

#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *fn_name, const char *dsc) {
  Serial.printf("%s(%s)@%d->%s\r\n", file, fn_name, line, dsc);
  Serial.flush();
}
#endif

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  if (tft.getStartCount() == 0) {
    tft.endWrite();
  }

  tft.pushImageDMA(area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1, (lgfx::swap565_t *)&color_p->full);

  lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}

/*Read the touchpad*/
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {

  bool touched;
  uint8_t gesture;
  uint16_t touchX,touchY; 

  touched=touch.getTouch(&touchX,&touchY,&gesture); 

  if (!touched)
  {
      data->state = LV_INDEV_STATE_REL;
  }
  else
  {
      data->state = LV_INDEV_STATE_PR;

      /*Set the coordinates*/
      data->point.x = touchX;
      data->point.y = touchY;

  }
}

void setup() {
  Serial.begin(115200); /* prepare for possible serial debug */
  Serial.println("Hello Arduino! (V8.2.X)");
  Serial.println("I am LVGL_Arduino");

  tft.init();  
  tft.initDMA();
  tft.startWrite();

  touch.begin();

  lv_init();

#if LV_USE_LOG != 0
  lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif

  lv_disp_draw_buf_init(&draw_buf, buf[0], buf[1], screenWidth * 30);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  /*Change the following line to your display resolution*/
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

#if 0
   /* Create simple label */
   lv_obj_t *label = lv_label_create( lv_scr_act() );
   lv_label_set_text( label, "Hello Arduino! (V8.0.X)" );
   lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
#else
  /* Try an example from the lv_examples Arduino library
      make sure to include it as written above.
   lv_example_btn_1();
   */

  // uncomment one of these demos
    lv_demo_widgets(); //小部件
  // lv_demo_keypad_encoder(); //键盘编码器
  // lv_demo_benchmark(); //基准测试
  // lv_demo_stress(); //压力测试
  // lv_demo_music(); //音乐
#endif
  Serial.println("Setup done");
}

void loop() {
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
}
modi12jin commented 2 years ago

@Fischkopppp testing successfully

https://user-images.githubusercontent.com/40233017/178342214-a282e807-30c6-42f6-9c3b-09bbd90cee6c.mp4

modi12jin commented 2 years ago

DS-CST816T数据手册V2.2.pdf

CST816S寄存器说明-20190508.pdf

P169H002-CTP.pdf

modi12jin commented 1 year ago

wx_camera_1676991215694

CST816T code is also applicable to CST816D

CST816D数据手册V1.0.pdf

modi12jin commented 1 year ago

If you use in ESP IDF please refer to this question

https://github.com/wirano/st77903_demo/issues/1

marklysze commented 1 year ago

Thanks for the CST816T code, I successfully used it on the LilyGO T-Display-S3 Touch version: https://github.com/Xinyuan-LilyGO/T-Display-S3

ArsenseLupin commented 1 year ago

Can only use ESP32S3? Why does esp32 devkit v1 report an error when burning the CST816T routine? The error is as follows: Warning: Could not auto-detect Flash size (FlashID=0xffffff, SizeID=0xff), defaulting to 4MB Compressed 8192 bytes to 47...

A fatal error occurred: Timed out waiting for packet content Failed uploading: uploading error: exit status 2

ChristianIannella commented 1 year ago

Dose it also work with CST816D?