34#if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
39#if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
42#if !LELY_NO_CO_RPDO || !LELY_NO_CO_TPDO
59 operator()(
co_dev_t* dev)
const noexcept {
65 Impl_(
Device* self, const ::std::string& dcf_txt,
68 virtual ~Impl_() =
default;
72 if (mutex) mutex->lock();
77 if (mutex) mutex->unlock();
81 netid() const noexcept {
90 void OnWrite(uint16_t idx, uint8_t subidx);
92 ::std::tuple<uint16_t, uint8_t>
93 RpdoMapping(uint8_t
id, uint16_t idx, uint8_t subidx,
94 ::std::error_code& ec)
const noexcept {
97 auto it = rpdo_mapping.find((
static_cast<uint32_t
>(
id) << 24) |
98 (
static_cast<uint32_t
>(idx) << 8) | subidx);
99 if (it != rpdo_mapping.end()) {
100 idx = (it->second >> 8) & 0xffff;
101 subidx = it->second & 0xff;
111 return ::std::make_tuple(idx, subidx);
114 ::std::tuple<uint8_t, uint16_t, uint8_t>
115 RpdoMapping(uint16_t idx, uint8_t subidx,
116 ::std::error_code& ec)
const noexcept {
119 auto it = rpdo_mapping.find((
static_cast<uint32_t
>(idx) << 8) | subidx);
120 if (it != rpdo_mapping.end()) {
121 id = (it->second >> 24) & 0xff;
122 idx = (it->second >> 8) & 0xffff;
123 subidx = it->second & 0xff;
133 return ::std::make_tuple(
id, idx, subidx);
136 ::std::tuple<uint16_t, uint8_t>
137 TpdoMapping(uint8_t
id, uint16_t idx, uint8_t subidx,
138 ::std::error_code& ec)
const noexcept {
141 auto it = tpdo_mapping.find((
static_cast<uint32_t
>(
id) << 24) |
142 (
static_cast<uint32_t
>(idx) << 8) | subidx);
143 if (it != tpdo_mapping.end()) {
144 idx = (it->second >> 8) & 0xffff;
145 subidx = it->second & 0xff;
155 return ::std::make_tuple(idx, subidx);
160 BasicLockable* mutex{
nullptr};
162 ::std::unique_ptr<co_dev_t, DeviceDeleter> dev;
165 ::std::map<uint32_t, uint32_t> rpdo_mapping;
168 ::std::map<uint32_t, uint32_t> tpdo_mapping;
171 ::std::function<void(uint16_t, uint8_t)> on_write;
173 ::std::function<void(uint8_t, uint16_t, uint8_t)> on_rpdo_write;
180 : impl_(new
Impl_(this, dcf_txt, dcf_bin,
id, mutex)) {}
183Device::~Device() =
default;
187 ::std::lock_guard<Impl_> lock(*impl_);
189 return impl_->netid();
194 ::std::lock_guard<Impl_> lock(*impl_);
202OnDnCon(
co_csdo_t*, uint16_t, uint8_t, uint32_t ac,
void* data)
noexcept {
203 *
static_cast<uint32_t*
>(data) = ac;
208OnUpCon(
co_csdo_t*, uint16_t, uint8_t, uint32_t ac,
const void* ptr,
size_t n,
209 void* data)
noexcept {
210 using traits = canopen_traits<T>;
211 using c_type =
typename traits::c_type;
213 auto t =
static_cast<::std::tuple<uint32_t&, T&>*
>(data);
217 ::std::error_code ec;
218 val = traits::construct(ptr, n, ec);
219 if (ec) ac =
static_cast<uint32_t
>(
sdo_errc(ec));
222 *t = ::std::forward_as_tuple(ac, traits::from_c_type(val));
224 traits::destroy(val);
230typename ::std::enable_if<is_canopen<T>::value, T>::type
232 ::std::error_code ec;
233 T value(
Read<T>(idx, subidx, ec));
239typename ::std::enable_if<is_canopen<T>::value, T>::type
240Device::Read(uint16_t idx, uint8_t subidx, ::std::error_code& ec)
const {
243 auto t = ::std::tie(ac, value);
245 ::std::lock_guard<Impl_> lock(*impl_);
261typename ::std::enable_if<is_canopen<T>::value>::type
263 ::std::error_code ec;
264 Write(idx, subidx, value, ec);
269typename ::std::enable_if<is_canopen<T>::value>::type
271 ::std::error_code& ec) {
274 auto val = traits::to_c_type(value, ec);
279 ::std::lock_guard<Impl_> lock(*impl_);
294 traits::destroy(val);
299Device::Write(uint16_t idx, uint8_t subidx, const ::std::string& value,
300 ::std::error_code& ec) {
301 Write(idx, subidx, value.c_str(), ec);
306Device::Write(uint16_t idx, uint8_t subidx, const ::std::vector<uint8_t>& value,
307 ::std::error_code& ec) {
308 Write(idx, subidx, value.data(), value.size(), ec);
311#ifndef DOXYGEN_SHOULD_SKIP_THIS
323 ::std::error_code&)
const;
331 ::std::error_code&)
const;
339 ::std::error_code&)
const;
347 ::std::error_code&)
const;
355 ::std::error_code&)
const;
363 ::std::error_code&)
const;
378 ::std::error_code&)
const;
380 const ::std::string&);
387 uint16_t, uint8_t)
const;
389 uint16_t, uint8_t, ::std::error_code&)
const;
391 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
396template ::std::basic_string<char16_t>
398template ::std::basic_string<char16_t>
400 ::std::error_code&)
const;
402 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
404 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
415 ::std::error_code&)
const;
427 ::std::error_code&)
const;
440 ::std::error_code&)
const;
449 ::std::error_code ec;
450 Write(idx, subidx, value, ec);
456 ::std::error_code& ec) {
457 Write(idx, subidx, value, ::std::char_traits<char>::length(value), ec);
462 ::std::error_code ec;
463 Write(idx, subidx, value, ec);
469 ::std::error_code& ec) {
472 auto val = traits::to_c_type(value, ec);
477 ::std::lock_guard<Impl_> lock(*impl_);
492 traits::destroy(val);
496Device::Write(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n) {
497 ::std::error_code ec;
498 Write(idx, subidx, p, n, ec);
504 ::std::error_code& ec) {
507 ::std::lock_guard<Impl_> lock(*impl_);
523 ::std::error_code ec;
530 ::std::error_code& ec) {
533 ::std::lock_guard<Impl_> lock(*impl_);
549 ::std::error_code ec;
576 ::std::error_code ec;
583 ::std::error_code& ec)
noexcept {
584 ::std::lock_guard<Impl_> lock(*impl_);
590typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
592 ::std::error_code ec;
599typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
601 ::std::error_code& ec)
const {
604 ::std::lock_guard<Impl_> lock(*impl_);
605 ::std::tie(idx, subidx) = impl_->RpdoMapping(
id, idx, subidx, ec);
608 return Read<T>(idx, subidx, ec);
612typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
614 ::std::error_code ec;
621typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
623 ::std::error_code& ec)
const {
626 ::std::lock_guard<Impl_> lock(*impl_);
627 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
630 return Read<T>(idx, subidx, ec);
634typename ::std::enable_if<is_canopen_basic<T>::value>::type
636 ::std::error_code ec;
642typename ::std::enable_if<is_canopen_basic<T>::value>::type
644 ::std::error_code& ec) {
647 ::std::lock_guard<Impl_> lock(*impl_);
648 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
650 if (!ec)
Write<T>(idx, subidx, value, ec);
653#ifndef DOXYGEN_SHOULD_SKIP_THIS
658 ::std::error_code&)
const;
661 ::std::error_code&)
const;
669 ::std::error_code&)
const;
672 ::std::error_code&)
const;
680 ::std::error_code&)
const;
683 ::std::error_code&)
const;
691 ::std::error_code&)
const;
694 ::std::error_code&)
const;
702 ::std::error_code&)
const;
705 ::std::error_code&)
const;
713 ::std::error_code&)
const;
716 ::std::error_code&)
const;
724 ::std::error_code&)
const;
727 ::std::error_code&)
const;
735 ::std::error_code&)
const;
738 ::std::error_code&)
const;
754 ::std::error_code&)
const;
757 ::std::error_code&)
const;
769 ::std::error_code&)
const;
772 ::std::error_code&)
const;
785 ::std::error_code&)
const;
788 ::std::error_code&)
const;
797 ::std::error_code ec;
804 ::std::error_code& ec)
noexcept {
805 ::std::lock_guard<Impl_> lock(*impl_);
811Device::OnWrite(::std::function<
void(uint16_t, uint8_t)> on_write) {
812 ::std::lock_guard<Impl_> lock(*impl_);
813 impl_->on_write = on_write;
818 ::std::function<
void(uint8_t, uint16_t, uint8_t)> on_rpdo_write) {
822 ::std::lock_guard<Impl_> lock(*impl_);
823 impl_->on_rpdo_write = on_rpdo_write;
829 return impl_->dev.get();
832const ::std::type_info&
834 ::std::error_code ec;
835 auto& ti =
Type(idx, subidx, ec);
840const ::std::type_info&
842 ::std::error_code& ec)
const noexcept {
860 return typeid(int8_t);
862 return typeid(int16_t);
864 return typeid(int32_t);
866 return typeid(uint8_t);
868 return typeid(uint16_t);
870 return typeid(uint32_t);
872 return typeid(float);
874 return typeid(::std::string);
876 return typeid(::std::vector<uint8_t>);
878 return typeid(::std::basic_string<char16_t>);
882 return typeid(::std::vector<uint8_t>);
885 return typeid(double);
890 return typeid(int64_t);
896 return typeid(uint64_t);
903typename ::std::enable_if<is_canopen<T>::value, T>::type
905 ::std::error_code ec;
906 auto value =
Get<T>(idx, subidx, ec);
912typename ::std::enable_if<is_canopen<T>::value, T>::type
914 ::std::error_code& ec)
const noexcept {
916 using c_type =
typename traits::c_type;
938 return traits::from_c_type(*pval);
942typename ::std::enable_if<is_canopen<T>::value>::type
944 ::std::error_code ec;
945 Set(idx, subidx, value, ec);
950typename ::std::enable_if<is_canopen<T>::value>::type
952 ::std::error_code& ec)
noexcept {
972 auto val = traits::to_c_type(value, ec);
974 auto p = traits::address(val);
975 auto n = traits::size(val);
985 traits::destroy(val);
990Device::Set(uint16_t idx, uint8_t subidx, const ::std::string& value,
991 ::std::error_code& ec)
noexcept {
992 Set(idx, subidx, value.c_str(), ec);
997Device::Set(uint16_t idx, uint8_t subidx, const ::std::vector<uint8_t>& value,
998 ::std::error_code& ec)
noexcept {
999 Set(idx, subidx, value.data(), value.size(), ec);
1002#ifndef DOXYGEN_SHOULD_SKIP_THIS
1007 ::std::error_code&)
const noexcept;
1010 ::std::error_code&)
noexcept;
1015 ::std::error_code&)
const noexcept;
1018 ::std::error_code&)
noexcept;
1023 ::std::error_code&)
const noexcept;
1026 ::std::error_code&)
noexcept;
1031 ::std::error_code&)
const noexcept;
1034 ::std::error_code&)
noexcept;
1039 ::std::error_code&)
const noexcept;
1042 ::std::error_code&)
noexcept;
1047 ::std::error_code&)
const noexcept;
1050 ::std::error_code&)
noexcept;
1055 ::std::error_code&)
const noexcept;
1058 ::std::error_code&)
noexcept;
1063 ::std::error_code&)
const noexcept;
1066 ::std::error_code&)
noexcept;
1071 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1073 const ::std::string&);
1080 uint16_t, uint8_t)
const;
1082 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1084 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
1092template ::std::basic_string<char16_t>
1094template ::std::basic_string<char16_t>
1096 ::std::error_code&)
const noexcept;
1098 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
1100 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
1101 ::std::error_code&)
noexcept;
1111 ::std::error_code&)
const noexcept;
1114 ::std::error_code&)
noexcept;
1123 ::std::error_code&)
const noexcept;
1126 ::std::error_code&)
noexcept;
1136 ::std::error_code&)
const noexcept;
1139 ::std::error_code&)
noexcept;
1145 ::std::error_code ec;
1146 Set(idx, subidx, value, ec);
1152 ::std::error_code& ec)
noexcept {
1153 Set(idx, subidx, value, ::std::char_traits<char>::length(value), ec);
1158 ::std::error_code ec;
1159 Set(idx, subidx, value, ec);
1165 ::std::error_code& ec)
noexcept {
1185 auto val = traits::to_c_type(value, ec);
1187 auto p = traits::address(val);
1188 auto n = traits::size(val);
1198 traits::destroy(val);
1202Device::Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n) {
1203 ::std::error_code ec;
1204 Set(idx, subidx, p, n, ec);
1209Device::Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n,
1210 ::std::error_code& ec)
noexcept {
1232#if !LELY_NO_CO_OBJ_FILE
1236 ::std::error_code ec;
1238 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"GetUploadFile");
1244 ::std::error_code& ec)
const noexcept {
1263 ::std::error_code ec;
1265 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"SetUploadFile");
1270 ::std::error_code& ec)
noexcept {
1294 ::std::error_code ec;
1296 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"GetDownloadFile");
1302 ::std::error_code& ec)
const noexcept {
1321 ::std::error_code ec;
1323 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"SetDownloadFile");
1328 ::std::error_code& ec)
noexcept {
1354 ::std::error_code ec;
1375#if !LELYY_NO_CO_MPDO
1382typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1384 ::std::error_code ec;
1385 auto value =
RpdoGet<T>(
id, idx, subidx, ec);
1391typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1393 ::std::error_code& ec)
const noexcept {
1395 ::std::tie(idx, subidx) = impl_->RpdoMapping(
id, idx, subidx, ec);
1397 return Get<T>(idx, subidx, ec);
1401typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1403 ::std::error_code ec;
1404 auto value =
TpdoGet<T>(
id, idx, subidx, ec);
1410typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1412 ::std::error_code& ec)
const noexcept {
1414 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1416 return Get<T>(idx, subidx, ec);
1420typename ::std::enable_if<is_canopen_basic<T>::value>::type
1422 ::std::error_code ec;
1423 TpdoSet(
id, idx, subidx, value, ec);
1428typename ::std::enable_if<is_canopen_basic<T>::value>::type
1430 ::std::error_code& ec)
noexcept {
1432 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1433 if (!ec)
Set<T>(idx, subidx, value, ec);
1436#ifndef DOXYGEN_SHOULD_SKIP_THIS
1441 ::std::error_code&)
const noexcept;
1444 ::std::error_code&)
const noexcept;
1447 ::std::error_code&)
noexcept;
1452 ::std::error_code&)
const noexcept;
1455 ::std::error_code&)
const noexcept;
1458 ::std::error_code&)
noexcept;
1463 ::std::error_code&)
const noexcept;
1466 ::std::error_code&)
const noexcept;
1469 ::std::error_code&)
noexcept;
1474 ::std::error_code&)
const noexcept;
1477 ::std::error_code&)
const noexcept;
1480 ::std::error_code&)
noexcept;
1485 ::std::error_code&)
const noexcept;
1488 ::std::error_code&)
const noexcept;
1491 ::std::error_code&)
noexcept;
1496 ::std::error_code&)
const noexcept;
1499 ::std::error_code&)
const noexcept;
1502 ::std::error_code&)
noexcept;
1507 ::std::error_code&)
const noexcept;
1510 ::std::error_code&)
const noexcept;
1513 ::std::error_code&)
noexcept;
1518 ::std::error_code&)
const noexcept;
1521 ::std::error_code&)
const noexcept;
1524 ::std::error_code&)
noexcept;
1537 ::std::error_code&)
const noexcept;
1540 ::std::error_code&)
const noexcept;
1543 ::std::error_code&)
noexcept;
1552 ::std::error_code&)
const noexcept;
1555 ::std::error_code&)
const noexcept;
1558 ::std::error_code&)
noexcept;
1568 ::std::error_code&)
const noexcept;
1571 ::std::error_code&)
const noexcept;
1574 ::std::error_code&)
noexcept;
1580 ::std::error_code ec;
1587 ::std::error_code& ec)
noexcept {
1589 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1590 if (!ec)
SetEvent(idx, subidx, ec);
1596 impl_->rpdo_mapping.clear();
1600 for (
int i = 0; !obj_1400 && i < 512; i++)
1602 for (; obj_1400; obj_1400 =
co_obj_next(obj_1400)) {
1604 if (i >= 512)
break;
1606 auto cobid = co_obj_get_val_u32(obj_1400, 1);
1612 id = co_obj_get_val_u32(obj_5800, 0) & 0xff;
1616 switch (cobid & 0x780) {
1631 if (!obj_1600)
continue;
1634 if (!obj_5a00)
continue;
1636 auto n = co_obj_get_val_u8(obj_1600, 0);
1638 if (n != co_obj_get_val_u8(obj_5a00, 0))
continue;
1639 for (
int j = 1; j <= n; j++) {
1640 auto rmap = co_obj_get_val_u32(obj_1600, j);
1641 auto tmap = co_obj_get_val_u32(obj_5a00, j);
1643 if (!rmap && !tmap)
continue;
1645 if ((rmap & 0xff) != (tmap & 0xff))
break;
1650 tmap |=
static_cast<uint32_t
>(
id) << 24;
1651 impl_->rpdo_mapping[tmap] = rmap;
1653 impl_->rpdo_mapping[rmap] = tmap;
1659 bool has_sam_mpdo =
false;
1662 for (
int i = 0; !obj_1400 && i <
CO_NUM_PDOS; i++)
1664 for (; !has_sam_mpdo && obj_1400; obj_1400 =
co_obj_next(obj_1400)) {
1670 if (co_obj_get_val_u8(obj_1400, 2) < 0xfe)
continue;
1674 has_sam_mpdo =
true;
1680 for (
int i = 0; !obj_1fd0 && i < 48; i++)
1682 for (; obj_1fd0; obj_1fd0 =
co_obj_next(obj_1fd0)) {
1684 auto n = co_obj_get_val_u8(obj_1fd0, 0);
1688 auto val = co_sub_get_val_u64(sub);
1691 uint32_t rmap = (val << 8) >> 40;
1692 uint32_t tmap =
ror32(val, 8);
1696 uint8_t min = (val >> 8) & 0xff;
1698 uint8_t blk = (val >> 56) & 0xff;
1699 if (blk) max += ::std::min(blk - 1, 0xff - min);
1701 for (
int j = 0; j <= max - min; j++) {
1703 if (
static_cast<uint8_t
>(j) > 0xff - (rmap & 0xff))
break;
1704 impl_->rpdo_mapping[tmap + j] = rmap + j;
1716 impl_->tpdo_mapping.clear();
1720 for (
int i = 0; !obj_1800 && i < 512; i++)
1722 for (; obj_1800; obj_1800 =
co_obj_next(obj_1800)) {
1724 if (i >= 512)
break;
1726 auto cobid = co_obj_get_val_u32(obj_1800, 1);
1732 id = co_obj_get_val_u32(obj_5c00, 0) & 0xff;
1736 switch (cobid & 0x780) {
1751 if (!obj_1a00)
continue;
1754 if (!obj_5e00)
continue;
1756 auto n = co_obj_get_val_u8(obj_1a00, 0);
1758 if (n != co_obj_get_val_u8(obj_5e00, 0))
continue;
1759 for (
int j = 1; j <= n; j++) {
1760 auto tmap = co_obj_get_val_u32(obj_1a00, j);
1761 auto rmap = co_obj_get_val_u32(obj_5e00, j);
1763 if (!rmap && !tmap)
continue;
1765 if ((tmap & 0xff) != (rmap & 0xff))
break;
1768 rmap |=
static_cast<uint32_t
>(
id) << 24;
1769 impl_->tpdo_mapping[rmap] = tmap;
1782 OnRpdoWrite(
id, idx, subidx);
1784 if (impl_->on_rpdo_write) {
1785 auto f = impl_->on_rpdo_write;
1793Device::Impl_::Impl_(
Device* self_, const ::std::string& dcf_txt,
1794 const ::std::string& dcf_bin, uint8_t
id,
1799 if (!dcf_bin.empty() &&
1819 if (
co_sub_on_dn(sub, req, &ac) == -1 || ac)
return ac;
1820 auto impl_ =
static_cast<Impl_*
>(data);
1825 static_cast<void*
>(
this));
1831Device::Impl_::OnWrite(uint16_t idx, uint8_t subidx) {
1832 self->OnWrite(idx, subidx);
1836 util::UnlockGuard<Impl_>
unlock(*
this);
1842 ::std::error_code ec;
1843 ::std::tie(
id, idx, subidx) = RpdoMapping(idx, subidx, ec);
1844 if (!ec) self->RpdoWrite(
id, idx, subidx);
This header file is part of the utilities library; it contains the bit function definitions.
uint_least32_t ror32(uint_least32_t x, unsigned int n)
Rotates the 32-bit unsigned integer x right by n bits.
The CANopen device description.
void RpdoWrite(uint8_t id, uint16_t idx, uint8_t subidx)
Invokes OnRpdoWrite() as if a value was written to an RPDO-mapped object in the local object dictiona...
uint8_t netid() const noexcept
Returns the network-ID.
void SetUploadFile(uint16_t idx, uint8_t subidx, const char *filename)
Sets the value of the UploadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type RpdoGet(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object in a remote object dictionary by reading the corresponding PDO-mapped...
void TpdoWriteEvent(uint8_t id, uint16_t idx, uint8_t subidx)
Triggers the transmission of every event-driven, asynchronous Transmit-PDO which is mapped into the s...
void WriteDcf(const uint8_t *begin, const uint8_t *end)
Submits a series of SDO download requests to the local object dictionary.
void UpdateTpdoMapping()
Updates the mapping from remote RPDO-mapped sub-objects to local TPDO-mapped sub-objects.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type TpdoGet(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a TPDO-mapped sub-object in the local object dictionary that will be written to an...
const ::std::type_info & Type(uint16_t idx, uint8_t subidx) const
Returns the type of a sub-object.
typename::std::enable_if< is_canopen< T >::value, T >::type Read(uint16_t idx, uint8_t subidx) const
Submits an SDO upload request to the local object dictionary.
void SetDownloadFile(uint16_t idx, uint8_t subidx, const char *filename)
Sets the value of the DownloadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value >::type TpdoWrite(uint8_t id, uint16_t idx, uint8_t subidx, T value)
Writes a value to a sub-object in a remote object dictionary by submitting an SDO download request to...
typename::std::enable_if< is_canopen< T >::value >::type Set(uint16_t idx, uint8_t subidx, const T &value)
Writes a CANopen value to a sub-object.
void UpdateRpdoMapping()
Updates the mapping from remote TPDO-mapped sub-objects to local RPDO-mapped sub-objects.
typename::std::enable_if< is_canopen< T >::value, T >::type Get(uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object.
void SetEvent(uint16_t idx, uint8_t subidx)
Checks if the specified sub-object in the local object dictionary can be mapped into a PDO and,...
void WriteEvent(uint16_t idx, uint8_t subidx)
Checks if the specified sub-object in the local object dictionary can be mapped into a PDO and,...
typename::std::enable_if< is_canopen_basic< T >::value >::type TpdoSet(uint8_t id, uint16_t idx, uint8_t subidx, T value)
Writes a value to a sub-object in a remote object dictionary by writing to the corresponding PDO-mapp...
Device(const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff, util::BasicLockable *mutex=nullptr)
Creates a new CANopen device description.
typename::std::enable_if< is_canopen< T >::value >::type Write(uint16_t idx, uint8_t subidx, const T &value)
Submits an SDO download request to the local object dictionary.
const char * GetDownloadFile(uint16_t idx, uint8_t subidx) const
Returns the value of the DownloadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type TpdoRead(uint8_t id, uint16_t idx, uint8_t subidx) const
Submits an SDO upload request to a TPDO-mapped sub-object in the local object dictionary,...
typename::std::enable_if< is_canopen_basic< T >::value, T >::type RpdoRead(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object in a remote object dictionary by submitting an SDO upload request to ...
void TpdoSetEvent(uint8_t id, uint16_t idx, uint8_t subidx)
Triggers the transmission of every event-driven, asynchronous Transmit-PDO which is mapped into the s...
__co_dev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
uint8_t id() const noexcept
Returns the node-ID.
const char * GetUploadFile(uint16_t idx, uint8_t subidx) const
Returns the value of the UploadFile attribute of a sub-object, if present.
An abstract interface conforming to the BasicLockable concept.
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
This header file is part of the CANopen library; it contains the device description declarations.
void co_dev_sam_mpdo_event(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified sub-object in the object dictionary of a CANopen device can be mapped into a ...
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.
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
int co_dev_set_id(co_dev_t *dev, co_unsigned8_t id)
Sets the node-ID of a CANopen device.
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
co_unsigned8_t co_dev_get_netid(const co_dev_t *dev)
Returns the network-ID of a CANopen device.
void co_dev_destroy(co_dev_t *dev)
Destroys a CANopen device, including all objects in its object dictionary.
void co_dev_tpdo_event(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified sub-object in the object dictionary of a CANopen device can be mapped into a ...
co_obj_t * co_dev_first_obj(const co_dev_t *dev)
Finds the first object (with the lowest index) in the object dictionary of a CANopen device.
int co_dev_read_dcf_file(co_dev_t *dev, co_unsigned16_t *pmin, co_unsigned16_t *pmax, const char *filename)
Reads the values of a range of objects from a file, in the concise DCF format, and stores them in the...
This is the internal header file of the C++ CANopen application library.
This header file is part of the CANopen library; it contains the Client-SDO declarations.
int co_dev_up_req(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, co_csdo_up_con_t *con, void *data)
Submits an upload request to a local device.
int co_dev_dn_val_req(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, co_unsigned16_t type, const void *val, co_csdo_dn_con_t *con, void *data)
Submits a download request to a local device.
int co_dev_dn_req(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, const void *ptr, size_t n, co_csdo_dn_con_t *con, void *data)
Submits a download request to a local device.
int co_dev_dn_dcf_req(co_dev_t *dev, const uint_least8_t *begin, const uint_least8_t *end, co_csdo_dn_con_t *con, void *data)
Submits a series of download requests to a local device.
This header file is part of the CANopen library; it contains the Electronic Data Sheet (EDS) and Devi...
co_dev_t * co_dev_create_from_dcf_file(const char *filename)
Creates a CANopen device from an EDS or DCF file.
This header file is part of the C++ CANopen application library; it contains the CANopen device descr...
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
This header file is part of the utilities library; it contains C++ convenience functions for creating...
inline ::std::error_code make_error_code(int errc=get_errc()) noexcept
Creates an error code value corresponding to the specified or current (thread-specific) native error ...
void throw_errc(int errc=get_errc())
Throws an std::system_error exception corresponding to the specified or current (thread-specific) nat...
struct __co_csdo co_csdo_t
An opaque CANopen Client-SDO service type.
struct __co_sub co_sub_t
An opaque CANopen sub-object type.
struct __co_obj co_obj_t
An opaque CANopen object type.
struct __co_dev co_dev_t
An opaque CANopen device type.
The namespace for the C++ CANopen application library.
constexpr bool is_canopen_same(uint16_t t1, uint16_t t2) noexcept
Returns true if the CANopen data types t1 and t2 map to the same C++ type, and false if not.
SdoErrc
The SDO abort codes.
@ NO_SUB
Sub-index does not exist.
@ TYPE_LEN
Data type does not match, length of service parameter does not match.
@ NO_OBJ
Object does not exist in the object dictionary.
@ NO_PDO
Object cannot be mapped to the PDO.
SdoErrc sdo_errc(::std::error_code ec)
Returns the SDO abort code corresponding to an error code.
void throw_sdo_error(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec)
Throws a lely::canopen::SdoError with the specified attributes if ec is an SDO error (ec....
This header file is part of the CANopen library; it contains the object dictionary declarations.
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.
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
int co_sub_set_download_file(co_sub_t *sub, const char *filename)
Sets the value of the DownloadFile attribute of a CANopen sub-object.
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
const void * co_sub_get_val(const co_sub_t *sub)
Returns a pointer to the current value of a CANopen sub-object.
const char * co_sub_get_download_file(const co_sub_t *sub)
Returns a pointer to the value of the DownloadFile attribute of a CANopen sub-object,...
int co_sub_set_upload_file(co_sub_t *sub, const char *filename)
Sets the value of the UploadFile attribute of a CANopen sub-object.
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
size_t co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
const char * co_sub_get_upload_file(const co_sub_t *sub)
Returns a pointer to the value of the UploadFile attribute of a CANopen sub-object,...
co_obj_t * co_obj_next(const co_obj_t *obj)
Finds the next object in the object dictionary of a CANopen device.
int co_sub_on_dn(co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
Implements the default behavior when a download indication is received by a CANopen sub-object.
void co_obj_set_dn_ind(co_obj_t *obj, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen object.
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
co_obj_t * co_sub_get_obj(const co_sub_t *sub)
Returns the a pointer to the CANopen object containing the specified sub-object.
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
This header file is part of the CANopen library; it contains the Process Data Object (PDO) declaratio...
#define CO_PDO_NUM_MAPS
The maximum number of mapped application objects in a single PDO.
#define CO_PDO_COBID_FRAME
The bit in the PDO COB-ID specifying whether to use an 11-bit (0) or 29-bit (1) CAN-ID.
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
#define CO_NUM_PDOS
The maximum number of Receive/Transmit-PDOs.
#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...
A CANopen SDO upload/download request.
The internal implementation of the CANopen device description.
void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
A class template mapping CANopen types to C and C++ types.
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
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.
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.
This header file is part of the CANopen library; it contains the CANopen value declarations.
const void * co_val_addressof(co_unsigned16_t type, const void *val)
Returns the address of the first byte in a value of the specified data type.
size_t co_val_sizeof(co_unsigned16_t type, const void *val)
Returns the size (in bytes) of a value of the specified data type.
size_t co_val_read_file(co_unsigned16_t type, void *val, const char *filename)
Reads a value of the specified data type from a file.
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.