ChimeraTK-DeviceAccess  03.18.00
SubdeviceRegisterAccessor.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2 // SPDX-License-Identifier: LGPL-3.0-or-later
3 
5 
6 #include <utility>
7 
8 namespace ChimeraTK {
9 
10  /********************************************************************************************************************/
11 
12  SubdeviceRegisterAccessor::SubdeviceRegisterAccessor(boost::shared_ptr<SubdeviceBackend> backend,
13  const std::string& registerPathName, boost::shared_ptr<NDRegisterAccessor<int32_t>> accAddress,
14  boost::shared_ptr<NDRegisterAccessor<int32_t>> accData, boost::shared_ptr<NDRegisterAccessor<int32_t>> accStatus,
15  size_t byteOffset, size_t numberOfWords)
16  : NDRegisterAccessor<int32_t>(registerPathName, {AccessMode::raw}), _backend(std::move(backend)),
17  _accAddress(std::move(accAddress)), _accDataArea(std::move(accData)), _accStatus(std::move(accStatus)),
18  _startAddress(byteOffset), _numberOfWords(numberOfWords) {
20  NDRegisterAccessor<int32_t>::buffer_2D[0].resize(numberOfWords);
21  _buffer.resize(numberOfWords);
22  }
23 
24  /********************************************************************************************************************/
25 
27  assert(false); // must never be called due to exception in doPreRead
28  }
29 
30  /********************************************************************************************************************/
31 
33  std::lock_guard<decltype(_backend->mutex)> lockGuard(_backend->mutex);
34  size_t nTransfers;
36  // for areaHandshake case with 1D array
37  // TODO FIXME shouldn't this be nTransfers = 1 ???
38  nTransfers = _numberOfWords;
39  }
40  else {
43  // This is "_numberOfWords / _accData->getNumberOfSamples()" rounded up:
44  nTransfers = (_numberOfWords + _accDataArea->getNumberOfSamples() - 1) / _accDataArea->getNumberOfSamples();
45  }
46  try {
47  size_t idx = 0;
48  for(size_t adr = _startAddress; adr < _startAddress + nTransfers; ++adr) {
49  // write address register (if applicable)
51  _accAddress->accessData(0) = static_cast<int32_t>(adr);
52  _accAddress->write();
53  usleep(_backend->addressToDataDelay);
54  }
55 
56  // write data register
58  int32_t val = (idx < _numberOfWords) ? _buffer[idx] : 0;
59  _accDataArea->accessData(0, idx) = val;
60  ++idx;
61  }
62  else {
63  for(size_t innerOffset = 0; innerOffset < _accDataArea->getNumberOfSamples(); ++innerOffset) {
64  // pad data with zeros, if _numberOfWords isn't an integer multiple of _accData->getNumberOfSamples()
65  int32_t val = (idx < _numberOfWords) ? _buffer[idx] : 0;
66  _accDataArea->accessData(0, innerOffset) = val;
67  ++idx;
68  }
69  }
70  _accDataArea->write();
71 
72  // wait until transaction is complete
75  // for 3regs/areaHandshake, wait until status register is 0 again
76  size_t retry = 0;
77  size_t max_retry = _backend->timeout * 1000 / _backend->sleepTime;
78  while(true) {
79  usleep(_backend->sleepTime);
80  _accStatus->read();
81  if(_accStatus->accessData(0) == 0) break;
82  if(++retry > max_retry) {
83  throw ChimeraTK::runtime_error("Write to register '" + _name +
84  "' failed: timeout waiting for cleared busy flag (" + _accStatus->getName() + ")");
85  }
86  }
87  }
88  else {
89  // for 2regs, wait given time
90  usleep(_backend->sleepTime);
91  }
92  }
93  }
94  catch(ChimeraTK::runtime_error& ex) {
95  _exceptionBackend->setException(ex.what());
96  throw;
97  }
98  return false;
99  }
100 
101  /********************************************************************************************************************/
102 
104  throw ChimeraTK::logic_error("Reading this register is not supported.");
105  }
106 
107  /********************************************************************************************************************/
108 
110  throw ChimeraTK::logic_error("Reading this register is not supported.");
111  }
112 
113  /********************************************************************************************************************/
114 
116  if(!_backend->isOpen()) {
117  throw ChimeraTK::logic_error("Device is not opened.");
118  }
119 
120  if(_accAddress && !_accAddress->isWriteable()) {
121  throw ChimeraTK::logic_error("SubdeviceRegisterAccessor[" + this->getName() + "]: address register '" +
122  _accAddress->getName() + "' is not writeable.");
123  }
124  if(!_accDataArea->isWriteable()) {
125  throw ChimeraTK::logic_error("SubdeviceRegisterAccessor[" + this->getName() + "]: data/area register '" +
126  _accDataArea->getName() + "' is not writeable.");
127  }
128  if(_backend->needStatusParam()) {
129  if(!_accStatus->isReadable()) {
130  throw ChimeraTK::logic_error("SubdeviceRegisterAccessor[" + this->getName() + "]: status register '" +
131  _accStatus->getName() + "' is not readable.");
132  }
133  }
134 
135  assert(NDRegisterAccessor<int32_t>::buffer_2D[0].size() == _buffer.size());
137  _accDataArea->setDataValidity(this->_dataValidity);
138  }
139 
140  /********************************************************************************************************************/
141 
144  }
145 
146  /********************************************************************************************************************/
147 
148  bool SubdeviceRegisterAccessor::mayReplaceOther(const boost::shared_ptr<TransferElement const>&) const {
149  return false;
150  }
151 
152  /********************************************************************************************************************/
153 
155  return false;
156  }
157 
158  /********************************************************************************************************************/
159 
161  return false;
162  }
163 
164  /********************************************************************************************************************/
165 
167  return true;
168  }
169 
170  /********************************************************************************************************************/
171 
172  std::vector<boost::shared_ptr<TransferElement>> SubdeviceRegisterAccessor::getHardwareAccessingElements() {
173  return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
174  }
175 
176  /********************************************************************************************************************/
177 
178  std::list<boost::shared_ptr<TransferElement>> SubdeviceRegisterAccessor::getInternalElements() {
180  }
181 
182  /********************************************************************************************************************/
183 
184  void SubdeviceRegisterAccessor::replaceTransferElement(boost::shared_ptr<TransferElement>) {}
185 
186 } // namespace ChimeraTK
ChimeraTK::SubdeviceRegisterAccessor::_accAddress
boost::shared_ptr< NDRegisterAccessor< int32_t > > _accAddress
Pointers to the three accessors.
Definition: SubdeviceRegisterAccessor.h:46
ChimeraTK::SubdeviceBackend::Type::threeRegisters
@ threeRegisters
ChimeraTK::runtime_error::what
const char * what() const noexcept override
Return the message describing what exactly went wrong.
Definition: Exception.cpp:14
ChimeraTK::AccessMode::raw
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
ChimeraTK::SubdeviceRegisterAccessor::isReadOnly
bool isReadOnly() const override
Definition: SubdeviceRegisterAccessor.cc:154
ChimeraTK::SubdeviceRegisterAccessor::_numberOfWords
size_t _numberOfWords
Definition: SubdeviceRegisterAccessor.h:51
ChimeraTK::SubdeviceRegisterAccessor::doWriteTransfer
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Definition: SubdeviceRegisterAccessor.cc:32
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
ChimeraTK::SubdeviceRegisterAccessor::_buffer
std::vector< int32_t > _buffer
internal buffer
Definition: SubdeviceRegisterAccessor.h:54
ChimeraTK::SubdeviceRegisterAccessor::isReadable
bool isReadable() const override
Definition: SubdeviceRegisterAccessor.cc:160
ChimeraTK::SubdeviceRegisterAccessor::getInternalElements
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Definition: SubdeviceRegisterAccessor.cc:178
ChimeraTK::SubdeviceRegisterAccessor::doPreWrite
void doPreWrite(TransferType type, VersionNumber) override
Definition: SubdeviceRegisterAccessor.cc:115
ChimeraTK::SubdeviceRegisterAccessor::getHardwareAccessingElements
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Definition: SubdeviceRegisterAccessor.cc:172
ChimeraTK::SubdeviceRegisterAccessor::doPreRead
void doPreRead(TransferType type) override
Definition: SubdeviceRegisterAccessor.cc:103
SubdeviceRegisterAccessor.h
ChimeraTK::SubdeviceRegisterAccessor::_accDataArea
boost::shared_ptr< NDRegisterAccessor< int32_t > > _accDataArea
Definition: SubdeviceRegisterAccessor.h:47
ChimeraTK::SubdeviceRegisterAccessor::_backend
boost::shared_ptr< SubdeviceBackend > _backend
Pointer to the backend.
Definition: SubdeviceRegisterAccessor.h:43
ChimeraTK::SubdeviceRegisterAccessor::_startAddress
size_t _startAddress
start address and length
Definition: SubdeviceRegisterAccessor.h:51
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
ChimeraTK::SubdeviceRegisterAccessor::doReadTransferSynchronously
void doReadTransferSynchronously() override
Definition: SubdeviceRegisterAccessor.cc:26
ChimeraTK::SubdeviceRegisterAccessor::_accStatus
boost::shared_ptr< NDRegisterAccessor< int32_t > > _accStatus
Definition: SubdeviceRegisterAccessor.h:48
ChimeraTK::SubdeviceRegisterAccessor::doPostWrite
void doPostWrite(TransferType type, VersionNumber) override
Definition: SubdeviceRegisterAccessor.cc:142
ChimeraTK::SubdeviceRegisterAccessor::SubdeviceRegisterAccessor
SubdeviceRegisterAccessor(boost::shared_ptr< SubdeviceBackend > backend, const std::string &registerPathName, boost::shared_ptr< NDRegisterAccessor< int32_t >> accAddress, boost::shared_ptr< NDRegisterAccessor< int32_t >> accDataArea, boost::shared_ptr< NDRegisterAccessor< int32_t >> accStatus, size_t byteOffset, size_t numberOfWords)
Definition: SubdeviceRegisterAccessor.cc:12
ChimeraTK::SubdeviceBackend::Type::twoRegisters
@ twoRegisters
ChimeraTK::SubdeviceRegisterAccessor::replaceTransferElement
void replaceTransferElement(boost::shared_ptr< TransferElement > newElement) override
Definition: SubdeviceRegisterAccessor.cc:184
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
ChimeraTK::SubdeviceRegisterAccessor::mayReplaceOther
bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &) const override
Definition: SubdeviceRegisterAccessor.cc:148
ChimeraTK::SubdeviceBackend::Type::areaHandshake
@ areaHandshake
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::SubdeviceRegisterAccessor::doPostRead
void doPostRead(TransferType type, bool hasNewData) override
Definition: SubdeviceRegisterAccessor.cc:109
ChimeraTK::NDRegisterAccessor< int32_t >
ChimeraTK::SubdeviceRegisterAccessor::isWriteable
bool isWriteable() const override
Definition: SubdeviceRegisterAccessor.cc:166
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51