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)
26 out[1] = (uint8_t)val_len;
29 memcpy(out + 2, val, val_len);
35size_t int_content(int32_t v, uint8_t *buf)
39 tmp[0] = (uint8_t)(v >> 24);
40 tmp[1] = (uint8_t)(v >> 16);
41 tmp[2] = (uint8_t)(v >> 8);
45 while (start < 3 && ((tmp[start] == 0x00 && (tmp[start + 1] & 0x80) == 0) ||
46 (tmp[start] == 0xFF && (tmp[start + 1] & 0x80) != 0)))
51 for (
size_t i = 0; i < n; i++)
53 buf[i] = tmp[start + i];
59size_t pc_iccp_state_q(uint8_t state, uint8_t flags,
const uint8_t time[4], uint8_t *out,
size_t cap)
68 uint8_t sq = (uint8_t)(((state & 0x3) << 6) | (flags & Iccp::ICCP_QUAL_MASK));
69 size_t r = tlv(0x85, &sq, 1, inner + n,
sizeof(inner) - n);
77 r = tlv(0x17, time, 4, inner + n,
sizeof(inner) - n);
85 return tlv(0xA2, inner, n, out, cap);
88size_t pc_iccp_real_q(int32_t milli, uint8_t flags,
const uint8_t time[4], uint8_t *out,
size_t cap)
97 size_t il = int_content(milli, ic);
98 size_t r = tlv(0x02, ic, il, inner + n,
sizeof(inner) - n);
104 uint8_t q = (uint8_t)(flags & Iccp::ICCP_QUAL_MASK);
105 r = tlv(0x85, &q, 1, inner + n,
sizeof(inner) - n);
113 r = tlv(0x17, time, 4, inner + n,
sizeof(inner) - n);
121 return tlv(0xA3, inner, n, out, cap);
ICCP / TASE.2 (IEC 60870-6) inter-control-center telemetry codec (PC_ENABLE_ICCP).