16static size_t put16be(uint8_t *p, uint16_t v)
18 p[0] = (uint8_t)(v >> 8);
19 p[1] = (uint8_t)(v & 0xFF);
23static size_t put32be(uint8_t *p, uint32_t v)
25 p[0] = (uint8_t)((v >> 24) & 0xFF);
26 p[1] = (uint8_t)((v >> 16) & 0xFF);
27 p[2] = (uint8_t)((v >> 8) & 0xFF);
28 p[3] = (uint8_t)(v & 0xFF);
32static uint16_t get16be(
const uint8_t *p)
34 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
37static uint32_t get32be(
const uint8_t *p)
39 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
44static size_t write_envelope(uint8_t *buf,
size_t cap, FocasFrameType type, uint16_t payload_len)
46 if (!buf || cap < (
size_t)FOCAS_FRAME_HDR_LEN + payload_len)
53 p += put16be(buf + p, FOCAS_PROTO_VERSION);
54 p += put16be(buf + p, (uint16_t)type);
55 p += put16be(buf + p, payload_len);
59size_t focas_build_open(uint8_t *buf,
size_t cap)
61 size_t p = write_envelope(buf, cap, FocasFrameType::open_req, 2);
64 p += put16be(buf + p, FOCAS_FRAME_DST);
68size_t focas_build_close(uint8_t *buf,
size_t cap)
70 return write_envelope(buf, cap, FocasFrameType::close_req, 0);
73size_t focas_build_request(uint8_t *buf,
size_t cap, FocasCmd cmd, int32_t v1, int32_t v2, int32_t v3, int32_t v4,
74 int32_t v5,
const uint8_t *extra,
size_t extra_len)
76 if (extra_len && !extra)
78 if (extra_len > 0xFFFF - (
size_t)FOCAS_REQ_BODY_LEN)
80 uint16_t payload_len = (uint16_t)(FOCAS_REQ_BODY_LEN + extra_len);
81 size_t p = write_envelope(buf, cap, FocasFrameType::command_req, payload_len);
84 p += put16be(buf + p, cmd.c1);
85 p += put16be(buf + p, cmd.c2);
86 p += put16be(buf + p, cmd.c3);
87 p += put32be(buf + p, (uint32_t)v1);
88 p += put32be(buf + p, (uint32_t)v2);
89 p += put32be(buf + p, (uint32_t)v3);
90 p += put32be(buf + p, (uint32_t)v4);
91 p += put32be(buf + p, (uint32_t)v5);
94 memcpy(buf + p, extra, extra_len);
100size_t focas_build_sysinfo(uint8_t *buf,
size_t cap)
102 return focas_build_request(buf, cap, FocasCommand::sys_info, 0, 0, 0, 0, 0,
nullptr, 0);
105size_t focas_build_read_alarm(uint8_t *buf,
size_t cap)
107 return focas_build_request(buf, cap, FocasCommand::read_alarm, 0, 0, 0, 0, 0,
nullptr, 0);
110size_t focas_build_read_param(uint8_t *buf,
size_t cap, int32_t first, int32_t last, int32_t axis)
112 return focas_build_request(buf, cap, FocasCommand::read_cnc_param, first, last, axis, 0, 0,
nullptr, 0);
115size_t focas_build_read_macro(uint8_t *buf,
size_t cap, int32_t first, int32_t last)
117 return focas_build_request(buf, cap, FocasCommand::read_macro, first, last, 0, 0, 0,
nullptr, 0);
120size_t focas_build_read_position(uint8_t *buf,
size_t cap, int32_t kind, int32_t axis)
122 return focas_build_request(buf, cap, FocasCommand::read_position, kind, axis, 0, 0, 0,
nullptr, 0);
125size_t focas_build_read_feedrate(uint8_t *buf,
size_t cap)
127 return focas_build_request(buf, cap, FocasCommand::read_feedrate, 0, 0, 0, 0, 0,
nullptr, 0);
130size_t focas_build_read_spindle(uint8_t *buf,
size_t cap)
132 return focas_build_request(buf, cap, FocasCommand::read_spindle, 0, 0, 0, 0, 0,
nullptr, 0);
135bool focas_parse_frame(
const uint8_t *buf,
size_t len, FocasFrame *out)
137 if (!buf || !out || len < (
size_t)FOCAS_FRAME_HDR_LEN)
139 if (buf[0] != 0xA0 || buf[1] != 0xA0 || buf[2] != 0xA0 || buf[3] != 0xA0)
141 out->version = get16be(buf + 4);
142 out->type = (FocasFrameType)get16be(buf + 6);
143 out->payload_len = get16be(buf + 8);
144 if ((
size_t)FOCAS_FRAME_HDR_LEN + out->payload_len > len)
146 out->payload = buf + FOCAS_FRAME_HDR_LEN;
150bool focas_parse_response(
const uint8_t *payload,
size_t payload_len, FocasResponse *out)
152 if (!payload || !out || payload_len < (
size_t)FOCAS_RESP_HDR_LEN)
154 out->c1 = get16be(payload);
155 out->c2 = get16be(payload + 2);
156 out->c3 = get16be(payload + 4);
157 out->status = (int16_t)get16be(payload + 6);
158 out->data_len = get16be(payload + 12);
159 if ((
size_t)FOCAS_RESP_HDR_LEN + out->data_len > payload_len)
161 out->data = payload + FOCAS_RESP_HDR_LEN;
165bool focas_parse_command_frame(
const uint8_t *buf,
size_t len, FocasResponse *out)
168 if (!focas_parse_frame(buf, len, &f))
170 if (f.type != FocasFrameType::command_resp)
172 return focas_parse_response(f.payload, f.payload_len, out);
175bool focas_parse_sysinfo(
const uint8_t *data,
size_t data_len, FocasSysInfo *out)
177 if (!data || !out || data_len < (
size_t)FOCAS_SYSINFO_LEN)
179 out->add_info = get16be(data);
180 out->max_axis = get16be(data + 2);
181 memcpy(out->cnc_type, data + 4, 2);
182 out->cnc_type[2] =
'\0';
183 memcpy(out->mt_type, data + 6, 2);
184 out->mt_type[2] =
'\0';
185 memcpy(out->series, data + 8, 4);
186 out->series[4] =
'\0';
187 memcpy(out->version, data + 12, 4);
188 out->version[4] =
'\0';
189 memcpy(out->axes, data + 16, 2);
194bool focas_parse_alarm(
const uint8_t *data,
size_t data_len, uint32_t *alarm_status)
196 if (!data || !alarm_status || data_len < 4)
198 *alarm_status = get32be(data);
202bool focas_decode8(
const uint8_t *chunk,
size_t len, FocasValue *out)
204 if (!chunk || !out || len < (
size_t)FOCAS_VALUE_LEN)
206 out->data = (int32_t)get32be(chunk);
207 out->base = chunk[5];
210 out->valid = !(chunk[6] == 0xFF && chunk[7] == 0xFF) && (out->base == 2 || out->base == 10);
214float focas_value_f(
const FocasValue *v)
219 for (uint8_t i = 0; i < v->exp; i++)
220 div *= (
float)v->base;
221 return (
float)v->data / div;
FANUC FOCAS Ethernet protocol codec (DETWS_ENABLE_FOCAS) - zero-heap request builders + response pars...