11#if PC_ENABLE_DEVICENET
15bool pc_devicenet_encode_id(uint32_t *
id, DeviceNetGroup group, uint8_t msg_id, uint8_t mac_id)
17 if (!
id || mac_id > DEVICENET_MAC_MASK)
23 case DeviceNetGroup::DEVICENET_GROUP_1:
28 *
id = DEVICENET_G1_BASE | ((uint32_t)msg_id << 6) | mac_id;
30 case DeviceNetGroup::DEVICENET_GROUP_2:
35 *
id = DEVICENET_G2_BASE | ((uint32_t)mac_id << 3) | msg_id;
37 case DeviceNetGroup::DEVICENET_GROUP_3:
42 *
id = DEVICENET_G3_BASE | ((uint32_t)msg_id << 6) | mac_id;
44 case DeviceNetGroup::DEVICENET_GROUP_4:
49 *
id = DEVICENET_G4_BASE | msg_id;
56bool pc_devicenet_decode_id(uint32_t can_id, DeviceNetId *out)
63 if (
id < DEVICENET_G2_BASE)
65 out->group = DeviceNetGroup::DEVICENET_GROUP_1;
66 out->msg_id = (uint8_t)((
id >> 6) & 0x0Fu);
67 out->mac_id = (uint8_t)(
id & DEVICENET_MAC_MASK);
70 if (
id < DEVICENET_G3_BASE)
72 out->group = DeviceNetGroup::DEVICENET_GROUP_2;
73 out->mac_id = (uint8_t)((
id >> 3) & DEVICENET_MAC_MASK);
74 out->msg_id = (uint8_t)(
id & 0x07u);
77 if (
id < DEVICENET_G4_BASE)
79 out->group = DeviceNetGroup::DEVICENET_GROUP_3;
80 out->msg_id = (uint8_t)((
id >> 6) & 0x07u);
81 out->mac_id = (uint8_t)(
id & DEVICENET_MAC_MASK);
86 out->group = DeviceNetGroup::DEVICENET_GROUP_4;
87 out->msg_id = (uint8_t)(
id & 0x3Fu);
94uint8_t pc_devicenet_msg_header(
bool frag,
bool xid, uint8_t mac_id)
96 return (uint8_t)((frag ? DEVICENET_HDR_FRAG : 0u) | (xid ? DEVICENET_HDR_XID : 0u) | (mac_id & DEVICENET_MAC_MASK));
99uint8_t pc_devicenet_frag_octet(uint8_t type, uint8_t count)
101 return (uint8_t)((type & DEVICENET_FRAG_TYPE_MASK) | (count & DEVICENET_FRAG_COUNT_MASK));
104bool pc_devicenet_build_explicit(
CanFrame *out, DeviceNetGroup group, uint8_t msg_id, uint8_t mac_id,
105 const uint8_t *body, uint8_t body_len)
107 if (!out || body_len > 7 || (body_len && !body))
112 if (!pc_devicenet_encode_id(&
id, group, msg_id, mac_id))
119 out->
dlc = (uint8_t)(1 + body_len);
120 memset(out->
data, 0,
sizeof(out->
data));
121 out->
data[0] = pc_devicenet_msg_header(
false,
false, mac_id);
124 memcpy(out->
data + 1, body, body_len);
129bool pc_devicenet_build_fragment(
CanFrame *out, DeviceNetGroup group, uint8_t msg_id, uint8_t mac_id,
bool xid,
130 uint8_t frag_type, uint8_t frag_count,
const uint8_t *data, uint8_t data_len)
133 if (!out || data_len > 6 || (data_len && !data) || (frag_type & (uint8_t)~DEVICENET_FRAG_TYPE_MASK) ||
134 (frag_count & (uint8_t)~DEVICENET_FRAG_COUNT_MASK))
139 if (!pc_devicenet_encode_id(&
id, group, msg_id, mac_id))
146 out->
dlc = (uint8_t)(2 + data_len);
147 memset(out->
data, 0,
sizeof(out->
data));
148 out->
data[0] = pc_devicenet_msg_header(
true, xid, mac_id);
149 out->
data[1] = pc_devicenet_frag_octet(frag_type, frag_count);
152 memcpy(out->
data + 2, data, data_len);
157void pc_devicenet_frag_reset(DeviceNetFragRx *rx)
161 memset(rx, 0,
sizeof(*rx));
170static_assert(PC_DEVICENET_MSG_MAX >= 254,
171 "PC_DEVICENET_MSG_MAX must be >= 254 (the largest single-frame append, body_len - 1 with "
172 "body_len at its uint8_t maximum) or frag_append can overflow on the first frame");
175static bool frag_append(DeviceNetFragRx *rx,
const uint8_t *p, uint8_t n)
177 if ((uint32_t)rx->len + n > PC_DEVICENET_MSG_MAX)
181 memcpy(rx->buf + rx->len, p, n);
182 rx->len = (uint16_t)(rx->len + n);
186DeviceNetFragResult pc_devicenet_frag_feed(DeviceNetFragRx *rx,
const uint8_t *body, uint8_t body_len)
188 if (!rx || !body || body_len < 1)
190 return DeviceNetFragResult::DEVICENET_FRAG_IGNORED;
193 if (!(body[0] & DEVICENET_HDR_FRAG))
195 pc_devicenet_frag_reset(rx);
198 if (body_len > 1 && !frag_append(rx, body + 1, (uint8_t)(body_len - 1)))
200 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
202 return DeviceNetFragResult::DEVICENET_FRAG_COMPLETE;
206 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
208 uint8_t type = body[1] & DEVICENET_FRAG_TYPE_MASK;
209 uint8_t count = body[1] & DEVICENET_FRAG_COUNT_MASK;
210 const uint8_t *data = body + 2;
211 uint8_t data_len = (uint8_t)(body_len - 2);
215 case DEVICENET_FRAG_FIRST:
216 pc_devicenet_frag_reset(rx);
218 rx->next_count = (uint8_t)((count + 1u) & DEVICENET_FRAG_COUNT_MASK);
221 if (data_len && !frag_append(rx, data, data_len))
223 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
225 return DeviceNetFragResult::DEVICENET_FRAG_STARTED;
226 case DEVICENET_FRAG_MIDDLE:
227 if (!rx->active || count != rx->next_count)
229 pc_devicenet_frag_reset(rx);
230 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
232 if (data_len && !frag_append(rx, data, data_len))
234 pc_devicenet_frag_reset(rx);
235 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
237 rx->next_count = (uint8_t)((count + 1u) & DEVICENET_FRAG_COUNT_MASK);
238 return DeviceNetFragResult::DEVICENET_FRAG_PROGRESS;
239 case DEVICENET_FRAG_LAST:
240 if (!rx->active || count != rx->next_count)
242 pc_devicenet_frag_reset(rx);
243 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
245 if (data_len && !frag_append(rx, data, data_len))
247 pc_devicenet_frag_reset(rx);
248 return DeviceNetFragResult::DEVICENET_FRAG_ERR;
251 return DeviceNetFragResult::DEVICENET_FRAG_COMPLETE;
253 return DeviceNetFragResult::DEVICENET_FRAG_IGNORED;
#define PC_CAN_STD_ID_MASK
11-bit standard identifier.
DeviceNet link-adaptation codec (PC_ENABLE_DEVICENET) - the CAN-specific layer of "CIP over CAN".
uint8_t data[PC_CAN_MAX_DLC]