Skip to content
Snippets Groups Projects
CbmTrdUnpackAlgoFasp2D.cxx 14.63 KiB
/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Pascal Raisig [committer], Alexandru Bercuci */


#include "CbmTrdUnpackAlgoFasp2D.h"

#include "CbmTrdDigi.h"
#include "CbmTrdParFasp.h"
#include "CbmTrdParModDigi.h"
#include "CbmTrdParSetDigi.h"
#include "CbmTrdParSetGain.h"
#include "CbmTrdParSetGas.h"
#include "CbmTrdParSpadic.h"

#include <FairParAsciiFileIo.h>
#include <FairParGenericSet.h>
#include <FairParamList.h>
#include <FairRuntimeDb.h>
#include <FairTask.h>
#include <Logger.h>

#include <Rtypes.h>
#include <RtypesCore.h>

#include <boost/format.hpp>

#define VERBOSE 0

using namespace std;

CbmTrdUnpackAlgoFasp2D::CbmTrdUnpackAlgoFasp2D() : CbmRecoUnpackAlgo("CbmTrdUnpackAlgoFasp2D"), fModuleId(), fAsicPar()
{
  memset(fTime, 0, NCRI * sizeof(ULong64_t));
}

//_________________________________________________________________________________
CbmTrdUnpackAlgoFasp2D::~CbmTrdUnpackAlgoFasp2D() {}

//_________________________________________________________________________________
Bool_t CbmTrdUnpackAlgoFasp2D::initParSet(FairParGenericSet* parset)
{
  FairParamList parList;
  Int_t nModules(0);
  if (strcmp(parset->ClassName(), "CbmTrdParSetAsic") == 0) {
    CbmTrdParSetAsic* setPar = static_cast<CbmTrdParSetAsic*>(parset);
    for (auto did : fModuleId) {
      const CbmTrdParSetAsic* setDet = static_cast<const CbmTrdParSetAsic*>(setPar->GetModuleSet(did));
      if (!setDet) continue;
      if (setDet->GetAsicType() != Int_t(CbmTrdDigi::eCbmTrdAsicType::kFASP)) continue;
      nModules++;
      std::vector<Int_t> a;
      setDet->GetAsicAddresses(&a);
      for (auto add : a) {
        CbmTrdParAsic* asic = (CbmTrdParAsic*) setDet->GetModulePar(add);
        if (asic->IsA() == CbmTrdParSpadic::Class()) continue;
        fAsicPar.addParam(asic);
        if (VERBOSE) asic->Print();
      }
    }
    //      setPar->printParams();
    LOG(info) << GetName() << "::initParSet - for container " << parset->ClassName() << " modules " << nModules
              << " asics " << fAsicPar.GetNrOfModules();
  }
  else if (strcmp(parset->ClassName(), "CbmTrdParSetDigi") == 0) {
    fDigiSet                          = static_cast<CbmTrdParSetDigi*>(parset);
    map<Int_t, CbmTrdParMod*> digiPar = fDigiSet->GetModuleMap();
    for (auto digi : digiPar)
      fModuleId.emplace_back(digi.first);
    // setPar->printParams();
    LOG(info) << GetName() << "::initParSet - for container " << parset->ClassName() << " modules " << fModuleId.size();
  }
  else if (strcmp(parset->ClassName(), "CbmTrdParSetGas") == 0) {
    CbmTrdParSetGas* setPar = static_cast<CbmTrdParSetGas*>(parset);
    setPar->printParams();
    nModules = setPar->GetNrOfModules();
  }
  else if (strcmp(parset->ClassName(), "CbmTrdParSetGain") == 0) {
    CbmTrdParSetGain* setPar = static_cast<CbmTrdParSetGain*>(parset);
    setPar->printParams();
    nModules = setPar->GetNrOfModules();
  }
  else {
    LOG(error) << "Parameter set " << parset->ClassName() << " not known. Skip.";
    return kFALSE;
  }
  return kTRUE;
}

