File quads_config_fe.cpp
File List > midas_fe > quads_config_fe.cpp
Go to the documentation of this file
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <iostream>
#include <list>
// clang-format off
#include "midas.h"
// clang-format on
#include "DummyFEBSlowcontrolInterface.h"
#include "FEBSlowcontrolInterface.h"
#include "Mutrig3Config.h"
#include "mcstd.h"
#include "mfe.h"
#include "missing_hardware.h"
#include "msystem.h"
#include "mudaq_device.h"
#include "odb_setup.h"
#include "odbxx.h"
#include "utils.h"
// MIDAS settings
const char* frontend_name = "Quads";
const char* frontend_file_name = __FILE__;
BOOL equipment_common_overwrite = TRUE;
// configuration variables
FEBSlowcontrolInterface* feb_sc;
midas::odb m_settings;
uint8_t bitpattern_mupix[N_BYTES_MUPIX] = {};
uint8_t bitpattern_mutrig[N_BYTES_MUTRIG] = {};
mudaq::DmaMudaqDevice* mup = nullptr;
std::vector<uint32_t> readout_banks = {};
std::vector<uint32_t> feb_hits = {0,0,0,0};
std::vector<uint32_t> feb_hits_last = {0,0,0,0};
std::vector<uint32_t> lvds_banks = {};
std::vector<uint32_t> matrix_banks = {};
std::vector<uint32_t> adc_banks = {};
std::vector<uint32_t> counters_XXCR = {};
std::vector<uint32_t> counters_XXCH = {};
std::vector<uint32_t> counters_XXCF = {};
std::vector<uint32_t> counters_XXCE = {};
std::vector<uint32_t> counters_XXCP = {};
std::vector<uint32_t> values_XXSM = {};
std::vector<float> values_XXTM = {};
// runstart
reset reset_protocol;
int init_mudaq(mudaq::MudaqDevice& mu) {
// open mudaq
if (!mu.open()) {
std::cout << "Could not open device " << std::endl;
cm_msg1(MINFO, "quads", "frontend_init", "Could not open device");
return FE_ERR_DRIVER;
}
// check mudaq
if (!mu.is_ok())
return FE_ERR_DRIVER;
else {
cm_msg1(MINFO, "quads", "frontend_init", "Mudaq device is ok");
}
#ifdef NO_A10_BOARD
cm_msg1(MINFO, "quads", "init_mudaq()", "We are running with NO_A10_BOARD");
feb_sc = new DummyFEBSlowcontrolInterface(mu);
#else
feb_sc = new FEBSlowcontrolInterface(mu);
#endif
return SUCCESS;
}
int write_command_by_id(uint8_t command, uint32_t payload, bool has_payload) {
uint32_t actual_payload = ((payload & 0xFF) << 24) + ((payload & 0xFF00) << 8) +
((payload & 0xFF0000) >> 8) + ((payload & 0xFF000000) >> 24);
if (has_payload) {
mup->write_register(RESET_LINK_RUN_NUMBER_REGISTER_W, actual_payload);
usleep(1000); // we sleep here to wait until the command is processed
}
// upper 3 bits (31:29) are FEB address:
// 0 -> 0, 1 -> 1, etc. 7 is all FEBs
// for the moment we only have 4 possible FEBs connected
mup->write_register(RESET_LINK_CTL_REGISTER_W, 0xE0000000 | command);
usleep(500000); // we sleep here to wait until the command is processed
mup->write_register(RESET_LINK_CTL_REGISTER_W, 0x0);
usleep(1000); // we sleep here to wait until the command is processed
return 0;
}
int write_command_by_name(const char* name, uint32_t payload = 0, uint16_t address = 0) {
auto it = reset_protocol.commands.find(name);
if (it != reset_protocol.commands.end()) {
if (address == 0) {
return write_command_by_id(it->second.command, payload, it->second.has_payload);
} else {
std::cout << "Addressed commands not yet implemented for A10" << std::endl;
return -1;
}
return 0;
}
std::cout << "Unknown command " << name << std::endl;
return -1;
}
void init_banks() {
midas::odb quads_settings("/Equipment/Quads/Settings", true);
// setup RCNT bank
std::string namename = std::string("Names RCNT");
std::vector<std::string> names;
// read rate and counters for the for links
for (int i = 0; i <= 3; ++i) {
names.push_back("SOP " + std::to_string(i) + " CNT");
names.push_back("SOP " + std::to_string(i) + " RATE");
names.push_back("SUB " + std::to_string(i) + " CNT");
names.push_back("SUB " + std::to_string(i) + " RATE");
names.push_back("HIT " + std::to_string(i) + " CNT");
names.push_back("HIT " + std::to_string(i) + " RATE");
names.push_back("FEB HIT " + std::to_string(i) + " RATE");
}
names.push_back("MUX CNT");
names.push_back("MUX RATE");
names.push_back("DMA CNT");
names.push_back("DMA RATE");
names.push_back("DMA SKIP");
names.push_back("DMA FULL");
names.push_back("READOUT RATE");
quads_settings[namename] = names;
// setup PCLS bank
namename = std::string("Names PCLS");
names.clear();
for (uint32_t i = 0; i < N_FEBS; i++) {
names.push_back("FEB" + std::to_string(i));
names.push_back("FEB" + std::to_string(i) + " N LVDS Links");
for (uint32_t j = 0; j < MAX_LVDS_LINKS_PER_FEB; j++) {
names.push_back("F" + std::to_string(i) + "L" + std::to_string(j) + " Status");
names.push_back("F" + std::to_string(i) + "L" + std::to_string(j) +
" Disparity Errors");
names.push_back("F" + std::to_string(i) + "L" + std::to_string(j) + " 8b/10b Errors");
names.push_back("F" + std::to_string(i) + "L" + std::to_string(j) + " Num Hits LVDS");
}
}
quads_settings[namename] = names;
namename = std::string("Names PVSC");
names.clear();
for (uint32_t i = 0; i < N_FEBS; i++) {
for (uint32_t j = 0; j < N_CHIPS; j++) {
std::string index = std::to_string(i * N_CHIPS + j);
names.push_back(index + " ID upper");
names.push_back(index + " ID lower");
for (uint32_t k = 0; k < nadcvals; k++) {
std::string s = index + " " + adcnames[k];
names.push_back(s);
}
}
}
quads_settings[namename] = names;
std::string nameMTCR = std::string("Names MTCR");
std::string nameMTCH = std::string("Names MTCH");
std::string nameMTCF = std::string("Names MTCF");
std::string nameMTCE = std::string("Names MTCE");
std::vector<std::string> namesMTCR;
std::vector<std::string> namesMTCH;
std::vector<std::string> namesMTCF;
std::vector<std::string> namesMTCE;
int globalch = 0;
int globalasic = 0;
for (uint32_t i = 0; i < N_FEBS; i++) {
for(uint32_t asic = 0; asic < N_MUTRIGS_PER_FEB; asic++) {
namesMTCH.push_back("hits asic " + std::to_string(globalasic));
namesMTCF.push_back("frame rate asic " + std::to_string(globalasic));
namesMTCE.push_back("CRC errors asic " + std::to_string(globalasic));
globalasic++;
for ( size_t ch = 0; ch < NMUTRIGCHANNELS; ch++ ) {
namesMTCR.push_back("rate channel " + std::to_string(globalch));
globalch++;
}
}
}
quads_settings[nameMTCR] = namesMTCR;
quads_settings[nameMTCH] = namesMTCH;
quads_settings[nameMTCF] = namesMTCF;
quads_settings[nameMTCE] = namesMTCE;
}
int begin_of_run() {
// bring the FEBs into running
#ifndef NO_A10_BOARD
midas::odb r("/Runinfo/Run number");
uint32_t run_number = r;
mup->write_register(RUN_NR_REGISTER_W, run_number);
uint32_t start_setup = 0;
start_setup = SET_RESET_BIT_RUN_START_ACK(start_setup);
start_setup = SET_RESET_BIT_RUN_END_ACK(start_setup);
mup->write_register_wait(RESET_REGISTER_W, start_setup, 1000);
mup->write_register(RESET_REGISTER_W, 0x0);
// send run start
write_command_by_name("Abort Run");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Stop Reset");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Run Prepare", run_number);
usleep(500000); // we sleep here to wait until the command is processed
uint32_t link_active_from_register;
uint16_t timeout_cnt = 300;
uint32_t link_active_from_odb = 0;
for (int idx = 0; idx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); ++idx)
if (m_settings["DAQ"]["Links"]["FEBsActive"][idx])
link_active_from_odb = link_active_from_odb || (0x1 << idx);
printf("Waiting for run prepare acknowledge from all FEBs\n");
// TODO: test this part of checking the run number
do {
timeout_cnt--;
link_active_from_register = mup->read_register_ro(RUN_NR_ACK_REGISTER_R);
printf("%u %u %u\n", timeout_cnt, link_active_from_odb, link_active_from_register);
usleep(10000);
} while ((link_active_from_register & link_active_from_odb) != link_active_from_odb &&
(timeout_cnt > 0));
if (timeout_cnt == 0) {
cm_msg1(MINFO, "quads", "quad_fe", "Run %d start denied - check if FEBs alive", run_number);
return CM_TRANSITION_CANCELED;
}
write_command_by_name("Sync");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Start Run");
#endif
return SUCCESS;
}
int end_of_run() {
// first we stop the FEBs
write_command_by_name("End Run");
return SUCCESS;
}
int frontend_exit_user() { return SUCCESS; }
int quad_loop() { return SUCCESS; }
void sc_settings_changed(midas::odb o) {
std::string name = o.get_name();
std::vector<std::string> names{
"MupixConfig",
"InitFEBs",
"ResetASICs",
"ADC Continuous Readout",
"Run Cycle FEB",
"MupixTDACConfig",
"Configure injection",
"Trigger injection loop",
"Full chip Injection",
"init_tmb",
"TestPulsesTDC",
"override_power_moduleid",
"module_power_mask",
"module_power",
"MutrigConfig",
"reset_datapath",
"reset_asics",
"reset_lvds",
"reset_counters",
"DataGenEnable",
"DataGenDisable",
"debug_readout_feb"
};
std::vector<std::string> names_no_reset{
"module_power_mask",
"module_power",
"TestPulsesTDC",
"debug_readout_feb",
};
if( (name == "module_power_mask" || name == "module_power") ){
UpdatePower(*feb_sc, m_settings);
}
bool found = (std::find(names.begin(), names.end(), name) != names.end());
bool no_reset = (std::find(names_no_reset.begin(), names_no_reset.end(), name) != names_no_reset.end());
if (found && (o || no_reset)){
cm_msg1(MINFO, "quads", "sc_settings_changed", "Setting changed (%s)", name.c_str());
if (name == "MupixConfig" && o) {
ConfigureASICs(*feb_sc, m_settings, bitpattern_mupix);
}
// TODO: this can be done in the frontend loop all the time
if (name == "InitFEBs" && o) {
InitFEBs(*feb_sc, m_settings);
}
if (name == "ResetASICs" && o) {
cm_msg1(MINFO, "quads", "sc_settings_changed", "Reset all ASICs");
resetASICs(*feb_sc, m_settings);
}
if (name == "debug_readout_feb" && o) {
cm_msg1(MINFO, "quads", "sc_settings_changed", "Set FEB into debug readout");
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
if (FEBActive && FEBsIsQuads)
feb_sc->FEB_write(febIDx, MP_USE_ARRIVAL_TIME1_REGISTER_W, 0xFFFFFFFF);
}
}
if (name == "debug_readout_feb" && !o) {
cm_msg1(MINFO, "quads", "sc_settings_changed", "Set FEB into normal readout");
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
if (FEBActive && FEBsIsQuads)
feb_sc->FEB_write(febIDx, MP_USE_ARRIVAL_TIME1_REGISTER_W, 0x0);
}
}
// if (name == "ADC Continuous Readout" && o) {
// adcContinuousReadout(*feb_sc, m_settings);
// }
if (name == "Run Cycle FEB" && o) {
// send run start
write_command_by_name("Abort Run");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Stop Reset");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Run Prepare", run_number);
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Sync");
usleep(500000); // we sleep here to wait until the command is processed
write_command_by_name("Start Run");
}
// MUPIX Commands //
// ************** //
if (name == "MupixTDACConfig" && o) {
ConfigureTDACs(*feb_sc, m_settings);
}
if (name == "Configure injection" && o) {
const std::vector<uint8_t> columns = m_settings["DAQ"]["Commands"]["Injection columns"];
const std::vector<uint8_t> rows = m_settings["DAQ"]["Commands"]["Injection rows"];
if (ConfigureInjectASICs(*feb_sc, columns, rows) != FE_SUCCESS)
cm_msg1(MINFO, "quads", "on_settings_changed", "injection configuration failed!");
}
if (name == "Trigger injection" && o) {
const uint32_t injection_pulse_duration =
m_settings["DAQ"]["Commands"]["Injection pulse duration"];
if (InjectASICs(*feb_sc, injection_pulse_duration) != FE_SUCCESS)
cm_msg1(MINFO, "quads", "on_settings_changed", "injection trigger failed!");
}
if (name == "Trigger injection loop" && o) {
const uint32_t injection_pulse_duration =
m_settings["DAQ"]["Commands"]["Injection pulse duration"];
const uint32_t num_repetitions = m_settings["DAQ"]["Commands"]["Number of pulses"];
const uint32_t wait_between_pulses =
m_settings["DAQ"]["Commands"]["Wait time between pulses (ms)"];
if (InjectASICsInLoop(*feb_sc, injection_pulse_duration, num_repetitions,
wait_between_pulses) != FE_SUCCESS)
cm_msg1(MINFO, "quads", "on_settings_changed", "injection trigger loop failed!");
}
if (name == "Full chip Injection" && o) {
const uint8_t min_columns = m_settings["DAQ"]["Commands"]["Injection min column"];
const uint8_t max_columns = m_settings["DAQ"]["Commands"]["Injection max column"];
const uint8_t min_rows = m_settings["DAQ"]["Commands"]["Injection min rows"];
const uint8_t max_rows = m_settings["DAQ"]["Commands"]["Injection max rows"];
const uint32_t injection_pulse_duration =
m_settings["DAQ"]["Commands"]["Injection pulse duration"];
const uint32_t num_repetitions = m_settings["DAQ"]["Commands"]["Number of pulses"];
const uint32_t wait_between_pulses =
m_settings["DAQ"]["Commands"]["Wait time between pulses (ms)"];
if (FullChipInjection(*feb_sc, m_settings, min_columns, max_columns, min_rows, max_rows,
injection_pulse_duration, num_repetitions,
wait_between_pulses) != FE_SUCCESS)
cm_msg1(MINFO, "quads", "on_settings_changed", "injection configuration failed!");
}
// MUTRIG Commands //
// *************** //
if(name == "init_tmb" && o){
TBinit(*feb_sc, m_settings);
}
if(name == "TestPulsesTDC"){
ChangeTDCTest(*feb_sc, m_settings);
}
if( name == "override_power_moduleid" && o){
UpdatePowerOverride(*feb_sc, m_settings);
}
if ( name == "MutrigConfig" && o) {
ConfigureMuTRiGASICs(*feb_sc, m_settings, bitpattern_mutrig);
}
if ( name == "reset_datapath" && o) {
MuTRiG_reset_datapath(*feb_sc, m_settings);
}
if ( name == "reset_asics" && o) {
MuTRiG_reset_asics(*feb_sc, m_settings);
}
if ( name == "reset_lvds" && o) {
MuTRiG_reset_lvds(*feb_sc, m_settings);
}
if ( name == "reset_counters" && o) {
MuTRiG_reset_counters(*feb_sc, m_settings);
}
// DAQ Commands //
// ************ //
if (name == "DataGenEnable" && o) {
midas::odb commands = m_settings["DAQ"]["Commands"];
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
if (FEBActive && FEBsIsQuads) {
uint32_t datagensetting = 0x1 << 31 | // data generator generates hits
0x1 << 17 | // data generator before the sorter
0x1 << 16 | // use hits from generator
(bool) commands["DataGenSync"] << 5 | // all FEBs have same start
(bool) commands["DataGenFullSteam"] << 4 | \
((uint8_t) commands["DataGenRate"] & 0xF);
//std::cout << std::hex << datagensetting << std::endl;
feb_sc->FEB_write(febIDx, MP_DATA_GEN_CONTROL_REGISTER_W, datagensetting);
}
}
cm_msg1(MINFO, "quads", "on_settings_changed()" , "enable data generator on the FPGA");
}
if (name == "DataGenDisable" && o) {
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
if (FEBActive && FEBsIsQuads)
feb_sc->FEB_write(febIDx, MP_DATA_GEN_CONTROL_REGISTER_W, 0x0);
}
cm_msg1(MINFO, "quads", "on_settings_changed()" , "disable data generator on the FPGA");
}
if(!no_reset)
o = false;
}
}
int frontend_init() {
// create ODB copy for settings
settings.connect_and_fix_structure("/Equipment/Quads/Settings/");
m_settings.connect("/Equipment/Quads/Settings");
// end and start of run
install_begin_of_run(begin_of_run);
install_end_of_run(end_of_run);
install_frontend_exit(frontend_exit_user);
install_frontend_loop(quad_loop);
// init dma and mudaq device
mup = new mudaq::DmaMudaqDevice("/dev/mudaq0");
int status = init_mudaq(*mup);
if (status != SUCCESS)
return FE_ERR_DRIVER;
// Set our transition sequence. The default is 500.
cm_set_transition_sequence(TR_START, 400);
// Set our transition sequence. The default is 500. Setting it
// to 700 means we are called AFTER most other clients.
cm_set_transition_sequence(TR_STOP, 600);
// reset runcontrol
// we write abort run
mup->write_register(RESET_LINK_CTL_REGISTER_W, 0x0);
usleep(500000); // we sleep here to wait until the command is processed
mup->write_register(RESET_LINK_CTL_REGISTER_W,
0xE0000000 | reset_protocol.commands.find("Abort Run")->second.command);
usleep(500000); // we sleep here to wait until the command is processed
mup->write_register(RESET_LINK_CTL_REGISTER_W, 0x0);
usleep(500000); // we sleep here to wait until the command is processed
mup->write_register(RESET_LINK_CTL_REGISTER_W,
0xE0000000 | reset_protocol.commands.find("Stop Reset")->second.command);
usleep(500000); // we sleep here to wait until the command is processed
mup->write_register(RESET_LINK_CTL_REGISTER_W, 0x0);
// init FEBs
InitFEBs(*feb_sc, m_settings);
// init banks
init_banks();
// start ADC readout
adcContinuousReadout(*feb_sc, m_settings);
// create watch
settings["DAQ/Commands"].watch(sc_settings_changed);
midas::odb custom("/Custom", true);
custom["Quads"] = "Quads/quad_basics.html";
custom["MuTRiG"] = "Mutrig/TimingScint.html";
return SUCCESS;
}
int read_sc_event(char* pevent, int off) {
// fill lvds bank
lvds_banks.clear();
uint32_t offset = 1;
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
lvds_banks.push_back(febIDx);
lvds_banks.push_back(MAX_LVDS_LINKS_PER_FEB);
if (FEBActive) {
std::vector<uint32_t> status(offset + (MAX_LVDS_LINKS_PER_FEB * 4));
feb_sc->FEB_read(febIDx, LVDS_STATUS_START_REGISTER_W, status, false);
uint32_t hits_feb = 0;
for (uint32_t i = 0; i < MAX_LVDS_LINKS_PER_FEB; i++) {
lvds_banks.push_back(status[offset + i * 4]);
lvds_banks.push_back(status[offset + i * 4 + 1]);
lvds_banks.push_back(status[offset + i * 4 + 2]);
lvds_banks.push_back(status[offset + i * 4 + 3]);
hits_feb += status[offset + i * 4 + 3];
}
feb_hits[febIDx] = hits_feb;
} else {
for (uint32_t i = 0; i < MAX_LVDS_LINKS_PER_FEB; i++) {
lvds_banks.push_back(0);
lvds_banks.push_back(0);
lvds_banks.push_back(0);
lvds_banks.push_back(0);
}
feb_hits[febIDx] = 0;
}
}
// fill counter banks for the readout
readout_banks.clear();
// read rate and counters for the for links
for (int i = 0; i <= 3; ++i) {
mup->write_register(SWB_COUNTER_REGISTER_W, i);
uint32_t sub_cnt = mup->read_register_ro(SWB_COUNTER_REGISTER_R);
uint32_t sub_rate = mup->read_register_ro(SWB_LINK_COUNTER_REGISTER_R);
mup->write_register(SWB_COUNTER_REGISTER_W, i+4);
uint32_t hit_cnt = mup->read_register_ro(SWB_COUNTER_REGISTER_R);
uint32_t hit_rate = mup->read_register_ro(SWB_LINK_COUNTER_REGISTER_R);
mup->write_register(SWB_COUNTER_REGISTER_W, i+8);
uint32_t package_cnt = mup->read_register_ro(SWB_COUNTER_REGISTER_R);
uint32_t package_rate = mup->read_register_ro(SWB_LINK_COUNTER_REGISTER_R);
readout_banks.push_back(package_cnt);
readout_banks.push_back(package_rate);
readout_banks.push_back(sub_cnt);
readout_banks.push_back(sub_rate);
readout_banks.push_back(hit_cnt);
readout_banks.push_back(hit_rate);
readout_banks.push_back(feb_hits[i] - feb_hits_last[i]);
feb_hits_last[i] = feb_hits[i];
}
// read MUX rate and cnts
mup->write_register(SWB_COUNTER_REGISTER_W, 12);
uint32_t mux_cnt = mup->read_register_ro(SWB_COUNTER_REGISTER_R) * 4;
uint32_t mux_rate = mup->read_register_ro(SWB_LINK_COUNTER_REGISTER_R) * 4;
readout_banks.push_back(mux_cnt);
readout_banks.push_back(mux_rate);
// read DMA rate and cnts
uint32_t dma_cnt = mup->read_register_ro(EVENT_BUILD_IDLE_NOT_HEADER_R) * 4;
uint32_t dma_rate = mup->read_register_ro(EVENT_BUILD_TAG_FIFO_FULL_R) * 4;
uint32_t dma_skip = mup->read_register_ro(EVENT_BUILD_SKIP_EVENT_DMA_R) * 4;
uint32_t dma_full = mup->read_register_ro(BUFFER_STATUS_REGISTER_R) * 4;
readout_banks.push_back(dma_cnt);
readout_banks.push_back(dma_rate);
readout_banks.push_back(dma_skip);
readout_banks.push_back(dma_full);
readout_banks.push_back(m_settings["Readout"]["HitRate"]);
// *************************************
// ************ MUPIX BANKS ***********
// *************************************
// fill matrix bank
matrix_banks.clear();
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
matrix_banks.push_back(febIDx);
matrix_banks.push_back(MAX_LVDS_LINKS_PER_FEB);
if (FEBActive && FEBsIsQuads) {
std::vector<uint32_t> data(1);
feb_sc->FEB_read(febIDx, MP_IS_A_0_REGISTER_R, data);
matrix_banks.push_back(data[0]);
feb_sc->FEB_read(febIDx, MP_IS_A_1_REGISTER_R, data);
matrix_banks.push_back(data[0]);
feb_sc->FEB_read(febIDx, MP_IS_B_0_REGISTER_R, data);
matrix_banks.push_back(data[0]);
feb_sc->FEB_read(febIDx, MP_IS_B_1_REGISTER_R, data);
matrix_banks.push_back(data[0]);
feb_sc->FEB_read(febIDx, MP_IS_C_0_REGISTER_R, data);
matrix_banks.push_back(data[0]);
feb_sc->FEB_read(febIDx, MP_IS_C_1_REGISTER_R, data);
matrix_banks.push_back(data[0]);
} else {
matrix_banks.push_back(0);
matrix_banks.push_back(0);
matrix_banks.push_back(0);
matrix_banks.push_back(0);
matrix_banks.push_back(0);
matrix_banks.push_back(0);
}
};
// fill ADC bank
adc_banks.clear();
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsQuads = m_settings["DAQ"]["Links"]["FEBsQuads"][febIDx];
if (FEBActive && FEBsIsQuads) {
vector<uint32_t> adcdata(N_CHIPS * 4 * 3);
feb_sc->FEB_read(febIDx, MP_READBACK_MEMS_START_REGISTER_R, adcdata);
for (uint32_t c = 0; c < N_CHIPS * 3; c += 3) {
adc_banks.push_back((c / 3 >> 8) & 0xFF);
adc_banks.push_back((c / 3) & 0xFF);
adc_banks.push_back((adcdata[0 + 4 * c] & 0xFF));
adc_banks.push_back(((adcdata[0 + 4 * c] >> 8) & 0xFF));
adc_banks.push_back(((adcdata[0 + 4 * c] >> 16) & 0xFF));
adc_banks.push_back(((adcdata[0 + 4 * c] >> 24) & 0xFF));
adc_banks.push_back((adcdata[1 + 4 * c] & 0xFF));
adc_banks.push_back(((adcdata[1 + 4 * c] >> 8) & 0xFF));
adc_banks.push_back(((adcdata[1 + 4 * c] >> 16) & 0xFF));
adc_banks.push_back(((adcdata[1 + 4 * c] >> 24) & 0xFF));
adc_banks.push_back((adcdata[2 + 4 * c] & 0xFF));
adc_banks.push_back(((adcdata[2 + 4 * c] >> 8) & 0xFF));
adc_banks.push_back(((adcdata[2 + 4 * c] >> 16) & 0xFF));
adc_banks.push_back(((adcdata[2 + 4 * c] >> 24) & 0xFF));
adc_banks.push_back((adcdata[3 + 4 * c] & 0xFF));
}
} else {
for (uint32_t c = 0; c < N_CHIPS * 3; c += 3) {
adc_banks.push_back((c / 3 >> 8) & 0xFF);
adc_banks.push_back((c / 3) & 0xFF);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
adc_banks.push_back(0);
}
}
}
// *************************************
// ************ MUTRIG BANKS ***********
// *************************************
// fill counter banks
counters_XXCH.clear();
counters_XXCF.clear();
counters_XXCE.clear();
counters_XXCR.clear();
counters_XXCP.clear();
//Note: febIDx is global, corresponding to the QSFP port
//Note: febSSIDx is subsystem-centric and starts from zero, corresponding to an increasing number of FEBs for the subsystem without any offset.
//For the subsystem, i.e. indices of MuTRiG channels and asics, febSSIDx is used
int32_t febSSIDx=-1;
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsMutrig = m_settings["DAQ"]["Links"]["FEBsMutrig"][febIDx];
if (FEBsIsMutrig)
febSSIDx++;
else
continue;
if (FEBActive) {
// reset counter address
feb_sc->FEB_write(febIDx, MUTRIG_CTRL_RESET_REGISTER_W, 0x10);
feb_sc->FEB_write(febIDx, MUTRIG_CTRL_RESET_REGISTER_W, 0x0);
// TODO: +2 should be fixed in firmware
std::vector<uint32_t> counter(2+N_MUTRIGS_PER_FEB*64);
feb_sc->FEB_read(febIDx, MUTRIG_CNT_ADDR_REGISTER_R, counter, true);
// reset counter address
feb_sc->FEB_write(febIDx, MUTRIG_CTRL_RESET_REGISTER_W, 0x10);
feb_sc->FEB_write(febIDx, MUTRIG_CTRL_RESET_REGISTER_W, 0x0);
for(int asic = 0; asic < N_MUTRIGS_PER_FEB; asic++) {
counters_XXCH.push_back(counter[2+asic*64+3]);
counters_XXCE.push_back(counter[2+asic*64+6]);
counters_XXCF.push_back(counter[2+asic*64+7]);
for ( size_t ch = 0; ch < NMUTRIGCHANNELS; ch++ )
counters_XXCR.push_back(counter[2+asic*64+8+ch]);
uint16_t finetime_extended_cur = counter[2+asic*64+55] & 0xFF;
uint16_t finetime_extended_last = counter[2+asic*64+54] & 0xFF;
uint16_t time8ns_cur = counter[2+asic*64+55] >> 8;
uint16_t time8ns_last = counter[2+asic*64+54] >> 8;
if ((time8ns_cur * 160 + finetime_extended_cur) >= (time8ns_last * 160 + finetime_extended_last))
counters_XXCP.push_back((time8ns_cur * 160 + finetime_extended_cur) - (time8ns_last * 160 + finetime_extended_last));
else counters_XXCP.push_back(0);
}
} else { // fill with zero to keep the size
for(int asic = 0; asic < N_MUTRIGS_PER_FEB; asic++) {
counters_XXCH.push_back(0);
counters_XXCE.push_back(0);
counters_XXCF.push_back(0);
for ( size_t ch = 0; ch < NMUTRIGCHANNELS; ch++ )
counters_XXCR.push_back(0);
counters_XXCP.push_back(0);
}
}
}
// fill mutrig temp banks
values_XXTM.clear();
std::vector<uint32_t> rval(N_TMB_MATRIX_TEMPERATURES, -1);
febSSIDx=-1;
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsMutrig = m_settings["DAQ"]["Links"]["FEBsMutrig"][febIDx];
int rpc_ret = -17;
if (FEBsIsMutrig)
febSSIDx++;
else
continue;
if (FEBActive)
rpc_ret = feb_sc->FEBsc_NiosRPC(febIDx, CMD_TILE_TEMPERATURES_READ, {});
if (FEBActive && rpc_ret != -17) {
feb_sc->FEB_read(febIDx, FEBSlowcontrolInterface::OFFSETS::FEBsc_RPC_DATAOFFSET, rval);
// store and scale temperatures
for (size_t idx=0; idx < N_TMB_MATRIX_TEMPERATURES; idx++) {
float fval = TMB_TEMPERATURE_FACTOR * to_signed_16b(rval[idx+1]);
if( ((rval[0]>>(idx)) & 0x01) == 0)
fval = 0;
//printf("XXTM idx = %lu gid=%lu : %x --> %f\n",idx,gID,rval[idx+1],fval);
values_XXTM.push_back(fval);
}
} else {
for (size_t idx=0; idx < N_TMB_MATRIX_TEMPERATURES; idx++)
values_XXTM.push_back(0xFFFFFFFF);
}
}
// fill TMB status
values_XXSM.clear();
std::vector<uint32_t> rval_SM(N_TMB_STATUS_VALUES, -1);
febSSIDx=-1;
for (uint32_t febIDx = 0; febIDx < m_settings["DAQ"]["Links"]["FEBsActive"].size(); febIDx++) {
bool FEBActive = m_settings["DAQ"]["Links"]["FEBsActive"][febIDx];
bool FEBsIsMutrig = m_settings["DAQ"]["Links"]["FEBsMutrig"][febIDx];
int rpc_ret = -17;
if (FEBsIsMutrig)
febSSIDx++;
else
continue;
rpc_ret = feb_sc->FEBsc_NiosRPC(febIDx, CMD_TILE_TMB_STATUS, {});
if (FEBActive && rpc_ret != -17) {
feb_sc->FEB_read(febIDx, FEBSlowcontrolInterface::OFFSETS::FEBsc_RPC_DATAOFFSET, rval_SM);
values_XXSM.push_back(rval_SM[0]);
values_XXSM.push_back(rval_SM[1]);
values_XXSM.push_back((int)roundf(TMB_TEMPERATURE_FACTOR * to_signed_16b(rval_SM[2]) * 100));
values_XXSM.push_back((int)roundf(TMB_TEMPERATURE_FACTOR * to_signed_16b(rval_SM[3]) * 100));
} else {
for (size_t idx=0; idx < N_TMB_MATRIX_TEMPERATURES; idx++) {
values_XXSM.push_back(0);
values_XXSM.push_back(0);
values_XXSM.push_back(0xFFFFFFFF);
values_XXSM.push_back(0xFFFFFFFF);
}
}
}
MuTRiGResetLVDSAddr(*feb_sc, m_settings);
// create bank, pdata
bk_init32a(pevent);
DWORD* pdata = NULL;
// create a bank with readout status
bk_create(pevent, "RCNT", TID_DWORD, (void**)&pdata);
for (auto data : readout_banks) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the lvds status
bk_create(pevent, "PCLS", TID_DWORD, (void**)&pdata);
for (auto data : lvds_banks) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the matrix status
bk_create(pevent, "PCMS", TID_DWORD, (void**)&pdata);
for (auto data : matrix_banks) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the ADC status
BYTE* pbyte = NULL;
bk_create(pevent, "PVSC", TID_BYTE, (void**)&pbyte);
for (auto data : adc_banks) *pbyte++ = data;
bk_close(pevent, pbyte);
// create a bank with the channel rate of the mutrig
bk_create(pevent, "MTCR", TID_DWORD, (void**)&pdata);
for (auto data : counters_XXCR) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the hit rate of the mutrig
bk_create(pevent, "MTCH", TID_DWORD, (void**)&pdata);
for (auto data : counters_XXCH) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the frame rate of the mutrig
bk_create(pevent, "MTCF", TID_DWORD, (void**)&pdata);
for (auto data : counters_XXCF) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with the CRC errors of the mutrig
bk_create(pevent, "MTCE", TID_DWORD, (void**)&pdata);
for (auto data : counters_XXCE) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with some time checks of the mutrig
bk_create(pevent, "MTCP", TID_DWORD, (void**)&pdata);
for (auto data : counters_XXCP) *pdata++ = data;
bk_close(pevent, pdata);
// create a bank with temperatures of the TMB
float* pfloat = NULL;
bk_create(pevent, "MTTM", TID_DWORD, (void**)&pfloat);
for (auto data : values_XXTM) *pfloat++ = data;
bk_close(pevent, pfloat);
// create a bank with the TMB status
bk_create(pevent, "MTSM", TID_DWORD, (void**)&pdata);
for (auto data : values_XXSM) *pdata++ = data;
bk_close(pevent, pdata);
return bk_size(pevent);
}
EQUIPMENT equipment[] = {{
"Quads", /* equipment name */
{1, 0, /* event ID, trigger mask */
"SYSTEM", /* event buffer */
EQ_PERIODIC, /* equipment type */
0, /* event source */
"MIDAS", /* format */
TRUE, /* enabled */
RO_RUNNING | RO_STOPPED | RO_ODB, /* read always, except during
transistions and update ODB */
1000, /* read every 1 sec */
0, /* stop run after this event limit */
0, /* number of sub events */
1, /* log history every event */
"", "", ""},
read_sc_event, /* readout routine */
},
{""}};