Skip to content
Snippets Groups Projects

Understanding the structure of TRD2D.

All threads resolved!

Files

+ 134
149
@@ -43,10 +43,7 @@ CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::CbmTrdFaspMessage(uint8_t c, uint8_t ty
{
}
CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo()
: CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo")
{
}
CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo() : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo") {}
//_________________________________________________________________________________
CbmTrdUnpackFaspAlgo::~CbmTrdUnpackFaspAlgo() {}
@@ -54,7 +51,6 @@ CbmTrdUnpackFaspAlgo::~CbmTrdUnpackFaspAlgo() {}
//_________________________________________________________________________________
Bool_t CbmTrdUnpackFaspAlgo::initParSet(FairParGenericSet* parset)
{
FairParamList parList;
Int_t nModules(0);
if (strcmp(parset->ClassName(), "CbmTrdParSetAsic") == 0) {
CbmTrdParSetAsic* setPar = static_cast<CbmTrdParSetAsic*>(parset);
@@ -96,7+92,7 @@
CbmTrdParSetGain* setPar = static_cast<CbmTrdParSetGain*>(parset);
setPar->printParams();
nModules = setPar->GetNrOfModules();
}
else {
LOG(error) << "Parameter set " << parset->ClassName() << " not known. Skip.";
return kFALSE;
@@ -144,7+140,7 @@
//_________________________________________________________________________________
void CbmTrdUnpackFaspAlgo::SetCrobMapping(const std::map<uint32_t, uint16_t[NCROBMOD]>& map)
{
if (fCrobMap) delete fCrobMap;
fCrobMap = new std::map<uint32_t, uint16_t[NCROBMOD]>(map);
if (fCompMap) delete fCompMap;
fCompMap = new std::map<uint16_t, std::pair<uint16_t, uint16_t>>; /// map eq_id -> (mod_id, crob_id)
for (auto& entry : map) {
uint16_t mod_id = entry.first;
for (uint8_t crob_id = 0; crob_id < NCROBMOD; crob_id++) {
uint16_t eq_id = entry.second[crob_id];
if (fCompMap->find(eq_id) != fCompMap->end()) {
LOG(error) << GetName() << "::SetCrobMapping: multiple entries for eq_id " << (int) eq_id << " found.";
return;
}
(*fCompMap)[eq_id] = std::make_pair(mod_id, crob_id);
}
}
}
//_________________________________________________________________________________
@@ -220,100 +228,93 @@ void CbmTrdUnpackFaspAlgo::mess_prt(CbmTrdFaspMessage* mess)
}
//_________________________________________________________________________________
bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage> messes)
bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage> messes, const uint16_t mod_id)
{
UChar_t lFasp(0xff);
UShort_t lchR, lchT;
Double_t r, t;
Int_t dt, dtime, ch, pad;
ULong64_t lTime, tdaqOffset(0);
CbmTrdParFasp* faspPar(nullptr);
const CbmTrdParFaspChannel* chCalib(nullptr);
CbmTrdParModDigi* digiPar(nullptr);
const UChar_t lFasp = messes[0].fasp;
const CbmTrdParFasp* faspPar = (CbmTrdParFasp*) fAsicPar.GetAsicPar(mod_id * 1000 + lFasp);
const CbmTrdParModDigi* digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(mod_id);
// link data to the position on the padplane
if (!faspPar) {
LOG(error) << GetName() << "::pushDigis - Par for FASP " << (int) lFasp << " in module " << mod_id
<< " missing. Skip.";
return false;
}
if (!digiPar) {
LOG(error) << GetName() << "::pushDigis - DIGI par for module " << mod_id << " missing. Skip.";
return false;
}
for (auto imess : messes) {
if (lFasp == 0xff) {
lFasp = messes[0].fasp;
// link data to the position on the padplane
if (!(faspPar = (CbmTrdParFasp*) fAsicPar.GetAsicPar(fMod * 1000 + lFasp))) {
LOG(error) << GetName() << "::pushDigis - Par for FASP " << (int) lFasp << " in module " << fMod
<< " missing. Skip.";
return false;
}
if (!(digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(fMod))) {
LOG(error) << GetName() << "::pushDigis - DIGI par for module " << fMod << " missing. Skip.";
return false;
}
// TODO temporary add DAQ time calibration for FASPRO.
// Should be absorbed in the ASIC parameter definition
if (digiPar->GetPadRow(faspPar->GetPadAddress(imess.ch)) % 2 == 0) tdaqOffset = 3;
// TODO temporary add DAQ time calibration for FASPRO.
// Should be absorbed in the ASIC parameter definition
ULong64_t tdaqOffset(0);
if (digiPar->GetPadRow(faspPar->GetPadAddress(messes[0].ch)) % 2 == 0) tdaqOffset = 3;
if (VERBOSE) faspPar->Print();
}
if (VERBOSE) mess_prt(&imess);
pad = faspPar->GetPadAddress(imess.ch);
chCalib = faspPar->GetChannel(imess.ch);
ch = 2 * pad + chCalib->HasPairingR();
lTime = fTime + tdaqOffset + imess.tlab;
lchR = 0;
lchT = 0;
if (chCalib->HasPairingR()) lchR = imess.data;
else
lchT = imess.data;
if (VERBOSE)
if (VERBOSE) faspPar->Print();
for (auto imess : messes) {
const Int_t pad = faspPar->GetPadAddress(imess.ch);
const CbmTrdParFaspChannel* chCalib = faspPar->GetChannel(imess.ch);
const ULong64_t lTime = fTime + tdaqOffset + imess.tlab;
const UShort_t lchR = chCalib->HasPairingR() ? imess.data : 0;
const UShort_t lchT = chCalib->HasPairingR() ? 0 : imess.data;
std::vector<CbmTrdDigi>& digiBuffer = fDigiBuffer[pad];
if (VERBOSE) {
const Int_t ch = 2 * pad + chCalib->HasPairingR();
mess_prt(&imess);
printf("fasp[%2d] ch[%4d / %2d] pad[%4d] row[%2d] col[%2d] %c[%4d]\n", lFasp, ch, imess.ch, pad,
digiPar->GetPadRow(pad), digiPar->GetPadColumn(pad), (chCalib->HasPairingT() ? 'T' : 'R'),
lchT > 0 ? lchT : lchR);
}
if (fDigiBuffer[fCrob][pad].size()) {
// check if last digi has both R/T message components. Update if not and is within time window
auto id = fDigiBuffer[fCrob][pad].rbegin(); // Should always be valid here.
// No need to extra check
dtime = (*id).GetTimeDAQ() - lTime;
bool use(false);
if (TMath::Abs(dtime) < 5) { // test message part of (last) digi
r = (*id).GetCharge(t, dt);
if (lchR && r < 0.1) { // set R charge on an empty slot
(*id).SetCharge(t, lchR, -dtime);
use = true;
}
else if (lchT && t < 0.1) { // set T charge on an empty slot
(*id).SetCharge(lchT, r, +dtime);
(*id).SetTimeDAQ(ULong64_t((*id).GetTimeDAQ() - dtime));
use = true;
}
}
if (digiBuffer.size() == 0) { // init pad position in map and build digi for message
digiBuffer.emplace_back(pad, lchT, lchR, lTime);
digiBuffer.back().SetAddressModule(mod_id);
continue;
}
// build digi for message when update failed
if (!use) {
fDigiBuffer[fCrob][pad].emplace_back(pad, lchT, lchR, lTime);
fDigiBuffer[fCrob][pad].back().SetAddressModule(fMod);
id = fDigiBuffer[fCrob][pad].rbegin();
}
// check if last digi has both R/T message components. Update if not and is within time window
auto id = digiBuffer.rbegin(); // Should always be valid here.
// No need to extra check
Double_t r, t;
Int_t dt;
const Int_t dtime = (*id).GetTimeDAQ() - lTime;
bool use(false);
if (id != fDigiBuffer[fCrob][pad].rend()) id++;
// update charge for previously allocated digis to account for FASPRO ADC buffering and read-out feature
use = false;
for (; id != fDigiBuffer[fCrob][pad].rend(); ++id) {
r = (*id).GetCharge(t, dt);
if (lchR && int(r)) { // update R charge and mark on digi
(*id).SetCharge(t, lchR, dt);
(*id).SetFlag(1);
use = true;
}
else if (lchT && int(t)) { // update T charge and mark on digi
(*id).SetCharge(lchT, r, dt);
(*id).SetFlag(0);
use = true;
}
if (use) break;
if (TMath::Abs(dtime) < 5) { // test message part of (last) digi
r = (*id).GetCharge(t, dt);
if (lchR && r < 0.1) { // set R charge on an empty slot
(*id).SetCharge(t, lchR, -dtime);
use = true;
}
else if (lchT && t < 0.1) { // set T charge on an empty slot
(*id).SetCharge(lchT, r, +dtime);
(*id).SetTimeDAQ(ULong64_t((*id).GetTimeDAQ() - dtime));
use = true;
}
}
else { // init pad position in map and build digi for message
fDigiBuffer[fCrob][pad].emplace_back(pad, lchT, lchR, lTime);
fDigiBuffer[fCrob][pad].back().SetAddressModule(fMod);
// build digi for message when update failed
if (!use) {
digiBuffer.emplace_back(pad, lchT, lchR, lTime);
digiBuffer.back().SetAddressModule(mod_id);
id = digiBuffer.rbegin();
}
// update charge for previously allocated digis to account for FASPRO ADC buffering and read-out feature
for (++id; id != digiBuffer.rend(); ++id) {
r = (*id).GetCharge(t, dt);
if (lchR && int(r)) { // update R charge and mark on digi
(*id).SetCharge(t, lchR, dt);
(*id).SetFlag(1);
break;
}
else if (lchT && int(t)) { // update T charge and mark on digi
(*id).SetCharge(lchT, r, dt);
(*id).SetFlag(0);
break;
}
}
}
messes.clear();
@@ -325,17 +326,16 @@ uint32_t CbmTrdUnpackFaspAlgo::ResetTimeslice()
{
uint32_t uNbLostDigis = 0;
/// PAL 03/08/2022: clear internal buffer at latest between two timeslices (TS are self contained!)
/// D.Smith: As of 27.4.2023 only loops over pads of a single component.
for (auto crobBuffer : fDigiBuffer) {
for (auto pad_id(0); pad_id < NFASPMOD * NFASPCH; pad_id++) {
if (!crobBuffer.second[pad_id].size()) continue;
for (auto pad_id(0); pad_id < NFASPMOD * NFASPCH; pad_id++) {
if (!fDigiBuffer[pad_id].size()) continue;
LOG(warn) << fName << "::ResetTimeslice - buffered digi @ CROB=" << crobBuffer.first << " / pad=" << pad_id
<< " store " << crobBuffer.second[pad_id].size() << " unprocessed digi.";
uNbLostDigis += crobBuffer.second[pad_id].size();
LOG(warn) << fName << "::ResetTimeslice - buffered digi @ CROB=" << fCrob << " / pad=" << pad_id << " store "
<< fDigiBuffer[pad_id].size() << " unprocessed digi.";
uNbLostDigis += fDigiBuffer[pad_id].size();
crobBuffer.second[pad_id].clear();
}
fDigiBuffer[pad_id].clear();
}
return uNbLostDigis;
}
@@ -346,9 +346,9 @@ void CbmTrdUnpackFaspAlgo::FinalizeComponent()
Int_t dt;
// push finalized digits to the next level
for (uint16_t ipad(0); ipad < NFASPMOD * NFASPCH; ipad++) {
if (!fDigiBuffer[fCrob][ipad].size()) continue;
if (!fDigiBuffer[ipad].size()) continue;
uint nIncomplete(0);
for (auto id = fDigiBuffer[fCrob][ipad].begin(); id != fDigiBuffer[fCrob][ipad].end(); id++) {
for (auto id = fDigiBuffer[ipad].begin(); id != fDigiBuffer[ipad].end(); id++) {
r = (*id).GetCharge(t, dt);
// check if digi has all signals CORRECTED
if (((t > 0) != (*id).IsFlagged(0)) || ((r > 0) != (*id).IsFlagged(1))) {
@@ -362,7 +362,7 @@ void CbmTrdUnpackFaspAlgo::FinalizeComponent()
fOutputVec.emplace_back(std::move((*id)));
}
// clear digi buffer wrt the digi which was forwarded to higher structures
fDigiBuffer[fCrob][ipad].clear();
fDigiBuffer[ipad].clear();
if (nIncomplete > 2) {
LOG(warn) << fName << "FinalizeComponent(" << fCrob << ") skip " << nIncomplete << " incomplete digi at pad "
<< ipad << ".\n";
@@ -371,48 +371,33 @@ void CbmTrdUnpackFaspAlgo::FinalizeComponent()
fCrob = 0xffff; // reset current crob id
}
// ---- unpack ----
// ----unpack----
bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
{
if (VERBOSE) printf("CbmTrdUnpackFaspAlgo::unpack 0x%04x %d\n", icomp, imslice);
// LOG(info) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice "<<imslice;
uint8_t crob_id = 0;
uint16_t eq_id;
bool unpackOk = true;
bool unpackOk = true;
//Double_t fdMsSizeInNs = 1.28e6;
auto msdesc = ts->descriptor(icomp, imslice);
// Cast required to silence a warning on macos (there a uint64_t is a llu)
if (VERBOSE) printf("time start %lu\n", static_cast<size_t>(msdesc.idx));
// define time wrt start of time slice in TRD/FASP clks [80 MHz]
fTime = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5);
// get MOD_id and CROB id from the equipment
bool mapped = false;
eq_id = msdesc.eq_id;
for (auto mod_id : fModuleId) {
for (crob_id = 0; crob_id < NCROBMOD; crob_id++) {
if (((*fCrobMap)[mod_id])[crob_id] == eq_id) break;
}
if (crob_id == NCROBMOD) continue;
// found module-cri pair
// buffer module configuration
if (fMod == 0xffff || fMod != mod_id) {
fMod = mod_id;
if (!init()) {
LOG(error) << GetName() << "::unpack - init mod_id=" << mod_id << " failed.";
return false;
}
}
mapped = true;
break;
}
if (!mapped) {
// get MOD_id and CROB id from the equipment, using the comp map: eq_id -> (mod_id, crob_id)
const uint16_t eq_id = msdesc.eq_id;
const auto it = fCompMap->find(eq_id);
if (it == fCompMap->end() || std::find(fModuleId.begin(), fModuleId.end(), it->second.first) == fModuleId.end()) {
LOG(error) << GetName() << "::unpack - CROB eq_id=" << eq_id << " not registered in the unpacker.";
return false;
}
const uint16_t mod_id = (*fCompMap)[eq_id].first;
const uint8_t crob_id = (*fCompMap)[eq_id].second;
if (fCrob == 0xffff) fCrob = icomp;
// Get the µslice size in bytes to calculate the number of completed words
@@ -452,7 +437,7 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
if (isaux) {
if (!ch_id) {
// clear buffer
if (vMess.size()) { pushDigis(vMess); }
if (vMess.size()) { pushDigis(vMess, mod_id); }
vMess.clear();
if (VERBOSE)
@@ -465,30 +450,30 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
else if (ch_id == 1) {
if (VERBOSE) cout << boost::format(" PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id);
}
continue;
}
else {
if (fFaspMap) fasp_id = ((*fFaspMap)[fMod])[fasp_id];
if (lFaspOld != fasp_id) {
// push
if (vMess.size()) { pushDigis(vMess); }
vMess.clear();
lFaspOld = fasp_id;
}
if (data & 0x1) {
LOG(warn) << GetName() << "::unpack - Data corrupted : detect end bit set.";
continue;
}
if (VERBOSE)
cout << boost::format(" DD : fasp_id=%02d ch_id=%02d slice=%03d data=%4d\n")
% static_cast<unsigned int>(fasp_id) % static_cast<unsigned int>(ch_id)
% static_cast<unsigned int>(slice) % static_cast<unsigned int>(data >> 1);
if (data & 0x2000) {
LOG(debug) << GetName() << "::unpack - Self-triggered data.";
data &= 0x1fff;
}
vMess.emplace_back(ch_id, kData, slice, data >> 1, crob_id, lFaspOld);
if (fFaspMap) fasp_id = ((*fFaspMap)[mod_id])[fasp_id];
if (lFaspOld != fasp_id) {
// push
if (vMess.size()) { pushDigis(vMess, mod_id); }
vMess.clear();
lFaspOld = fasp_id;
}
if (data & 0x1) {
LOG(warn) << GetName() << "::unpack - Data corrupted : detect end bit set.";
continue;
}
if (VERBOSE)
cout << boost::format(" DD : fasp_id=%02d ch_id=%02d slice=%03d data=%4d\n")
% static_cast<unsigned int>(fasp_id) % static_cast<unsigned int>(ch_id)
% static_cast<unsigned int>(slice) % static_cast<unsigned int>(data >> 1);
if (data & 0x2000) {
LOG(debug) << GetName() << "::unpack - Self-triggered data.";
data &= 0x1fff;
}
vMess.emplace_back(ch_id, kData, slice, data >> 1, crob_id, lFaspOld);
//prt_wd(*wd);
}
return unpackOk;
Loading