//_________________________________________________________________________________
std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
CbmTrdUnpackAlgoFasp2D::GetParContainerRequest(std::string geoTag, std::uint32_t runId)
{
  LOG(info) << GetName() << "::GetParContainerRequest - for container " << geoTag.data() << " run " << runId << "  "
            << fParFilesBasePath.data();

  // Basepath for default Trd parameter sets (those connected to a geoTag)
  std::string basepath = Form("%s/trd_%s", fParFilesBasePath.data(), geoTag.data());
  std::string temppath = "";

  // Digest the runId information in case of runId = 0 we use the default fall back
  std::string runpath = "";
  if (runId != 0) { runpath = ".run" + std::to_string(runId); }

  temppath = basepath + runpath + ".digi" + ".par";
  fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetDigi>()));
  temppath = basepath + runpath + ".asic" + ".par";
  fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetAsic>()));
  //   temppath = basepath + runpath + ".gas" + ".par";
  //   fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetGas>()));
  //   temppath = basepath + runpath + ".gain" + ".par";
  //   fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetGain>()));

  return &fParContVec;
}

//_________________________________________________________________________________
void CbmTrdUnpackAlgoFasp2D::SetAsicMapping(const std::map<uint32_t, uint8_t[NFASPMOD]>& asicMap)
{
  if (!fFaspMap) fFaspMap = new std::map<uint32_t, uint8_t[NFASPMOD]>(asicMap);
  else {
    delete fFaspMap;
    fFaspMap = new std::map<uint32_t, uint8_t[NFASPMOD]>(asicMap);
  }
}

//_________________________________________________________________________________
void CbmTrdUnpackAlgoFasp2D::PrintAsicMapping()
{
  if (!fFaspMap) {
    LOG(info) << GetName() << "No asic mapping loaded.";
    return;
  }
  LOG(info) << GetName() << "Fasp Asic mapping on modules:";
  for (auto imod : (*fFaspMap)) {
    printf("Mod [%6d] : ", imod.first);
    for (int ifasp(0); ifasp < NFASPMOD; ifasp++) {
      int jfasp = imod.second[ifasp];
      printf("%2d ", (jfasp == 0xff ? -1 : jfasp));
    }
    printf("\n");
  }
}

//_________________________________________________________________________________
CbmTrdUnpackAlgoFasp2D::CbmTrdFaspMessageType CbmTrdUnpackAlgoFasp2D::mess_type(uint32_t wd)
{
  if ((wd >> kMessCh) & 0x1) return kData;
  return kEpoch;
}

//_________________________________________________________________________________
void CbmTrdUnpackAlgoFasp2D::mess_readDW(uint32_t w, CbmTrdFaspContent* mess)
{
  uint32_t wd(w), shift(0);
  mess->ch = wd & 0xf;
  shift += Int_t(kMessCh);
  mess->type = (wd >> shift) & 0x1;
  shift += Int_t(kMessType);
  mess->tlab = (wd >> shift) & 0x7f;
  shift += Int_t(kMessTlab);
  mess->data = (wd >> shift) & 0x3fff;
  shift += Int_t(kMessData);
  mess->fasp = (wd >> shift) & 0x3f;

  printf("DBG :: ");
  mess_prt(mess);
}

//_________________________________________________________________________________
void CbmTrdUnpackAlgoFasp2D::mess_readEW(uint32_t w, CbmTrdFaspContent* mess)
{
  uint32_t wd(w), shift(0);
  mess->ch = wd & 0xf;
  shift += Int_t(kMessCh);
  mess->type = (wd >> shift) & 0x1;
  shift += Int_t(kMessType);
  mess->epoch = (wd >> shift) & 0x1fffff;
  shift += Int_t(kMessEpoch);
  mess->cri = (wd >> shift) & 0x3f;
  printf("DBG :: ");
  mess_prt(mess);
}

//_________________________________________________________________________________
void CbmTrdUnpackAlgoFasp2D::mess_prt(CbmTrdFaspContent* mess)
{
  if (mess->type == kData)
    cout << boost::format("    DATA : fasp_id=%02d ch_id=%02d tclk=%03d data=%4d\n")
              % static_cast<unsigned int>(mess->fasp) % static_cast<unsigned int>(mess->ch)
              % static_cast<unsigned int>(mess->tlab) % static_cast<unsigned int>(mess->data);
  else
    cout << boost::format("    EPOCH: cri_id=%02d ch_id=%02d epoch=%05d\n") % static_cast<unsigned int>(mess->cri)
              % static_cast<unsigned int>(mess->ch) % static_cast<unsigned int>(mess->epoch);
}

