I'm creating a bare-bones data filter to help me make sense of the bytes constantly streaming between control panel and main board of a Canon Pixma MX340 multi-function inkjet. I'll start with just one of the two wires, control panel to main board. There are two advantages to starting this way. The first is that, from a few snippets examined with a logic analyzer, the data is just a single byte. (Well, there are two byte sequences upon startup, but steady state has only single bytes.) Either a byte reporting the state of the button matrix, or a byte 0x20 acknowledging something sent by the main board. The second is that, in the steady state, the the button matrix state is reported once every 9.2ms. Which means I always have some data to work with as I get the basics in place, no need to fuss with the MX340.

Data constantly coming in every 9.2ms creates a flood of data impractical to peruse in my logic analyzer timeline view, so a simple data filter does wonders. I start by ignoring the 0x20 acknowledgement bytes and focus on the button matrix state. Comparing each incoming byte with the previous byte, the program only reports if there is a change in value. Such logic gave me a program that reports the updated value as I press buttons on the control panel. With this tool up and running, it only took a few minutes to obtain the values (sometimes called scancode) for every button on the matrix.

(The "Power" and "Stop" buttons are wired directly to the main board and not part of the matrix.)

Earlier I looked at four of these buttons and hypothesized the value is related to their circuit board wiring. Indeed if I sort them by scan code value in a 4x8 table, their pattern line up with pins of the K13988 chip scanning this button array. Expressed as hexadecimal (0x prefix) the scan code pattern didn't jump out at me. I wrote them out in binary (0b prefix) and there's definitely something, and the pattern finally became clear when I wrote the scan code out in octal (0o prefix).

NEC
K13988
Pin
20 23 24 22
3 0x89
0b10001001
0o211

SW201
7
0x8A
0b10001010
0o212

SW208
1
0x8B
0b10001011
0o213

SW214
*
0x8C
0b10001100
0o214

SW221
4
4 0x91
0b10010001
0o221

SW206
Fax Quality
0x92
0b10010010
0o222

SW212
Settings
0x93
0b10010011
0o223

SW219
Back
0x94
0b10010100
0o224

SW226
Menu
5 0x99
0b10011001
0o231

SW202
8
0x9A
0b10011010
0o232

SW209
2
0x9B
0b10011011
0o233

SW215
0
0x9C
0b10011100
0o234

SW222
5
6 0xA1
0b10100001
0o241

SW203
9
0xA2
0b10100010
0o242

SW210
3
0xA3
0b10100011
0o243

SW216
#
0xA4
0b10100100
0o244

SW223
6
7 0xA9
0b10101001
0o251

SW204
Copy
0xAA
0b10101010
0o252

(No Switch)
(Unused)
0xAB
0b10101011
0o253

SW217
Fax
0xAC
0b10101100
0o254

SW224
Scan
8 0xB1
0b10110001
0o261

SW205
Black & White
0xB2
0b10110010
0o262

SW211
Redial/Pause
0xB3
0b10110011
0o263

SW218
Color
0xB4
0b10110100
0o264

SW225
Coded Dial
1 0xC9
0b11001001
0o311

SW207
OK
0xCA
0b11001010
0o312

SW213
Right/+
0xCB
0b11001011
0o313

SW220
Left/-
0xCC
0b11001100
0o314

SW227
Hook

A pattern is also visible in the silkscreen label for each of these switches. Though it doesn't seem to line up in either pin order or report value order. There's also a gap in the matrix as pin 7 + 23 scan code 0xAA is unused. Switch numbering didn't skip that entry but continues uninterrupted. Given those facts, I don't think there's much value in sorting by silkscreen switch label number, so I'll keep this table sorted by button press reporting scan code values.

While smashing buttons to get scan codes to assemble this table, I also rediscovered how to toggle the two LEDs also controlled by the K13988 chip allowing me to capture and decode related commands.


This teardown ran far longer than I originally thought it would. Click here to rewind back to where this adventure started.