16size_t pc_melsec_build_read(uint8_t *buf,
size_t cap, uint8_t device_code, uint32_t head_device, uint16_t points,
17 uint16_t monitoring_timer)
19 if (!buf || cap < MELSEC_3E_READ_REQ_LEN)
24 buf[p++] = MELSEC_3E_REQ_SUBHEADER0;
25 buf[p++] = MELSEC_3E_REQ_SUBHEADER1;
26 buf[p++] = MELSEC_NETWORK_DEFAULT;
27 buf[p++] = MELSEC_PC_DEFAULT;
28 p +=
pc_wr16le(buf + p, MELSEC_DEST_IO_DEFAULT);
29 buf[p++] = MELSEC_DEST_MULTIDROP_DEFAULT;
32 p +=
pc_wr16le(buf + p, MELSEC_3E_READ_REQ_DATA_LEN);
33 p +=
pc_wr16le(buf + p, monitoring_timer);
34 p +=
pc_wr16le(buf + p, MELSEC_CMD_BATCH_READ);
35 p +=
pc_wr16le(buf + p, MELSEC_SUBCMD_WORD);
36 buf[p++] = (uint8_t)(head_device & 0xFF);
37 buf[p++] = (uint8_t)((head_device >> 8) & 0xFF);
38 buf[p++] = (uint8_t)((head_device >> 16) & 0xFF);
39 buf[p++] = device_code;
44size_t pc_melsec_build_write(uint8_t *buf,
size_t cap, uint8_t device_code, uint32_t head_device, uint16_t points,
45 uint16_t monitoring_timer,
const uint8_t *data,
size_t data_len)
47 if (!buf || (data_len && !data))
51 if (data_len > (
size_t)(0xFFFFu - MELSEC_3E_READ_REQ_DATA_LEN))
55 if (cap < MELSEC_3E_READ_REQ_LEN + data_len)
60 buf[p++] = MELSEC_3E_REQ_SUBHEADER0;
61 buf[p++] = MELSEC_3E_REQ_SUBHEADER1;
62 buf[p++] = MELSEC_NETWORK_DEFAULT;
63 buf[p++] = MELSEC_PC_DEFAULT;
64 p +=
pc_wr16le(buf + p, MELSEC_DEST_IO_DEFAULT);
65 buf[p++] = MELSEC_DEST_MULTIDROP_DEFAULT;
67 p +=
pc_wr16le(buf + p, (uint16_t)(MELSEC_3E_READ_REQ_DATA_LEN + data_len));
68 p +=
pc_wr16le(buf + p, monitoring_timer);
69 p +=
pc_wr16le(buf + p, MELSEC_CMD_BATCH_WRITE);
70 p +=
pc_wr16le(buf + p, MELSEC_SUBCMD_WORD);
71 buf[p++] = (uint8_t)(head_device & 0xFF);
72 buf[p++] = (uint8_t)((head_device >> 8) & 0xFF);
73 buf[p++] = (uint8_t)((head_device >> 16) & 0xFF);
74 buf[p++] = device_code;
78 memcpy(buf + p, data, data_len);
84bool pc_melsec_parse_response(
const uint8_t *buf,
size_t len, MelsecResponse *out)
87 if (!buf || !out || len < MELSEC_3E_RES_MIN_LEN)
91 if (buf[0] != MELSEC_3E_RES_SUBHEADER0 || buf[1] != MELSEC_3E_RES_SUBHEADER1)
95 uint16_t data_length =
pc_rd16le(buf + MELSEC_3E_RES_LEN_OFFSET);
96 if (data_length < MELSEC_ENDCODE_LEN)
100 if (MELSEC_3E_RES_DATALEN_BASE + (
size_t)data_length > len)
104 out->end_code =
pc_rd16le(buf + MELSEC_3E_RES_DATALEN_BASE);
105 out->data = buf + MELSEC_3E_RES_DATA_OFFSET;
106 out->data_len = (size_t)data_length - MELSEC_ENDCODE_LEN;
Fixed-width integer serializers into a raw uint8_t* buffer - one source of truth.
uint16_t pc_rd16le(const uint8_t *p)
Read a little-endian u16 at p.
size_t pc_wr16le(uint8_t *p, uint16_t v)
Write v little-endian at p.
Mitsubishi MELSEC MC protocol (binary 3E frame) codec (PC_ENABLE_MELSEC) - zero-heap batch-read reque...