В качестве прототипов - SLIP и WAKE. Недостаток первого - неудобные stuff-коды, усложняющие работу в полудуплексном режиме, у второго - наличие байта адреса, который вполне мог бы отсутствовать для всех безадресных команд.
Не долго думая:
Код
#define Slp_packet_end 0xFF /* indicates end of packet */
#define Slp_stuffing_esc 0xFE /* indicates byte stuffing */
#define Slp_byte_esc_end 0xFD /* ESC ESC_END means END data byte */
#define Slp_byte_esc_esc 0xFC /* ESC ESC_ESC means ESC data byte */
Протокол пакетный, пакет заканчивается символом Slp_packet_end. А в полудуплексном режиме так же имеет префикс из 2х символов Slp_packet_end. Остальное, в общем, аналогично SLIP.
Пакет начинается с кода команды. Далее, в случае адресных команд, идет адрес. В отличие от WAKE.
Диапазон команд поделен пополам: 0x00..0x7F - запросы мастера, 0x80..0xFF - ответы слейвов.
Код
#define Slp_commands 0x00
#define Slp_pipe_commands 0x00 // потоковые, безадресные команды
#define Slp_system_commands 0x10 // системные, безадресные команды
#define Slp_sysdev_commands 0x20 // системные, MAC-адресные (16 байт) команды
#define Slp_device_commands 0x30 // адресные (байт) команды
#define Slp_user_commands 0x40 // определяется пользователем
#define Slp_responses 0x80 // ответы
Код ответа формируется из кода команды запроса + 0x80. Далее идет адрес слейва, если адрес был в запросе.
В случае если команда устройством не поддерживается, либо при ее выполнении возникла ошибка, формирование ответа на этом заканчивается.
Т.е. размер пакета может быть переменный. Но максимальный размер пакета, наверно нужно ограничить где-то 64 байтами - вопрос открыт.
Все пакеты завершаются CRC16, полином 0x1021, дающий такие результаты на контрольных последовательностях
Код
// Пустой пакет 0x1D0F
// A 0x9479
// 1234567890 xE5CC
// 256*A chars 0xE938