16uint16_t pc_mbplus_crc(
const uint8_t *bytes,
size_t len)
23size_t pc_mbplus_build(uint8_t address, uint8_t control,
const uint8_t *payload,
size_t payload_len, uint8_t *out,
26 if (!out || (payload_len && !payload) || address < 1 || address > Mbplus::MBPLUS_MAX_STATION)
30 size_t n = 1 + 1 + 1 + payload_len + 2 + 1;
36 out[i++] = Mbplus::MBPLUS_FLAG;
42 memcpy(out + i, payload, payload_len);
45 uint16_t crc = pc_mbplus_crc(out + body, (i - body));
46 out[i++] = (uint8_t)crc;
47 out[i++] = (uint8_t)(crc >> 8);
48 out[i++] = Mbplus::MBPLUS_FLAG;
52bool pc_mbplus_parse(
const uint8_t *frame,
size_t len, MbPlusFrame *out)
55 if (!frame || !out || len < 6)
59 if (frame[0] != Mbplus::MBPLUS_FLAG || frame[len - 1] != Mbplus::MBPLUS_FLAG)
64 size_t body_end = len - 1;
65 size_t crc_pos = body_end - 2;
66 size_t covered = crc_pos - 1;
67 uint16_t want = pc_mbplus_crc(frame + 1, covered);
68 uint16_t got = (uint16_t)(frame[crc_pos] | (frame[crc_pos + 1] << 8));
73 out->address = frame[1];
74 out->control = frame[2];
75 out->payload = (covered > 2) ? (frame + 3) :
nullptr;
76 out->payload_len = covered - 2;
80uint8_t pc_mbplus_next_token(uint8_t current, uint8_t max_station)
86 return (current >= max_station) ? 1 : (uint8_t)(current + 1);
Parameterized CRC engine - one source of truth for every cyclic redundancy check.
constexpr pc_crc_params PC_CRC16_X25
CRC-16/X-25 (HDLC FCS). check = 0x906E. Used by services/radio/thread, mbplus, nema_ts2.
uint32_t pc_crc(const pc_crc_params *p, const uint8_t *data, size_t len)
One-shot CRC of len octets at data.
Modbus Plus HDLC token-bus frame codec (PC_ENABLE_MBPLUS).