3.0 KiB
UBus
Minimal hdlc-over-half-duplex-rs485 bus protcol.
Bus
Bus is running half-duplex 115200bps UART over RS485 line.
Framing
All frames transmitted over a bus are encoded using HDLC rules:
- Start byte (0x7e)
- Message payload
- 0x7d or 0x7e bytes in message payload are substituted with [0x7e, byte ^ 0x20]
- Last 2 bytes of message payload are CRC16
CRC-CCITT
checksum- NOTE: byte escaping applies here as well!
- NOTE: checksumming over all message bytes including the checksum should result in checksum 0... (this is a feature of pretty much all CRC algorithms, that, it seems, not many people are aware of)
- Message delimiter (end byte, 0x7e)
- Next message may follow immediately (but won't, see below...)
Addressing
Bus supports 126 addresses 0x00 = bus master 0x01 - 0x3e = bus slave
Most significant bit indicates message direction. Slaves responsing to requests need to set 0b10000000.
Messages
Master → slave
struct msg {
uint8_t target;
uint8_t request_type;
uint8_t request_payload[]; // depends on message type, may be ommitted
uint16_t checksum; // crc16 ccitt
}
Slave → master
struct msg {
uint8_t source; // target ^ 0x80
uint8_t response_type;
uint8_t response_payload[]; // depends on message type, may be ommitted
uint16_t checksum; // crc16 ccitt
}
Broadcast messages
Broadcast messages (target 0xff) are handled TDMA-style. Receiving nodes get assigned _broadcast_timeslot (20ms) each for their response. Every slave needs to respond after (addr * _broadcast_timeslot) ms after final request delimiter byte (0x7e). (TODO: this needs to be properly implemented in serial interrupt by peeking at last byte received... This is impossible unless we patch standard Arduino Serial implementation)
20ms is enough for approximately 200 bytes of effective application payload response for every node.
Message type
0x0x System Block
0x00 - Status Poll
Basic bus status poll.
struct req { };
struct resp {
uint8_t status;
// 00h - ok
// 01h - ffh = error
};
0x01 - Identify
Light up status LED for 0.5s.
struct req { };
struct resp { };
0x02 - Query Supported Commands
struct req { };
struct resp {
uint8_t commands[]; // implemented message IDs
};
0x1x IO Block
0x10 - GPIO Write
struct req {
struct {
uint8_t io_num;
uint8_t value;
} pins[];
};
struct resp {
uint8_t status;
// 00h = ok
// 01h - ffh error;
};
0x11 - GPIO Read
struct req {
uint8_t pins[];
};
struct resp {
uint8_t values[];
};
0x12 - WS2812 Write
struct req {
uint8_t pin;
uint8_t data; // packed RGB data, num_leds * 3
};
struct resp {
uint8_t status;
// 00h = ok
// 01h - ffh error;
};
0x2x Peripheral Block
0x20 - NFC Read
Read NFC reader.
struct req { };
struct resp {
uint8_t uid[]; // empty if no card read
};