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 {
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)) {}
183 Device::~Device() =
default;
187 ::std::lock_guard<Impl_> lock(*impl_);
189 return impl_->netid();
194 ::std::lock_guard<Impl_> lock(*impl_);
202 OnDnCon(
co_csdo_t*, uint16_t, uint8_t, uint32_t ac,
void* data) noexcept {
203 *
static_cast<uint32_t*
>(data) = ac;
208 OnUpCon(
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);
230 typename ::std::enable_if<is_canopen<T>::value, T>::type
232 ::std::error_code ec;
233 T value(Read<T>(idx, subidx, ec));
239 typename ::std::enable_if<is_canopen<T>::value, T>::type
240 Device::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_);
261 typename ::std::enable_if<is_canopen<T>::value>::type
262 Device::Write(uint16_t idx, uint8_t subidx,
const T& value) {
263 ::std::error_code ec;
264 Write(idx, subidx, value, ec);
269 typename ::std::enable_if<is_canopen<T>::value>::type
271 ::std::error_code& ec) {
272 using traits = canopen_traits<T>;
274 auto val = traits::to_c_type(value, ec);
279 ::std::lock_guard<Impl_> lock(*impl_);
294 traits::destroy(val);
299 Device::Write(uint16_t idx, uint8_t subidx, const ::std::string& value,
300 ::std::error_code& ec) {
301 Write(idx, subidx, value.c_str(), ec);
306 Device::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
314 template bool Device::Read<bool>(uint16_t, uint8_t)
const;
315 template bool Device::Read<bool>(uint16_t, uint8_t, ::std::error_code&)
const;
316 template void Device::Write<bool>(uint16_t, uint8_t,
const bool&);
317 template void Device::Write<bool>(uint16_t, uint8_t,
const bool&,
321 template int8_t Device::Read<int8_t>(uint16_t, uint8_t)
const;
322 template int8_t Device::Read<int8_t>(uint16_t, uint8_t,
323 ::std::error_code&)
const;
324 template void Device::Write<int8_t>(uint16_t, uint8_t,
const int8_t&);
325 template void Device::Write<int8_t>(uint16_t, uint8_t,
const int8_t&,
329 template int16_t Device::Read<int16_t>(uint16_t, uint8_t)
const;
330 template int16_t Device::Read<int16_t>(uint16_t, uint8_t,
331 ::std::error_code&)
const;
332 template void Device::Write<int16_t>(uint16_t, uint8_t,
const int16_t&);
333 template void Device::Write<int16_t>(uint16_t, uint8_t,
const int16_t&,
337 template int32_t Device::Read<int32_t>(uint16_t, uint8_t)
const;
338 template int32_t Device::Read<int32_t>(uint16_t, uint8_t,
339 ::std::error_code&)
const;
340 template void Device::Write<int32_t>(uint16_t, uint8_t,
const int32_t&);
341 template void Device::Write<int32_t>(uint16_t, uint8_t,
const int32_t&,
345 template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t)
const;
346 template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t,
347 ::std::error_code&)
const;
348 template void Device::Write<uint8_t>(uint16_t, uint8_t,
const uint8_t&);
349 template void Device::Write<uint8_t>(uint16_t, uint8_t,
const uint8_t&,
353 template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t)
const;
354 template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t,
355 ::std::error_code&)
const;
356 template void Device::Write<uint16_t>(uint16_t, uint8_t,
const uint16_t&);
357 template void Device::Write<uint16_t>(uint16_t, uint8_t,
const uint16_t&,
361 template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t)
const;
362 template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t,
363 ::std::error_code&)
const;
364 template void Device::Write<uint32_t>(uint16_t, uint8_t,
const uint32_t&);
365 template void Device::Write<uint32_t>(uint16_t, uint8_t,
const uint32_t&,
369 template float Device::Read<float>(uint16_t, uint8_t)
const;
370 template float Device::Read<float>(uint16_t, uint8_t, ::std::error_code&)
const;
371 template void Device::Write<float>(uint16_t, uint8_t,
const float&);
372 template void Device::Write<float>(uint16_t, uint8_t,
const float&,
376 template ::std::string Device::Read<::std::string>(uint16_t, uint8_t)
const;
377 template ::std::string Device::Read<::std::string>(uint16_t, uint8_t,
378 ::std::error_code&)
const;
379 template void Device::Write<::std::string>(uint16_t, uint8_t,
380 const ::std::string&);
386 template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
387 uint16_t, uint8_t)
const;
388 template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
389 uint16_t, uint8_t, ::std::error_code&)
const;
390 template void Device::Write<::std::vector<uint8_t>>(
391 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
396 template ::std::basic_string<char16_t>
397 Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
398 template ::std::basic_string<char16_t>
399 Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t,
400 ::std::error_code&)
const;
401 template void Device::Write<::std::basic_string<char16_t>>(
402 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
403 template void Device::Write<::std::basic_string<char16_t>>(
404 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
413 template double Device::Read<double>(uint16_t, uint8_t)
const;
414 template double Device::Read<double>(uint16_t, uint8_t,
415 ::std::error_code&)
const;
416 template void Device::Write<double>(uint16_t, uint8_t,
const double&);
417 template void Device::Write<double>(uint16_t, uint8_t,
const double&,
425 template int64_t Device::Read<int64_t>(uint16_t, uint8_t)
const;
426 template int64_t Device::Read<int64_t>(uint16_t, uint8_t,
427 ::std::error_code&)
const;
428 template void Device::Write<int64_t>(uint16_t, uint8_t,
const int64_t&);
429 template void Device::Write<int64_t>(uint16_t, uint8_t,
const int64_t&,
438 template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t)
const;
439 template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t,
440 ::std::error_code&)
const;
441 template void Device::Write<uint64_t>(uint16_t, uint8_t,
const uint64_t&);
442 template void Device::Write<uint64_t>(uint16_t, uint8_t,
const uint64_t&,
445 #endif // DOXYGEN_SHOULD_SKIP_THIS
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);
496 Device::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_);
586 SetEvent(idx, subidx, ec);
590 typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
592 ::std::error_code ec;
593 T value(RpdoRead<T>(
id, idx, subidx, ec));
599 typename ::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);
612 typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
614 ::std::error_code ec;
615 T value(TpdoRead<T>(
id, idx, subidx, ec));
621 typename ::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);
634 typename ::std::enable_if<is_canopen_basic<T>::value>::type
636 ::std::error_code ec;
642 typename ::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
656 template bool Device::RpdoRead<bool>(uint8_t, uint16_t, uint8_t)
const;
657 template bool Device::RpdoRead<bool>(uint8_t, uint16_t, uint8_t,
658 ::std::error_code&)
const;
659 template bool Device::TpdoRead<bool>(uint8_t, uint16_t, uint8_t)
const;
660 template bool Device::TpdoRead<bool>(uint8_t, uint16_t, uint8_t,
661 ::std::error_code&)
const;
662 template void Device::TpdoWrite<bool>(uint8_t, uint16_t, uint8_t,
bool);
663 template void Device::TpdoWrite<bool>(uint8_t, uint16_t, uint8_t,
bool,
667 template int8_t Device::RpdoRead<int8_t>(uint8_t, uint16_t, uint8_t)
const;
668 template int8_t Device::RpdoRead<int8_t>(uint8_t, uint16_t, uint8_t,
669 ::std::error_code&)
const;
670 template int8_t Device::TpdoRead<int8_t>(uint8_t, uint16_t, uint8_t)
const;
671 template int8_t Device::TpdoRead<int8_t>(uint8_t, uint16_t, uint8_t,
672 ::std::error_code&)
const;
673 template void Device::TpdoWrite<int8_t>(uint8_t, uint16_t, uint8_t, int8_t);
674 template void Device::TpdoWrite<int8_t>(uint8_t, uint16_t, uint8_t, int8_t,
678 template int16_t Device::RpdoRead<int16_t>(uint8_t, uint16_t, uint8_t)
const;
679 template int16_t Device::RpdoRead<int16_t>(uint8_t, uint16_t, uint8_t,
680 ::std::error_code&)
const;
681 template int16_t Device::TpdoRead<int16_t>(uint8_t, uint16_t, uint8_t)
const;
682 template int16_t Device::TpdoRead<int16_t>(uint8_t, uint16_t, uint8_t,
683 ::std::error_code&)
const;
684 template void Device::TpdoWrite<int16_t>(uint8_t, uint16_t, uint8_t, int16_t);
685 template void Device::TpdoWrite<int16_t>(uint8_t, uint16_t, uint8_t, int16_t,
689 template int32_t Device::RpdoRead<int32_t>(uint8_t, uint16_t, uint8_t)
const;
690 template int32_t Device::RpdoRead<int32_t>(uint8_t, uint16_t, uint8_t,
691 ::std::error_code&)
const;
692 template int32_t Device::TpdoRead<int32_t>(uint8_t, uint16_t, uint8_t)
const;
693 template int32_t Device::TpdoRead<int32_t>(uint8_t, uint16_t, uint8_t,
694 ::std::error_code&)
const;
695 template void Device::TpdoWrite<int32_t>(uint8_t, uint16_t, uint8_t, int32_t);
696 template void Device::TpdoWrite<int32_t>(uint8_t, uint16_t, uint8_t, int32_t,
700 template uint8_t Device::RpdoRead<uint8_t>(uint8_t, uint16_t, uint8_t)
const;
701 template uint8_t Device::RpdoRead<uint8_t>(uint8_t, uint16_t, uint8_t,
702 ::std::error_code&)
const;
703 template uint8_t Device::TpdoRead<uint8_t>(uint8_t, uint16_t, uint8_t)
const;
704 template uint8_t Device::TpdoRead<uint8_t>(uint8_t, uint16_t, uint8_t,
705 ::std::error_code&)
const;
706 template void Device::TpdoWrite<uint8_t>(uint8_t, uint16_t, uint8_t, uint8_t);
707 template void Device::TpdoWrite<uint8_t>(uint8_t, uint16_t, uint8_t, uint8_t,
711 template uint16_t Device::RpdoRead<uint16_t>(uint8_t, uint16_t, uint8_t)
const;
712 template uint16_t Device::RpdoRead<uint16_t>(uint8_t, uint16_t, uint8_t,
713 ::std::error_code&)
const;
714 template uint16_t Device::TpdoRead<uint16_t>(uint8_t, uint16_t, uint8_t)
const;
715 template uint16_t Device::TpdoRead<uint16_t>(uint8_t, uint16_t, uint8_t,
716 ::std::error_code&)
const;
717 template void Device::TpdoWrite<uint16_t>(uint8_t, uint16_t, uint8_t, uint16_t);
718 template void Device::TpdoWrite<uint16_t>(uint8_t, uint16_t, uint8_t, uint16_t,
722 template uint32_t Device::RpdoRead<uint32_t>(uint8_t, uint16_t, uint8_t)
const;
723 template uint32_t Device::RpdoRead<uint32_t>(uint8_t, uint16_t, uint8_t,
724 ::std::error_code&)
const;
725 template uint32_t Device::TpdoRead<uint32_t>(uint8_t, uint16_t, uint8_t)
const;
726 template uint32_t Device::TpdoRead<uint32_t>(uint8_t, uint16_t, uint8_t,
727 ::std::error_code&)
const;
728 template void Device::TpdoWrite<uint32_t>(uint8_t, uint16_t, uint8_t, uint32_t);
729 template void Device::TpdoWrite<uint32_t>(uint8_t, uint16_t, uint8_t, uint32_t,
733 template float Device::RpdoRead<float>(uint8_t, uint16_t, uint8_t)
const;
734 template float Device::RpdoRead<float>(uint8_t, uint16_t, uint8_t,
735 ::std::error_code&)
const;
736 template float Device::TpdoRead<float>(uint8_t, uint16_t, uint8_t)
const;
737 template float Device::TpdoRead<float>(uint8_t, uint16_t, uint8_t,
738 ::std::error_code&)
const;
739 template void Device::TpdoWrite<float>(uint8_t, uint16_t, uint8_t,
float);
740 template void Device::TpdoWrite<float>(uint8_t, uint16_t, uint8_t,
float,
752 template double Device::RpdoRead<double>(uint8_t, uint16_t, uint8_t)
const;
753 template double Device::RpdoRead<double>(uint8_t, uint16_t, uint8_t,
754 ::std::error_code&)
const;
755 template double Device::TpdoRead<double>(uint8_t, uint16_t, uint8_t)
const;
756 template double Device::TpdoRead<double>(uint8_t, uint16_t, uint8_t,
757 ::std::error_code&)
const;
758 template void Device::TpdoWrite<double>(uint8_t, uint16_t, uint8_t,
double);
759 template void Device::TpdoWrite<double>(uint8_t, uint16_t, uint8_t,
double,
767 template int64_t Device::RpdoRead<int64_t>(uint8_t, uint16_t, uint8_t)
const;
768 template int64_t Device::RpdoRead<int64_t>(uint8_t, uint16_t, uint8_t,
769 ::std::error_code&)
const;
770 template int64_t Device::TpdoRead<int64_t>(uint8_t, uint16_t, uint8_t)
const;
771 template int64_t Device::TpdoRead<int64_t>(uint8_t, uint16_t, uint8_t,
772 ::std::error_code&)
const;
773 template void Device::TpdoWrite<int64_t>(uint8_t, uint16_t, uint8_t, int64_t);
774 template void Device::TpdoWrite<int64_t>(uint8_t, uint16_t, uint8_t, int64_t,
783 template uint64_t Device::RpdoRead<uint64_t>(uint8_t, uint16_t, uint8_t)
const;
784 template uint64_t Device::RpdoRead<uint64_t>(uint8_t, uint16_t, uint8_t,
785 ::std::error_code&)
const;
786 template uint64_t Device::TpdoRead<uint64_t>(uint8_t, uint16_t, uint8_t)
const;
787 template uint64_t Device::TpdoRead<uint64_t>(uint8_t, uint16_t, uint8_t,
788 ::std::error_code&)
const;
789 template void Device::TpdoWrite<uint64_t>(uint8_t, uint16_t, uint8_t, uint64_t);
790 template void Device::TpdoWrite<uint64_t>(uint8_t, uint16_t, uint8_t, uint64_t,
793 #endif // DOXYGEN_SHOULD_SKIP_THIS
797 ::std::error_code ec;
804 ::std::error_code& ec) noexcept {
805 ::std::lock_guard<Impl_> lock(*impl_);
807 TpdoSetEvent(
id, idx, subidx, ec);
811 Device::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();
832 const ::std::type_info&
834 ::std::error_code ec;
835 auto& ti =
Type(idx, subidx, ec);
840 const ::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);
903 typename ::std::enable_if<is_canopen<T>::value, T>::type
905 ::std::error_code ec;
906 auto value = Get<T>(idx, subidx, ec);
912 typename ::std::enable_if<is_canopen<T>::value, T>::type
914 ::std::error_code& ec)
const noexcept {
915 using traits = canopen_traits<T>;
916 using c_type =
typename traits::c_type;
938 return traits::from_c_type(*pval);
942 typename ::std::enable_if<is_canopen<T>::value>::type
943 Device::Set(uint16_t idx, uint8_t subidx,
const T& value) {
944 ::std::error_code ec;
945 Set(idx, subidx, value, ec);
950 typename ::std::enable_if<is_canopen<T>::value>::type
951 Device::Set(uint16_t idx, uint8_t subidx,
const T& value,
952 ::std::error_code& ec) noexcept {
953 using traits = canopen_traits<T>;
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);
990 Device::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);
997 Device::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
1005 template bool Device::Get<bool>(uint16_t, uint8_t)
const;
1006 template bool Device::Get<bool>(uint16_t, uint8_t,
1007 ::std::error_code&)
const noexcept;
1008 template void Device::Set<bool>(uint16_t, uint8_t,
const bool&);
1009 template void Device::Set<bool>(uint16_t, uint8_t,
const bool&,
1010 ::std::error_code&) noexcept;
1013 template int8_t Device::Get<int8_t>(uint16_t, uint8_t)
const;
1014 template int8_t Device::Get<int8_t>(uint16_t, uint8_t,
1015 ::std::error_code&)
const noexcept;
1016 template void Device::Set<int8_t>(uint16_t, uint8_t,
const int8_t&);
1017 template void Device::Set<int8_t>(uint16_t, uint8_t,
const int8_t&,
1018 ::std::error_code&) noexcept;
1021 template int16_t Device::Get<int16_t>(uint16_t, uint8_t)
const;
1022 template int16_t Device::Get<int16_t>(uint16_t, uint8_t,
1023 ::std::error_code&)
const noexcept;
1024 template void Device::Set<int16_t>(uint16_t, uint8_t,
const int16_t&);
1025 template void Device::Set<int16_t>(uint16_t, uint8_t,
const int16_t&,
1026 ::std::error_code&) noexcept;
1029 template int32_t Device::Get<int32_t>(uint16_t, uint8_t)
const;
1030 template int32_t Device::Get<int32_t>(uint16_t, uint8_t,
1031 ::std::error_code&)
const noexcept;
1032 template void Device::Set<int32_t>(uint16_t, uint8_t,
const int32_t&);
1033 template void Device::Set<int32_t>(uint16_t, uint8_t,
const int32_t&,
1034 ::std::error_code&) noexcept;
1037 template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t)
const;
1038 template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t,
1039 ::std::error_code&)
const noexcept;
1040 template void Device::Set<uint8_t>(uint16_t, uint8_t,
const uint8_t&);
1041 template void Device::Set<uint8_t>(uint16_t, uint8_t,
const uint8_t&,
1042 ::std::error_code&) noexcept;
1045 template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t)
const;
1046 template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t,
1047 ::std::error_code&)
const noexcept;
1048 template void Device::Set<uint16_t>(uint16_t, uint8_t,
const uint16_t&);
1049 template void Device::Set<uint16_t>(uint16_t, uint8_t,
const uint16_t&,
1050 ::std::error_code&) noexcept;
1053 template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t)
const;
1054 template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t,
1055 ::std::error_code&)
const noexcept;
1056 template void Device::Set<uint32_t>(uint16_t, uint8_t,
const uint32_t&);
1057 template void Device::Set<uint32_t>(uint16_t, uint8_t,
const uint32_t&,
1058 ::std::error_code&) noexcept;
1061 template float Device::Get<float>(uint16_t, uint8_t)
const;
1062 template float Device::Get<float>(uint16_t, uint8_t,
1063 ::std::error_code&)
const noexcept;
1064 template void Device::Set<float>(uint16_t, uint8_t,
const float&);
1065 template void Device::Set<float>(uint16_t, uint8_t,
const float&,
1066 ::std::error_code&) noexcept;
1069 template ::std::string Device::Get<::std::string>(uint16_t, uint8_t)
const;
1070 template ::std::string Device::Get<::std::string>(
1071 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1072 template void Device::Set<::std::string>(uint16_t, uint8_t,
1073 const ::std::string&);
1079 template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
1080 uint16_t, uint8_t)
const;
1081 template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
1082 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1083 template void Device::Set<::std::vector<uint8_t>>(
1084 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
1092 template ::std::basic_string<char16_t>
1093 Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
1094 template ::std::basic_string<char16_t>
1095 Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t,
1096 ::std::error_code&)
const noexcept;
1097 template void Device::Set<::std::basic_string<char16_t>>(
1098 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
1099 template void Device::Set<::std::basic_string<char16_t>>(
1100 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
1101 ::std::error_code&) noexcept;
1109 template double Device::Get<double>(uint16_t, uint8_t)
const;
1110 template double Device::Get<double>(uint16_t, uint8_t,
1111 ::std::error_code&)
const noexcept;
1112 template void Device::Set<double>(uint16_t, uint8_t,
const double&);
1113 template void Device::Set<double>(uint16_t, uint8_t,
const double&,
1114 ::std::error_code&) noexcept;
1121 template int64_t Device::Get<int64_t>(uint16_t, uint8_t)
const;
1122 template int64_t Device::Get<int64_t>(uint16_t, uint8_t,
1123 ::std::error_code&)
const noexcept;
1124 template void Device::Set<int64_t>(uint16_t, uint8_t,
const int64_t&);
1125 template void Device::Set<int64_t>(uint16_t, uint8_t,
const int64_t&,
1126 ::std::error_code&) noexcept;
1134 template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t)
const;
1135 template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t,
1136 ::std::error_code&)
const noexcept;
1137 template void Device::Set<uint64_t>(uint16_t, uint8_t,
const uint64_t&);
1138 template void Device::Set<uint64_t>(uint16_t, uint8_t,
const uint64_t&,
1139 ::std::error_code&) noexcept;
1141 #endif // DOXYGEN_SHOULD_SKIP_THIS
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);
1202 Device::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);
1209 Device::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 {
1350 #endif // !LELY_NO_CO_OBJ_FILE
1354 ::std::error_code ec;
1373 #if !LELY_NO_CO_TPDO
1375 #if !LELYY_NO_CO_MPDO
1378 #endif // !LELY_NO_CO_TPDO
1382 typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1384 ::std::error_code ec;
1385 auto value = RpdoGet<T>(
id, idx, subidx, ec);
1391 typename ::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);
1401 typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1403 ::std::error_code ec;
1404 auto value = TpdoGet<T>(
id, idx, subidx, ec);
1410 typename ::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);
1420 typename ::std::enable_if<is_canopen_basic<T>::value>::type
1422 ::std::error_code ec;
1423 TpdoSet(
id, idx, subidx, value, ec);
1428 typename ::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
1439 template bool Device::RpdoGet<bool>(uint8_t, uint16_t, uint8_t)
const;
1440 template bool Device::RpdoGet<bool>(uint8_t, uint16_t, uint8_t,
1441 ::std::error_code&)
const noexcept;
1442 template bool Device::TpdoGet<bool>(uint8_t, uint16_t, uint8_t)
const;
1443 template bool Device::TpdoGet<bool>(uint8_t, uint16_t, uint8_t,
1444 ::std::error_code&)
const noexcept;
1445 template void Device::TpdoSet<bool>(uint8_t, uint16_t, uint8_t,
bool);
1446 template void Device::TpdoSet<bool>(uint8_t, uint16_t, uint8_t,
bool,
1447 ::std::error_code&) noexcept;
1450 template int8_t Device::RpdoGet<int8_t>(uint8_t, uint16_t, uint8_t)
const;
1451 template int8_t Device::RpdoGet<int8_t>(uint8_t, uint16_t, uint8_t,
1452 ::std::error_code&)
const noexcept;
1453 template int8_t Device::TpdoGet<int8_t>(uint8_t, uint16_t, uint8_t)
const;
1454 template int8_t Device::TpdoGet<int8_t>(uint8_t, uint16_t, uint8_t,
1455 ::std::error_code&)
const noexcept;
1456 template void Device::TpdoSet<int8_t>(uint8_t, uint16_t, uint8_t, int8_t);
1457 template void Device::TpdoSet<int8_t>(uint8_t, uint16_t, uint8_t, int8_t,
1458 ::std::error_code&) noexcept;
1461 template int16_t Device::RpdoGet<int16_t>(uint8_t, uint16_t, uint8_t)
const;
1462 template int16_t Device::RpdoGet<int16_t>(uint8_t, uint16_t, uint8_t,
1463 ::std::error_code&)
const noexcept;
1464 template int16_t Device::TpdoGet<int16_t>(uint8_t, uint16_t, uint8_t)
const;
1465 template int16_t Device::TpdoGet<int16_t>(uint8_t, uint16_t, uint8_t,
1466 ::std::error_code&)
const noexcept;
1467 template void Device::TpdoSet<int16_t>(uint8_t, uint16_t, uint8_t, int16_t);
1468 template void Device::TpdoSet<int16_t>(uint8_t, uint16_t, uint8_t, int16_t,
1469 ::std::error_code&) noexcept;
1472 template int32_t Device::RpdoGet<int32_t>(uint8_t, uint16_t, uint8_t)
const;
1473 template int32_t Device::RpdoGet<int32_t>(uint8_t, uint16_t, uint8_t,
1474 ::std::error_code&)
const noexcept;
1475 template int32_t Device::TpdoGet<int32_t>(uint8_t, uint16_t, uint8_t)
const;
1476 template int32_t Device::TpdoGet<int32_t>(uint8_t, uint16_t, uint8_t,
1477 ::std::error_code&)
const noexcept;
1478 template void Device::TpdoSet<int32_t>(uint8_t, uint16_t, uint8_t, int32_t);
1479 template void Device::TpdoSet<int32_t>(uint8_t, uint16_t, uint8_t, int32_t,
1480 ::std::error_code&) noexcept;
1483 template uint8_t Device::RpdoGet<uint8_t>(uint8_t, uint16_t, uint8_t)
const;
1484 template uint8_t Device::RpdoGet<uint8_t>(uint8_t, uint16_t, uint8_t,
1485 ::std::error_code&)
const noexcept;
1486 template uint8_t Device::TpdoGet<uint8_t>(uint8_t, uint16_t, uint8_t)
const;
1487 template uint8_t Device::TpdoGet<uint8_t>(uint8_t, uint16_t, uint8_t,
1488 ::std::error_code&)
const noexcept;
1489 template void Device::TpdoSet<uint8_t>(uint8_t, uint16_t, uint8_t, uint8_t);
1490 template void Device::TpdoSet<uint8_t>(uint8_t, uint16_t, uint8_t, uint8_t,
1491 ::std::error_code&) noexcept;
1494 template uint16_t Device::RpdoGet<uint16_t>(uint8_t, uint16_t, uint8_t)
const;
1495 template uint16_t Device::RpdoGet<uint16_t>(uint8_t, uint16_t, uint8_t,
1496 ::std::error_code&)
const noexcept;
1497 template uint16_t Device::TpdoGet<uint16_t>(uint8_t, uint16_t, uint8_t)
const;
1498 template uint16_t Device::TpdoGet<uint16_t>(uint8_t, uint16_t, uint8_t,
1499 ::std::error_code&)
const noexcept;
1500 template void Device::TpdoSet<uint16_t>(uint8_t, uint16_t, uint8_t, uint16_t);
1501 template void Device::TpdoSet<uint16_t>(uint8_t, uint16_t, uint8_t, uint16_t,
1502 ::std::error_code&) noexcept;
1505 template uint32_t Device::RpdoGet<uint32_t>(uint8_t, uint16_t, uint8_t)
const;
1506 template uint32_t Device::RpdoGet<uint32_t>(uint8_t, uint16_t, uint8_t,
1507 ::std::error_code&)
const noexcept;
1508 template uint32_t Device::TpdoGet<uint32_t>(uint8_t, uint16_t, uint8_t)
const;
1509 template uint32_t Device::TpdoGet<uint32_t>(uint8_t, uint16_t, uint8_t,
1510 ::std::error_code&)
const noexcept;
1511 template void Device::TpdoSet<uint32_t>(uint8_t, uint16_t, uint8_t, uint32_t);
1512 template void Device::TpdoSet<uint32_t>(uint8_t, uint16_t, uint8_t, uint32_t,
1513 ::std::error_code&) noexcept;
1516 template float Device::RpdoGet<float>(uint8_t, uint16_t, uint8_t)
const;
1517 template float Device::RpdoGet<float>(uint8_t, uint16_t, uint8_t,
1518 ::std::error_code&)
const noexcept;
1519 template float Device::TpdoGet<float>(uint8_t, uint16_t, uint8_t)
const;
1520 template float Device::TpdoGet<float>(uint8_t, uint16_t, uint8_t,
1521 ::std::error_code&)
const noexcept;
1522 template void Device::TpdoSet<float>(uint8_t, uint16_t, uint8_t,
float);
1523 template void Device::TpdoSet<float>(uint8_t, uint16_t, uint8_t,
float,
1524 ::std::error_code&) noexcept;
1535 template double Device::RpdoGet<double>(uint8_t, uint16_t, uint8_t)
const;
1536 template double Device::RpdoGet<double>(uint8_t, uint16_t, uint8_t,
1537 ::std::error_code&)
const noexcept;
1538 template double Device::TpdoGet<double>(uint8_t, uint16_t, uint8_t)
const;
1539 template double Device::TpdoGet<double>(uint8_t, uint16_t, uint8_t,
1540 ::std::error_code&)
const noexcept;
1541 template void Device::TpdoSet<double>(uint8_t, uint16_t, uint8_t,
double);
1542 template void Device::TpdoSet<double>(uint8_t, uint16_t, uint8_t,
double,
1543 ::std::error_code&) noexcept;
1550 template int64_t Device::RpdoGet<int64_t>(uint8_t, uint16_t, uint8_t)
const;
1551 template int64_t Device::RpdoGet<int64_t>(uint8_t, uint16_t, uint8_t,
1552 ::std::error_code&)
const noexcept;
1553 template int64_t Device::TpdoGet<int64_t>(uint8_t, uint16_t, uint8_t)
const;
1554 template int64_t Device::TpdoGet<int64_t>(uint8_t, uint16_t, uint8_t,
1555 ::std::error_code&)
const noexcept;
1556 template void Device::TpdoSet<int64_t>(uint8_t, uint16_t, uint8_t, int64_t);
1557 template void Device::TpdoSet<int64_t>(uint8_t, uint16_t, uint8_t, int64_t,
1558 ::std::error_code&) noexcept;
1566 template uint64_t Device::RpdoGet<uint64_t>(uint8_t, uint16_t, uint8_t)
const;
1567 template uint64_t Device::RpdoGet<uint64_t>(uint8_t, uint16_t, uint8_t,
1568 ::std::error_code&)
const noexcept;
1569 template uint64_t Device::TpdoGet<uint64_t>(uint8_t, uint16_t, uint8_t)
const;
1570 template uint64_t Device::TpdoGet<uint64_t>(uint8_t, uint16_t, uint8_t,
1571 ::std::error_code&)
const noexcept;
1572 template void Device::TpdoSet<uint64_t>(uint8_t, uint16_t, uint8_t, uint64_t);
1573 template void Device::TpdoSet<uint64_t>(uint8_t, uint16_t, uint8_t, uint64_t,
1574 ::std::error_code&) noexcept;
1576 #endif // DOXYGEN_SHOULD_SKIP_THIS
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);
1595 #if !LELY_NO_CO_RPDO
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;
1657 #if !LELY_NO_CO_MPDO
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;
1709 #endif // !LELY_NO_CO_MPDO
1710 #endif // !LELY_NO_CO_RPDO
1715 #if !LELY_NO_CO_TPDO
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;
1772 #endif // !LELY_NO_CO_TPDO
1782 OnRpdoWrite(
id, idx, subidx);
1784 if (impl_->on_rpdo_write) {
1785 auto f = impl_->on_rpdo_write;
1793 Device::Impl_::Impl_(
Device* self_, const ::std::string& dcf_txt,
1794 const ::std::string& dcf_bin, uint8_t
id,
1799 if (!dcf_bin.empty() &&
1801 util::throw_errc(
"Device");
1804 util::throw_errc(
"Device");
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));
1828 #endif // !LELY_NO_CO_DCF
1831 Device::Impl_::OnWrite(uint16_t idx, uint8_t subidx) {
1832 self->OnWrite(idx, subidx);
1836 util::UnlockGuard<Impl_>
unlock(*
this);
1840 #if !LELY_NO_CO_RPDO
1842 ::std::error_code ec;
1843 ::std::tie(
id, idx, subidx) = RpdoMapping(idx, subidx, ec);
1844 if (!ec)
self->RpdoWrite(
id, idx, subidx);