Issues with CST816S controller / libraries.

TwystNeko

Member
So I snagged one of those nice WaveShare 1.28" round LCDs, with the GC9A01 driver. Got that working with a library found on here, so that's great. Now I'm trying to get the touch screen working, and there's a couple of libraries that seem simple enough, but neither of them compile because they're made for the ESP8266. I'm using a Teensy 4.1.

The first one, (https://github.com/fbiego/CST816S/tree/main) invokes "FunctionalInterrupts.h" from the ESP8266 standard libraries, and won't compile. I'm not experienced enough to figure out how to change from that to the Teensy interrupts. They seem similar, but it's all magic to me at this point.

The second one (https://github.com/koendv/cst816t/blob/master/src/cst816t.cpp )seems to be more fleshed out, but it fails when calling TwoWire(SDA, SCL) - which, again, is how it's done in the ESP8266 ecosystem.


In both cases, I don't know how to refactor the library to make them work. I suspect the first one would be a lot easier, but...


Help!

Also, I'm using the Audio board, as I want to make this a (strange) but functional audio player. So I'm using alternate pins - specifically, SDA2 (25), SCL2 (24), RST (37) and INT (40).
 
For the second library (https://github.com/koendv/cst816t), I'm guessing that when when you say "it fails when calling TwoWire Wire2(SDA,SCL)", you mean it fails to build. For T4.1, that line would cause an error because Wire2 is already defined in the Wire library.

I was able to get the touchme.ino example to build by changing the pin numbers and commenting out the declaration of TwoWire Wire2 as shown below, and then modifying line 121 of cst816t.cpp to contain explicit casts to resolve an ambiguity error. I don't have the hardware, so I can't test it, but it does build.

Code:
  wire.requestFrom( (uint8_t)addr, (uint8_t)length, true );

Code:
/* demo for the CST816T capacitive touch ic */

#include <Wire.h>
#include "cst816t.h"

#define TP_SDA 25 //PB11
#define TP_SCL 24 //PB10
#define TP_RST 37 //PA15
#define TP_IRQ 40 //PB3

//TwoWire Wire2(TP_SDA, TP_SCL);
cst816t touchpad(Wire2, TP_RST, TP_IRQ);

void setup() {
  // decode everything: single click, double click, long press, swipe up, swipe down, swipe left, swipe right
  touchpad.begin(mode_motion);
  Serial.println(touchpad.version());
}

void loop() {
  if (touchpad.available())
    Serial.println(touchpad.state());
}
 
Thanks for the help.

I tried this out, and while it did compile and upload, it seems to get stuck in a loop of rebooting, as I get the windows disconnect sound every second or so. Can't even get the serial monitor to open. Did manage to put the demo code I was using back on, so no trouble there, but that fix didn't work. :<

Right now I'm basically ripping apart the first library, de-classing it, just to make it work. So far, so good, but I haven't touch the interrupt stuff yet
 
Last edited:
Thanks for the help.

I tried this out, and while it did compile and upload, it seems to get stuck in a loop of rebooting, as I get the windows disconnect sound every second or so. Can't even get the serial monitor to open. Did manage to put the demo code I was using back on, so no trouble there, but that fix didn't work. :<

It may be closer to working than you think, and you do at least have a starting point for debugging. The first thing I would do is add the two lines below at the top of setup(). The crash may simply be due to calling Serial.println() without initializing Serial.

Code:
  Serial.begin( 9600 );
  while (!Serial) {}
 
okay, so I've been banging away at the first library, and de-classed it, as it were. It works, mostly! Here's the code I'm using.

Code:
//touch.h 
#include <stdint.h>
#include <Arduino.h>

enum GESTURE { 
  NONE = 0x00,
  SWIPE_UP = 0x01,
  SWIPE_DOWN = 0x02,
  SWIPE_LEFT = 0x03,
  SWIPE_RIGHT = 0x04,
  SINGLE_CLICK = 0x05,
  DOUBLE_CLICK = 0x0B,
  LONG_PRESS = 0x0C
};

struct touch_data { 
  byte gestureID;
  byte points;
  byte event;
  int x;
  int y;
  uint8_t version;
  uint8_t versionInfo[3];
};

Code:
#include <Arduino.h>
#include <Wire.h>
#include "touch.h"

#define T_SDA 25
#define T_SCL 24
#define T_RST 37
#define T_INT 40

#define T_ADDR 0x15
#define T_MODE RISING

bool volatile event_available = false;

touch_data tdata;

void read_touch();
uint8_t i2c_read(uint8_t , uint8_t , uint8_t , uint8_t );
uint8_t i2c_write(uint8_t, uint8_t, uint8_t, uint8_t);
String parseGesture(uint8_t);
void touch_init();
void handleISR();
bool available();


void setup() {
  Serial.begin(115200);
  touch_init();

}


void loop() {
if(available()) { 
  Serial.println(parseGesture());
}


}

bool available() { 
  if(event_available) { 
    read_touch();
    event_available = false;
    return true;
  }
  return false;
}

uint8_t i2c_read(uint16_t addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t length) { 
  Wire2.beginTransmission(addr);
  Wire2.write(reg_addr);
  if(Wire2.endTransmission(true)) return -1;

  Wire2.requestFrom((uint8_t)addr,(uint8_t)length,(bool)true);
  for(uint8_t i = 0; i < length; i++) { 
    *reg_data++ = Wire2.read();
  }
  return 0;
}

uint8_t i2c_write(uint8_t addr, uint8_t reg_addr, const uint8_t *reg_data, uint8_t length) { 
  Wire2.beginTransmission(addr);
  Wire2.write(reg_addr);
  for(uint8_t i = 0; i < length; i++) { 
    Wire2.write(*reg_data++);
  }
  if(Wire2.endTransmission(true)) return -1;
  return 0;
}

void read_touch() { 
  byte raw_touch[8];
  i2c_read(T_ADDR, 0x01, raw_touch, 6);
  tdata.gestureID = raw_touch[0];
  tdata.points = raw_touch[1];
  tdata.event = raw_touch[2]>>6;
  tdata.x = raw_touch[3];
  tdata.y = raw_touch[5];
}

String parseGesture() { 
  switch(tdata.gestureID) { 
    case NONE:
      return "NONE";
      break;
    case SWIPE_DOWN:
      return "SWIPE DOWN";
      break;
    case SWIPE_UP:
      return "SWIPE UP";
      break;
    case SWIPE_LEFT:
      return "SWIPE LEFT";
      break;
    case SWIPE_RIGHT:
      return "SWIPE RIGHT";
      break;
    case SINGLE_CLICK:
      return "SINGLE CLICK";
      break;
    case DOUBLE_CLICK:
      return "DOUBLE CLICK";
      break;
    case LONG_PRESS:
      return "LONG PRESS";
      break;
    default:
      return "UNKNOWN";
      break;
  }
}

void handleISR() { 
  event_available = true;
}

void touch_init() { 
  Wire2.setSCL(T_SCL);
  Wire2.setSDA(T_SDA);
  Wire2.begin();
  pinMode(T_INT, INPUT);
  pinMode(T_RST, OUTPUT);

  digitalWrite(T_RST, HIGH);
  delay(50);
  digitalWrite(T_RST, LOW);
  delay(5);
  digitalWrite(T_RST, HIGH);
  delay(50);

  i2c_read(T_ADDR,0x15, &tdata.version, 1);
  delay(5);
  i2c_read(T_ADDR, 0xA7, tdata.versionInfo, 3);
  attachInterrupt(T_INT, handleISR, T_MODE);

}

So, the issue I'm running into, which is very minor, seems to be that it won't detect a double-click, so maybe it needs debouncing?
 
okay, so I've been banging away at the first library, and de-classed it, as it were. It works, mostly! Here's the code I'm using.

Code:
//touch.h
#include <stdint.h>
#include <Arduino.h>

enum GESTURE {
  NONE = 0x00,
  SWIPE_UP = 0x01,
  SWIPE_DOWN = 0x02,
  SWIPE_LEFT = 0x03,
  SWIPE_RIGHT = 0x04,
  SINGLE_CLICK = 0x05,
  DOUBLE_CLICK = 0x0B,
  LONG_PRESS = 0x0C
};

struct touch_data {
  byte gestureID;
  byte points;
  byte event;
  int x;
  int y;
  uint8_t version;
  uint8_t versionInfo[3];
};

Code:
#include <Arduino.h>
#include <Wire.h>
#include "touch.h"

#define T_SDA 25
#define T_SCL 24
#define T_RST 37
#define T_INT 40

#define T_ADDR 0x15
#define T_MODE RISING

bool volatile event_available = false;

touch_data tdata;

void read_touch();
uint8_t i2c_read(uint8_t , uint8_t , uint8_t , uint8_t );
uint8_t i2c_write(uint8_t, uint8_t, uint8_t, uint8_t);
String parseGesture(uint8_t);
void touch_init();
void handleISR();
bool available();


void setup() {
  Serial.begin(115200);
  touch_init();

}


void loop() {
if(available()) {
  Serial.println(parseGesture());
}


}

bool available() {
  if(event_available) {
    read_touch();
    event_available = false;
    return true;
  }
  return false;
}

uint8_t i2c_read(uint16_t addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t length) {
  Wire2.beginTransmission(addr);
  Wire2.write(reg_addr);
  if(Wire2.endTransmission(true)) return -1;

  Wire2.requestFrom((uint8_t)addr,(uint8_t)length,(bool)true);
  for(uint8_t i = 0; i < length; i++) {
    *reg_data++ = Wire2.read();
  }
  return 0;
}

uint8_t i2c_write(uint8_t addr, uint8_t reg_addr, const uint8_t *reg_data, uint8_t length) {
  Wire2.beginTransmission(addr);
  Wire2.write(reg_addr);
  for(uint8_t i = 0; i < length; i++) {
    Wire2.write(*reg_data++);
  }
  if(Wire2.endTransmission(true)) return -1;
  return 0;
}

void read_touch() {
  byte raw_touch[8];
  i2c_read(T_ADDR, 0x01, raw_touch, 6);
  tdata.gestureID = raw_touch[0];
  tdata.points = raw_touch[1];
  tdata.event = raw_touch[2]>>6;
  tdata.x = raw_touch[3];
  tdata.y = raw_touch[5];
}

String parseGesture() {
  switch(tdata.gestureID) {
    case NONE:
      return "NONE";
      break;
    case SWIPE_DOWN:
      return "SWIPE DOWN";
      break;
    case SWIPE_UP:
      return "SWIPE UP";
      break;
    case SWIPE_LEFT:
      return "SWIPE LEFT";
      break;
    case SWIPE_RIGHT:
      return "SWIPE RIGHT";
      break;
    case SINGLE_CLICK:
      return "SINGLE CLICK";
      break;
    case DOUBLE_CLICK:
      return "DOUBLE CLICK";
      break;
    case LONG_PRESS:
      return "LONG PRESS";
      break;
    default:
      return "UNKNOWN";
      break;
  }
}

void handleISR() {
  event_available = true;
}

void touch_init() {
  Wire2.setSCL(T_SCL);
  Wire2.setSDA(T_SDA);
  Wire2.begin();
  pinMode(T_INT, INPUT);
  pinMode(T_RST, OUTPUT);

  digitalWrite(T_RST, HIGH);
  delay(50);
  digitalWrite(T_RST, LOW);
  delay(5);
  digitalWrite(T_RST, HIGH);
  delay(50);

  i2c_read(T_ADDR,0x15, &tdata.version, 1);
  delay(5);
  i2c_read(T_ADDR, 0xA7, tdata.versionInfo, 3);
  attachInterrupt(T_INT, handleISR, T_MODE);

}

So, the issue I'm running into, which is very minor, seems to be that it won't detect a double-click, so maybe it needs debouncing?
Hi,
Very nice work. I had the same problems as well with a pico and GC9A01 with touch. Your code worked fine, one thing I do not understand as I'm not very familiar with this is the existence of the NONE at the gestures. Can this be avoided ? Is there a reason to have it ?
Lucas
 
Back
Top