12 #include <ChimeraTK/cppext/finally.hpp>
16 template<
typename UserType,
typename DataConverterType,
bool isRaw>
24 template<
typename UserType,
typename DataConverterType,
bool isRaw>
35 _dev = boost::dynamic_pointer_cast<NumericAddressedBackend>(dev);
37 throw ChimeraTK::logic_error(
"NumericAddressedBackendRegisterAccessor is used with a backend which is not "
38 "a NumericAddressedBackend.");
60 if(numberOfWords == 0) {
63 if(numberOfWords > 1) {
65 "Requested number of words is larger than 1 in VOID register '" + registerPathName +
"'!");
67 if(wordOffsetInRegister > 0) {
72 if(numberOfWords == 0) {
83 registerPathName +
"'!");
93 _rawAccessor = boost::make_shared<NumericAddressedLowLevelTransferElement>(
107 throw ChimeraTK::logic_error(
"Given UserType when obtaining the NumericAddressedBackendRegisterAccessor in "
108 "raw mode does not match the expected type. Use an " +
110 " instead! (Register name: " + registerPathName +
"')");
127 if(!
_dev->isOpen())
return;
129 _rawAccessor->setActiveException(this->_activeException);
132 if(!hasNewData)
return;
134 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
136 typedef decltype(t) RawType;
137 auto itsrc = (RawType*)_rawAccessor->begin(_registerInfo.address);
138 _dataConverter.template vectorToCooked<UserType>(itsrc, itsrc + buffer_2D[0].size(), buffer_2D[0].begin());
144 auto* itdst = buffer_2D[0].data();
145 memcpy(itdst, itsrc, buffer_2D[0].size() *
sizeof(UserType));
151 this->_versionNumber =
_rawAccessor->getVersionNumber();
161 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
164 "NumericAddressedBackend: Writing to a non-writeable register is not allowed (Register name: " +
168 typedef decltype(t) RawType;
169 auto itsrc = (RawType*)_rawAccessor->begin(_registerInfo.address);
170 for(auto itdst = buffer_2D[0].begin(); itdst != buffer_2D[0].end(); ++itdst) {
171 *itsrc = _dataConverter.template toRaw<UserType>(*itdst);
179 auto itsrc = buffer_2D[0].begin();
180 memcpy(&(*itdst), &(*itsrc), buffer_2D[0].size() *
sizeof(UserType));
188 if(!_registerInfo.isReadable()) {
190 "NumericAddressedBackend: Reading from a non-readable register is not allowed (Register name: " +
191 _registerInfo.getRegisterName() +
").");
193 _rawAccessor->preRead(type);
197 if(!_dev->isOpen())
return;
198 _rawAccessor->setActiveException(this->_activeException);
199 _rawAccessor->postWrite(type, versionNumber);
202 [[nodiscard]]
bool mayReplaceOther(
const boost::shared_ptr<TransferElement const>& other)
const override {
203 auto rhsCasted = boost::dynamic_pointer_cast<
205 if(!rhsCasted)
return false;
206 if(_dev != rhsCasted->_dev)
return false;
207 if(_registerInfo != rhsCasted->_registerInfo)
return false;
208 if(_dataConverter != rhsCasted->_dataConverter)
return false;
212 [[nodiscard]]
bool isReadOnly()
const override {
return isReadable() && !isWriteable(); }
214 [[nodiscard]]
bool isReadable()
const override {
return _registerInfo.isReadable(); }
216 [[nodiscard]]
bool isWriteable()
const override {
return _registerInfo.isWriteable(); }
218 template<
typename COOKED_TYPE>
219 COOKED_TYPE getAsCooked_impl(
unsigned int channel,
unsigned int sample);
221 template<
typename COOKED_TYPE>
222 void setAsCooked_impl(
unsigned int channel,
unsigned int sample, COOKED_TYPE value);
232 this->_exceptionBackend = exceptionBackend;
233 _rawAccessor->setExceptionBackend(exceptionBackend);
245 boost::shared_ptr<NumericAddressedLowLevelTransferElement>
_rawAccessor;
248 boost::shared_ptr<NumericAddressedBackend>
_dev;
251 return _rawAccessor->getHardwareAccessingElements();
255 return {_rawAccessor};
259 auto casted = boost::dynamic_pointer_cast<NumericAddressedLowLevelTransferElement>(newElement);
260 if(casted && casted->isMergeable(_rawAccessor)) {
261 size_t newStartAddress = std::min(casted->_startAddress, _rawAccessor->_startAddress);
262 size_t newStopAddress = std::max(
263 casted->_startAddress + casted->_numberOfBytes, _rawAccessor->_startAddress + _rawAccessor->_numberOfBytes);
264 size_t newNumberOfBytes = newStopAddress - newStartAddress;
265 casted->changeAddress(newStartAddress, newNumberOfBytes);
266 _rawAccessor = casted;
268 _rawAccessor->setExceptionBackend(this->_exceptionBackend);
275 template<
typename RawT,
typename CookedT>
277 static CookedT
vectorToCooked(DataConverterType&,
const typename std::vector<RawT>::const_iterator&,
278 const typename std::vector<RawT>::const_iterator&,
const typename std::vector<CookedT>::iterator&) {
281 static RawT
toRaw(DataConverterType&, CookedT&) {
285 template<
typename CookedT>
288 const typename std::vector<int8_t>::const_iterator& start,
289 const typename std::vector<int8_t>::const_iterator& end,
290 const typename std::vector<CookedT>::iterator& cooked) {
291 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
293 static int8_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
295 template<
typename CookedT>
298 const typename std::vector<int16_t>::const_iterator& start,
299 const typename std::vector<int16_t>::const_iterator& end,
300 const typename std::vector<CookedT>::iterator& cooked) {
301 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
303 static int16_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
305 template<
typename CookedT>
308 const typename std::vector<int32_t>::const_iterator& start,
309 const typename std::vector<int32_t>::const_iterator& end,
310 const typename std::vector<CookedT>::iterator& cooked) {
311 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
313 static int32_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
321 template<
typename UserType,
typename DataConverterType,
bool isRaw>
322 template<
typename COOKED_TYPE>
324 unsigned int channel,
unsigned int sample) {
326 std::vector<COOKED_TYPE> cookedData(1);
330 return cookedData[0];
337 template<
typename UserType,
typename DataConverterType,
bool isRaw>
338 template<
typename COOKED_TYPE>
340 unsigned int channel,
unsigned int sample, COOKED_TYPE value) {