This program reads data from a single Mesytec MVLC controller into a ringbuffer. Note that this program is not part of FRIB/NSCLDAQ but requires an installation of the Mesytec mvlc userspace driver. The environment variable MVLCROOT in the command above, is defined by you to point to the top level directory of this installation. At the time I'm writing this, that is /usr/opt/mesytec-mvlc/0.1.0 at the FRIB or using the FRRIB containerized bookworm environment.
The configFile on the command line is the output of mvlcgenerate when run on a VMUSBReadout daqconfig file.
Note that in the list of options below, one and only one of the following options must be provided to describe the MVLC from which data will be collected:
--mvlc-eth Specifies the connection will be Ethernet.
--mvlc-usb specifies the first MVLC device found on the USB
system will be used (suitable when there's only one device present).
--mvlc-usb-index Specifies that a specific index in the enumerated
list of MVLC devices attached to the USB be used. This is not really safe, in my opinion
as it relies on a predictable enumeration by linux.
--mvlc-usb-serial Specifies the serial number string of a specific
MVLC that is attached to the USB. This is the safest option to use when you are
selecting from more than one attached MVLC.
Note that the crate configuration file can also specify the MVLC to use however as that comes from a template file used by mvlcgenerate it, normally, should be overidden by one o fthe options above.
-?, -h, --helpDisplay brief usage information in case you can't remember how to run the program.
--mvlc-eth hostnamemvlc ethernet hostname (overrides CrateConfig).
--mvlc-usbConnects to the first MVLC in the USB enumeration of devices. This is simplest to use when only one MVLC is attached to the host system via USB.
--mvlc-usb-index indexConnect to the mvlc with the given usb device index (overrides CrateConfig). At system startup, and when a USB device is plugged in, or unplugged, linux creates an enumeration of devices (think of it as an array of device types and their connection specifications). This option allows you to connect to a specific MVLC by where it appears in this enumeration. Imagine the array described above with all non MVLC devices removed, the index parameter is the index into this reduced array that specifies the MVLC. to use.
If it were me, I'd use --mvlc-usb-serial rather than this option.
--mvlc-usb-serial serialConnect to the mvlc with the given usb serial number (overrides CrateConfig). Each MVLC has a serial number string that is on the module. Supplying one of those strings as the serial parameter of the option selects the MVLC module with the matching serial number string.
--init-onlyRun the DAQ init sequence and exit
--ignore-vme-init-errorsIgnore VME errors during the DAQ init sequence
--ring ringRing buffer name. The name of the ring buffer to which the program will supply data. The ring parameter must be the name, not URI of the ring buffer, as ring buffer producers can only produce to local ringbuffers.
If not provided, the ring name is the logged in user name.
--sourceid sourceid
When a timestamp extractor is provided,
(see --timestamp-library below), this sets the source id in the
body headers of ring items submitted to the ring. This option, in combination
with --timstamp-library allows for data from this source to be
merged with other sources using the FRIB/NSCLDAQ event builder.
--timestamp-library shared-objectTime stamp shared library file. shared-object is a shared object library that contains code that knows how to extract a timestamp from each physics event body. See TIMESTAMP EXTRACTION PLUGINS to learn how to write a timestamp extractor and build it into a suitable library.
Note that you may need to make it clear which directory the timestamp extractor lives in due to the normal shared library load paths. For example myextractor.so may fail to load while ./myextractor.so will succeed.
--debugEnable debug logging. Useful for me but not for you. Disabled by default.
--traceEnable trace logging. Useful for me but not for you. Disabled by default.
The fribdaq-readout is controlled by commands that are accepted on its stdin. These commands are complmetely compatible with t he standard FRIB/NSCLDAQ readout command sets and, like all FRIB/NSCLDAQ readout command interpreters run inside an event driven Tcl intpereter making it compatible with the ReST server and ReadoutShell.
In order to be used with the FRIB/NSCLDAQ event builder, timstamps must be
extracted from events. This is done by supplying a timstamp extractor
shared object with the --timestamp-library. This section
desribes the requirements of a timstamp extractor and how to build it.
Let's start by looking at a silly example, buliding it and describing how to make it useful. The silly example will just return an incrementing timestamp:
Example 13-1. Silly timestamp extractor for fribdaq-readout
// Filename: tsextract.cpp #include <fribdaq/parser_callbacks.h>#include <stdint.h> // Timestamp extractors must have C linkage: extern "C" {
/** Sample timestamp extractor normal extractors need to look at the data which are in the module structs */ uint64_t
extract_timestamp(unsigned numModules, const mesytec::mvlc::readout_parser::ModuleData* event) { static uint64_t timestamp = 0; return timestamp++;
} }
Let's first tear this apart bit by bit, and then show how to build it. Then we'll describe what we need to do to make a more intersting timestamp extractor.


