Plus Deck 2C Serial Protocol

Commands

Commands are sent as individual bytes:

byte (dec) byte (hex) byte (binary) command
01 01 0000 0001 play side A
02 02 0000 0010 play side B
03 03 0000 0011 fast-forward
04 04 0000 0100 rewind
05 05 0000 0101 toggle pause
06 06 0000 0110 stop
08 08 0000 1000 eject
11 0B 0000 1011 subscribe
12 0C 0000 1100 unsubscribe

These appear to be more or less in-order, though that leaves questions about the significance of skipping 0x07 (7) and 0x09-0x0A (9-10). On a cursory glance, there don't seem to be any significant byte masks, range starts, etc. The most likely scenario is that 0x00 and 0xA are reserved, and subscribe/unsubscribe exist on a block that starts at 0x0A.

It's believed that this is more or less exhaustive. Clicking other buttons, such as looping behavior, don't seem to send commands - it's believed this behavior is implemented in software - and the device doesn't advertise any other behavior, such as writing to tape (the mic jack seems entirely for proxying to the front panel). That said, testing some other bytes to see what happens may be worthwhile.

Statuses

Statuses are emitted in a relatively tight loop as individual bytes:

byte (dec) byte (hex) byte (binary) status
10 0A 0000 1010 playing side A
12 0C 0000 1100 paused on side A (unsubscribe 1)
20 14 0001 0100 playing side B
21 15 0001 0101 ready/subscribed
22 16 0001 0110 paused on side B (unsubscribe 2)
30 1E 0001 1110 fast-forwarding
40 28 0010 1000 rewinding
50 32 0011 0010 stopped
60 3C 0011 1100 ejected

Note that I have not produced any error codes - hitting buttons twice is idempotent, and hitting buttons on eject does not yield any code other than 0x3C (60).

Unlike commands, there are a few clear relationships between the bytes chosen. Categories are chosen starting at multiples of 10:

Range Start Meaning
10 (0x0A) Play/Pause, Side A
20 (0x14) Play/Pause, Side B
30 (0x1E) Fast Movement, Side A
40 (0x28) Fast Movement, Side B
50 (0x32) Stopped
60 (0x3C) Ejected

In addition, play and pause commands are separated by 2. For example, playing side A is 10 (0x0A), while pausing side A is 12 (0x0C) = 10 + 2.

The outlier is ready/subscribed, at 21 (0x15), right in between playing B (20) and paused B (22). I believe this event is an accident. My evidence for this is that there isn't a clear event for unsubscribing. Instead, the device either emits 12 (0x0C) or 22 (0x16), - paused on A and paused on B respectively. This makes me think that some incidental aspect of the device's design causes it to emit these bytes, and that, while that behavior seems reliable, it's not intentional.

Something I haven't tried is seeing if plugging/unplugging headphones triggers any events. I don't expect them but it's worth checking.