21constexpr FocasCmd FocasCommand::read_cnc_param;
22constexpr FocasCmd FocasCommand::read_macro;
23constexpr FocasCmd FocasCommand::set_macro;
24constexpr FocasCmd FocasCommand::sys_info;
25constexpr FocasCmd FocasCommand::read_alarm;
26constexpr FocasCmd FocasCommand::read_prg_num;
27constexpr FocasCmd FocasCommand::read_seq_num;
28constexpr FocasCmd FocasCommand::read_alarm_info;
29constexpr FocasCmd FocasCommand::read_feedrate;
30constexpr FocasCmd FocasCommand::read_spindle;
31constexpr FocasCmd FocasCommand::read_position;
32constexpr FocasCmd FocasCommand::read_diag;
33constexpr FocasCmd FocasCommand::read_spindle2;
34constexpr FocasCmd FocasCommand::read_datetime;
35constexpr FocasCmd FocasCommand::read_servo_load;
36constexpr FocasCmd FocasCommand::read_axis_names;
37constexpr FocasCmd FocasCommand::read_spindle_names;
38constexpr FocasCmd FocasCommand::read_cnc_param3;
39constexpr FocasCmd FocasCommand::read_macro_dbl;
40constexpr FocasCmd FocasCommand::read_pmc;
43static size_t put16be(uint8_t *p, uint16_t v)
45 p[0] = (uint8_t)(v >> 8);
46 p[1] = (uint8_t)(v & 0xFF);
50static size_t put32be(uint8_t *p, uint32_t v)
52 p[0] = (uint8_t)((v >> 24) & 0xFF);
53 p[1] = (uint8_t)((v >> 16) & 0xFF);
54 p[2] = (uint8_t)((v >> 8) & 0xFF);
55 p[3] = (uint8_t)(v & 0xFF);
59static uint16_t get16be(
const uint8_t *p)
61 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
64static uint32_t get32be(
const uint8_t *p)
66 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
71static size_t write_envelope(uint8_t *buf,
size_t cap, FocasFrameType type, uint16_t payload_len)
73 if (!buf || cap < (
size_t)FOCAS_FRAME_HDR_LEN + payload_len)
82 p += put16be(buf + p, FOCAS_PROTO_VERSION);
83 p += put16be(buf + p, (uint16_t)type);
84 p += put16be(buf + p, payload_len);
88size_t pc_focas_build_open(uint8_t *buf,
size_t cap)
90 size_t p = write_envelope(buf, cap, FocasFrameType::open_req, 2);
95 p += put16be(buf + p, FOCAS_FRAME_DST);
99size_t pc_focas_build_close(uint8_t *buf,
size_t cap)
101 return write_envelope(buf, cap, FocasFrameType::close_req, 0);
104size_t pc_focas_build_request(uint8_t *buf,
size_t cap, FocasCmd cmd, int32_t v1, int32_t v2, int32_t v3, int32_t v4,
105 int32_t v5,
const uint8_t *extra,
size_t extra_len)
107 if (extra_len && !extra)
111 if (extra_len > 0xFFFF - (
size_t)FOCAS_REQ_BODY_LEN)
115 uint16_t payload_len = (uint16_t)(FOCAS_REQ_BODY_LEN + extra_len);
116 size_t p = write_envelope(buf, cap, FocasFrameType::command_req, payload_len);
121 p += put16be(buf + p, cmd.c1);
122 p += put16be(buf + p, cmd.c2);
123 p += put16be(buf + p, cmd.c3);
124 p += put32be(buf + p, (uint32_t)v1);
125 p += put32be(buf + p, (uint32_t)v2);
126 p += put32be(buf + p, (uint32_t)v3);
127 p += put32be(buf + p, (uint32_t)v4);
128 p += put32be(buf + p, (uint32_t)v5);
131 memcpy(buf + p, extra, extra_len);
137size_t pc_focas_build_sysinfo(uint8_t *buf,
size_t cap)
139 return pc_focas_build_request(buf, cap, FocasCommand::sys_info, 0, 0, 0, 0, 0,
nullptr, 0);
142size_t pc_focas_build_read_alarm(uint8_t *buf,
size_t cap)
144 return pc_focas_build_request(buf, cap, FocasCommand::read_alarm, 0, 0, 0, 0, 0,
nullptr, 0);
147size_t pc_focas_build_read_param(uint8_t *buf,
size_t cap, int32_t first, int32_t last, int32_t axis)
149 return pc_focas_build_request(buf, cap, FocasCommand::read_cnc_param, first, last, axis, 0, 0,
nullptr, 0);
152size_t pc_focas_build_read_macro(uint8_t *buf,
size_t cap, int32_t first, int32_t last)
154 return pc_focas_build_request(buf, cap, FocasCommand::read_macro, first, last, 0, 0, 0,
nullptr, 0);
157size_t pc_focas_build_read_position(uint8_t *buf,
size_t cap, int32_t kind, int32_t axis)
159 return pc_focas_build_request(buf, cap, FocasCommand::read_position, kind, axis, 0, 0, 0,
nullptr, 0);
162size_t pc_focas_build_read_feedrate(uint8_t *buf,
size_t cap)
164 return pc_focas_build_request(buf, cap, FocasCommand::read_feedrate, 0, 0, 0, 0, 0,
nullptr, 0);
167size_t pc_focas_build_read_spindle(uint8_t *buf,
size_t cap)
169 return pc_focas_build_request(buf, cap, FocasCommand::read_spindle, 0, 0, 0, 0, 0,
nullptr, 0);
172bool pc_focas_parse_frame(
const uint8_t *buf,
size_t len, FocasFrame *out)
174 if (!buf || !out || len < (
size_t)FOCAS_FRAME_HDR_LEN)
178 if (buf[0] != 0xA0 || buf[1] != 0xA0 || buf[2] != 0xA0 || buf[3] != 0xA0)
182 out->version = get16be(buf + 4);
183 out->type = (FocasFrameType)get16be(buf + 6);
184 out->payload_len = get16be(buf + 8);
185 if ((
size_t)FOCAS_FRAME_HDR_LEN + out->payload_len > len)
189 out->payload = buf + FOCAS_FRAME_HDR_LEN;
193bool pc_focas_parse_response(
const uint8_t *payload,
size_t payload_len, FocasResponse *out)
195 if (!payload || !out || payload_len < (
size_t)FOCAS_RESP_HDR_LEN)
199 out->c1 = get16be(payload);
200 out->c2 = get16be(payload + 2);
201 out->c3 = get16be(payload + 4);
202 out->status = (int16_t)get16be(payload + 6);
203 out->data_len = get16be(payload + 12);
204 if ((
size_t)FOCAS_RESP_HDR_LEN + out->data_len > payload_len)
208 out->data = payload + FOCAS_RESP_HDR_LEN;
212bool pc_focas_parse_command_frame(
const uint8_t *buf,
size_t len, FocasResponse *out)
215 if (!pc_focas_parse_frame(buf, len, &f))
219 if (f.type != FocasFrameType::command_resp)
223 return pc_focas_parse_response(f.payload, f.payload_len, out);
226bool pc_focas_parse_sysinfo(
const uint8_t *data,
size_t data_len, FocasSysInfo *out)
228 if (!data || !out || data_len < (
size_t)FOCAS_SYSINFO_LEN)
232 out->add_info = get16be(data);
233 out->max_axis = get16be(data + 2);
234 memcpy(out->cnc_type, data + 4, 2);
235 out->cnc_type[2] =
'\0';
236 memcpy(out->mt_type, data + 6, 2);
237 out->mt_type[2] =
'\0';
238 memcpy(out->series, data + 8, 4);
239 out->series[4] =
'\0';
240 memcpy(out->version, data + 12, 4);
241 out->version[4] =
'\0';
242 memcpy(out->axes, data + 16, 2);
247bool pc_focas_parse_alarm(
const uint8_t *data,
size_t data_len, uint32_t *alarm_status)
249 if (!data || !alarm_status || data_len < 4)
253 *alarm_status = get32be(data);
257bool pc_focas_decode8(
const uint8_t *chunk,
size_t len, FocasValue *out)
259 if (!chunk || !out || len < (
size_t)FOCAS_VALUE_LEN)
263 out->data = (int32_t)get32be(chunk);
264 out->base = chunk[5];
267 out->valid = !(chunk[6] == 0xFF && chunk[7] == 0xFF) && (out->base == 2 || out->base == 10);
271float pc_focas_value_f(
const FocasValue *v)
278 for (uint8_t i = 0; i < v->exp; i++)
280 div *= (float)v->base;
282 return (
float)v->data / div;
FANUC FOCAS Ethernet protocol codec (PC_ENABLE_FOCAS) - zero-heap request builders + response parsers...