Timstamp extractor functions must be defined in side a extern "C" block to turn off mangling of their names.


Before turning to making this a useful extractor, let's look at how to create the shared image. This compilation command will do that:
The -share4d and -fPIC are required when building
shared images. In the -I we assume that MVLCROOT
is an evironment variable you have pointed to the root of a mesytec-mvlc intallation.
At the FRIB this might translate to /usr/opt/mesytec-mvlc/0.1.0.
This needed to define the structure that is passed to the extractor.
You might well ask why we bothered to use the C++ compiler rather than the C compiler (which would remove the need for an extern "C"). This is because C does not have namespaces, and is allowed to pad structures differently than C++ and still be standard compliant. The mesytec::mvlc::readout_parser::ModuleData is defined in nested namespaces and compiled by C++
Let's modify this extractor to take the first 64 bits of the event as the timestamp. For now we won't worry about how the timestamp was written to the data, just that the first 64 bit word is the timestamp. Always.
To do this we need to know how the event is passed to us. Data are read from the
MVLC In 'modules'. This is because the mdaq program the MVLC support software was originally
written for has you adding hardware modules to the readout. The parameters passed to the
timstamp extractor reflects this as well. The numModules is the
number of parameters that were read. The event points to an array of
mesytec::mvlc::readout_parser::ModuleData. Each element of that array
describes a module and provides its data.
mesytec::mvlc::readout_parser::ModuleData is a struct that has the following elements:
dataDescribes the data, in practice, this is the only field we need in each module.
prefixSizeData consist of a statically allocated prefix followed by a dynamically allocated data body. This indicates the size of the prefix. In our case the entire data block is the chunk of the event we care about.
dynamicSizeSize of the dynamically allocated chunk. We normally don't need this.
suffixSizeSize of the suffix chunk. We don't need this.
hasDynamicTrue if there is a dynamic chunk. We normally don't need to worry about this field.
The important fieled is the data field. It is a mesytec::mvlc::readout_parser::DataBlock struct which has the following fields:
dataPointer to the actual event data.
sizeSize in units of uint32_t of the data chunk.
Note that all of these definitions are in the fribdaq/parser_callbacks.h which is installed when the Mesytec software is installed with fribdaq-readout enabled.
The explanation above should make it pretty clear how to write a timestamp extractor where the timestamp is in the first 64 bits of the event:
Example 13-2. Extracting a timestamp from the first 64 bits of MVLC data
#include <fribdaq/parser_callbacks.h>
#include <stdint.h>
// Timestamp extractors must have C linkage:
extern "C" {
/** Sample timestamp extractor
normal extractors need to look at the data which are
in the module structs
*/
uint64_t
extract_timestamp(unsigned numModules, const mesytec::mvlc::readout_parser::ModuleData* event) {
const uint64_t* pTs = reinterpret_cast<const uint64_t*>(event->data.data);
return *pTs;
}
}
You can use this as a template to build a timestamp extractor that matches the data for your event.