Binary, Octal, of Hexadecimal representation ... I've always preferred Hex. as I can look at a 3-byte TMCC command packed as the 24 low order bits in an unsigned int. The entirety of the TMCC command set can be represented as a table/list/dictionary.
When the TMCC protocol was published in the '90s, I wrote some code to decode and display the commands received from a serial port. An initial interpretation of the protocol resulted in messy if-else code. The Legacy protocol made things worse. I've transition to a table-driven approach. Each command is an entry in the table where the entry ID (key, index, whatever) is the TMCC command with the variable bits (address and data) masked out. The exception is set absolute speed, and a few other commands, where a data value is needed. An entry for each possible data value (shown in the Set Relative Speed commands) enlarges the table. Doing the same for Set Absolute Speed Step would enlarge the table considerably as TMCC1 has 32 speed steps and TMCC2 has 200 steps (with today's plentiful memory, that may no longer be a barrier).
Decoding a three byte TMCC command is simple. Pack the three bytes as a 24-bit value in an unsigned int (32 bits or larger). Use the uint as a key to lookup the TMCC table entry by first masking out the address bits. If there are no variable data bits, the table entry is found on the first lookup. If command has data bits, then the table entry can't be found so my code has retry logic (using a variable data mask) to lookup variable data commands. Once the table entry is found, then the command can be decoded into human readable text.
The construction of a TMCC command is simple once the table entry is selected. The TMCC command is a unsigned int (32 bits or larger).
//
// build the 24-bit command, given the protocol, address, optional data value, and a reference to the TMCC command table
//
uint dataMask = CreateBitMask(tableEntry.maxDataValue); // bitmask for the largest variable data value
uint dataBits = ((uint)dataValue & dataMask);
uint protocolTypeBits = (uint)protocol << 16; //16252928=F8 16449536=FB 16646144=FE
uint addressBits = ((uint)tmccAddr << ((protocol == TMCCProtocolType.TMCC1) ? 7 : 9));
uint tmccCommandBits = ((uint)tableEntry.ID & 0xFFFF);
uint tmccCommand = protocolTypeBits | addressBits | tmccCommandBits | dataBits;
The TMCC command table:
// TMCC1 commands with 0xFE prefixed:
// ID TYPE CATEGORY MaxDataValue Text
{ 0xFE0000, TMCCType.Engine, TMCCCategory.Direction, 0, "Forward Direction"},
{ 0xFE0001, TMCCType.Engine, TMCCCategory.Direction, 0, "Toggle Direction"},
{ 0xFE0003, TMCCType.Engine, TMCCCategory.Direction, 0, "Reverse Direction"},
.........
{ 0xFE0040, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed -5"},
{ 0xFE0041, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed -4"},
{ 0xFE0042, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed -3"},
{ 0xFE0043, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed -2"},
{ 0xFE0044, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed -1"},
{ 0xFE0045, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed 0 (no change)"},
{ 0xFE0046, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed +1"},
{ 0xFE0047, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed +2"},
{ 0xFE0048, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed +3"},
{ 0xFE0049, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed +4"},
{ 0xFE004A, TMCCType.Engine, TMCCCategory.Speed, 0, "Set Relative Speed +5"},
{ 0xFE0060, TMCCType.Engine, TMCCCategory.Speed, 31, "Set Absolute Speed Step"}, //Max data value = 31
{ 0xFE4000, TMCCType.Switch, TMCCCategory.Direction, 0, "Throw THROUGH"},
{ 0xFE401F, TMCCType.Switch, TMCCCategory.Direction, 0, "Throw OUT"},
{ 0xFE402B, TMCCType.Switch, TMCCCategory.Settings, 0, "Set Address"},
{ 0xFE4040, TMCCType.Switch, TMCCCategory.Settings, 9, "Assign to Route THROUGH"}, //Max data value = 9
{ 0xFE4060, TMCCType.Switch, TMCCCategory.Settings, 9, "Assign to Route OUT"}, //Max data value = 9
..................
{ 0xFEFFFF, TMCCType.System, TMCCCategory.Other, 0, "System Halt"}
The attached C# code snippets have the full TMCC1 table. It may port to other coding environments without too much effort.