//_________________________________________________________________________________
bool CbmTrdUnpackAlgoFasp2D::pushDigis(std::vector<CbmTrdUnpackAlgoFasp2D::CbmTrdFaspContent*> messes)
{
  UChar_t lFasp(0xff);
  UShort_t lchR, lchT;
  Double_t r, t;
  Int_t dt, dtime, ch, pad, row;
  ULong64_t tlab;
  CbmTrdParFasp* faspPar(nullptr);
  const CbmTrdParFaspChannel* chCalib(nullptr);
  CbmTrdParModDigi* digiPar(nullptr);
  vector<CbmTrdDigi*> digis;
  for (auto imess : messes) {
    if (lFasp == 0xff) {
      lFasp = messes[0]->fasp;
      // link data to the position on the padplane
      if (!(faspPar = (CbmTrdParFasp*) fAsicPar.GetAsicPar(imess->cri * 1000 + lFasp))) {
        LOG(error) << GetName() << "::pushDigis - Par for FASP " << (int) lFasp << " in module " << imess->cri
                   << " missing. Skip.";
        return false;
      }
      if (!(digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(imess->cri))) {
        LOG(error) << GetName() << "::pushDigis - DIGI par for module " << imess->cri << " missing. Skip.";
        return false;
      }
      if (VERBOSE) faspPar->Print();
      pad     = faspPar->GetChannelAddress(imess->ch);
      chCalib = faspPar->GetChannel(imess->ch);
      ch      = 2 * pad + chCalib->HasPairingR();
      row     = digiPar->GetPadRow(pad);
      if (VERBOSE)
        printf("fasp[%2d] ch[%4d / %2d] pad[%4d] row[%2d] col[%2d] tilt[%d]\n", lFasp, ch, imess->ch, pad, row,
               digiPar->GetPadColumn(pad), chCalib->HasPairingT());
    }

    if (VERBOSE) mess_prt(imess);

    lchR    = 0;
    lchT    = 0;
    chCalib = faspPar->GetChannel(imess->ch);
    if (chCalib->HasPairingR()) lchR = imess->data;
    else
      lchT = imess->data;
    pad = faspPar->GetChannelAddress(imess->ch);

    bool use(false);
    for (auto id : digis) {
      if (id->GetAddressChannel() != pad) continue;
      dtime = id->GetTimeDAQ() - imess->tlab;
      if (TMath::Abs(dtime) < 5) {
        r = id->GetCharge(t, dt);
        if (lchR && !int(r)) {
          id->SetCharge(t, lchR, -dtime);
          use = true;
          break;
        }
        else if (lchT && !int(t)) {
          tlab = id->GetTimeDAQ();
          id->SetCharge(lchT, r, +dtime);
          id->SetTimeDAQ(ULong64_t(tlab - dtime));
          use = true;
          break;
        }
      }
    }

    if (!use) {
      CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, imess->tlab);
      digi->SetAddressModule(imess->cri);
      digis.push_back(digi);
    }
    delete imess;
  }

  // push finalized digits to the next level
  for (vector<CbmTrdDigi*>::iterator id = digis.begin(); id != digis.end(); id++) {
    (*id)->SetTimeDAQ(fTime[0] + (*id)->GetTimeDAQ());
    fOutputVec.emplace_back(*std::move(*id));
    if (VERBOSE) cout << (*id)->ToString();
  }

  digis.clear();
  messes.clear();
  return true;
}

