ChimeraTK-DeviceAccess  03.18.00
Questions and Answers

This page is answering questions which users have asked when working with the DeviceAccess Library.

Why do RegisterAccessors not have an assignment operator for other RegisterAccessors?

We decided to explicitly disable the assignmet of one accessor to another because it is ambiguous what the excpected behaviour is:

  • Assign the data values of the other accessor?
  • Replace the complete accessor, incl. the register it points to. Depending on the contect where you use it you might expect either, so we decided to disable it to avoid unexpected behaviour.

Use explicit conversion and replace() (defined in the NDRegisterAccessorBridge base class) to disctinguish which functionalitily you want:

// Note: This is calling the copy constructor, not the assignment operator.
auto a = _device->getScalarRegisterAccessor<int>("REG_A");
auto b = _device->getScalarRegisterAccessor<int>("REG_B");
a = int(b); // replace the value of 'a' with the value of 'b'
a.replace(b); // replace the whole accessor, now 'a' points to REG_B

Details:

The original implementation had the default assignment operator which would replace the whole accessor, incl. the register it points to. This is what you need in the constructor of a class to initialise its member accessors:

// in the header (class definition)
ScalarRegisterAccessor<int> _a,_b;
// in the .cc file (implementation of the constructor)
_a = _device->getScalarRegisterAccessor<int>("REG_A");
_b = _device->getScalarRegisterAccessor<int>("REG_B");

In addition the Accessors have operators which let you treat it like the primitive data type it represents (or the std::vector of it):

_a = 7; // Assigment for int works, explicitly defined
_b.read();
_a += _b; // Works through implicit conversion,
// increases the content of _a by the content of _b.
_a.write();


With the assignment operator, however, this leads to unexpected behaviour:

_a = _b * 2; // replaces the value of _a with 2* value of _b
_a = _b; // WHOOPS, _a now points to "REG_B"

If we would have designed the assignment operator to only replace the value, the initialisation of the variable would behave unintuitively:

// This works as expected because in fact the copy constructor is called,
// although the syntax uses the euqals sign.
auto c = _device->getScalarRegisterAccessor<int>("REG_C");
// This does not work. 'd' is not initialised yet and the value assignment
// is called, which leads to an assertion because of null pointer
// dereferencing at run time.
ScalarRegisterAccessor<int> d;
d = _device->getScalarRegisterAccessor<int>("REG_D");

Hence, we decided that there is no intuitive implementation for the assigment operator and explicitly deactivated it. The last example assigning to d will already fail at compile time.

Why can I not read SEQUENCE registers?

The entries SEQUENCE_DMA_0 etc. in the map file are a crutch to implement multiplexed 2D registers, together with the according AREA_MULTIPLEXED_SEQUENCE register. You cannot directly read them. The entry in the register catalogue only exists for historical implementation reasons. However, QtHardMon in versions 0.x used this entry to display the according channel of the 2D register, so it gave the impression you could directly read the sequence.

The registers SEQUENCE_DMA_xx and AREA_MULTIPLEXED_SEQUENCE_DMA together describe the register "DMA" (register name can vary). To get the accoding sequence use a 2D accessor of "DMA" and get the channel you want (see 2D Register Accessors example). In QtHardMon 1.x and newer, use the register DMA and also select the correct channel.