11#if DETWS_ENABLE_DIRECTNET
17char hex_digit(uint8_t nibble)
20 return (
char)(nibble < 10 ? (
'0' + nibble) : (
'A' + nibble - 10));
23void put_hex(uint8_t *p, uint32_t value,
int digits)
25 for (
int i = 0; i < digits; i++)
26 p[i] = (uint8_t)hex_digit((uint8_t)(value >> (4 * (digits - 1 - i))));
30uint8_t detws_dnet_lrc(
const uint8_t *bytes,
size_t len)
33 for (
size_t i = 0; i < len; i++)
38size_t detws_dnet_header(uint8_t slave, uint8_t type, uint16_t address, uint8_t blocks, uint8_t *out,
size_t cap)
41 const size_t n = 1 + 2 + 1 + 4 + 2 + 1 + 1;
45 out[i++] = DnetByte::DNET_SOH;
46 put_hex(out + i, slave, 2);
49 put_hex(out + i, address, 4);
51 put_hex(out + i, blocks, 2);
53 out[i++] = DnetByte::DNET_ETB;
55 out[i] = detws_dnet_lrc(out + 1, i - 1);
60size_t detws_dnet_data(
const uint8_t *data,
size_t data_len, uint8_t *out,
size_t cap)
62 if (!out || (data_len && !data))
64 size_t n = 1 + data_len + 1 + 1;
68 out[i++] = DnetByte::DNET_STX;
71 memcpy(out + i, data, data_len);
74 out[i++] = DnetByte::DNET_ETX;
76 out[i] = detws_dnet_lrc(out + 1, i - 1);
81bool detws_dnet_data_parse(
const uint8_t *frame,
size_t len,
const uint8_t **data,
size_t *data_len)
83 if (!frame || len < 3)
85 if (frame[0] != DnetByte::DNET_STX)
88 size_t etx_idx = len - 2;
89 if (frame[etx_idx] != DnetByte::DNET_ETX)
91 if (detws_dnet_lrc(frame + 1, len - 2) != frame[len - 1])
94 *data = (etx_idx > 1) ? (frame + 1) :
nullptr;
96 *data_len = etx_idx - 1;
AutomationDirect / Koyo DirectNET serial frame codec (DETWS_ENABLE_DIRECTNET).