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
translate,
read_register,
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 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
-
virtual std::map<felix::DeviceId, std::vector<std::uint64_t>> FelixClientThreadExtension520::translate(const std::vector<std::uint64_t> &fids) = 0
-
virtual std::map<std::string, std::vector<felix::BitFieldRecord>> FelixClientThreadExtension520::read_register(const felix::DeviceId &dev_id, const std::string &name) const = 0
-
virtual void FelixClientThreadExtension520::write_register(const felix::DeviceId &dev_id, const std::string &name, std::uint64_t value) const = 0
Example
1const auto fids = std::vector<std::uint64_t>{0x1000000000080000};
2
3std::map<felix::DeviceId, std::vector<std::uint64_t>> device_id_to_fid = client.translate(fids);
4
5for (const auto& device : device_id_to_fid | std::views::keys()) {
6 std::map<std::string, std::vector<BitFieldRecord>> results = client.read_register(device_id_to_fid.begin()->first, "REG_MAP_VERSION");
7
8 for (auto const& result: results) {
9 std::println("Reply for felix-io deivce: {}, Name: {}", device, result.first);
10 for (auto const& value: result.second) {
11 std::println(" Value: {}", value);
12 }
13 }
14}
Deprecated API
Before felix-io we provided similar functionality through felix-register. We can interface
felix-register from felix-client using the
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.
-
virtual Status FelixClientThreadExtension42::send_cmd(const std::vector<uint64_t> &fids, Cmd cmd, const std::vector<std::string> &cmd_args, std::vector<Reply> &replies) = 0
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 ascmd_args(1 argument in total).SET: write a register. Pass exactly one register name ascmd_argsplus 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 ascmd_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 ofNOOP,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 sentstatus: Thestatuscode of the reply (see below)value: Value returned by the server (set in case ofGETcommand)message: Error message (set in case of status code not equal toOK)
-
enum FelixClientThreadExtension::Status
Values:
-
enumerator OK
-
enumerator ERROR
-
enumerator ERROR_NO_SUBSCRIPTION
-
enumerator ERROR_NO_CONNECTION
-
enumerator ERROR_NO_REPLY
-
enumerator ERROR_INVALID_CMD
-
enumerator ERROR_INVALID_ARGS
-
enumerator ERROR_INVALID_REGISTER
-
enumerator ERROR_NOT_AUTHORIZED
-
enumerator OK
Example
1const auto fids = std::vector<std::uint64_t>{0x1000000000080000, 0x1010000000080000};
2
3auto replies = std::vector<FelixClientThread::Reply>{};
4const auto status = fct.send_cmd(fids, FelixClientThread::Cmd::GET, {"REG_MAP_VERSION"}, replies);
5
6std::println("Status: {}", std::to_underlying(status));
7for (const auto& reply : replies) {
8 std::println("Reply for felix-register FID: {:#x}, Status: {}, Value: {:#x}, Message: {}", reply.ctrl_fid, std::to_underlying(reply.status), reply.value, reply.message);
9}