// ---- unpack ----
bool CbmTrdUnpackAlgoFasp2D::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
{
  if (VERBOSE) printf("CbmTrdUnpackAlgoFasp2D::unpack 0x%04x %d\n", icomp, imslice);
  //LOG(info) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice "<<imslice;

  uint32_t mod_id = 5;
  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[0] = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5);

  // Get the µslice size in bytes to calculate the number of completed words
  auto mssize = msdesc.size;

  // Get the number of complete words in the input MS buffer.
  std::uint32_t nwords = mssize / 4;  //fBytesPerWord;

  const auto mspointer = ts->content(icomp, imslice);

  // We have 32 bit spadic frames in this readout version
  const auto mscontent = reinterpret_cast<const size_t*>(mspointer);

  const uint32_t* wd = reinterpret_cast<const uint32_t*>(mscontent);


  UChar_t lFaspOld(0xff);
  vector<CbmTrdFaspContent*> vDigi;
  CbmTrdFaspContent* mess(nullptr);
  for (uint64_t j = 0; j < nwords; j++, wd++) {
    //     // Select the appropriate conversion type of the word according to the message type
    //     switch(mess_type(*wd)){
    //       case CbmTrdFaspMessageType::kData:
    //         mess_readDW(*wd, &mess);
    //         break;
    //       case CbmTrdFaspMessageType::kEpoch:
    //         mess_readEW(*wd, &mess);
    //         break;
    //     }
    uint32_t w      = *wd;
    uint8_t ch_id   = w & 0xf;
    uint8_t isaux   = (w >> 4) & 0x1;
    uint8_t slice   = (w >> 5) & 0x7f;
    uint16_t data   = (w >> 12) & 0x3fff;
    uint32_t epoch  = (w >> 5) & 0x1fffff;
    uint8_t fasp_id = (w >> 26) & 0x3f;
    // std::cout<<"fasp_id="<<static_cast<unsigned int>(fasp_id)<<" ch_id="<<static_cast<unsigned int>(ch_id)<<" isaux="<<static_cast<unsigned int>(isaux)<<std::endl;
    if (isaux) {
      if (!ch_id) {
        if (VERBOSE)
          cout << boost::format("    EE : fasp_id=%02d ch_id=%02d epoch=%03d\n") % static_cast<unsigned int>(fasp_id)
                    % static_cast<unsigned int>(ch_id) % static_cast<unsigned int>(epoch);

        if (vDigi.size()) { pushDigis(vDigi); }
        vDigi.clear();
        lFaspOld = 0xff;

        fTime[fasp_id] += 128;
      }
      else if (ch_id == 1) {
        if (VERBOSE) cout << boost::format("    PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id);
      }
    }
    else {
      if (fFaspMap) fasp_id = ((*fFaspMap)[mod_id])[fasp_id];

      if (lFaspOld != fasp_id) {
        // push
        if (vDigi.size()) { pushDigis(vDigi); }
        vDigi.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;
      }
      mess       = new CbmTrdFaspContent;
      mess->ch   = ch_id;
      mess->type = 1;
      mess->tlab = slice;
      mess->data = data >> 1;
      mess->fasp = lFaspOld;
      mess->cri  = mod_id;
      vDigi.push_back(mess);
    }
    //prt_wd(*wd);
  }
  return unpackOk;
}

//_____________________________________________________________
void CbmTrdUnpackAlgoFasp2D::prt_wd(uint32_t w)
{
  //    out<<w<<std::endl;
  uint8_t ch_id   = w & 0xf;
  uint8_t isaux   = (w >> 4) & 0x1;
  uint8_t slice   = (w >> 5) & 0x7f;
  uint16_t data   = (w >> 12) & 0x3fff;
  uint32_t epoch  = (w >> 5) & 0x1fffff;
  uint8_t fasp_id = (w >> 26) & 0x3f;
  //    out<<"fasp_id="<<static_cast<unsigned int>(fasp_id)<<" ch_id="<<static_cast<unsigned int>(ch_id)<<" isaux="<<static_cast<unsigned int>(isaux)<<std::endl;
  if (isaux) {
    if (!ch_id) { cout << boost::format("EE: %08d\n") % epoch; }
    else if (ch_id == 1) {
      cout << boost::format("    PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id);
    }
  }
  else {
    cout << boost::format("    DATA: w=%08x fasp_id=%02d ch_id=%02d slice=%03d data=%04d\n") % w
              % static_cast<unsigned int>(fasp_id) % static_cast<unsigned int>(ch_id) % static_cast<unsigned int>(slice)
              % static_cast<unsigned int>(data >> 1);
  }
}

ClassImp(CbmTrdUnpackAlgoFasp2D)