Recreate i2c from logic analyzer to arduino

Hello i am reverse engineering a touch panel from its original controller. I have used a logic analyze to analyze the transaction. and i have already identfied the data of interest

Imaage

Now what makes this very hard since this is i2c i do not know who is the one "sending" the data since the line is biderectional.

As you can see the logic analyzer have identified seven "cluster" per transaction The first one is the address simple enough, the second one is what i think is an address, third and the seventh are the register of interest since when i press a button there will be a change on those address depending on the button pressed as for 4th,5th,6th i could not get them to change but it does not matter as all button presses are already mapped to the 3r and 7th register.

Now i would like to swap out its original controller with an Arduino, and i have to recreate that request , i already have checked the voltage level and its 5v.

Before i try to communicate with an arduuino, iwould like to ask if i am correct in doing this

#include <Wire.h>

void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop() {
  Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #0x53

  while (Wire.available()) { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  }

You have a touch screen and its controller. That You have been reverse engineering regarding the I2C bus. Well done.
Removing that controller You need to reverse engineering the controller signals to the screen. Right?

Why replace the controller? Why not use it instead?

IMO you should send a command and parameters to the slave before expecting it to return data, see the Wire lib SFRRanger_Reader example step 3.

Railroader:
You have a touch screen and its controller. That You have been reverse engineering regarding the I2C bus. Well done.
Removing that controller You need to reverse engineering the controller signals to the screen. Right?

Why replace the controller? Why not use it instead?

to add some features it dont have, and make some other changes that i didnt like on the original :slight_smile:

DrDiettrich:
IMO you should send a command and parameters to the slave before expecting it to return data, see the Wire lib SFRRanger_Reader example step 3.

So it would look something like this ?

  Wire.beginTransmission(0x53); 
  Wire.write(byte(0x84));      

  Wire.requestFrom(0x53, 5);    // request 2 bytes from slave device #112

the image above is how every transmission look like exempt for the 3rd and 7th byte which changes depending on what i press.
Using the marking on the touch IC i could not find a datasheet which makes it a bit hard on how to pull data,
So you are saying the second byte is from the master an the remaingin 5 bytes is the response from the touch IC?

A command can be followed by none or more parameters like register number or mode. You'll find examples in the data sheets of any I2C slave device.

Is the notation "R(0x53)" the 7-bit shifted I2C address 0x53 with read-bit ? Then 6 bytes are read.
Did you confirm with a I2C Scanner sketch that the I2C address is 0x53 ?
Are you sure that there is only a read request on the I2C bus ? Most sensors require to have a register address that needs to be written or a command to be written, but some touch sensors support only one read command.

You should check if you got 6 bytes when you request 6 bytes.
Don't overflow the I2C with requests, the device might not like that. Perhaps a delay of 50ms is already good enough.

not tested:

void loop() 
{
  byte myData[6];

  Serial.println( "---------------------");
  Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #0x53
  if( Wire.available == 6)    // got the same amount of bytes that was requested ?
  {
    Wire.readBytes( myData, 6);
    for( int i=0; i<6; i++)
    {
      Serial.print( "0x");
      if( myData[i] < 0x10)
        Serial.print( "0");
      Serial.print( myData[i], HEX);
      Serial.print( ", ");
    }
    Serial.println();
  }
  else
  {
    Serial.println( "no valid data returned");
  }
  delay( 200);   // Give the device time to breath
}

Why bother about the I2C bus? You intend to remove the controller and replace it. Start tracking the signals between the screen snd the controller.

Koepel:
Is the notation "R(0x53)" the 7-bit shifted I2C address 0x53 with read-bit ? Then 6 bytes are read.
Did you confirm with a I2C Scanner sketch that the I2C address is 0x53 ?
Are you sure that there is only a read request on the I2C bus ? Most sensors require to have a register address that needs to be written or a command to be written, but some touch sensors support only one read command.

You should check if you got 6 bytes when you request 6 bytes.
Don't overflow the I2C with requests, the device might not like that. Perhaps a delay of 50ms is already good enough.

not tested:

void loop() 

{
 byte myData[6];

Serial.println( "---------------------");
 Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #0x53
 if( Wire.available == 6)    // got the same amount of bytes that was requested ?
 {
   Wire.readBytes( myData, 6);
   for( int i=0; i<6; i++)
   {
     Serial.print( "0x");
     if( myData[i] < 0x10)
       Serial.print( "0");
     Serial.print( myData[i], HEX);
     Serial.print( ", ");
   }
   Serial.println();
 }
 else
 {
   Serial.println( "no valid data returned");
 }
 delay( 200);   // Give the device time to breath
}

The first data does not look the same
image
i think its just started the wrong address?? because when i pessed some buttons its now split into 2 bytes second and 3rd after the address. also the button thats supposed to be in the 7th byte is now not there,
I tried adding a write function but it does not change the response

void loop()
{
  byte myData[6];

  Serial.println( "---------------------");
  Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #0x53
  Wire.write(byte(0x84));     // attempting to start at 0x84
  
  if( Wire.available() == 6)    // got the same amount of bytes that was requested ?
  {
    Wire.readBytes( myData, 6);
    for( int i=0; i<6; i++)
    {
      Serial.print( "0x");
      if( myData[i] < 0x10)
        Serial.print( "0");
      Serial.print( myData[i], HEX);
      Serial.print( ", ");
    }
    Serial.println();
  }
  else
  {
    Serial.println( "no valid data returned");
  }
  delay( 200);   // Give the device time to breath
}

I can not see that picture.
Can you show pictures of all the I2C bus activity ? Is there really a "write" before the picture of the capture in your top post ?
In the picture, the 0x84 is read from the device. That is not written.

With a LHT00SU1 logic analyzer with sigrok/PulseView, the data can be analyzed on a computer.

Koepel:
I can not see that picture.
Can you show pictures of all the I2C bus activity ? Is there really a "write" before the picture of the capture in your top post ?
In the picture, the 0x84 is read from the device. That is not written.

With a LHT00SU1 logic analyzer with sigrok/PulseView, the data can be analyzed on a computer.
https://www.banggood.com/Geekcreit-LHT00SU1-Virtual-Oscilloscope-Logic-Analyzer-I2C-SPI-CAN-Uart-p-988565.html

So this is where i am now, so i thought why am i getting a different reading on the logic anylzer from the Arduino
and the original controller. I guessed that there must have been an some initialization settings that was set. So i removed the interrupt pin which triggered the read request so that i wont get flodded with data and low and behold
sorry i cant upload a picture none of the image hosting sites are working for me for some reason but heres the output on my Logic Analyzer terminal

write to 0x53 ack data: 0xB1 0x43 0x00 0x04 
write to 0x53 ack data: 0xC0 0x0D 0x00 
write to 0x53 ack data: 0xC1 0x0D 0x00 
write to 0x53 ack data: 0xC2 0x0D 0x00 
write to 0x53 ack data: 0xC3 0x0D 0x00 
write to 0x53 ack data: 0xC4 0x0D 0x00 
write to 0x53 ack data: 0xC5 0x15 0x00 
write to 0x53 ack data: 0xC6 0x15 0x00 
write to 0x53 ack data: 0xC7 0x15 0x00 
write to 0x53 ack data: 0xC8 0x15 0x00 
write to 0x53 ack data: 0xC9 0x15 0x00 
write to 0x53 ack data: 0xCA 0x15 0x00 
write to 0x53 ack data: 0xCB 0x15 0x00 
write to 0x53 ack data: 0xCC 0x15 0x00 
write to 0x53 ack data: 0xD0 0x02 0x00 
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x00 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x80 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x80 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x80 0x00 0x00 0x00 0x00 0x00
read to 0x53 ack data: 0x80 0x00 0x00 0x00 0x00 0x00

So i double confirmed this by first hooking the touch panel to the original controller, then i swaped the i2c bus with the arduino's withouut disconnecting power. and sure enough your code is now outputting the proper values

#include <Wire.h> //include Wire.h library

void setup()
{
  Wire.begin(); // Wire communication begin
  Serial.begin(9600); // The baudrate of Serial monitor is set in 9600
  while (!Serial); // Waiting for Serial Monitor
  Serial.println("\nI2C Scanner");

  Wire.beginTransmission(0x53);   // 1st
  Wire.send(byte(0xB1));
  Wire.send(byte(0x43));
  Wire.send(byte(0x00));
  Wire.send(byte(0x04));
  Wire.endTransmission();


  Wire.beginTransmission(0x53);   // 2nd
  Wire.send(byte(0xC0));
  Wire.send(byte(0x0D));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 3rd
  Wire.send(byte(0xC1));
  Wire.send(byte(0x0D));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 4th
  Wire.send(byte(0xC2));
  Wire.send(byte(0x0D));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 5th
  Wire.send(byte(0xC3));
  Wire.send(byte(0x0D));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 6th
  Wire.send(byte(0xC4));
  Wire.send(byte(0x0D));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 7th
  Wire.send(byte(0xC5));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 8th
  Wire.send(byte(0xC6));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 9th
  Wire.send(byte(0xC7));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 10th
  Wire.send(byte(0xC8));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 11th
  Wire.send(byte(0xC9));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 12th
  Wire.send(byte(0xCA));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 13th
  Wire.send(byte(0xCB));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 14th
  Wire.send(byte(0xCC));
  Wire.send(byte(0x15));
  Wire.send(byte(0x00));
  Wire.endTransmission();

  Wire.beginTransmission(0x53);   // 15th
  Wire.send(byte(0xD0));
  Wire.send(byte(0x02));
  Wire.send(byte(0x00));
  Wire.endTransmission();



}

void loop()
{
  byte myData[6];

  Serial.println( "---------------------");
  Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #0x53

  if ( Wire.available() == 6)   // got the same amount of bytes that was requested ?
  {
    Wire.readBytes( myData, 6);

    for ( int i = 0; i < 6; i++)
    {
      Serial.print( "0x");
      if ( myData[i] < 0x10)
        Serial.print( "0");
      Serial.print( myData[i], HEX);
      Serial.print( ", ");
    }
    Serial.println();

  }

  else
  {
    Serial.println( "no valid data returned");
  }
  delay( 200);   // Give the device time to breath
}

So i painstakingly manually inputted those value, BUT i am getting an error saying

'class TwoWire' has no member named 'send'; did you mean 'end'?

what? the word Wire.sen even turns orange on my IDE ?

The standard output method for all Stream classes is write(), and class TwoWire most probably inherits from Stream.

You don't have to quote my whole post, what I wrote is already there :wink:

That seems to be initialization of registers, all the B1 to D0 are probably registers.

A function puts the hexadecimal number in a nicer way in the source code. That is easier to check if they are right.
They are right by the way, because I used a macro recorder to create those lines from your numbers, so I skipped the painstakingly manually part :stuck_out_tongue:

void setup()
{
  Wire.begin();

  delay( 2000);   // maybe the TouchPanel needs time to startup

  // Initialize the Touch Panel.
  writeTouchPanel4( 0xB1, 0x43, 0x00, 0x04);
  writeTouchPanel3( 0xC0, 0x0D, 0x00);
  writeTouchPanel3( 0xC1, 0x0D, 0x00);
  writeTouchPanel3( 0xC2, 0x0D, 0x00);
  writeTouchPanel3( 0xC3, 0x0D, 0x00);
  writeTouchPanel3( 0xC4, 0x0D, 0x00);
  writeTouchPanel3( 0xC5, 0x15, 0x00);
  writeTouchPanel3( 0xC6, 0x15, 0x00);
  writeTouchPanel3( 0xC7, 0x15, 0x00);
  writeTouchPanel3( 0xC8, 0x15, 0x00);
  writeTouchPanel3( 0xC9, 0x15, 0x00);
  writeTouchPanel3( 0xCA, 0x15, 0x00);
  writeTouchPanel3( 0xCB, 0x15, 0x00);
  writeTouchPanel3( 0xCC, 0x15, 0x00);
  writeTouchPanel3( 0xD0, 0x02, 0x00);
}

void loop()
{
  ...
}

void writeTouchPanel4( int a, int b, int c, int d)
{
  Wire.beginTransmission( 0x53);
  Wire.write( a);
  Wire.write( b);
  Wire.write( c);
  Wire.write( d);
  Wire.endTransmission();
}

void writeTouchPanel3( int a, int b, int c)
{
  Wire.beginTransmission( 0x53);
  Wire.write( a);
  Wire.write( b);
  Wire.write( c);
  Wire.endTransmission();
}

The 'send' is what I call: mistake number 5.
For the normal I2C communication at 100kHz to 400kHz, there is either a I2C-read or I2C-write operation on the bus. They can not be mixed. Maybe my alternative explanation explains it better than the Arduino reference.

If it works, can you extract the right information from the data ?

It works great now ! thank you vey much sir !

i must have been reading an outdated guide all along

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.