Lely core libraries  2.3.4
pdo.c
Go to the documentation of this file.
1 
24 #include "co.h"
25 
26 #if !LELY_NO_CO_RPDO || !LELY_NO_CO_TPDO
27 
28 #include <lely/can/msg.h>
29 #include <lely/co/dev.h>
30 #include <lely/co/obj.h>
31 #include <lely/co/pdo.h>
32 #include <lely/co/sdo.h>
33 #include <lely/util/endian.h>
34 
35 #include <assert.h>
36 
37 static co_unsigned32_t co_dev_cfg_pdo_comm(const co_dev_t *dev,
38  co_unsigned16_t idx, const struct co_pdo_comm_par *par);
39 
40 static co_unsigned32_t co_dev_cfg_pdo_map(const co_dev_t *dev,
41  co_unsigned16_t num, const struct co_pdo_map_par *par);
42 
43 #if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
44 co_unsigned32_t co_mpdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev,
45  struct co_sdo_req *req, const uint_least8_t *buf, size_t n);
46 #endif
47 
48 #if !LELY_NO_CO_RPDO
49 
50 co_unsigned32_t
51 co_dev_chk_rpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
52 {
53  assert(dev);
54 
55  if (co_type_is_basic(idx) && !subidx) {
56  // If the object is a dummy entry, check if it is enabled.
57  if (!(co_dev_get_dummy(dev) & (1 << idx)))
58  return CO_SDO_AC_NO_OBJ;
59  } else {
60  co_obj_t *obj = co_dev_find_obj(dev, idx);
61  if (!obj)
62  return CO_SDO_AC_NO_OBJ;
63 
64  co_sub_t *sub = co_obj_find_sub(obj, subidx);
65  if (!sub)
66  return CO_SDO_AC_NO_SUB;
67 
68  unsigned int access = co_sub_get_access(sub);
69  if (!(access & CO_ACCESS_WRITE))
70  return CO_SDO_AC_NO_WRITE;
71 
72  if (!co_sub_get_pdo_mapping(sub) || !(access & CO_ACCESS_RPDO))
73  return CO_SDO_AC_NO_PDO;
74  }
75 
76  return 0;
77 }
78 
79 co_unsigned32_t
80 co_dev_cfg_rpdo(const co_dev_t *dev, co_unsigned16_t num,
81  const struct co_pdo_comm_par *comm,
82  const struct co_pdo_map_par *map)
83 {
84  assert(comm);
85 
86  co_unsigned32_t ac = 0;
87 
88  struct co_pdo_comm_par par = *comm;
89  // Disable the RPDO service before configuring any parameters.
91  ac = co_dev_cfg_rpdo_comm(dev, num, &par);
92  if (ac)
93  return ac;
94 
95  ac = co_dev_cfg_rpdo_map(dev, num, map);
96  if (ac)
97  return ac;
98 
99  // Re-enable the RPDO service if necessary.
100  if (!(comm->cobid & CO_PDO_COBID_VALID))
101  ac = co_dev_cfg_rpdo_comm(dev, num, comm);
102  return ac;
103 }
104 
105 co_unsigned32_t
106 co_dev_cfg_rpdo_comm(const co_dev_t *dev, co_unsigned16_t num,
107  const struct co_pdo_comm_par *par)
108 {
109  if (!num || num > CO_NUM_PDOS)
110  return CO_SDO_AC_NO_OBJ;
111 
112  return co_dev_cfg_pdo_comm(dev, 0x1400 + num - 1, par);
113 }
114 
115 co_unsigned32_t
116 co_dev_cfg_rpdo_map(const co_dev_t *dev, co_unsigned16_t num,
117  const struct co_pdo_map_par *par)
118 {
119  if (!num || num > CO_NUM_PDOS)
120  return CO_SDO_AC_NO_OBJ;
121 
122  return co_dev_cfg_pdo_map(dev, 0x1600 + num - 1, par);
123 }
124 
125 #endif // !LELY_NO_CO_RPDO
126 
127 #if !LELY_NO_CO_TPDO
128 
129 co_unsigned32_t
130 co_dev_chk_tpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
131 {
132  assert(dev);
133 
134  co_obj_t *obj = co_dev_find_obj(dev, idx);
135  if (!obj)
136  return CO_SDO_AC_NO_OBJ;
137 
138  co_sub_t *sub = co_obj_find_sub(obj, subidx);
139  if (!sub)
140  return CO_SDO_AC_NO_SUB;
141 
142  unsigned int access = co_sub_get_access(sub);
143  if (!(access & CO_ACCESS_READ))
144  return CO_SDO_AC_NO_READ;
145 
146  if (!co_sub_get_pdo_mapping(sub) || !(access & CO_ACCESS_TPDO))
147  return CO_SDO_AC_NO_PDO;
148 
149  return 0;
150 }
151 
152 co_unsigned32_t
153 co_dev_cfg_tpdo(const co_dev_t *dev, co_unsigned16_t num,
154  const struct co_pdo_comm_par *comm,
155  const struct co_pdo_map_par *map)
156 {
157  assert(comm);
158 
159  co_unsigned32_t ac = 0;
160 
161  struct co_pdo_comm_par par = *comm;
162  // Disable the TPDO service before configuring any parameters.
163  par.cobid |= CO_PDO_COBID_VALID;
164  ac = co_dev_cfg_tpdo_comm(dev, num, &par);
165  if (ac)
166  return ac;
167 
168  ac = co_dev_cfg_tpdo_map(dev, num, map);
169  if (ac)
170  return ac;
171 
172  // Re-enable the TPDO service if necessary.
173  if (!(comm->cobid & CO_PDO_COBID_VALID))
174  ac = co_dev_cfg_tpdo_comm(dev, num, comm);
175  return ac;
176 }
177 
178 co_unsigned32_t
179 co_dev_cfg_tpdo_comm(const co_dev_t *dev, co_unsigned16_t num,
180  const struct co_pdo_comm_par *par)
181 {
182  if (!num || num > CO_NUM_PDOS)
183  return CO_SDO_AC_NO_OBJ;
184 
185  return co_dev_cfg_pdo_comm(dev, 0x1800 + num - 1, par);
186 }
187 
188 co_unsigned32_t
189 co_dev_cfg_tpdo_map(const co_dev_t *dev, co_unsigned16_t num,
190  const struct co_pdo_map_par *par)
191 {
192  if (!num || num > CO_NUM_PDOS)
193  return CO_SDO_AC_NO_OBJ;
194 
195  return co_dev_cfg_pdo_map(dev, 0x1a00 + num - 1, par);
196 }
197 
198 #endif // !LELY_NO_CO_TPDO
199 
200 #if !LELY_NO_CO_MPDO
201 
202 int
204  const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
205 {
206  assert(dev);
207 
208  // Loop over all sub-objects in the object scanner list (1FA0..1FCF).
209  co_obj_t *obj = NULL;
210  for (co_unsigned16_t i = 0x1fa0; !obj && i <= 0x1fcf; i++)
211  obj = co_dev_find_obj(dev, i);
212  for (; obj && co_obj_get_idx(obj) <= 0x1fcf; obj = co_obj_next(obj)) {
213  co_unsigned8_t n = co_obj_get_val_u8(obj, 0);
214  if (!n)
215  continue;
217  for (; sub && co_sub_get_subidx(sub) <= n;
218  sub = co_sub_next(sub)) {
219  co_unsigned32_t val = co_sub_get_val_u32(sub);
220  if (!val)
221  continue;
222  // Check if the object index matches.
223  if (((val >> 8) & 0xffff) != idx)
224  continue;
225  // Check if the object sub-index is part of the
226  // specified block.
227  co_unsigned8_t min = val & 0xff;
228  if (subidx < min)
229  continue;
230  co_unsigned8_t max = min;
231  co_unsigned8_t blk = (val >> 24) & 0xff;
232  if (blk)
233  max += MIN(blk - 1, 0xff - min);
234  if (subidx > max)
235  continue;
236 
237  return 1;
238  }
239  }
240 
241  return 0;
242 }
243 
244 int
245 co_dev_map_sam_mpdo(const co_dev_t *dev, co_unsigned8_t id, co_unsigned16_t idx,
246  co_unsigned8_t subidx, co_unsigned16_t *pidx,
247  co_unsigned8_t *psubidx)
248 {
249  assert(dev);
250 
251  // Loop over all sub-objects in the object dispatching list
252  // (1FD0..1FFF).
253  co_obj_t *obj = NULL;
254  for (co_unsigned16_t i = 0x1fd0; !obj && i <= 0x1fff; i++)
255  obj = co_dev_find_obj(dev, i);
256  for (; obj && co_obj_get_idx(obj) <= 0x1fff; obj = co_obj_next(obj)) {
257  co_unsigned8_t n = co_obj_get_val_u8(obj, 0);
258  if (!n)
259  continue;
261  for (; sub && co_sub_get_subidx(sub) <= n;
262  sub = co_sub_next(sub)) {
263  co_unsigned64_t val = co_sub_get_val_u64(sub);
264  if (!val)
265  continue;
266  // Check if the remote node-ID and object index match.
267  if ((val & 0xff) != id)
268  continue;
269  if (((val >> 16) & 0xffff) != idx)
270  continue;
271  // Check if the remote object sub-index is part of the
272  // specified block.
273  co_unsigned8_t min = (val >> 8) & 0xff;
274  if (subidx < min)
275  continue;
276  co_unsigned8_t max = min;
277  co_unsigned8_t blk = (val >> 54) & 0xff;
278  if (blk)
279  max += MIN(blk - 1, 0xff - min);
280  if (subidx > max)
281  continue;
282 
283  if (pidx)
284  *pidx = (val >> 40) & 0xffff;
285  if (psubidx) {
286  *psubidx = (val >> 32) & 0xff;
287  *psubidx += subidx - min;
288  }
289  return 1;
290  }
291  }
292 
293  return 0;
294 }
295 
296 #endif // !LELY_NO_CO_MPDO
297 
298 co_unsigned32_t
299 co_pdo_map(const struct co_pdo_map_par *par, const co_unsigned64_t *val,
300  co_unsigned8_t n, uint_least8_t *buf, size_t *pn)
301 {
302  assert(par);
303  assert(val);
304 
305  if (par->n > CO_PDO_NUM_MAPS || n != par->n)
306  return CO_SDO_AC_PDO_LEN;
307 
308  size_t offset = 0;
309  for (size_t i = 0; i < par->n; i++) {
310  co_unsigned32_t map = par->map[i];
311  if (!map)
312  continue;
313 
314  co_unsigned8_t len = map & 0xff;
315  if (offset + len > CAN_MAX_LEN * 8)
316  return CO_SDO_AC_PDO_LEN;
317 
318  uint_least8_t tmp[sizeof(co_unsigned64_t)] = { 0 };
319  stle_u64(tmp, val[i]);
320  if (buf && pn && offset + len <= *pn * 8)
321  bcpyle(buf, offset, tmp, 0, len);
322 
323  offset += len;
324  }
325 
326  if (pn)
327  *pn = (offset + 7) / 8;
328 
329  return 0;
330 }
331 
332 co_unsigned32_t
333 co_pdo_unmap(const struct co_pdo_map_par *par, const uint_least8_t *buf,
334  size_t n, co_unsigned64_t *val, co_unsigned8_t *pn)
335 {
336  assert(par);
337  assert(buf);
338 
339  if (par->n > CO_PDO_NUM_MAPS)
340  return CO_SDO_AC_PDO_LEN;
341 
342  size_t offset = 0;
343  for (size_t i = 0; i < par->n; i++) {
344  co_unsigned32_t map = par->map[i];
345  if (!map)
346  continue;
347 
348  co_unsigned8_t len = map & 0xff;
349  if (offset + len > n * 8)
350  return CO_SDO_AC_PDO_LEN;
351 
352  uint_least8_t tmp[sizeof(co_unsigned64_t)] = { 0 };
353  bcpyle(tmp, 0, buf, offset, len);
354  if (val && pn && i < *pn)
355  val[i] = ldle_u64(tmp);
356 
357  offset += len;
358  }
359 
360  if (pn)
361  *pn = par->n;
362 
363  return 0;
364 }
365 
366 #if !LELY_NO_CO_RPDO
367 co_unsigned32_t
368 co_pdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev,
369  struct co_sdo_req *req, const uint_least8_t *buf, size_t n,
370  int chk)
371 {
372  assert(par);
373  assert(dev);
374  assert(req);
375  assert(buf);
376 
377  if (par->n > CO_PDO_NUM_MAPS) {
378 #if LELY_NO_CO_MPDO
379  return CO_SDO_AC_PDO_LEN;
380 #else
381  return co_mpdo_dn(par, dev, req, buf, n);
382 #endif // !LELY_NO_CO_MPDO
383  }
384 
385  if (n > CAN_MAX_LEN)
386  return CO_SDO_AC_PDO_LEN;
387 
388  size_t offset = 0;
389  for (size_t i = 0; i < par->n; i++) {
390  co_unsigned32_t map = par->map[i];
391  if (!map)
392  continue;
393 
394  co_unsigned16_t idx = (map >> 16) & 0xffff;
395  co_unsigned8_t subidx = (map >> 8) & 0xff;
396  co_unsigned8_t len = map & 0xff;
397 
398  // Check the PDO length.
399  if (offset + len > n * 8)
400  return CO_SDO_AC_PDO_LEN;
401 
402  // Check, if necessary, whether the sub-object exists and can be
403  // mapped into an RPDO (or is a valid dummy entry).
404  co_unsigned32_t ac = 0;
405  if (chk && (ac = co_dev_chk_rpdo(dev, idx, subidx)))
406  return ac;
407 
408  co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
409  if (sub) {
410  // Copy the value and download it into the sub-object.
411  uint_least8_t tmp[CAN_MAX_LEN] = { 0 };
412  bcpyle(tmp, 0, buf, offset, len);
413  co_sdo_req_clear(req);
414  req->size = (len + 7) / 8;
415  req->buf = tmp;
416  req->nbyte = req->size;
417  ac = co_sub_dn_ind(sub, req);
418  if (ac)
419  return ac;
420  }
421 
422  offset += len;
423  }
424 
425  return 0;
426 }
427 #endif // !LELY_NO_CO_RPDO
428 
429 #if !LELY_NO_CO_TPDO
430 
431 co_unsigned32_t
432 co_pdo_up(const struct co_pdo_map_par *par, const co_dev_t *dev,
433  struct co_sdo_req *req, uint_least8_t *buf, size_t *pn, int chk)
434 {
435  assert(par);
436  assert(dev);
437  assert(req);
438 
439  if (par->n > CO_PDO_NUM_MAPS)
440  return CO_SDO_AC_PDO_LEN;
441 
442  size_t offset = 0;
443  for (size_t i = 0; i < par->n; i++) {
444  co_unsigned32_t map = par->map[i];
445  if (!map)
446  continue;
447 
448  co_unsigned16_t idx = (map >> 16) & 0xffff;
449  co_unsigned8_t subidx = (map >> 8) & 0xff;
450  co_unsigned8_t len = map & 0xff;
451 
452  // Check the PDO length.
453  if (offset + len > CAN_MAX_LEN * 8)
454  return CO_SDO_AC_PDO_LEN;
455 
456  // Check, if necessary, whether the sub-object exists and can be
457  // mapped into a TPDO.
458  co_unsigned32_t ac = 0;
459  if (chk && (ac = co_dev_chk_tpdo(dev, idx, subidx)))
460  return ac;
461 
462  // Upload the value of the sub-object and copy the value.
463  co_sdo_req_clear(req);
464  ac = co_sub_up_ind(co_dev_find_sub(dev, idx, subidx), req);
465  if (ac)
466  return ac;
467  if (!co_sdo_req_first(req) || !co_sdo_req_last(req))
468  return CO_SDO_AC_PDO_LEN;
469  if (buf && pn && offset + len <= *pn * 8)
470  bcpyle(buf, offset, req->buf, 0, len);
471 
472  offset += len;
473  }
474 
475  if (pn)
476  *pn = (offset + 7) / 8;
477 
478  return 0;
479 }
480 
481 #if !LELY_NO_CO_MPDO
482 co_unsigned32_t
483 co_sam_mpdo_up(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx,
484  struct co_sdo_req *req, uint_least8_t buf[4])
485 {
486  assert(dev);
487  assert(req);
488 
489  // Check whether the sub-object can be mapped into a SAM-MPDO.
490  if (!co_dev_chk_sam_mpdo(dev, idx, subidx))
491  return CO_SDO_AC_NO_PDO;
492 
493  // Check whether the sub-object exists and can be mapped into a TPDO.
494  co_unsigned32_t ac = co_dev_chk_tpdo(dev, idx, subidx);
495  if (ac)
496  return ac;
497 
498  // Upload the value of the sub-object.
499  co_sdo_req_clear(req);
500  ac = co_sub_up_ind(co_dev_find_sub(dev, idx, subidx), req);
501  if (ac)
502  return ac;
503  // Check if the value is complete and fits in the PDO.
504  if (req->size > 4 || !co_sdo_req_first(req) || !co_sdo_req_last(req))
505  return CO_SDO_AC_PDO_LEN;
506  if (buf) {
507  // Copy the value and pad it with zeros, if necessary.
508  memcpy(buf, req->buf, req->size);
509  for (size_t i = req->size; i < 4; i++)
510  buf[i] = 0;
511  }
512 
513  return 0;
514 }
515 #endif // !LELY_NO_CO_MPDO
516 
517 #endif // !LELY_NO_CO_TPDO
518 
519 static co_unsigned32_t
520 co_dev_cfg_pdo_comm(const co_dev_t *dev, co_unsigned16_t idx,
521  const struct co_pdo_comm_par *par)
522 {
523  assert(dev);
524  assert(par);
525 
526  co_unsigned32_t ac = 0;
527 
528  co_obj_t *obj = co_dev_find_obj(dev, idx);
529  if (!obj)
530  return CO_SDO_AC_NO_OBJ;
531 
532  // Check if all sub-objects are available.
533  co_unsigned8_t n = co_obj_get_val_u8(obj, 0x00);
534  if (par->n > n)
535  return CO_SDO_AC_NO_SUB;
536 
537  // Configure the COB-ID.
538  if (par->n >= 1) {
539  co_sub_t *sub = co_obj_find_sub(obj, 0x01);
540  if (!sub)
541  return CO_SDO_AC_NO_SUB;
543  }
544 
545  // Configure the transmission type.
546  if (par->n >= 2 && !ac) {
547  co_sub_t *sub = co_obj_find_sub(obj, 0x02);
548  if (!sub)
549  return CO_SDO_AC_NO_SUB;
550  ac = co_sub_dn_ind_val(sub, CO_DEFTYPE_UNSIGNED8, &par->trans);
551  }
552 
553  // Configure the inhibit time.
554  if (par->n >= 3 && !ac) {
555  co_sub_t *sub = co_obj_find_sub(obj, 0x03);
556  if (!sub)
557  return CO_SDO_AC_NO_SUB;
558  ac = co_sub_dn_ind_val(
559  sub, CO_DEFTYPE_UNSIGNED16, &par->inhibit);
560  }
561 
562  // Configure the event timer.
563  if (par->n >= 5 && !ac) {
564  co_sub_t *sub = co_obj_find_sub(obj, 0x05);
565  if (!sub)
566  return CO_SDO_AC_NO_SUB;
568  }
569 
570  // Configure the SYNC start value.
571  if (par->n >= 6 && !ac) {
572  co_sub_t *sub = co_obj_find_sub(obj, 0x06);
573  if (!sub)
574  return CO_SDO_AC_NO_SUB;
575  ac = co_sub_dn_ind_val(sub, CO_DEFTYPE_UNSIGNED8, &par->sync);
576  }
577 
578  return ac;
579 }
580 
581 static co_unsigned32_t
582 co_dev_cfg_pdo_map(const co_dev_t *dev, co_unsigned16_t idx,
583  const struct co_pdo_map_par *par)
584 {
585  assert(dev);
586  assert(par);
587 
588  co_unsigned32_t ac = 0;
589 
590  co_obj_t *obj = co_dev_find_obj(dev, idx);
591  if (!obj)
592  return CO_SDO_AC_NO_OBJ;
593 
594  co_sub_t *sub_00 = co_obj_find_sub(obj, 0x00);
595  if (!sub_00)
596  return CO_SDO_AC_NO_SUB;
597 
598  // Disable mapping by setting subindex 0x00 to zero.
599  ac = co_sub_dn_ind_val(
600  sub_00, CO_DEFTYPE_UNSIGNED8, &(co_unsigned8_t){ 0 });
601  if (ac)
602  return ac;
603 
604  if (par->n <= CO_PDO_NUM_MAPS) {
605  // Copy the mapping parameters.
606  for (co_unsigned8_t i = 1; i <= par->n; i++) {
607  co_sub_t *sub = co_obj_find_sub(obj, i);
608  if (!sub)
609  return CO_SDO_AC_NO_SUB;
611  &par->map[i - 1]);
612  if (ac)
613  return ac;
614  }
615  }
616 
617  // Enable mapping.
618  return co_sub_dn_ind_val(sub_00, CO_DEFTYPE_UNSIGNED8, &par->n);
619 }
620 
621 #if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
622 co_unsigned32_t
623 co_mpdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev,
624  struct co_sdo_req *req, const uint_least8_t *buf, size_t n)
625 {
626  assert(par);
627  assert(dev);
628  assert(req);
629  assert(buf);
630 
631  if ((par->n != CO_PDO_MAP_SAM_MPDO && par->n != CO_PDO_MAP_DAM_MPDO)
632  || n != CAN_MAX_LEN)
633  return CO_SDO_AC_PDO_LEN;
634 
635  co_unsigned8_t id = buf[0];
636  co_unsigned16_t idx = ldle_u16(buf + 1);
637  co_unsigned8_t subidx = buf[3];
638  if (id & 0x80) {
639  // Ignore an unexpected DAM-MPDO.
640  if (par->n != CO_PDO_MAP_DAM_MPDO)
641  return 0;
642  // Check if the node-ID matches.
643  id &= 0x7f;
644  if (id && id != co_dev_get_id(dev))
645  return 0;
646  } else {
647  // Ignore an unexpected SAM-MPDO.
648  if (par->n != CO_PDO_MAP_SAM_MPDO)
649  return 0;
650  // Find the local object index and sub-index in the object
651  // dispatching list.
652  if (!co_dev_map_sam_mpdo(dev, id, idx, subidx, &idx, &subidx))
653  return 0;
654  }
655 
656  // Check whether the sub-object exists and can be mapped into a PDO (or
657  // is a valid dummy entry).
658  co_unsigned32_t ac = co_dev_chk_rpdo(dev, idx, subidx);
659  if (ac)
660  return ac;
661 
662  co_sub_t *sub = co_dev_find_sub(dev, idx, subidx);
663  if (sub) {
664  co_unsigned16_t type = co_sub_get_type(sub);
665  // Download the value to the sub-object.
666  co_sdo_req_clear(req);
667  // Discard any padding bytes.
668  req->size = co_type_is_basic(type)
669  ? MIN(co_type_sizeof(type), 4)
670  : 4;
671  req->buf = buf + 4;
672  req->nbyte = req->size;
673  ac = co_sub_dn_ind(sub, req);
674  if (ac)
675  return ac;
676  }
677 
678  return 0;
679 }
680 #endif // !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
681 
682 #endif // !LELY_NO_CO_RPDO || !LELY_NO_CO_TPDO
CO_PDO_COBID_VALID
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
Definition: pdo.h:37
ldle_u64
uint_least64_t ldle_u64(const uint_least8_t src[8])
Loads a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:690
co_pdo_comm_par::sync
co_unsigned8_t sync
SYNC start value.
Definition: pdo.h:77
dev.h
CO_SDO_AC_NO_PDO
#define CO_SDO_AC_NO_PDO
SDO abort code: Object cannot be mapped to the PDO.
Definition: sdo.h:96
co_pdo_unmap
co_unsigned32_t co_pdo_unmap(const struct co_pdo_map_par *par, const uint_least8_t *buf, size_t n, co_unsigned64_t *val, co_unsigned8_t *pn)
Unmaps a PDO into its constituent values.
Definition: pdo.c:333
CO_DEFTYPE_UNSIGNED32
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition: type.h:50
CO_ACCESS_READ
#define CO_ACCESS_READ
The object can be read.
Definition: obj.h:57
co_pdo_comm_par::n
co_unsigned8_t n
Highest sub-index supported.
Definition: pdo.h:66
CO_PDO_MAP_SAM_MPDO
#define CO_PDO_MAP_SAM_MPDO
The value of sub-index 0 of the PDO mapping parameter record indicating a a source address mode multi...
Definition: pdo.h:52
co_pdo_comm_par::event
co_unsigned16_t event
Event timer.
Definition: pdo.h:75
CO_DEFTYPE_UNSIGNED16
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition: type.h:47
co_dev_cfg_rpdo
co_unsigned32_t co_dev_cfg_rpdo(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *comm, const struct co_pdo_map_par *map)
Configures the communication and parameters of a Receive-PDO service.
Definition: pdo.c:80
MIN
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
co_dev_chk_rpdo
co_unsigned32_t co_dev_chk_rpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified object is valid and can be mapped into a Receive-PDO.
Definition: pdo.c:51
co_type_is_basic
int co_type_is_basic(co_unsigned16_t type)
Returns 1 if the specified (static) data type is a basic type, and 0 if not.
Definition: type.c:28
co_pdo_dn
co_unsigned32_t co_pdo_dn(const struct co_pdo_map_par *par, co_dev_t *dev, struct co_sdo_req *req, const uint_least8_t *buf, size_t n, int chk)
Writes mapped PDO values to the object dictionary through a local SDO download request.
Definition: pdo.c:368
CO_ACCESS_TPDO
#define CO_ACCESS_TPDO
The object can be mapped to a TPDO.
Definition: obj.h:63
co_dev_get_id
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
Definition: dev.c:197
co_dev_map_sam_mpdo
int co_dev_map_sam_mpdo(const co_dev_t *dev, co_unsigned8_t id, co_unsigned16_t idx, co_unsigned8_t subidx, co_unsigned16_t *pidx, co_unsigned8_t *psubidx)
Checks if the specified remote object is part of the object dispatching list (objects 1FD0....
Definition: pdo.c:245
co_sub_next
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
Definition: obj.c:542
co_dev_cfg_rpdo_map
co_unsigned32_t co_dev_cfg_rpdo_map(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_map_par *par)
Configures the mapping parameters of a Receive-PDO service by updating CANopen object 1600 - 17FF (RP...
Definition: pdo.c:116
CO_DEFTYPE_UNSIGNED8
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition: type.h:44
co.h
co_sub_get_pdo_mapping
int co_sub_get_pdo_mapping(const co_sub_t *sub)
Returns 1 if it is possible to map the specified CANopen sub-object into a PDO, and 0 if not.
Definition: obj.c:802
co_pdo_comm_par
A PDO communication parameter record.
Definition: pdo.h:64
co_pdo_comm_par::trans
co_unsigned8_t trans
Transmission type.
Definition: pdo.h:70
sdo.h
co_pdo_map_par::n
co_unsigned8_t n
Number of mapped objects in PDO.
Definition: pdo.h:92
CO_SDO_AC_NO_OBJ
#define CO_SDO_AC_NO_OBJ
SDO abort code: Object does not exist in the object dictionary.
Definition: sdo.h:93
co_obj_first_sub
co_sub_t * co_obj_first_sub(const co_obj_t *obj)
Finds the first sub-object (with the lowest sub-index) in a CANopen object.
Definition: obj.c:249
co_pdo_map_par::map
co_unsigned32_t map[CO_PDO_NUM_MAPS]
An array of objects to be mapped.
Definition: pdo.h:94
co_dev_get_dummy
co_unsigned32_t co_dev_get_dummy(const co_dev_t *dev)
Returns the data types supported by a CANopen device for mapping dummy entries in PDOs (one bit for e...
Definition: dev.c:551
CAN_MAX_LEN
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:72
co_obj_next
co_obj_t * co_obj_next(const co_obj_t *obj)
Finds the next object in the object dictionary of a CANopen device.
Definition: obj.c:147
co_type_sizeof
size_t co_type_sizeof(co_unsigned16_t type)
Returns the native size (in bytes) of a value of the specified data type, or 1 if it is not a static ...
Definition: type.c:52
CO_ACCESS_RPDO
#define CO_ACCESS_RPDO
The object can be mapped to an RPDO.
Definition: obj.h:66
CO_SDO_AC_NO_SUB
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
Definition: sdo.h:132
co_sdo_req
A CANopen SDO upload/download request.
Definition: sdo.h:181
co_sdo_req_clear
void co_sdo_req_clear(struct co_sdo_req *req)
Clears a CANopen SDO upload/download request, including its buffer.
Definition: sdo.c:129
CO_NUM_PDOS
#define CO_NUM_PDOS
The maximum number of Receive/Transmit-PDOs.
Definition: pdo.h:28
co_sam_mpdo_up
co_unsigned32_t co_sam_mpdo_up(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, struct co_sdo_req *req, uint_least8_t buf[4])
Reads the value of the specified SAM-MPDO-mapped object from the local object dictionary through a lo...
Definition: pdo.c:483
co_dev_cfg_tpdo
co_unsigned32_t co_dev_cfg_tpdo(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *comm, const struct co_pdo_map_par *map)
Configures the communication and parameters of a Transmit-PDO service.
Definition: pdo.c:153
co_obj_find_sub
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
Definition: obj.c:240
co_dev_chk_sam_mpdo
int co_dev_chk_sam_mpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified object is part of the object scanner list (objects 1FA0..1FCF) and can be tra...
Definition: pdo.c:203
co_pdo_comm_par::inhibit
co_unsigned16_t inhibit
Inhibit time.
Definition: pdo.h:72
co_sdo_req_first
int co_sdo_req_first(const struct co_sdo_req *req)
Returns 1 if the specified request includes the first segment, and 0 otherwise.
Definition: sdo.h:343
CO_PDO_MAP_DAM_MPDO
#define CO_PDO_MAP_DAM_MPDO
The value of sub-index 0 of the PDO mapping parameter record indicating a a destination address mode ...
Definition: pdo.h:58
co_sub_up_ind
co_unsigned32_t co_sub_up_ind(const co_sub_t *sub, struct co_sdo_req *req)
Invokes the upload indication function of a CANopen sub-object, registered with co_sub_set_up_ind().
Definition: obj.c:1066
co_sdo_req::size
size_t size
The total size (in bytes) of the value to be uploaded/downloaded.
Definition: sdo.h:187
CO_PDO_NUM_MAPS
#define CO_PDO_NUM_MAPS
The maximum number of mapped application objects in a single PDO.
Definition: pdo.h:34
CO_SDO_AC_PDO_LEN
#define CO_SDO_AC_PDO_LEN
SDO abort code: The number and length of the objects to be mapped would exceed the PDO length.
Definition: sdo.h:102
CO_SDO_AC_NO_WRITE
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
Definition: sdo.h:90
co_dev_cfg_rpdo_comm
co_unsigned32_t co_dev_cfg_rpdo_comm(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *par)
Configures the communication parameters of a Receive-PDO service by updating CANopen object 1400 - 15...
Definition: pdo.c:106
co_sdo_req_last
int co_sdo_req_last(const struct co_sdo_req *req)
Returns 1 if the specified request includes the last segment, and 0 otherwise.
Definition: sdo.h:349
co_sub_dn_ind_val
co_unsigned32_t co_sub_dn_ind_val(co_sub_t *sub, co_unsigned16_t type, const void *val)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition: obj.c:974
__co_obj
A CANopen object.
Definition: obj.h:31
co_sub_dn_ind
co_unsigned32_t co_sub_dn_ind(co_sub_t *sub, struct co_sdo_req *req)
Invokes the download indication function of a CANopen sub-object, registered with co_sub_set_dn_ind()...
Definition: obj.c:958
co_sub_get_type
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
Definition: obj.c:603
__co_dev
A CANopen device.
Definition: dev.h:30
stle_u64
void stle_u64(uint_least8_t dst[8], uint_least64_t x)
Stores a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:672
co_dev_chk_tpdo
co_unsigned32_t co_dev_chk_tpdo(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified object is valid and can be mapped into a Transmit-PDO.
Definition: pdo.c:130
co_sdo_req::nbyte
size_t nbyte
The number of bytes available at buf.
Definition: sdo.h:191
co_sdo_req::buf
const void * buf
A pointer to the next bytes to be uploaded/downloaded.
Definition: sdo.h:189
msg.h
CO_ACCESS_WRITE
#define CO_ACCESS_WRITE
The object can be written.
Definition: obj.h:60
pdo.h
co_sub_get_subidx
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
Definition: obj.c:559
bcpyle
void bcpyle(uint_least8_t *dst, int dstbit, const uint_least8_t *src, int srcbit, size_t n)
Copies n bits from a source to a destination buffer.
Definition: endian.c:123
co_pdo_comm_par::cobid
co_unsigned32_t cobid
COB-ID.
Definition: pdo.h:68
obj.h
CO_SDO_AC_NO_READ
#define CO_SDO_AC_NO_READ
SDO abort code: Attempt to read a write only object.
Definition: sdo.h:87
ldle_u16
uint_least16_t ldle_u16(const uint_least8_t src[2])
Loads a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:516
co_dev_cfg_tpdo_comm
co_unsigned32_t co_dev_cfg_tpdo_comm(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_comm_par *par)
Configures the communication parameters of a Transmit-PDO service by updating CANopen object 1800 - 1...
Definition: pdo.c:179
__co_sub
A CANopen sub-object.
Definition: obj.h:53
co_dev_find_sub
co_sub_t * co_dev_find_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Finds a sub-object in the object dictionary of a CANopen device.
Definition: dev.c:290
co_sub_get_access
unsigned int co_sub_get_access(const co_sub_t *sub)
Returns the access type of a CANopen sub-object.
Definition: obj.c:778
co_pdo_map_par
A PDO mapping parameter record.
Definition: pdo.h:90
co_pdo_up
co_unsigned32_t co_pdo_up(const struct co_pdo_map_par *par, const co_dev_t *dev, struct co_sdo_req *req, uint_least8_t *buf, size_t *pn, int chk)
Reads mapped PDO values from the object dictionary through a local SDO upload request.
Definition: pdo.c:432
co_obj_get_idx
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:164
co_dev_cfg_tpdo_map
co_unsigned32_t co_dev_cfg_tpdo_map(const co_dev_t *dev, co_unsigned16_t num, const struct co_pdo_map_par *par)
Configures the mapping parameters of a Transmit-PDO service by updating CANopen object 1A00 - 1BFF (T...
Definition: pdo.c:189
co_dev_find_obj
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
Definition: dev.c:279
co_pdo_map
co_unsigned32_t co_pdo_map(const struct co_pdo_map_par *par, const co_unsigned64_t *val, co_unsigned8_t n, uint_least8_t *buf, size_t *pn)
Maps values into a PDO.
Definition: pdo.c:299
endian.h