I am reverse engineering the serial protocol for a console and it has been relatively straight forward until I got to decoding the reports for a frequency control that consists of a small knob with a larger outer knob.
The hardware has two rotary encoders that drive the position event reports.
The console uses a serial ack/nak protocol that continuously streams reports in a packet format that has the following attributes:
Lead byte is an 0xA5
Payload Data byte values do not exceed a value of 0x7F, zero is allowed.
- Checksum is computed by XOR’ing the payload bytes.
- After resetting the console the output repeats every twenty clicks of the small knob.
- After resetting the console the output repeats every ten clicks of the large knob.
- Output data is variable based on the position of the other knob, so the report is for both knobs.
- Clicking the same knob counter-clockwise, returns the previous event report.
- The event report ID value is 0x0C.
- In other types of event reports the third byte is the overflow of the second byte.
Small knob alone after console reset:
0C 0C 5B //index 00
0C 11 5B //index 01
0C 16 5B //index 02
0C 1B 5B //index 03
0C 20 5B //index 04
0C 25 5B //index 05
0C 2A 5B //index 06
0C 2F 5B //index 07
0C 50 5A //index 08
0C 55 5A //index 09
0C 5A 5A //index 10
0C 5F 5A //index 11
0C 64 5A //index 12
0C 69 5A //index 13
0C 6E 5A //index 14
0C 73 5A //index 15
0C 78 5A //index 16
0C 7D 5A //index 17
0C 02 5B //index 18
0C 07 5B //index 19
Large knob after console reset:
0C 0C 5B //index 00
0C 70 5B //index 01
0C 6C 54 //index 02
0C 50 55 //index 03
0C 34 56 //index 04
0C 18 57 //index 05
0C 7C 57 //index 06
0C 60 58 //index 07
0C 44 59 //index 08
0C 28 5A //index 09
Console reset followed by first rotating large and small knobs counter-clockwise one position. Then rotating the large knob clockwise one position, followed by the small knob.
Large Knob - Small Knob
0C 28 5A - 0C 23 5A //Index -1 rotate counter-clockwise one position
0C 07 5B - 0C 0C 5B //Index 00
0C 70 5B - 0C 75 5B //Index 01
0C 71 54 - 0C 76 54 //Index 02
0C 5A 55 - 0C 5F 55 //Index 03
0C 43 56 - 0C 48 56 //Index 04
0C 2C 57 - 0C 31 57 //Index 05
0C 15 58 - 0C 1A 58 //Index 06
0C 7E 58 - 0C 03 59 //Index 07
0C 67 59 - 0C 08 59 //Index 08
0C 6C 59 - 0C 71 59 //Index 09
0C 55 5A - 0C 5A 5A //Index 10
0C 3E 5B - 0C 43 5B //Index 11
0C 3F 54 - 0C 44 54 //Index 12
0C 28 55 - 0C 2D 55 //Index 13
0C 11 56 - 0C 16 56 //Index 14
0C 7A 56 - 0C 7F 56 //Index 15
0C 63 57 - 0C 68 57 //Index 16
0C 4C 58 - 0C 51 58 //Index 17
0C 35 59 - 0C 3A 59 //Index 18
0C 1E 5A - 0C 23 5A //Index 19
0C 07 5B - 0C 0C 5B //Index 20
0C 70 5B - 0C 75 5B //Index 21
0C 71 54 - 0C 76 54 //Index 22
0C 5A 55 - 0C 5F 55 //Index 23
0C 43 56 - 0C 48 56 //Index 24
0C 2C 57 - 0C 31 57 //Index 25
0C 15 58 - 0C 1A 58 //Index 26
0C 7E 58 - 0C 03 59 //Index 27
0C 67 59 - 0C 08 59 //Index 28
0C 6C 59 - 0C 71 59 //Index 29
0C 55 5A - 0C 5A 5A //Index 30
0C 3E 5B - 0C 43 5B //Index 31
0C 3F 54 - 0C 44 54 //Index 32
0C 28 55 - 0C 2D 55 //Index 33
0C 11 56 - 0C 16 56 //Index 34
0C 7A 56 - 0C 7F 56 //Index 35
0C 63 57 - 0C 68 57 //Index 36
0C 4C 58 - 0C 51 58 //Index 37
0C 35 59 - 0C 3A 59 //Index 38
0C 1E 5A - 0C 23 5A //Index 39
0C 07 5B - 0C 0C 5B //Index 40