1
\$\begingroup\$

I have a 9 inch touch panel which has a GT911 controller and works with I2C. I should configure its registers and then read the touched points' coordinates. It has 6 pins (Vcc, GNd, INT, RST, SCA, SDA).

You can find the link to the datasheet and the programming guide which includes the registers names at the end of the question.

So far, I can reset the touch panel and also read/write data from/into the registers, but the config array is probably wrong or there is another mistake I'm making. I want to read the coordinates of one point and after that configure the touch panel so I can use a proper stylus.

Here is my code which is probably horrible because I'm quite new to this area:

#include <Wire.h>

#define int_pin 2
#define rst_pin 5
#define i2c_addr_5D 0b1011101
#define i2c_addr_BA 0b10111010
#define i2c_addr_BB 0b10111011
#define i2c_addr_14 0b0010100
#define i2c_addr_28 0b00101000
#define i2c_addr_29 0b00101001
#define GOODIX_REG_COMMAND        0x8040

static uint8_t g911xFW[] = {
  0x81, 0x00, 0x04, 0x58, 0x02, 0x0A, 0x0C, 0x20, 0x01, 0x08, 0x28, 0x05, 0x50, 
  0x3C, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x89, 0x2A, 0x0B, 0x2D, 0x2B, 0x0F, 0x0A, 0x00, 0x00, 0x01, 0xA9, 0x03, 
  0x2D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 
  0x59, 0x94, 0xC5, 0x02, 0x07, 0x00, 0x00, 0x04, 0x93, 0x24, 0x00, 0x7D, 0x2C, 
  0x00, 0x6B, 0x36, 0x00, 0x5D, 0x42, 0x00, 0x53, 0x50, 0x00, 0x53, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 
  0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x04, 0x06, 0x08, 0x0A, 0x0F, 0x10, 0x12, 0x16, 0x18, 0x1C, 0x1D, 0x1E, 
  0x1F, 0x20, 0x21, 0x22, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00
};

uint8_t i2c_addr = i2c_addr_5D;
uint8_t event; 
uint8_t data;
uint8_t check;
uint8_t read_config_array[6][32];
uint8_t write_config_array[6][32];
uint8_t read_config[184];
uint8_t fresh_regs[2];

char product_id[5];

void touchInterrupt() {
  noInterrupts();
  event = 1;
  interrupts();
}

bool powerOn(bool addr) {
  delay(500);
  uint8_t reset_result = reset(addr);
  delay(500);
  return reset_result;
}

bool reset(bool addr) {
  delay(1);

  pinMode(int_pin , OUTPUT);
  pinMode(rst_pin , OUTPUT);
  digitalWrite(int_pin , LOW);
  digitalWrite(rst_pin , LOW);

  delay(15);

  if (addr) {
    digitalWrite(int_pin, HIGH); // LOW for 0x5D and HIGH for 0x14
  } else {
    digitalWrite(int_pin, LOW);
  }
        
  delayMicroseconds(110);

  pinMode(rst_pin, INPUT);
  /*
  pinMode(rst_pin, INPUT);

  if (digitalRead(rst_pin) != HIGH) {
    return false;
  }
  */
        
  delay(6);
  digitalWrite(int_pin, LOW);
  delay(51);
  pinMode(int_pin , INPUT);
  attachInterrupt(digitalPinToInterrupt(int_pin), touchInterrupt, RISING);
  return true;
}

uint8_t calcCheckSum(uint8_t *buf, uint8_t len) {
  uint8_t ccsum = 0;

  for (uint8_t i = 0; i < len; i++) {
    ccsum += buf[i];
  }

  ccsum = (~ccsum) + 1;
  return ccsum;
}

uint8_t readCheckSum() {
  configRead();
  check = calcCheckSum(read_config , 184);
  Serial.print("needed checksum = ");
  Serial.println(check , HEX) ;
  return check;
}

bool i2cWrite(uint8_t write_i2c_addr, uint16_t write_reg_addr, uint8_t DATA) {
  Serial.println("writing started");
  Wire.beginTransmission(write_i2c_addr);
  check = Wire.write(highByte(write_reg_addr));
  check = Wire.write(lowByte(write_reg_addr));
  check = Wire.write(DATA);
  check = Wire.endTransmission();

  if (!check) {
    return true ;
  } else {
    Serial.print("!!!failed to write in ");
    Serial.print(write_reg_addr , HEX);
    Serial.print(" with the i2c address of ");
    Serial.print(write_i2c_addr , HEX);
    Serial.print(" with the error number of ");
    Serial.println(check);
    return false;
  }
}

