Programming the interrupt output on the CST816S touchscreen controller for a Waveshare 1.28" Touch LCD

Has anyone managed to program a touchscreen with a CST816S touchscreen controller so that the interrupt pin TP_INT goes low ONLY when a gesture is detected? Currently this pin goes low whenever I touch the touchscreen regardless of whether a gesture is detected.

I’ve tried writing numerous values to the register 0xFA but this has not changed how the interrupt pin operates. This register is IrqCt1 according to the register declaration document downloaded from this website:

Some of the other registers do work (for example writing to IrqPluseWidth (0xED) does change the width of the low pulse on the interrupt pin when the screen is touched).

Unfortunately there’s discrepancies throughout the register list including for the IrqCt1 register and in general the registers are poorly explained.

The CST816S chip on my Waveshare 1.28" Touch LCD has the following details:
chip ID - 181 (from register 0xA7)
project ID - 56 (from register 0xA8)
firmware version - 1 (from register 0xA9)

Let me know if it’s helpful and I’ll post the code.

Thanks,
James

Hey @James36651, welcome to the forums!

Sending code is definitely useful, even just to have another set of eyes check over it!

I haven’t used this exact touch LCD before but the CST816S seems to be fairly commonly used for touch and gesture detection.

I found this CST816T Arduino library on Github by koendv that creates simple functions to setup the device and change modes.

Their gesture-interrupt mode is named according to the register reference doc.

I did a bit of digging in the source code for this library (src > cst816t.cpp) and the following two lines are used to write register values for the interrupt register and the motion mask register.

i2c_write(CST816T_ADDRESS, REG_IRQ_CTL, &irq_en, 1);
i2c_write(CST816T_ADDRESS, REG_MOTION_MASK, &motion_mask, 1);

where:

CST816T_ADDRESS = 0x15 # Device I2C Address
REG_IRQ_CTL = 0xFA     # IRQ Register Address
REG_MOTION_MASK = 0xEC # Motion MaskRegister Address

When the IRQ mode is set to “mode_motion”, the value within irq_en will be according to the following:

image

Where:

IRQ_EN_MOTION | IRQ_EN_LONGPRESS = 0x10 | 0x01 = 0x11 = 0b00010001
MOTION_MASK_DOUBLE_CLICK = 0b001

So the IrqCtl register will have bit4 and bit0 set and all others reset, which seems to correspond to EnMotion and OnceWLP. The MotionMask register will have bit 0 set and all others reset, though I’m unsure how necessary this change is.

I’m not sure which microcontroller you’re using, perhaps you can just use this library if you’re on Arduino. At any rate, setting these bits accordingly seems to have worked for koendv (author of the library).

Let us know how this goes!

Hi @Zach ,

thanks for the quick response and investigation, really appreciate it. I’m using an arduino uno minima. I downloaded the koendv library and attempted to use the touchme example, it compiles (as long as I change the values for TP_SDA and TP_SCL), but it wasn’t printing gestures like it’s supposed to do. I’ll look into it further in the next day or two but it looks like it’s writing to the same registers and values as I’ve attempted to.

Here’s my code, hopefully you pick up something I’ve overlooked:

#include <Wire.h>

#define CST816S_ADDR 0x15  // I2C address of the CST816S
#define GESTURE_REG 0x01   // Register for gesture data
#define FINGER_NUM 0x02 //reg for number of fingers touching screen
#define CHIP_ID 0xA7 //reg for chip id
#define X_POSH 0x03 //reg for x pos
#define X_POSL 0x04 //reg for x pos
#define BPC0H 0xB0 //
#define BPC0L 0xB1
#define BPC1H 0xB2
#define BPC1L 0xB3
#define MOTIONMASK 0xEC
#define DEBOUNCE_TIME 0xFB
#define INTERRUPT_REG 0xFA
#define INTERRUPT_PULSE 0xED
#define DEBOUNCE_T 0xFB

