Accessing FELIX card registers ============================== felix-io allows to interface with the regular and i2c registers of the FELIX card. It replaces felix-register. We can interface to felix-io from felix-client using the :cpp:func:`translate`, :cpp:func:`read_register`, :cpp:func:`write_register` functions. The ``translate`` function takes a vector of fids and returns a map of device_ids. This translation is required as there is one felix-io endpoint per device. If the device ID is well known, it may also be used directly, in all other cases this function can transform any standard FIDs to a unique list of device IDs, mapped to the provided FIDs. In case of an invalid or unknown FID a ``felix::BusException`` is thrown. The ``read_register`` and ``write_register`` functions are used to actually read or write data from the FELIX device. Both functions take the device ID as the first argument to address the given device. The ``read_register`` functions takes the register name to be read as an argument and returns a map of name to vector of :cpp:struct:`class BitFieldRecord`. In case the value read is a single register, this map has one entry and the key is the provided name. In case a group of registers was queried, it contains one key per member of that register group. The ``BitFieldRecord`` struct contains contains the raw value, the unit, and the decoded value (for example, a temperature in Celsius). ``write_register`` takes the value as to be set as well and returns nothing. In case of failures a ``felix::FelixIoException`` is thrown containing the underlying error. For more information see _felix-io: https://gitlab.cern.ch/atlas-tdaq-felix/felix-io-api .. doxygenfunction:: FelixClientThreadExtension520::translate :no-link: :outline: .. doxygenfunction:: FelixClientThreadExtension520::read_register :no-link: :outline: .. doxygenfunction:: FelixClientThreadExtension520::write_register :no-link: :outline: Example ------- .. code-block:: cpp :linenos: const auto fids = std::vector{0x1000000000080000}; std::map> device_id_to_fid = client.translate(fids); for (const auto& device : device_id_to_fid | std::views::keys()) { std::map> results = client.read_register(device_id_to_fid.begin()->first, "REG_MAP_VERSION"); for (auto const& result: results) { std::println("Reply for felix-io deivce: {}, Name: {}", device, result.first); for (auto const& value: result.second) { std::println(" Value: {}", value); } } } Deprecated API -------------- Before felix-io we provided similar functionality through felix-register. We can interface felix-register from felix-client using the :cpp:func:`send_cmd` function. This function sends a message to felix-register and waits for a response. The function takes a vector of fids, a command and a list of arguments. The command is a string and the arguments are a list of strings. It also takes an out parameter to store the replies received by felix-register. Success or failure is reported by the returned status code. .. doxygenfunction:: FelixClientThreadExtension42::send_cmd :no-link: :outline: A command can be sent to multiple felixes by providing multiple FIDs in the ``fids`` parameter. It will only send one command once per FELIX instance. Commands -------- - ``UNKOWN``: do not use it. - ``NOOP``: do not use it. - ``GET``: read a register. Pass exactly one register name as ``cmd_args`` (1 argument in total). - ``SET``: write a register. Pass exactly one register name as ``cmd_args`` plus the value you want to set it to (2 arguments in total). - ``TRIGGER``: do not use it. - ``ECR_RESET``: Set the ECR counter. Pass the counter as ``cmd_args`` (1 argument in total). Return codes ------------ - ``OK``: Success, or you did not pass any FIDs. - ``ERROR``: General error. - ``ERROR_NO_SUBSCRIPTION``: If the bus information is missing or we cannot subscribe. - ``ERROR_NO_CONNECTION``: If we cannot send the request. - ``ERROR_NO_REPLY``: If no reply arrived within the timeout. - ``ERROR_INVALID_CMD``: Command is not one of ``NOOP``, ``GET``, ``SET``, ``ECR_RESET``. - ``ERROR_INVALID_ARGS``: Number of command arguments not correct for given command. - ``ERROR_INVALID_REGISTER``: If a register cannot be read. - ``ERROR_NOT_AUTHORIZED``: If a register cannot be written. Replies ------- The ``replies`` parameter contains a list of replies either containing the response from the server or information about errors. The reply contains the following fields: - ``ctrl_fid``: The FID to which the command is sent - ``status``: The :cpp:enumerator:`status` code of the reply (see below) - ``value``: Value returned by the server (set in case of ``GET`` command) - ``message``: Error message (set in case of status code not equal to ``OK``) .. doxygenenum:: FelixClientThreadExtension::Status :no-link: :outline: Example ------- .. code-block:: cpp :linenos: const auto fids = std::vector{0x1000000000080000, 0x1010000000080000}; auto replies = std::vector{}; const auto status = fct.send_cmd(fids, FelixClientThread::Cmd::GET, {"REG_MAP_VERSION"}, replies); std::println("Status: {}", std::to_underlying(status)); for (const auto& reply : replies) { std::println("Reply for felix-register FID: {:#x}, Status: {}, Value: {:#x}, Message: {}", reply.ctrl_fid, std::to_underlying(reply.status), reply.value, reply.message); }