bool i2cWriteBytes(uint8_t write_i2c_addr, uint16_t write_reg_addr, uint8_t len, uint8_t *buf) {
  uint8_t i = 0, j = 0;
  int diff = 0;

  Serial.println("writing started");
  while (j < len) {
    diff = len - j;
    Wire.beginTransmission(write_i2c_addr);
    Wire.write(highByte(write_reg_addr + j));
    Wire.write(lowByte(write_reg_addr + j));

    for (i = 0; i < 32 && i < diff; i++) {
      Wire.write(buf[i + j]);
      read_config[i + j] = buf[i + j];
    }
   
    Wire.endTransmission();  
    j += i;
    check = calcCheckSum(read_config, 184);
    Serial.print("step checksum");
    Serial.println(check, HEX);
    Wire.beginTransmission(write_i2c_addr);
    Wire.write(highByte(0x80FF));
    Wire.write(lowByte(0x80FF));
    Wire.write(check);
    Wire.write(0x01);
    Wire.endTransmission();
  }
}

uint8_t i2cRead(uint8_t read_i2c_addr, uint16_t read_reg_addr) {
  uint8_t DATA;

  Serial.println(read_i2c_addr, HEX);

  Wire.beginTransmission(read_i2c_addr);
  Wire.write(highByte(read_reg_addr));
  Wire.write(lowByte(read_reg_addr));
  Wire.endTransmission();

  if (check) {
    Serial.print("!!!failed to start the raeding process in ");
    Serial.print(read_reg_addr , HEX);
    Serial.print(" with the i2c address of ");
    Serial.print(read_i2c_addr , HEX);
    Serial.print(" with the error number of ");
    Serial.println(check);
    return false;
  }

  Wire.beginTransmission(read_i2c_addr);
  check = Wire.requestFrom(read_i2c_addr, 1);
  check = Wire.available();
 
  if (check) {
    uint8_t DATA = Wire.read();
  }

  Serial.print("data = ");
  Serial.println(DATA, HEX);
  check = Wire.endTransmission();

  if (!check) {
    return DATA;
  } else {
    Serial.print("failed to read data from ");
    Serial.print(read_reg_addr,HEX;
    Serial.print(" with the i2c address of ");
    Serial.print(read_i2c_addr, HEX);
    Serial.print(" with the error number of ");
    Serial.println(check);
    return false;
  }
}

uint8_t i2cReadBytes(uint8_t read_i2c_addr, uint16_t read_reg_addr, uint8_t len, uint8_t *buf) {
  uint8_t i = 0, j = 0; int diff = 0;
  Serial.println("reading started");

  while (j < len) {
    diff = len - j;
    Wire.beginTransmission(read_i2c_addr);
    Wire.write(highByte(read_reg_addr + j));
    Wire.write(lowByte(read_reg_addr + j));
    Wire.endTransmission();  
    Wire.beginTransmission(read_i2c_addr);

    if (diff > 32) {
      Wire.requestFrom(read_i2c_addr, 32);
    } else {
      Wire.requestFrom(read_i2c_addr, diff);
    }

    while (Wire.available()) {
      buf[j] = Wire.read();
      Serial.print(buf[j], HEX);
      Serial.print(" , ");
      j++;
    }

    Wire.endTransmission();  
  }
}

bool productId(char *target) {
  i2cReadBytes(i2c_addr, 0x8140, 4, target);

  Serial.println(target[0]);
}

void configUpdate() {
  uint8_t len1 = 0x80A2 - 0x8047 + 1;
  uint8_t len2 = 0x80FE - 0x80A2;
  uint8_t buf[2];
  buf[0] = calcCheckSum(g911xFW, sizeof(g911xFW));

  Serial.print("checksum to be written: ");
  Serial.println(buf[0], HEX); 
  buf[1] = 0x01;
  i2cWrite(i2c_addr, GOODIX_REG_COMMAND, 0x00);
  productId(product_id);

  if (product_id[0] != '9') {
    Serial.println("product id doesn't match");
    return;
  }

  i2cWriteBytes(i2c_addr, 0x8047, sizeof(g911xFW), g911xFW);
  i2cWriteBytes(i2c_addr, 0x80FF, 2, buf);

  Serial.println("config seems to be updated");
}

void configRead() {
  uint8_t len1 = 0x80A2 - 0x8047 + 1;
  uint8_t len2 = 0x80FE - 0x80A2 ;
  uint8_t buf[2];

  i2cReadBytes(0x5D, 0x8047, 184, read_config);

  Serial.println("");

  i2cReadBytes(0x5D, 0x80FF, 2, fresh_regs);
              
  Serial.print("the checksum in the register: ");
  Serial.println(fresh_regs[0], HEX);
  Serial.print("the config_fresh register : ");
  Serial.println(fresh_regs[1], HEX);
}

void setup() {
  Serial.begin(115200);
  while(!Serial);
  Wire.begin();
  Wire.setClock(400000);

  check = powerOn(false);
  if (check == false) {
    Serial.println("reset failed");
  } else {
    Serial.println("reset successful");
  }

  configRead();
  configUpdate();
  readCheckSum();
  Serial.println("");
}

void loop() {
  uint16_t points[5][2]; 
  uint8_t low_byte, high_byte;
  noInterrupts();
  bool event_saver = event;
  event = 0;
  interrupts();

  if (event_saver) {
    Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!event happened!!!!!!!!!!!!!!!!!!!!!!!");
              
    i2cWrite(i2c_addr, GOODIX_REG_COMMAND, 0x00);
    data = i2cRead(i2c_addr, 0x814E);

    Serial.println("");
    Serial.println("");

    bool msb = bitRead(data, 7);

    if (msb == 1) {
      i2cWrite(i2c_addr, 0x8040, 0x00);
                  
      low_byte = i2cRead(i2c_addr, 0x8150);
      high_byte = i2cRead(i2c_addr, 0x8151);
      points[0][0] = (high_byte << 8) + low_byte;

      Serial.print(" x = ");
      Serial.println(points[0][0]);

      low_byte = i2cRead(i2c_addr, 0x8152);
      high_byte = i2cRead(i2c_addr, 0x8153);
      points[0][1] = (high_byte << 8) + low_byte ;
  
      Serial.print(" y = ");
      Serial.println(points[0][1]);

      i2cWrite(i2c_addr, 0x814E, 0x00);
    }

    //Serial.println(digitalRead(int_pin));
  }
  delay(10);
}

datasheet

programming guide

\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

This is a independant observation on GT911 i2c address. Its i2c address must be selected during reset phase, else it does not communicate with any of the 2 i2c addresses. I wished it responds to a default i2c address. But that is not the case.

\$\endgroup\$
0
\$\begingroup\$

@Mohammad.

You have in your code: #define i2c_addr_5D 0b1011101. Error: you wrote byte with 7 bits long, not eight! So, 0x5D is 0b01011101.

The same is for #define i2c_addr_14 0b0010100 - 0b00010100.

Check if you made similar mistakes somewhere else.

Question: why are you doing anything in the matrix? This is factory setup and you can mess something and block the panel.

As you can see from my code I only READ FROM coordinate registers and nothing else. (Btw. I have application that read and write to the firmware registers but this is only for me and I do not want to be responsible if someone destroy the panel).

Try to read my code carefully. I explained most of the things how to do them and why to do it.

Check the schematics twice.

Just make new project in PlatformIO, copy-paste everything from my main.cpp, find the Leonardo's COM port, compile to Leonardo and that is it. Than open my WPF app in MS Visual studio Community, compile it and run.

And DO NOT write anything in the firmware "g911xFW[]" registers if you are not 100% sure what you are doing.

Link on YouTube for the others who want to experiment: https://www.youtube.com/watch?v=t6X8YDWSYBg&lc=UgxycIxZXRqjizt2GrR4AaABAg.9SQ42yvSnoS9SqCB_Xz7VI

Link on GitHub with WPF app code and PlatformIO code for Arduino Leonado: https://github.com/Pecilije/GT911-Capacitive-Touch-Glass-Panel

Pecilije Velicanstveni.

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.