const byte interruptPin = 1; //interruupt 1 (pin 3 on arduino)
const byte resetPin = 4;
volatile int gestureVar=0;

void gestureCheck()
{
  gestureVar=1;
}

void setup() {
    pinMode(resetPin, OUTPUT);
    Serial.begin(115200);
    while(!Serial)
    {}
    Serial.println("aTEST"); //put in as a test
   
   //---------unreset so screen is in active mode
    digitalWrite(resetPin, LOW);
    delay(50);
    digitalWrite(resetPin,HIGH);//setting this pin is preventing/delaying from being able to communicate with i2c...
    delay(50);
    //pinMode(resetPin, INPUT); //TP works better when this pin is left as input for some reason
    Wire.begin();
  //-----------

    Wire.beginTransmission(CST816S_ADDR);
    Wire.write(INTERRUPT_REG); //register
//    Wire.write(INTERRUPT_PULSE); //register
//    Wire.write(DEBOUNCE_T); //register
    Wire.write(0b00010001); //interrupt condition <---------- try modifying this
    Serial.print(Wire.endTransmission());
    Serial.println(" - irq reg");

    Wire.beginTransmission(CST816S_ADDR);
    Wire.write(INTERRUPT_PULSE); //register    
    Wire.write(0b00000001); //interrupt condition <---------- try modifying this
    Serial.print(Wire.endTransmission());
    Serial.println(" - pulse width");

    Wire.beginTransmission(CST816S_ADDR);
    //delay(500); 
    Wire.write(MOTIONMASK); //register
    Wire.write(0x01); //enable double click
    Serial.print(Wire.endTransmission());
    Serial.println(" - Motion mask");

    Wire.beginTransmission(CST816S_ADDR);
    Wire.write(MOTIONMASK); //register    
    Wire.endTransmission();
    Wire.requestFrom(CST816S_ADDR, 1);
    if(Wire.available())
    {
      uint8_t motionMask2 = Wire.read();
      Serial.print("motionM2 confirm: ");
      Serial.println(motionMask2);
    }

    Wire.beginTransmission(CST816S_ADDR);
    Wire.write(INTERRUPT_REG); //register    
    Wire.endTransmission();
    Wire.requestFrom(CST816S_ADDR, 1);
    if(Wire.available())
    {
      uint8_t interruptReg = Wire.read();
      Serial.print("intReg confirm: ");
      Serial.println(interruptReg);
    }

//    attachInterrupt(0, gestureCheck, FALLING); 

}

void loop() {

  if(digitalRead(A2)==0)
    {
    Wire.beginTransmission(CST816S_ADDR);
    Wire.write(GESTURE_REG);
    Wire.endTransmission();
    Wire.requestFrom(CST816S_ADDR, 1);
    
    if (Wire.available()) {
        uint8_t gesture = Wire.read();
        switch (gesture) {
            //case 0x00:
                //Serial.print("no gesture - ");
                //Serial.println(millis());
            case 0x01:
                Serial.print("swipe up - ");
                Serial.println(millis());
                break;
            case 0x02:
                Serial.print("swipe down - ");
                Serial.println(millis());
                break;
            case 0x03:
                Serial.print("swipe left - ");
                Serial.println(millis());
                break;
            case 0x04:
                Serial.print("swipe right - ");
                Serial.println(millis());
                break;
            case 0x0B:
                Serial.print("double click - ");
                Serial.println(millis());
                break;
        }
    digitalWrite(13,1);
    delay(10);
    digitalWrite(13,0);
    }

    //gestureVar=0;
    }
      
}
1 Like

Hey @James36651,

let us know if you end up figuring this out, seems like a complicated one.

Having a look through your code I can’t see anything obviously incorrect although it may help to address the registers in order. The datasheet, while vague, does seem to indicate that modifying 0xFA before 0xFB for example may prove more successful.

Best of luck with this!