29#define HDLC_TRY_PUT_BYTE(byte, frame, error_handling) \
32 if ((frame)->length + 1 > (frame)->capacity) \
34 goto error_handling; \
36 (frame)->payload[(frame)->length++] = byte; \
39#define HDLC_BIT_STUFF_ONES_LIMIT 5U
59 if (frame == NULL || (payload == NULL && payload_length > 0) || (frame->
capacity < 2) ||
69 for (
size_t i = 0; i < payload_length; i++)
77 uint16_t crc16 =
hdlc_crc16(payload, payload_length);
91 LOG_DEBUG(
"HDLC ENCODE: len=%zu first=0x%02X last=0x%02X\r\n", frame->
length,
111#define SHIFT_IN_BIT(out_byte, bitorder, bit, bitpos) \
112 (bitorder) ? ((out_byte) | ((bit) << (bitpos))) : ((out_byte) | ((bit) << (7 - (bitpos))))
114#define ENCODER_TRY_FLUSH_BYTE_OUT(encoder, frame, error_handling) \
117 if ((++(encoder)->out_bits_used) == CHAR_BIT) \
119 HDLC_TRY_PUT_BYTE(((encoder)->out_byte), (frame), error_handling); \
120 (encoder)->out_bits_used = 0; \
121 (encoder)->out_byte = 0; \
125#define ENCODER_ZERO_PAD_AND_DRAIN(encoder, frame, error_handling) \
128 if ((encoder)->out_bits_used > 0) \
130 HDLC_TRY_PUT_BYTE((encoder)->out_byte, frame, error_handling); \
131 (encoder)->out_byte = 0; \
132 (encoder)->ones_run = 0; \
133 (encoder)->out_bits_used = 0; \
139 uint8_t bitmask = bit ? (encoder->
ones_run++, 1) : (encoder->
ones_run = 0, 0);
158 for (uint8_t i = 0; i < CHAR_BIT; i++)
160 size_t bit_pos = encoder->
lsb_first ? i : (CHAR_BIT - 1U - i);
162 bool bit = ((
byte >> bit_pos) & 0x01U) != 0U;
174 if (frame == NULL || (payload == NULL && payload_length > 0) || (frame->
capacity < 2) ||
184 .
out_byte = 0, .out_bits_used = 0, .ones_run = 0, .lsb_first = lsb_first};
186 for (
size_t i = 0; i < payload_length; i++)
194 uint16_t crc16 =
hdlc_crc16(payload, payload_length);
195 if (!
hdlc_put_byte(&encoder, (crc16 >> CHAR_BIT) & 0xFF, frame) ||
208 LOG_DEBUG(
"HDLC ENCODE(BIT): len=%zu first=0x%02X last=0x%02X\r\n", frame->
length,
uint16_t hdlc_crc16(const uint8_t *payload, size_t num_bytes)
Compute HDLC CRC16 (FCS) over a payload.
#define ENCODER_ZERO_PAD_AND_DRAIN(encoder, frame, error_handling)
#define ENCODER_TRY_FLUSH_BYTE_OUT(encoder, frame, error_handling)
static bool hdlc_put_byte(hdlc_encoder_t *encoder, uint8_t byte, HDLC_FRAME_T *frame)
#define HDLC_TRY_PUT_BYTE(byte, frame, error_handling)
bool hdlc_encode(const uint8_t *payload, const size_t payload_length, HDLC_FRAME_T *frame, bool lsb_first)
Encode payload into an HDLC bit-stuffed frame.
#define SHIFT_IN_BIT(out_byte, bitorder, bit, bitpos)
bool hdlc_encode_byte(const uint8_t *payload, const size_t payload_length, HDLC_FRAME_T *frame)
Encode payload using byte-escaping HDLC compatibility path.
static bool hdlc_escape_if_needed(uint8_t byte, HDLC_FRAME_T *frame)
#define HDLC_BIT_STUFF_ONES_LIMIT
static bool hdlc_put_bit(hdlc_encoder_t *encoder, bool bit, HDLC_FRAME_T *frame)
Generic HDLC frame buffer descriptor.