Skip to content

Instantly share code, notes, and snippets.

@Gkiokan
Created March 8, 2026 15:15
Show Gist options
  • Select an option

  • Save Gkiokan/8aefe4cdb439e4bf2c6c6fda1f7857db to your computer and use it in GitHub Desktop.

Select an option

Save Gkiokan/8aefe4cdb439e4bf2c6c6fda1f7857db to your computer and use it in GitHub Desktop.
pa5x ribbon controll board debugg
[FOUND] I2C device found at address 0x0B
@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 9, 2026

Offset Logic in Ghidra What it represents
0x08 cVar7 / Mode 0x18 (Scanning), 0x02 (Active Touch)
0x0E uVar21 (Bitmask) Touch Status: A bitmask of which segments are active.
0x10 - 0x11 uVar17 (16-bit) Rough Position: The "Segment ID" that has the strongest signal.
0x12 - 0x13 iVar10 (Interpolated) High-Res Position: The 0–255 (or 0–1023) position of your finger.

@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 9, 2026

This table is the "DNA" of your ribbon controller. Each entry in this table usually follows a fixed size (e.g., 12 or 16 bytes). Here is the structure the code is parsing:

Offset Size Meaning
+0x00 4 bytes Pointer to the next object (the "Link")
+0x04 4 bytes ID / Key (This is where it matches 0x08, 0x12, etc.)
+0x08 4 bytes Data Pointer (Where the actual value lives in RAM)
+0x0C 1 byte Type/Permissions (0 = Read Only, 1 = Read/Write)
+0x0D 1 byte Child Count (How many sub-items are under this one)

@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 9, 2026

  1. The 14-Sensor Array (while (iVar10 != 0xe))
    This part of the code confirms exactly how many physical pads are on your ribbon: 14 sensors (0xe).

C
do {
// ... logic for sensor signal processing ...
iVar10 = iVar10 + 1;
puVar26 = puVar26 + 5;
} while (iVar10 != 0xe);
The code loops through these 14 sensors, reading their raw capacitance values and comparing them to a "Baseline."

  1. The Centroid Calculation (The High-Res Value)
    This is the "Smoking Gun" for your high-resolution data. The code uses a weighted average to determine where your finger is between those 14 pads:

C
iVar10 = FUN_00006ec8(DAT_00001378 * (uVar14 - uVar19), uVar17 + uVar19 + uVar14);
*(short *)(iVar16 + 0x32) = (short)(uVar29 * iVar25 + iVar10 + 0x7f >> 8);
uVar29: The "Coarse" position (which of the 14 pads has the strongest signal).

iVar10: The "Fine" offset (how far your finger is leaning toward the left or right neighbor).

0x32: The high-resolution result is stored at Offset 0x32 in the RAM block pointed to by iVar16.

*(undefined1 *)(param_1 + DAT_00000fcc) = 0x12; // Register ID 0x12
*(undefined1 *)(param_1 + DAT_00000fd0) = 6; // Length or Status
*(char *)(param_1 + DAT_00000fd4) = cVar7; // The actual data byte
This confirms that Register 0x12 is indeed the Touch Position. The reason it appeared as 0 earlier is likely because the "State" (cVar7) was set to 0 (No Touch).

  1. The "Demo Mode" Gatekeeper
    Look at the beginning of the function:

C
cVar7 = *(char *)(param_1 + DAT_00000fa0);
if (cVar7 == '\0') { ... }
if (cVar7 == '\x01') { ... }
if (cVar7 == '\x02') { ... }
This is a State Machine.

State 0: Power-on / Calibrating.

State 1: Idle / Waiting for touch.

State 2: Active Scanning.

State 3/4: Sending data to the Host (the ribbon's internal master or your ESP32).

@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 9, 2026

## Your Packet Structure Summary

Based on this function and the ones before it, your 6-byte packet likely looks like this:

Byte Offset | Value / Meaning | Source -- | -- | -- 0 | 0x12 (Header) | Hardcoded in 0d10 1 | 0x06 (Length) | Hardcoded in 0d10 2 | param_1 (Zone/ID) | Input to 0d10 3 | X-Coordinate | From FUN_00001880 4 | Y-Coordinate | From FUN_00001880 5 | Checksum / Status | Calculated before buffer push

@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 9, 2026

We found several "Magic Numbers" that you will need for your ESP32 code:

0x230: A flag indicating if an averaging cycle is complete.

0x0D: A special state (likely "Calibration Mode" or "Deep Sleep").

0x12: Again, confirming the Start Header for all outgoing data.

@Gkiokan
Copy link
Copy Markdown
Author

Gkiokan commented Mar 10, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment