18size_t tlv(uint8_t tag,
const uint8_t *val,
size_t val_len, uint8_t *out,
size_t cap)
20 if (val_len > 0x7F || 2 + val_len > cap)
23 out[1] = (uint8_t)val_len;
25 memcpy(out + 2, val, val_len);
30size_t int_content(int32_t v, uint8_t *buf)
34 tmp[0] = (uint8_t)(v >> 24);
35 tmp[1] = (uint8_t)(v >> 16);
36 tmp[2] = (uint8_t)(v >> 8);
40 while (start < 3 && ((tmp[start] == 0x00 && (tmp[start + 1] & 0x80) == 0) ||
41 (tmp[start] == 0xFF && (tmp[start + 1] & 0x80) != 0)))
44 for (
size_t i = 0; i < n; i++)
45 buf[i] = tmp[start + i];
50size_t detws_iccp_state_q(uint8_t state, uint8_t flags,
const uint8_t time[4], uint8_t *out,
size_t cap)
57 uint8_t sq = (uint8_t)(((state & 0x3) << 6) | (flags & Iccp::ICCP_QUAL_MASK));
58 size_t r = tlv(0x85, &sq, 1, inner + n,
sizeof(inner) - n);
64 r = tlv(0x17, time, 4, inner + n,
sizeof(inner) - n);
70 return tlv(0xA2, inner, n, out, cap);
73size_t detws_iccp_real_q(int32_t milli, uint8_t flags,
const uint8_t time[4], uint8_t *out,
size_t cap)
80 size_t il = int_content(milli, ic);
81 size_t r = tlv(0x02, ic, il, inner + n,
sizeof(inner) - n);
85 uint8_t q = (uint8_t)(flags & Iccp::ICCP_QUAL_MASK);
86 r = tlv(0x85, &q, 1, inner + n,
sizeof(inner) - n);
92 r = tlv(0x17, time, 4, inner + n,
sizeof(inner) - n);
98 return tlv(0xA3, inner, n, out, cap);
ICCP / TASE.2 (IEC 60870-6) inter-control-center telemetry codec (DETWS_ENABLE_ICCP).