LCOV - code coverage report
Current view: top level - TRD/TRDbase - AliTRDmcmSim.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 781 1373 56.9 %
Date: 2016-06-14 17:26:59 Functions: 38 60 63.3 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : /* $Id$ */
      17             : 
      18             : ///////////////////////////////////////////////////////////////////////////////
      19             : //                                                                           //
      20             : //  TRD MCM (Multi Chip Module) simulator                                    //
      21             : //  which simulates the TRAP processing after the AD-conversion.             //
      22             : //  The relevant parameters (i.e. configuration settings of the TRAP)        //
      23             : //  are taken from AliTRDtrapConfig.                                         //
      24             : //                                                                           //
      25             : ///////////////////////////////////////////////////////////////////////////////
      26             : 
      27             : #include <iostream>
      28             : #include <iomanip>
      29             : 
      30             : #include "TCanvas.h"
      31             : #include "TH1F.h"
      32             : #include "TH2F.h"
      33             : #include "TGraph.h"
      34             : #include "TLine.h"
      35             : #include "TRandom.h"
      36             : #include "TClonesArray.h"
      37             : #include "TMath.h"
      38             : #include <TTree.h>
      39             : 
      40             : #include "AliLog.h"
      41             : #include "AliRunLoader.h"
      42             : #include "AliLoader.h"
      43             : 
      44             : #include "AliTRDfeeParam.h"
      45             : #include "AliTRDcalibDB.h"
      46             : #include "AliTRDtrapConfig.h"
      47             : #include "AliTRDdigitsManager.h"
      48             : #include "AliTRDarrayADC.h"
      49             : #include "AliTRDarrayDictionary.h"
      50             : #include "AliTRDtrackletMCM.h"
      51             : #include "AliTRDmcmSim.h"
      52             : #include "TTreeStream.h"
      53             : 
      54          48 : ClassImp(AliTRDmcmSim)
      55             : 
      56             : Bool_t AliTRDmcmSim::fgApplyCut = kTRUE;
      57             : Int_t  AliTRDmcmSim::fgAddBaseline = 0;
      58             : Bool_t AliTRDmcmSim::fgStoreClusters = kFALSE;
      59             : 
      60          48 : const Int_t AliTRDmcmSim::fgkFormatIndex = std::ios_base::xalloc();
      61             : 
      62             : const UShort_t AliTRDmcmSim::fgkFPshifts[4] = {11, 14, 17, 21};
      63             : 
      64             : 
      65        1206 : AliTRDmcmSim::AliTRDmcmSim() :
      66           6 :   TObject(),
      67           6 :   fInitialized(kFALSE),
      68           6 :   fDetector(-1),
      69           6 :   fRobPos(-1),
      70           6 :   fMcmPos(-1),
      71           6 :   fRow (-1),
      72           6 :   fNTimeBin(-1),
      73           6 :   fADCR(NULL),
      74           6 :   fADCF(NULL),
      75           6 :   fMCMT(NULL),
      76           6 :   fTrackletArray(NULL),
      77           6 :   fZSMap(NULL),
      78           6 :   fTrklBranchName("mcmtrklbranch"),
      79           6 :   fFeeParam(NULL),
      80           6 :   fTrapConfig(NULL),
      81           6 :   fDigitsManager(NULL),
      82           6 :   fPedAcc(NULL),
      83           6 :   fGainCounterA(NULL),
      84           6 :   fGainCounterB(NULL),
      85           6 :   fTailAmplLong(NULL),
      86           6 :   fTailAmplShort(NULL),
      87           6 :   fNHits(0),
      88           6 :   fFitReg(NULL),
      89           6 :   fDebugStream(0x0)
      90          30 : {
      91             :   //
      92             :   // AliTRDmcmSim default constructor
      93             :   // By default, nothing is initialized.
      94             :   // It is necessary to issue Init before use.
      95             : 
      96          48 :   for (Int_t iDict = 0; iDict < 3; iDict++)
      97          18 :     fDict[iDict] = 0x0;
      98             : 
      99           6 :   fFitPtr[0] = 0;
     100           6 :   fFitPtr[1] = 0;
     101           6 :   fFitPtr[2] = 0;
     102           6 :   fFitPtr[3] = 0;
     103          12 : }
     104             : 
     105             : AliTRDmcmSim::~AliTRDmcmSim()
     106          36 : {
     107             :   //
     108             :   // AliTRDmcmSim destructor
     109             :   //
     110             : 
     111           6 :   if(fInitialized) {
     112         220 :     for( Int_t iAdc = 0 ; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++ ) {
     113         210 :       delete [] fADCR[iAdc];
     114         210 :       delete [] fADCF[iAdc];
     115             :     }
     116          10 :     delete [] fADCR;
     117          10 :     delete [] fADCF;
     118          10 :     delete [] fZSMap;
     119          10 :     delete [] fMCMT;
     120             : 
     121          10 :     delete [] fPedAcc;
     122          10 :     delete [] fGainCounterA;
     123          10 :     delete [] fGainCounterB;
     124          10 :     delete [] fTailAmplLong;
     125          10 :     delete [] fTailAmplShort;
     126          10 :     delete [] fFitReg;
     127             : 
     128           5 :     fTrackletArray->Delete();
     129          10 :     delete fTrackletArray;
     130             :   }
     131          18 : }
     132             : 
     133             : void AliTRDmcmSim::Init( Int_t det, Int_t robPos, Int_t mcmPos, Bool_t /* newEvent */ )
     134             : {
     135             :   //
     136             :   // Initialize the class with new MCM position information
     137             :   // memory is allocated in the first initialization
     138             :   //
     139             : 
     140       83200 :   if (!fInitialized) {
     141           5 :     fFeeParam      = AliTRDfeeParam::Instance();
     142           5 :     fTrapConfig    = AliTRDcalibDB::Instance()->GetTrapConfig();
     143           5 :   }
     144             : 
     145       41600 :   fDetector      = det;
     146       41600 :   fRobPos        = robPos;
     147       41600 :   fMcmPos        = mcmPos;
     148       41600 :   fRow           = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
     149             : 
     150       41600 :   if (!fInitialized) {
     151           5 :     fADCR    = new Int_t *[AliTRDfeeParam::GetNadcMcm()];
     152           5 :     fADCF    = new Int_t *[AliTRDfeeParam::GetNadcMcm()];
     153           5 :     fZSMap   = new Int_t  [AliTRDfeeParam::GetNadcMcm()];
     154           5 :     fGainCounterA = new UInt_t[AliTRDfeeParam::GetNadcMcm()];
     155           5 :     fGainCounterB = new UInt_t[AliTRDfeeParam::GetNadcMcm()];
     156           5 :     fNTimeBin     = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kC13CPUA, fDetector, fRobPos, fMcmPos);
     157         220 :     for( Int_t iAdc = 0 ; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++ ) {
     158         105 :       fADCR[iAdc] = new Int_t[fNTimeBin];
     159         105 :       fADCF[iAdc] = new Int_t[fNTimeBin];
     160             :     }
     161             : 
     162             :     // filter registers
     163           5 :     fPedAcc = new UInt_t[AliTRDfeeParam::GetNadcMcm()]; // accumulator for pedestal filter
     164           5 :     fTailAmplLong = new UShort_t[AliTRDfeeParam::GetNadcMcm()];
     165           5 :     fTailAmplShort = new UShort_t[AliTRDfeeParam::GetNadcMcm()];
     166             : 
     167             :     // tracklet calculation
     168           5 :     fFitReg = new FitReg_t[AliTRDfeeParam::GetNadcMcm()];
     169          10 :     fTrackletArray = new TClonesArray("AliTRDtrackletMCM", fgkMaxTracklets);
     170             : 
     171           5 :     fMCMT = new UInt_t[fgkMaxTracklets];
     172           5 :   }
     173             : 
     174       41600 :   fInitialized = kTRUE;
     175             : 
     176       41600 :   Reset();
     177       41600 : }
     178             : 
     179             : void AliTRDmcmSim::Reset()
     180             : {
     181             :   // Resets the data values and internal filter registers
     182             :   // by re-initialising them
     183             : 
     184       83200 :   if( !CheckInitialized() )
     185             :     return;
     186             : 
     187     1830400 :   for( Int_t iAdc = 0 ; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++ ) {
     188    48920970 :     for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
     189    23586885 :       fADCR[iAdc][it] = 0;
     190    23586885 :       fADCF[iAdc][it] = 0;
     191             :     }
     192      873600 :     fZSMap[iAdc] = -1;      // Default unread, low active bit mask
     193      873600 :     fGainCounterA[iAdc] = 0;
     194      873600 :     fGainCounterB[iAdc] = 0;
     195             :   }
     196             : 
     197      416000 :   for(Int_t i = 0; i < fgkMaxTracklets; i++) {
     198      166400 :     fMCMT[i] = 0;
     199             :   }
     200             : 
     201      332800 :   for (Int_t iDict = 0; iDict < 3; iDict++)
     202      124800 :     fDict[iDict] = 0x0;
     203             : 
     204       41600 :   FilterPedestalInit();
     205       41600 :   FilterGainInit();
     206       41600 :   FilterTailInit();
     207       83200 : }
     208             : 
     209             : void AliTRDmcmSim::SetNTimebins(Int_t ntimebins)
     210             : {
     211             :   // Reallocate memory if a change in the number of timebins
     212             :   // is needed (should not be the case for real data)
     213             : 
     214          10 :   if( !CheckInitialized() )
     215             :     return;
     216             : 
     217           5 :   fNTimeBin = ntimebins;
     218         220 :   for( Int_t iAdc = 0 ; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++ ) {
     219         210 :     delete [] fADCR[iAdc];
     220         210 :     delete [] fADCF[iAdc];
     221         105 :     fADCR[iAdc] = new Int_t[fNTimeBin];
     222         105 :     fADCF[iAdc] = new Int_t[fNTimeBin];
     223             :   }
     224           5 : }
     225             : 
     226             : Bool_t AliTRDmcmSim::LoadMCM(AliRunLoader* const runloader, Int_t det, Int_t rob, Int_t mcm)
     227             : {
     228             :   // loads the ADC data as obtained from the digitsManager for the specified MCM.
     229             :   // This method is meant for rare execution, e.g. in the visualization. When called
     230             :   // frequently use SetData(...) instead.
     231             : 
     232           0 :   Init(det, rob, mcm);
     233             : 
     234           0 :   if (!runloader) {
     235           0 :     AliError("No Runloader given");
     236           0 :     return kFALSE;
     237             :   }
     238             : 
     239           0 :   AliLoader *trdLoader = runloader->GetLoader("TRDLoader");
     240           0 :   if (!trdLoader) {
     241           0 :     AliError("Could not get TRDLoader");
     242           0 :     return kFALSE;
     243             :   }
     244             : 
     245             :   Bool_t retval = kTRUE;
     246           0 :   trdLoader->LoadDigits();
     247           0 :   fDigitsManager = 0x0;
     248           0 :   AliTRDdigitsManager *digMgr = new AliTRDdigitsManager();
     249           0 :   digMgr->SetSDigits(0);
     250           0 :   digMgr->CreateArrays();
     251           0 :   digMgr->ReadDigits(trdLoader->TreeD());
     252           0 :   AliTRDarrayADC *digits = (AliTRDarrayADC*) digMgr->GetDigits(det);
     253           0 :   if (digits->HasData()) {
     254           0 :     digits->Expand();
     255             : 
     256           0 :     if (fNTimeBin != digits->GetNtime()) {
     257           0 :       AliWarning(Form("Changing no. of timebins from %i to %i", fNTimeBin, digits->GetNtime()));
     258           0 :       SetNTimebins(digits->GetNtime());
     259           0 :     }
     260             : 
     261           0 :     SetData(digits);
     262           0 :   }
     263             :   else
     264             :     retval = kFALSE;
     265             : 
     266           0 :   delete digMgr;
     267             : 
     268           0 :   return retval;
     269           0 : }
     270             : 
     271             : void AliTRDmcmSim::NoiseTest(Int_t nsamples, Int_t mean, Int_t sigma, Int_t inputGain, Int_t inputTail)
     272             : {
     273             :   // This function can be used to test the filters.
     274             :   // It feeds nsamples of ADC values with a gaussian distribution specified by mean and sigma.
     275             :   // The filter chain implemented here consists of:
     276             :   // Pedestal -> Gain -> Tail
     277             :   // With inputGain and inputTail the input to the gain and tail filter, respectively,
     278             :   // can be chosen where
     279             :   // 0: noise input
     280             :   // 1: pedestal output
     281             :   // 2: gain output
     282             :   // The input has to be chosen from a stage before.
     283             :   // The filter behaviour is controlled by the TRAP parameters from AliTRDtrapConfig in the
     284             :   // same way as in normal simulation.
     285             :   // The functions produces four histograms with the values at the different stages.
     286             : 
     287           0 :   if( !CheckInitialized() )
     288             :     return;
     289             : 
     290           0 :   TString nameInputGain;
     291           0 :   TString nameInputTail;
     292             : 
     293           0 :   switch (inputGain) {
     294             :       case 0:
     295           0 :         nameInputGain = "Noise";
     296             :         break;
     297             : 
     298             :       case 1:
     299           0 :         nameInputGain = "Pedestal";
     300             :         break;
     301             : 
     302             :       default:
     303           0 :         AliError("Undefined input to tail cancellation filter");
     304           0 :         return;
     305             :   }
     306             : 
     307           0 :   switch (inputTail) {
     308             :       case 0:
     309           0 :         nameInputTail = "Noise";
     310             :         break;
     311             : 
     312             :       case 1:
     313           0 :         nameInputTail = "Pedestal";
     314             :         break;
     315             : 
     316             :       case 2:
     317           0 :         nameInputTail = "Gain";
     318             :         break;
     319             : 
     320             :       default:
     321           0 :         AliError("Undefined input to tail cancellation filter");
     322           0 :         return;
     323             :   }
     324             : 
     325           0 :   TH1F *h   = new TH1F("noise", "Gaussian Noise;sample;ADC count",
     326           0 :                        nsamples, 0, nsamples);
     327           0 :   TH1F *hfp = new TH1F("ped", "Noise #rightarrow Pedestal filter;sample;ADC count", nsamples, 0, nsamples);
     328           0 :   TH1F *hfg = new TH1F("gain",
     329           0 :                        (nameInputGain + "#rightarrow Gain;sample;ADC count").Data(),
     330             :                        nsamples, 0, nsamples);
     331           0 :   TH1F *hft = new TH1F("tail",
     332           0 :                        (nameInputTail + "#rightarrow Tail;sample;ADC count").Data(),
     333             :                        nsamples, 0, nsamples);
     334           0 :   h->SetStats(kFALSE);
     335           0 :   hfp->SetStats(kFALSE);
     336           0 :   hfg->SetStats(kFALSE);
     337           0 :   hft->SetStats(kFALSE);
     338             : 
     339             :   Int_t value;  // ADC count with noise (10 bit)
     340             :   Int_t valuep; // pedestal filter output (12 bit)
     341             :   Int_t valueg; // gain filter output (12 bit)
     342             :   Int_t valuet; // tail filter value (12 bit)
     343             : 
     344           0 :   for (Int_t i = 0; i < nsamples; i++) {
     345           0 :     value = (Int_t) gRandom->Gaus(mean, sigma);  // generate noise with gaussian distribution
     346           0 :     h->SetBinContent(i, value);
     347             : 
     348           0 :     valuep = FilterPedestalNextSample(1, 0, ((Int_t) value) << 2);
     349             : 
     350           0 :     if (inputGain == 0)
     351           0 :       valueg = FilterGainNextSample(1, ((Int_t) value) << 2);
     352             :     else
     353           0 :       valueg = FilterGainNextSample(1, valuep);
     354             : 
     355           0 :     if (inputTail == 0)
     356           0 :       valuet = FilterTailNextSample(1, ((Int_t) value) << 2);
     357           0 :     else if (inputTail == 1)
     358           0 :       valuet = FilterTailNextSample(1, valuep);
     359             :     else
     360           0 :       valuet = FilterTailNextSample(1, valueg);
     361             : 
     362           0 :     hfp->SetBinContent(i, valuep >> 2);
     363           0 :     hfg->SetBinContent(i, valueg >> 2);
     364           0 :     hft->SetBinContent(i, valuet >> 2);
     365             :   }
     366             : 
     367           0 :   TCanvas *c = new TCanvas;
     368           0 :   c->Divide(2,2);
     369           0 :   c->cd(1);
     370           0 :   h->Draw();
     371           0 :   c->cd(2);
     372           0 :   hfp->Draw();
     373           0 :   c->cd(3);
     374           0 :   hfg->Draw();
     375           0 :   c->cd(4);
     376           0 :   hft->Draw();
     377           0 : }
     378             : 
     379             : Bool_t AliTRDmcmSim::CheckInitialized() const
     380             : {
     381             :   //
     382             :   // Check whether object is initialized
     383             :   //
     384             : 
     385      457610 :   if( ! fInitialized )
     386           0 :     AliError(Form ("AliTRDmcmSim is not initialized but function other than Init() is called."));
     387             : 
     388      228805 :   return fInitialized;
     389             : }
     390             : 
     391             : void AliTRDmcmSim::Print(Option_t* const option) const
     392             : {
     393             :   // Prints the data stored and/or calculated for this MCM.
     394             :   // The output is controlled by option which can be a sequence of any of
     395             :   // the following characters:
     396             :   // R - prints raw ADC data
     397             :   // F - prints filtered data
     398             :   // H - prints detected hits
     399             :   // T - prints found tracklets
     400             :   // The later stages are only meaningful after the corresponding calculations
     401             :   // have been performed.
     402             : 
     403           0 :   if ( !CheckInitialized() )
     404             :     return;
     405             : 
     406           0 :   printf("MCM %i on ROB %i in detector %i\n", fMcmPos, fRobPos, fDetector);
     407             : 
     408           0 :   TString opt = option;
     409           0 :   if (opt.Contains("R") || opt.Contains("F")) {
     410           0 :     std::cout << *this;
     411             :   }
     412             : 
     413           0 :   if (opt.Contains("H")) {
     414           0 :     printf("Found %i hits:\n", fNHits);
     415           0 :     for (Int_t iHit = 0; iHit < fNHits; iHit++) {
     416           0 :       printf("Hit %3i in timebin %2i, ADC %2i has charge %3i and position %3i\n",
     417           0 :              iHit,  fHits[iHit].fTimebin, fHits[iHit].fChannel, fHits[iHit].fQtot, fHits[iHit].fYpos);
     418             :     }
     419           0 :   }
     420             : 
     421           0 :   if (opt.Contains("T")) {
     422           0 :     printf("Tracklets:\n");
     423           0 :     for (Int_t iTrkl = 0; iTrkl < fTrackletArray->GetEntriesFast(); iTrkl++) {
     424           0 :       printf("tracklet %i: 0x%08x\n", iTrkl, ((AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl])->GetTrackletWord());
     425             :     }
     426           0 :   }
     427           0 : }
     428             : 
     429             : void AliTRDmcmSim::Draw(Option_t* const option)
     430             : {
     431             :   // Plots the data stored in a 2-dim. timebin vs. ADC channel plot.
     432             :   // The option selects what data is plotted and can be a sequence of
     433             :   // the following characters:
     434             :   // R - plot raw data (default)
     435             :   // F - plot filtered data (meaningless if R is specified)
     436             :   // In addition to the ADC values:
     437             :   // H - plot hits
     438             :   // T - plot tracklets
     439             : 
     440           0 :   if( !CheckInitialized() )
     441             :     return;
     442             : 
     443           0 :   TString opt = option;
     444             : 
     445           0 :   TH2F *hist = new TH2F("mcmdata", Form("Data of MCM %i on ROB %i in detector %i", \
     446           0 :                                         fMcmPos, fRobPos, fDetector), \
     447           0 :                         AliTRDfeeParam::GetNadcMcm(), -0.5, AliTRDfeeParam::GetNadcMcm()-.5, fNTimeBin, -.5, fNTimeBin-.5);
     448           0 :   hist->GetXaxis()->SetTitle("ADC Channel");
     449           0 :   hist->GetYaxis()->SetTitle("Timebin");
     450           0 :   hist->SetStats(kFALSE);
     451             : 
     452           0 :   if (opt.Contains("R")) {
     453           0 :     for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     454           0 :       for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     455           0 :         hist->SetBinContent(iAdc+1, iTimeBin+1, fADCR[iAdc][iTimeBin] >> fgkAddDigits);
     456             :       }
     457             :     }
     458           0 :   }
     459             :   else {
     460           0 :     for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     461           0 :       for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     462           0 :         hist->SetBinContent(iAdc+1, iTimeBin+1, fADCF[iAdc][iTimeBin] >> fgkAddDigits);
     463             :       }
     464             :     }
     465             :   }
     466           0 :   hist->Draw("colz");
     467             : 
     468           0 :   if (opt.Contains("H")) {
     469           0 :     TGraph *grHits = new TGraph();
     470           0 :     for (Int_t iHit = 0; iHit < fNHits; iHit++) {
     471           0 :       grHits->SetPoint(iHit,
     472           0 :                        fHits[iHit].fChannel + 1 + fHits[iHit].fYpos/256.,
     473           0 :                        fHits[iHit].fTimebin);
     474             :     }
     475           0 :     grHits->Draw("*");
     476           0 :   }
     477             : 
     478           0 :   if (opt.Contains("T")) {
     479           0 :     TLine *trklLines = new TLine[4];
     480           0 :     for (Int_t iTrkl = 0; iTrkl < fTrackletArray->GetEntries(); iTrkl++) {
     481           0 :       AliTRDtrackletMCM *trkl = (AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl];
     482           0 :       Float_t padWidth = 0.635 + 0.03 * (fDetector % 6);
     483           0 :       Float_t offset   = padWidth/256. * ((((((fRobPos & 0x1) << 2) + (fMcmPos & 0x3)) * 18) << 8) - ((18*4*2 - 18*2 - 3) << 7)); // revert adding offset in FitTracklet
     484           0 :       Int_t   ndrift   = fTrapConfig->GetDmemUnsigned(fgkDmemAddrNdrift, fDetector, fRobPos, fMcmPos) >> 5;
     485             :       Float_t slope    = 0;
     486           0 :       if (ndrift)
     487           0 :         slope = trkl->GetdY() * 140e-4 / ndrift;
     488             : 
     489           0 :       Int_t t0 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS, fDetector, fRobPos, fMcmPos);
     490           0 :       Int_t t1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE, fDetector, fRobPos, fMcmPos);
     491             : 
     492           0 :       trklLines[iTrkl].SetX1((offset - (trkl->GetY() - slope * t0)) / padWidth); // ??? sign?
     493           0 :       trklLines[iTrkl].SetY1(t0);
     494           0 :       trklLines[iTrkl].SetX2((offset - (trkl->GetY() - slope * t1)) / padWidth); // ??? sign?
     495           0 :       trklLines[iTrkl].SetY2(t1);
     496           0 :       trklLines[iTrkl].SetLineColor(2);
     497           0 :       trklLines[iTrkl].SetLineWidth(2);
     498           0 :       printf("Tracklet %i: y = %f, dy = %f, offset = %f\n", iTrkl, trkl->GetY(), (trkl->GetdY() * 140e-4), offset);
     499           0 :       trklLines[iTrkl].Draw();
     500             :     }
     501           0 :   }
     502           0 : }
     503             : 
     504             : void AliTRDmcmSim::SetData( Int_t adc, const Int_t* const data )
     505             : {
     506             :   //
     507             :   // Store ADC data into array of raw data
     508             :   //
     509             : 
     510           0 :   if( !CheckInitialized() ) return;
     511             : 
     512           0 :   if( adc < 0 || adc >= AliTRDfeeParam::GetNadcMcm() ) {
     513           0 :     AliError(Form ("Error: ADC %i is out of range (0 .. %d).", adc, AliTRDfeeParam::GetNadcMcm()-1));
     514           0 :     return;
     515             :   }
     516             : 
     517           0 :   for( Int_t it = 0 ;  it < fNTimeBin ; it++ ) {
     518           0 :     fADCR[adc][it] = (Int_t) (data[it]) << fgkAddDigits;
     519           0 :     fADCF[adc][it] = (Int_t) (data[it]) << fgkAddDigits;
     520             :   }
     521           0 : }
     522             : 
     523             : void AliTRDmcmSim::SetData( Int_t adc, Int_t it, Int_t data )
     524             : {
     525             :   //
     526             :   // Store ADC data into array of raw data
     527             :   //
     528             : 
     529           0 :   if( !CheckInitialized() ) return;
     530             : 
     531           0 :   if( adc < 0 || adc >= AliTRDfeeParam::GetNadcMcm() ) {
     532           0 :     AliError(Form ("Error: ADC %i is out of range (0 .. %d).", adc, AliTRDfeeParam::GetNadcMcm()-1));
     533           0 :     return;
     534             :   }
     535             : 
     536           0 :   fADCR[adc][it] = data << fgkAddDigits;
     537           0 :   fADCF[adc][it] = data << fgkAddDigits;
     538           0 : }
     539             : 
     540             : void AliTRDmcmSim::SetData(AliTRDarrayADC* const adcArray, AliTRDdigitsManager * const digitsManager)
     541             : {
     542             :   // Set the ADC data from an AliTRDarrayADC
     543             : 
     544       41600 :   if( !CheckInitialized() )
     545             :     return;
     546             : 
     547       20800 :   fDigitsManager = digitsManager;
     548       20800 :   if (fDigitsManager) {
     549           0 :     for (Int_t iDict = 0; iDict < 3; iDict++) {
     550           0 :       AliTRDarrayDictionary *newDict = (AliTRDarrayDictionary*) fDigitsManager->GetDictionary(fDetector, iDict);
     551           0 :       if (fDict[iDict] != 0x0 && newDict != 0x0) {
     552             : 
     553           0 :         if (fDict[iDict] == newDict)
     554           0 :           continue;
     555             : 
     556           0 :         fDict[iDict] = newDict;
     557           0 :         if(fDict[iDict]->GetDim() != 0)
     558           0 :           fDict[iDict]->Expand();
     559             :       }
     560             :       else {
     561           0 :         fDict[iDict] = newDict;
     562           0 :         if (fDict[iDict] && (fDict[iDict]->GetDim() != 0) )
     563           0 :           fDict[iDict]->Expand();
     564             :       }
     565             : 
     566             :       // If there is no data, set dictionary to zero to avoid crashes
     567           0 :       if (fDict[iDict]->GetDim() == 0)  {
     568             :          // AliError(Form("Dictionary %i of det. %i has dim. 0", iDict, fDetector));
     569           0 :         fDict[iDict] = 0x0;
     570           0 :       }
     571           0 :     }
     572           0 :   }
     573             : 
     574       20800 :   if (fNTimeBin != adcArray->GetNtime())
     575           4 :     SetNTimebins(adcArray->GetNtime());
     576             : 
     577       20800 :   Int_t offset = (fMcmPos % 4 + 1) * 21 + (fRobPos % 2) * 84 - 1;
     578             : 
     579     1164800 :   for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     580    24710400 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     581    11793600 :       Int_t value = adcArray->GetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin);
     582             :       // treat 0 as suppressed,
     583             :       // this is not correct but reported like that from arrayADC
     584    11998422 :       if (value <= 0 || (offset - iAdc < 1) || (offset - iAdc > 165)) {
     585    11691459 :         fADCR[iAdc][iTimeBin] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     586    11691459 :         fADCF[iAdc][iTimeBin] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     587    11691459 :       }
     588             :       else {
     589      102141 :         fZSMap[iAdc] = 0;
     590      102141 :         fADCR[iAdc][iTimeBin] = (value << fgkAddDigits) + (fgAddBaseline << fgkAddDigits);
     591      102141 :         fADCF[iAdc][iTimeBin] = (value << fgkAddDigits) + (fgAddBaseline << fgkAddDigits);
     592             :       }
     593             :     }
     594             :   }
     595       41600 : }
     596             : 
     597             : void AliTRDmcmSim::SetDataByPad(const AliTRDarrayADC* const adcArray, AliTRDdigitsManager * const digitsManager)
     598             : {
     599             :   // Set the ADC data from an AliTRDarrayADC
     600             :   // (by pad, to be used during initial reading in simulation)
     601             : 
     602       41600 :   if( !CheckInitialized() )
     603             :     return;
     604             : 
     605       20800 :   fDigitsManager = digitsManager;
     606       20800 :   if (fDigitsManager) {
     607      166400 :     for (Int_t iDict = 0; iDict < 3; iDict++) {
     608       62400 :       AliTRDarrayDictionary *newDict = (AliTRDarrayDictionary*) fDigitsManager->GetDictionary(fDetector, iDict);
     609       62400 :       if (fDict[iDict] != 0x0 && newDict != 0x0) {
     610             : 
     611           0 :         if (fDict[iDict] == newDict)
     612           0 :           continue;
     613             : 
     614           0 :         fDict[iDict] = newDict;
     615           0 :         fDict[iDict]->Expand();
     616           0 :       }
     617             :       else {
     618       62400 :         fDict[iDict] = newDict;
     619       62400 :         if (fDict[iDict])
     620       62400 :           fDict[iDict]->Expand();
     621             :       }
     622             : 
     623             :       // If there is no data, set dictionary to zero to avoid crashes
     624       62400 :       if (fDict[iDict]->GetDim() == 0)  {
     625           0 :         AliError(Form("Dictionary %i of det. %i has dim. 0", iDict, fDetector));
     626           0 :         fDict[iDict] = 0x0;
     627           0 :       }
     628       62400 :     }
     629       20800 :   }
     630             : 
     631       20800 :   if (fNTimeBin != adcArray->GetNtime())
     632           1 :     SetNTimebins(adcArray->GetNtime());
     633             : 
     634       20800 :   Int_t offset = (fMcmPos % 4 + 1) * 18 + (fRobPos % 2) * 72 + 1;
     635             : 
     636     1164800 :   for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     637    24710400 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     638             :       Int_t value = -1;
     639    11793600 :       Int_t pad = offset - iAdc;
     640    11793600 :       if (pad > -1 && pad < 144)
     641    11583000 :         value = adcArray->GetData(GetRow(), offset - iAdc, iTimeBin);
     642             :       //      Int_t value = adcArray->GetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin);
     643    33915726 :       if (value < 0 || (offset - iAdc < 1) || (offset - iAdc > 165)) {
     644      767637 :         fADCR[iAdc][iTimeBin] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     645      767637 :         fADCF[iAdc][iTimeBin] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     646      767637 :       }
     647             :       else {
     648    11025963 :         fZSMap[iAdc] = 0;
     649    11025963 :         fADCR[iAdc][iTimeBin] = (value << fgkAddDigits) + (fgAddBaseline << fgkAddDigits);
     650    11025963 :         fADCF[iAdc][iTimeBin] = (value << fgkAddDigits) + (fgAddBaseline << fgkAddDigits);
     651             :       }
     652             :     }
     653             :   }
     654       41600 : }
     655             : 
     656             : void AliTRDmcmSim::SetDataPedestal( Int_t adc )
     657             : {
     658             :   //
     659             :   // Store ADC data into array of raw data
     660             :   //
     661             : 
     662           0 :   if( !CheckInitialized() )
     663             :     return;
     664             : 
     665           0 :   if( adc < 0 || adc >= AliTRDfeeParam::GetNadcMcm() ) {
     666             :     return;
     667             :   }
     668             : 
     669           0 :   for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
     670           0 :     fADCR[adc][it] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     671           0 :     fADCF[adc][it] = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP, fDetector, fRobPos, fMcmPos) + (fgAddBaseline << fgkAddDigits);
     672             :   }
     673           0 : }
     674             : 
     675             : Bool_t AliTRDmcmSim::GetHit(Int_t index, Int_t &channel, Int_t &timebin, Int_t &qtot, Int_t &ypos, Float_t &y, Int_t &label) const
     676             : {
     677             :   // retrieve the MC hit information (not available in TRAP hardware)
     678             : 
     679           0 :   if (index < 0 || index >= fNHits)
     680           0 :     return kFALSE;
     681             : 
     682           0 :   channel = fHits[index].fChannel;
     683           0 :   timebin = fHits[index].fTimebin;
     684           0 :   qtot    = fHits[index].fQtot;
     685           0 :   ypos    = fHits[index].fYpos;
     686           0 :   y       = (Float_t) ((((((fRobPos & 0x1) << 2) + (fMcmPos & 0x3)) * 18) << 8) - ((18*4*2 - 18*2 - 1) << 7) -
     687           0 :                         (channel << 8) - ypos)
     688           0 :     * (0.635 + 0.03 * (fDetector % 6))
     689           0 :     / 256.0;
     690           0 :   label   = fHits[index].fLabel[0];
     691             : 
     692           0 :   return kTRUE;
     693           0 : }
     694             : 
     695             : Int_t AliTRDmcmSim::GetCol( Int_t adc )
     696             : {
     697             :   //
     698             :   // Return column id of the pad for the given ADC channel
     699             :   //
     700             : 
     701           0 :   if( !CheckInitialized() )
     702           0 :     return -1;
     703             : 
     704           0 :   Int_t col = fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, adc);
     705           0 :   if (col < 0 || col >= fFeeParam->GetNcol())
     706           0 :     return -1;
     707             :   else
     708           0 :     return col;
     709           0 : }
     710             : 
     711             : Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t bufSize, UInt_t iEv) const
     712             : {
     713             :   //
     714             :   // Produce raw data stream from this MCM and put in buf
     715             :   // Returns number of words filled, or negative value
     716             :   // with -1 * number of overflowed words
     717             :   //
     718             : 
     719       41600 :   if( !CheckInitialized() )
     720           0 :     return 0;
     721             : 
     722             :   UInt_t  x;
     723             :   UInt_t  mcmHeader = 0;
     724             :   UInt_t  adcMask = 0;
     725             :   Int_t   nw  = 0;  // Number of written words
     726             :   Int_t   of  = 0;  // Number of overflowed words
     727       20800 :   Int_t   rawVer   = fFeeParam->GetRAWversion();
     728             :   Int_t **adc;
     729             :   Int_t   nActiveADC = 0;       // number of activated ADC bits in a word
     730             : 
     731       20800 :   if( !CheckInitialized() )
     732           0 :     return 0;
     733             : 
     734       20800 :   if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBSF, fDetector, fRobPos, fMcmPos) != 0) // store unfiltered data
     735       20800 :     adc = fADCR;
     736             :   else
     737           0 :     adc = fADCF;
     738             : 
     739             :   // Produce ADC mask : nncc cccm mmmm mmmm mmmm mmmm mmmm 1100
     740             :   //                            n : unused , c : ADC count, m : selected ADCs
     741       41600 :   if( rawVer >= 3 &&
     742       20800 :       (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kC15CPUA, fDetector, fRobPos, fMcmPos) & (1 << 13))) { // check for zs flag in TRAP configuration
     743      915200 :     for( Int_t iAdc = 0 ; iAdc < AliTRDfeeParam::GetNadcMcm() ; iAdc++ ) {
     744      436800 :       if( ~fZSMap[iAdc] != 0 ) { //  0 means not suppressed
     745        3801 :         adcMask |= (1 << (iAdc+4) );      // last 4 digit reserved for 1100=0xc
     746        3801 :         nActiveADC++;           // number of 1 in mmm....m
     747        3801 :       }
     748             :     }
     749             : 
     750       41017 :     if ((nActiveADC == 0) &&
     751       20217 :         (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kC15CPUA, fDetector, fRobPos, fMcmPos) & (1 << 8))) // check for DEH flag in TRAP configuration
     752       20217 :       return 0;
     753             : 
     754             :     // assemble adc mask word
     755         583 :     adcMask |= (1 << 30) | ( ( 0x3FFFFFFC ) & (~(nActiveADC) << 25) ) | 0xC;    // nn = 01, ccccc are inverted, 0xc=1100
     756         583 :   }
     757             : 
     758             :   // MCM header
     759         583 :   mcmHeader = (1<<31) | (fRobPos << 28) | (fMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC;
     760         583 :   if (nw < bufSize)
     761         583 :     buf[nw++] = mcmHeader;
     762             :   else
     763             :     of++;
     764             : 
     765             :   // ADC mask
     766         583 :   if( adcMask != 0 ) {
     767         583 :     if (nw < bufSize)
     768         583 :       buf[nw++] = adcMask;
     769             :     else
     770           0 :       of++;
     771             :   }
     772             : 
     773             :   // Produce ADC data. 3 timebins are packed into one 32 bits word
     774             :   // In this version, different ADC channel will NOT share the same word
     775             : 
     776             :   UInt_t aa=0, a1=0, a2=0, a3=0;
     777             : 
     778       25652 :   for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
     779       24486 :     if( rawVer>= 3 && ~fZSMap[iAdc] == 0 ) continue; // Zero Suppression, 0 means not suppressed
     780        3801 :     aa = !(iAdc & 1) + 2;
     781       76020 :     for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
     782      102627 :       a1 = ((iT    ) < fNTimeBin ) ? adc[iAdc][iT  ] >> fgkAddDigits : 0;
     783      102627 :       a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] >> fgkAddDigits : 0;
     784      102627 :       a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] >> fgkAddDigits : 0;
     785       34209 :       x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
     786       34209 :       if (nw < bufSize) {
     787       34209 :         buf[nw++] = x;
     788       34209 :       }
     789             :       else {
     790           0 :         of++;
     791             :       }
     792             :     }
     793        3801 :   }
     794             : 
     795        1166 :   if( of != 0 ) return -of; else return nw;
     796       20800 : }
     797             : 
     798             : Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t bufSize )
     799             : {
     800             :   //
     801             :   // Produce tracklet data stream from this MCM and put in buf
     802             :   // Returns number of words filled, or negative value
     803             :   // with -1 * number of overflowed words
     804             :   //
     805             : 
     806       41600 :   if( !CheckInitialized() )
     807           0 :     return 0;
     808             : 
     809             :   Int_t   nw  = 0;  // Number of written words
     810             :   Int_t   of  = 0;  // Number of overflowed words
     811             : 
     812             :   // Produce tracklet data. A maximum of four 32 Bit words will be written per MCM
     813             :   // fMCMT is filled continuously until no more tracklet words available
     814             : 
     815       42318 :   for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
     816         359 :     if (nw < bufSize)
     817         359 :       buf[nw++] = ((AliTRDtrackletMCM*) (*fTrackletArray)[iTracklet])->GetTrackletWord();
     818             :     else
     819           0 :       of++;
     820             :   }
     821             : 
     822       41600 :   if( of != 0 ) return -of; else return nw;
     823       20800 : }
     824             : 
     825             : void AliTRDmcmSim::Filter()
     826             : {
     827             :   //
     828             :   // Filter the raw ADC values. The active filter stages and their
     829             :   // parameters are taken from AliTRDtrapConfig.
     830             :   // The raw data is stored separate from the filtered data. Thus,
     831             :   // it is possible to run the filters on a set of raw values
     832             :   // sequentially for parameter tuning.
     833             :   //
     834             : 
     835       41600 :   if( !CheckInitialized() )
     836             :     return;
     837             : 
     838             :   // Apply filters sequentially. Bypass is handled by filters
     839             :   // since counters and internal registers may be updated even
     840             :   // if the filter is bypassed.
     841             :   // The first filter takes the data from fADCR and
     842             :   // outputs to fADCF.
     843             : 
     844             :   // Non-linearity filter not implemented.
     845       20800 :   FilterPedestal();
     846       20800 :   FilterGain();
     847       20800 :   FilterTail();
     848             :   // Crosstalk filter not implemented.
     849       41600 : }
     850             : 
     851             : void AliTRDmcmSim::FilterPedestalInit(Int_t baseline)
     852             : {
     853             :   // Initializes the pedestal filter assuming that the input has
     854             :   // been constant for a long time (compared to the time constant).
     855             : 
     856       83200 :   UShort_t    fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC, fDetector, fRobPos, fMcmPos); // 0..3, 0 - fastest, 3 - slowest
     857             : 
     858     1830400 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++)
     859      873600 :     fPedAcc[iAdc] = (baseline << 2) * (1 << fgkFPshifts[fptc]);
     860       41600 : }
     861             : 
     862             : UShort_t AliTRDmcmSim::FilterPedestalNextSample(Int_t adc, Int_t timebin, UShort_t value)
     863             : {
     864             :   // Returns the output of the pedestal filter given the input value.
     865             :   // The output depends on the internal registers and, thus, the
     866             :   // history of the filter.
     867             : 
     868    23587200 :   UShort_t    fpnp = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP, fDetector, fRobPos, fMcmPos); // 0..511 -> 0..127.75, pedestal at the output
     869    11793600 :   UShort_t    fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC, fDetector, fRobPos, fMcmPos); // 0..3, 0 - fastest, 3 - slowest
     870    11793600 :   UShort_t    fpby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPBY, fDetector, fRobPos, fMcmPos); // 0..1 bypass, active low
     871             : 
     872             :   UShort_t accumulatorShifted;
     873             :   Int_t correction;
     874             :   UShort_t inpAdd;
     875             : 
     876    11793600 :   inpAdd = value + fpnp;
     877             : 
     878    11793600 :   accumulatorShifted = (fPedAcc[adc] >> fgkFPshifts[fptc]) & 0x3FF;   // 10 bits
     879    11793600 :   if (timebin == 0) // the accumulator is disabled in the drift time
     880             :   {
     881      436800 :     correction = (value & 0x3FF) - accumulatorShifted;
     882      436800 :     fPedAcc[adc] = (fPedAcc[adc] + correction) & 0x7FFFFFFF;             // 31 bits
     883      436800 :   }
     884             : 
     885    11793600 :   if (fpby == 0)
     886    11793600 :     return value;
     887             : 
     888           0 :   if (inpAdd <= accumulatorShifted)
     889           0 :     return 0;
     890             :   else
     891             :   {
     892           0 :     inpAdd = inpAdd - accumulatorShifted;
     893           0 :     if (inpAdd > 0xFFF)
     894           0 :       return 0xFFF;
     895             :     else
     896           0 :       return inpAdd;
     897             :   }
     898    11793600 : }
     899             : 
     900             : void AliTRDmcmSim::FilterPedestal()
     901             : {
     902             :   //
     903             :   // Apply pedestal filter
     904             :   //
     905             :   // As the first filter in the chain it reads data from fADCR
     906             :   // and outputs to fADCF.
     907             :   // It has only an effect if previous samples have been fed to
     908             :   // find the pedestal. Currently, the simulation assumes that
     909             :   // the input has been stable for a sufficiently long time.
     910             : 
     911     1185600 :   for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     912    24710400 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     913    11793600 :       fADCF[iAdc][iTimeBin] = FilterPedestalNextSample(iAdc, iTimeBin, fADCR[iAdc][iTimeBin]);
     914             :     }
     915             :   }
     916       20800 : }
     917             : 
     918             : void AliTRDmcmSim::FilterGainInit()
     919             : {
     920             :   // Initializes the gain filter. In this case, only threshold
     921             :   // counters are reset.
     922             : 
     923     1872000 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     924             :     // these are counters which in hardware continue
     925             :     // until maximum or reset
     926      873600 :     fGainCounterA[iAdc] = 0;
     927      873600 :     fGainCounterB[iAdc] = 0;
     928             :   }
     929       41600 : }
     930             : 
     931             : UShort_t AliTRDmcmSim::FilterGainNextSample(Int_t adc, UShort_t value)
     932             : {
     933             :   // Apply the gain filter to the given value.
     934             :   // BEGIN_LATEX O_{i}(t) = #gamma_{i} * I_{i}(t) + a_{i} END_LATEX
     935             :   // The output depends on the internal registers and, thus, the
     936             :   // history of the filter.
     937             : 
     938    23587200 :   UShort_t    fgby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGBY, fDetector, fRobPos, fMcmPos); // bypass, active low
     939    11793600 :   UShort_t    fgf  = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGF0 + adc), fDetector, fRobPos, fMcmPos); // 0x700 + (0 & 0x1ff);
     940    11793600 :   UShort_t    fga  = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGA0 + adc), fDetector, fRobPos, fMcmPos); // 40;
     941    11793600 :   UShort_t    fgta = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTA, fDetector, fRobPos, fMcmPos); // 20;
     942    11793600 :   UShort_t    fgtb = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTB, fDetector, fRobPos, fMcmPos); // 2060;
     943             : 
     944    11793600 :   UInt_t fgfExtended = 0x700 + fgf;      // The corr factor which is finally applied has to be extended by 0x700 (hex) or 0.875 (dec)
     945             :                                          // because fgf=0 correspons to 0.875 and fgf=511 correspons to 1.125 - 2^(-11)
     946             :                                          // (see TRAP User Manual for details)
     947             : 
     948             :   UInt_t corr; // corrected value
     949             : 
     950    11793600 :   value &= 0xFFF;
     951    11793600 :   corr = (value * fgfExtended) >> 11;
     952    11793600 :   corr = corr > 0xfff ? 0xfff : corr;
     953    11793600 :   corr = AddUintClipping(corr, fga, 12);
     954             : 
     955             :   // Update threshold counters
     956             :   // not really useful as they are cleared with every new event
     957    23587200 :   if (!((fGainCounterA[adc] == 0x3FFFFFF) || (fGainCounterB[adc] == 0x3FFFFFF)))
     958             :   // stop when full
     959             :   {
     960    11793600 :     if (corr >= fgtb)
     961         111 :       fGainCounterB[adc]++;
     962    11793489 :     else if (corr >= fgta)
     963    11793489 :       fGainCounterA[adc]++;
     964             :   }
     965             : 
     966    11793600 :   if (fgby == 1)
     967           0 :     return corr;
     968             :   else
     969    11793600 :     return value;
     970    11793600 : }
     971             : 
     972             : void AliTRDmcmSim::FilterGain()
     973             : {
     974             :   // Read data from fADCF and apply gain filter.
     975             : 
     976      936000 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
     977    24460800 :     for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
     978    11793600 :         fADCF[iAdc][iTimeBin] = FilterGainNextSample(iAdc, fADCF[iAdc][iTimeBin]);
     979             :     }
     980             :   }
     981       20800 : }
     982             : 
     983             : void AliTRDmcmSim::FilterTailInit(Int_t baseline)
     984             : {
     985             :   // Initializes the tail filter assuming that the input has
     986             :   // been at the baseline value (configured by FTFP) for a
     987             :   // sufficiently long time.
     988             : 
     989             :   // exponents and weight calculated from configuration
     990       83200 :   UShort_t    alphaLong = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL, fDetector, fRobPos, fMcmPos); // the weight of the long component
     991       41600 :   UShort_t    lambdaLong = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL, fDetector, fRobPos, fMcmPos) & 0x1FF); // the multiplier
     992       41600 :   UShort_t    lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS, fDetector, fRobPos, fMcmPos) & 0x1FF); // the multiplier
     993             : 
     994       41600 :   Float_t lambdaL = lambdaLong  * 1.0 / (1 << 11);
     995       41600 :   Float_t lambdaS = lambdaShort * 1.0 / (1 << 11);
     996       41600 :   Float_t alphaL  = alphaLong   * 1.0 / (1 << 11);
     997             :   Float_t qup, qdn;
     998       41600 :   qup = (1 - lambdaL) * (1 - lambdaS);
     999       41600 :   qdn = 1 - lambdaS * alphaL - lambdaL * (1 - alphaL);
    1000       41600 :   Float_t kdc = qup/qdn;
    1001             : 
    1002             :   Float_t kt, ql, qs;
    1003             :   UShort_t aout;
    1004             : 
    1005       41600 :   if (baseline < 0)
    1006       41600 :     baseline = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP, fDetector, fRobPos, fMcmPos);
    1007             : 
    1008       41600 :   ql = lambdaL * (1 - lambdaS) *      alphaL;
    1009       41600 :   qs = lambdaS * (1 - lambdaL) * (1 - alphaL);
    1010             : 
    1011     1830400 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
    1012      873600 :     Int_t value = baseline & 0xFFF;
    1013      873600 :     Int_t corr = (value * fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGF0 + iAdc), fDetector, fRobPos, fMcmPos)) >> 11;
    1014      873600 :     corr = corr > 0xfff ? 0xfff : corr;
    1015      873600 :     corr = AddUintClipping(corr, fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGA0 + iAdc), fDetector, fRobPos, fMcmPos), 12);
    1016             : 
    1017      873600 :     kt = kdc * baseline;
    1018      873600 :     aout = baseline - (UShort_t) kt;
    1019             : 
    1020      873600 :     fTailAmplLong[iAdc]  = (UShort_t) (aout * ql / (ql + qs));
    1021      873600 :     fTailAmplShort[iAdc] = (UShort_t) (aout * qs / (ql + qs));
    1022             :   }
    1023       41600 : }
    1024             : 
    1025             : UShort_t AliTRDmcmSim::FilterTailNextSample(Int_t adc, UShort_t value)
    1026             : {
    1027             :   // Returns the output of the tail filter for the given input value.
    1028             :   // The output depends on the internal registers and, thus, the
    1029             :   // history of the filter.
    1030             : 
    1031             :   // exponents and weight calculated from configuration
    1032    23587200 :   UShort_t    alphaLong   = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL, fDetector, fRobPos, fMcmPos);                          // the weight of the long component
    1033    11793600 :   UShort_t    lambdaLong  = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL, fDetector, fRobPos, fMcmPos) & 0x1FF); // the multiplier of the long component
    1034    11793600 :   UShort_t    lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS, fDetector, fRobPos, fMcmPos) & 0x1FF); // the multiplier of the short component
    1035             : 
    1036             :   // intermediate signals
    1037             :   UInt_t   aDiff;
    1038             :   UInt_t   alInpv;
    1039             :   UShort_t aQ;
    1040             :   UInt_t   tmp;
    1041             : 
    1042    11793600 :   UShort_t inpVolt = value & 0xFFF;    // 12 bits
    1043             : 
    1044             :   // add the present generator outputs
    1045    11793600 :   aQ = AddUintClipping(fTailAmplLong[adc], fTailAmplShort[adc], 12);
    1046             : 
    1047             :   // calculate the difference between the input and the generated signal
    1048    11793600 :   if (inpVolt > aQ)
    1049    11793495 :     aDiff = inpVolt - aQ;
    1050             :   else
    1051             :     aDiff = 0;
    1052             : 
    1053             :   // the inputs to the two generators, weighted
    1054    11793600 :   alInpv = (aDiff * alphaLong) >> 11;
    1055             : 
    1056             :   // the new values of the registers, used next time
    1057             :   // long component
    1058    11793600 :   tmp = AddUintClipping(fTailAmplLong[adc], alInpv, 12);
    1059    11793600 :   tmp =  (tmp * lambdaLong) >> 11;
    1060    11793600 :   fTailAmplLong[adc] = tmp & 0xFFF;
    1061             :   // short component
    1062    11793600 :   tmp = AddUintClipping(fTailAmplShort[adc], aDiff - alInpv, 12);
    1063    11793600 :   tmp =  (tmp * lambdaShort) >> 11;
    1064    11793600 :   fTailAmplShort[adc] = tmp & 0xFFF;
    1065             : 
    1066             :   // the output of the filter
    1067    11793600 :   if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTBY, fDetector, fRobPos, fMcmPos) == 0) // bypass mode, active low
    1068    11793600 :     return value;
    1069             :   else
    1070           0 :     return aDiff;
    1071    11793600 : }
    1072             : 
    1073             : void AliTRDmcmSim::FilterTail()
    1074             : {
    1075             :   // Apply tail cancellation filter to all data.
    1076             : 
    1077     1185600 :   for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    1078    24710400 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
    1079    11793600 :       fADCF[iAdc][iTimeBin] = FilterTailNextSample(iAdc, fADCF[iAdc][iTimeBin]);
    1080             :     }
    1081             :   }
    1082       20800 : }
    1083             : 
    1084             : void AliTRDmcmSim::ZSMapping()
    1085             : {
    1086             :   //
    1087             :   // Zero Suppression Mapping implemented in TRAP chip
    1088             :   // only implemented for up to 30 timebins
    1089             :   //
    1090             :   // See detail TRAP manual "Data Indication" section:
    1091             :   // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
    1092             :   //
    1093             : 
    1094       83200 :   if( !CheckInitialized() )
    1095             :     return;
    1096             : 
    1097       41600 :   Int_t eBIS = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIS, fDetector, fRobPos, fMcmPos);
    1098       41600 :   Int_t eBIT = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIT, fDetector, fRobPos, fMcmPos);
    1099       41600 :   Int_t eBIL = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIL, fDetector, fRobPos, fMcmPos);
    1100       41600 :   Int_t eBIN = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIN, fDetector, fRobPos, fMcmPos);
    1101             : 
    1102       41600 :   Int_t **adc = fADCF;
    1103             : 
    1104     1830400 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++)
    1105      873600 :     fZSMap[iAdc] = -1;
    1106             : 
    1107     2329600 :   for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
    1108             :     Int_t iAdc; // current ADC channel
    1109             :     Int_t ap;
    1110             :     Int_t ac;
    1111             :     Int_t an;
    1112             :     Int_t mask;
    1113             :     Int_t supp; // suppression of the current channel (low active)
    1114             : 
    1115             :     // ----- first channel -----
    1116             :     iAdc = 0;
    1117             : 
    1118             :     ap = 0 >> fgkAddDigits;               // previous
    1119     1123200 :     ac = adc[iAdc  ][it] >> fgkAddDigits; // current
    1120     1123200 :     an = adc[iAdc+1][it] >> fgkAddDigits; // next
    1121             : 
    1122     3369600 :     mask  = ( ac >=  ap && ac >=  an ) ? 0 : 0x1; // peak center detection
    1123     1123200 :     mask += ( ap + ac + an > eBIT )    ? 0 : 0x2; // cluster
    1124     1123200 :     mask += ( ac > eBIS )              ? 0 : 0x4; // absolute large peak
    1125             : 
    1126     1123200 :     supp = (eBIL >> mask) & 1;
    1127             : 
    1128     1123200 :     fZSMap[iAdc] &= ~((1-supp) << it);
    1129     1123200 :     if( eBIN == 0 ) {  // neighbour sensitivity
    1130     1123200 :       fZSMap[iAdc+1] &= ~((1-supp) << it);
    1131     1123200 :     }
    1132             : 
    1133             :     // ----- last channel -----
    1134     1123200 :     iAdc = AliTRDfeeParam::GetNadcMcm() - 1;
    1135             : 
    1136     1123200 :     ap = adc[iAdc-1][it] >> fgkAddDigits; // previous
    1137     1123200 :     ac = adc[iAdc  ][it] >> fgkAddDigits; // current
    1138             :     an = 0 >> fgkAddDigits;               // next
    1139             : 
    1140     3196681 :     mask  = ( ac >=  ap && ac >=  an ) ? 0 : 0x1; // peak center detection
    1141     1123200 :     mask += ( ap + ac + an > eBIT )    ? 0 : 0x2; // cluster
    1142     1123200 :     mask += ( ac > eBIS )              ? 0 : 0x4; // absolute large peak
    1143             : 
    1144     1123200 :     supp = (eBIL >> mask) & 1;
    1145             : 
    1146     1123200 :     fZSMap[iAdc] &= ~((1-supp) << it);
    1147     1123200 :     if( eBIN == 0 ) {  // neighbour sensitivity
    1148     1123200 :       fZSMap[iAdc-1] &= ~((1-supp) << it);
    1149     1123200 :     }
    1150             : 
    1151             :     // ----- middle channels -----
    1152    44928000 :     for( iAdc = 1 ; iAdc < AliTRDfeeParam::GetNadcMcm()-1; iAdc++ ) {
    1153    21340800 :       ap = adc[iAdc-1][it] >> fgkAddDigits; // previous
    1154    21340800 :       ac = adc[iAdc  ][it] >> fgkAddDigits; // current
    1155    21340800 :       an = adc[iAdc+1][it] >> fgkAddDigits; // next
    1156             : 
    1157    59825230 :       mask  = ( ac >=  ap && ac >=  an ) ? 0 : 0x1; // peak center detection
    1158    21340800 :       mask += ( ap + ac + an > eBIT )    ? 0 : 0x2; // cluster
    1159    21340800 :       mask += ( ac > eBIS )              ? 0 : 0x4; // absolute large peak
    1160             : 
    1161    21340800 :       supp = (eBIL >> mask) & 1;
    1162             : 
    1163    21340800 :       fZSMap[iAdc] &= ~((1-supp) << it);
    1164    21340800 :       if( eBIN == 0 ) {  // neighbour sensitivity
    1165    21340800 :         fZSMap[iAdc-1] &= ~((1-supp) << it);
    1166    21340800 :         fZSMap[iAdc+1] &= ~((1-supp) << it);
    1167    21340800 :       }
    1168             :     }
    1169             : 
    1170             :   }
    1171       83200 : }
    1172             : 
    1173             : void AliTRDmcmSim::AddHitToFitreg(Int_t adc, UShort_t timebin, UShort_t qtot, Short_t ypos, Int_t label[])
    1174             : {
    1175             :   // Add the given hit to the fit register which is lateron used for
    1176             :   // the tracklet calculation.
    1177             :   // In addition to the fit sums in the fit register MC information
    1178             :   // is stored.
    1179             : 
    1180       47790 :   if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0, fDetector, fRobPos, fMcmPos)) &&
    1181       15930 :       (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0, fDetector, fRobPos, fMcmPos)))
    1182        4767 :     fFitReg[adc].fQ0 += qtot;
    1183             : 
    1184       26084 :   if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1, fDetector, fRobPos, fMcmPos)) &&
    1185       10154 :       (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1, fDetector, fRobPos, fMcmPos)))
    1186       10154 :     fFitReg[adc].fQ1 += qtot;
    1187             : 
    1188       31860 :   if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS, fDetector, fRobPos, fMcmPos) ) &&
    1189       15930 :       (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE, fDetector, fRobPos, fMcmPos)))
    1190             :   {
    1191       15930 :     fFitReg[adc].fSumX  += timebin;
    1192       15930 :     fFitReg[adc].fSumX2 += timebin*timebin;
    1193       15930 :     fFitReg[adc].fNhits++;
    1194       15930 :     fFitReg[adc].fSumY  += ypos;
    1195       15930 :     fFitReg[adc].fSumY2 += ypos*ypos;
    1196       15930 :     fFitReg[adc].fSumXY += timebin*ypos;
    1197       47790 :     AliDebug(10, Form("fitreg[%2i] in timebin %2i: X=%i, X2=%i, N=%i, Y=%i, Y2=%i, XY=%i, Q0=%i, Q1=%i",
    1198             :                       adc, timebin, fFitReg[adc].fSumX, fFitReg[adc].fSumX2, fFitReg[adc].fNhits,
    1199             :                       fFitReg[adc].fSumY, fFitReg[adc].fSumY2, fFitReg[adc].fSumXY, fFitReg[adc].fQ0, fFitReg[adc].fQ1));
    1200             :   }
    1201             : 
    1202             :   // register hits (MC info)
    1203       15930 :   fHits[fNHits].fChannel = adc;
    1204       15930 :   fHits[fNHits].fQtot = qtot;
    1205       15930 :   fHits[fNHits].fYpos = ypos;
    1206       15930 :   fHits[fNHits].fTimebin = timebin;
    1207       15930 :   fHits[fNHits].fLabel[0] = label[0];
    1208       15930 :   fHits[fNHits].fLabel[1] = label[1];
    1209       15930 :   fHits[fNHits].fLabel[2] = label[2];
    1210       15930 :   fNHits++;
    1211       15930 : }
    1212             : 
    1213             : void AliTRDmcmSim::CalcFitreg()
    1214             : {
    1215             :   // Preprocessing.
    1216             :   // Detect the hits and fill the fit registers.
    1217             :   // Requires 12-bit data from fADCF which means Filter()
    1218             :   // has to be called before even if all filters are bypassed.
    1219             : 
    1220             :   //??? to be clarified:
    1221             :   UInt_t adcMask = 0xffffffff;
    1222             : 
    1223             :   Bool_t hitQual;
    1224       83200 :   Int_t adcLeft, adcCentral, adcRight;
    1225       41600 :   UShort_t timebin, adcch, timebin1, timebin2, qtotTemp;
    1226             :   Short_t ypos, fromLeft, fromRight, found;
    1227       41600 :   UShort_t qTotal[19+1]; // the last is dummy
    1228       41600 :   UShort_t marked[6], qMarked[6], worse1, worse2;
    1229             : 
    1230       41600 :   if (fgStoreClusters) {
    1231             :     timebin1 = 0;
    1232           0 :     timebin2 = fNTimeBin;
    1233           0 :   }
    1234             :   else {
    1235             :     // find first timebin to be looked at
    1236       41600 :     timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS, fDetector, fRobPos, fMcmPos);
    1237       83200 :     if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0, fDetector, fRobPos, fMcmPos)
    1238       41600 :         < timebin1)
    1239           0 :       timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0, fDetector, fRobPos, fMcmPos);
    1240       83200 :     if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1, fDetector, fRobPos, fMcmPos)
    1241       41600 :         < timebin1)
    1242           0 :       timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1, fDetector, fRobPos, fMcmPos);
    1243             : 
    1244             :     // find last timebin to be looked at
    1245       41600 :     timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE, fDetector, fRobPos, fMcmPos);
    1246       83200 :     if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0, fDetector, fRobPos, fMcmPos)
    1247       41600 :         > timebin2)
    1248           0 :       timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0, fDetector, fRobPos, fMcmPos);
    1249       83200 :     if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1, fDetector, fRobPos, fMcmPos)
    1250       41600 :         > timebin2)
    1251           0 :       timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1, fDetector, fRobPos, fMcmPos);
    1252             :   }
    1253             : 
    1254             :   // reset the fit registers
    1255       41600 :   fNHits = 0;
    1256     1664000 :   for (adcch = 0; adcch < AliTRDfeeParam::GetNadcMcm()-2; adcch++) // due to border channels
    1257             :   {
    1258      790400 :     fFitReg[adcch].fNhits = 0;
    1259      790400 :     fFitReg[adcch].fQ0    = 0;
    1260      790400 :     fFitReg[adcch].fQ1    = 0;
    1261      790400 :     fFitReg[adcch].fSumX  = 0;
    1262      790400 :     fFitReg[adcch].fSumY  = 0;
    1263      790400 :     fFitReg[adcch].fSumX2 = 0;
    1264      790400 :     fFitReg[adcch].fSumY2 = 0;
    1265      790400 :     fFitReg[adcch].fSumXY = 0;
    1266             :   }
    1267             : 
    1268     1331200 :   for (timebin = timebin1; timebin < timebin2; timebin++)
    1269             :   {
    1270             :     // first find the hit candidates and store the total cluster charge in qTotal array
    1271             :     // in case of not hit store 0 there.
    1272    24960000 :     for (adcch = 0; adcch < AliTRDfeeParam::GetNadcMcm()-2; adcch++) {
    1273    11856000 :       if ( ( (adcMask >> adcch) & 7) == 7) //??? all 3 channels are present in case of ZS
    1274             :       {
    1275    11856000 :         adcLeft  = fADCF[adcch  ][timebin];
    1276    11856000 :         adcCentral  = fADCF[adcch+1][timebin];
    1277    11856000 :         adcRight = fADCF[adcch+2][timebin];
    1278             : 
    1279    11856000 :         if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVBY, fDetector, fRobPos, fMcmPos) == 0) {
    1280             :           // bypass the cluster verification
    1281             :           hitQual = kTRUE;
    1282    11856000 :         }
    1283             :         else {
    1284           0 :           hitQual = ( (adcLeft * adcRight) <
    1285           0 :                       ((fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVT, fDetector, fRobPos, fMcmPos) * adcCentral*adcCentral) >> 10) );
    1286           0 :           if (hitQual)
    1287           0 :             AliDebug(5, Form("cluster quality cut passed with %3i, %3i, %3i - threshold %3i -> %i",
    1288             :                              adcLeft, adcCentral, adcRight,
    1289             :                              fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVT, fDetector, fRobPos, fMcmPos),
    1290             :                              fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVT, fDetector, fRobPos, fMcmPos) * adcCentral*adcCentral));
    1291             :         }
    1292             : 
    1293             :         // The accumulated charge is with the pedestal!!!
    1294    11856000 :         qtotTemp = adcLeft + adcCentral + adcRight;
    1295    11856000 :         if ((fDebugStream) && (qtotTemp > 130)) {
    1296           0 :           (*fDebugStream) << "testtree"
    1297           0 :                           << "qtot=" << qtotTemp
    1298           0 :                           << "qleft=" << adcLeft
    1299           0 :                           << "qcent=" << adcCentral
    1300           0 :                           << "qright=" << adcRight
    1301           0 :                           << "\n";
    1302           0 :         }
    1303    11895885 :         if ( (hitQual) &&
    1304    11856000 :              (qtotTemp >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT, fDetector, fRobPos, fMcmPos)) &&
    1305       69772 :              (adcLeft <= adcCentral) &&
    1306       39885 :              (adcCentral > adcRight) )
    1307       16020 :           qTotal[adcch] = qtotTemp;
    1308             :         else
    1309    11839980 :           qTotal[adcch] = 0;
    1310             :       }
    1311             :       else
    1312           0 :         qTotal[adcch] = 0; //jkl
    1313    11856000 :       if (qTotal[adcch] != 0)
    1314       48060 :         AliDebug(10,Form("ch %2d   qTotal %5d",adcch, qTotal[adcch]));
    1315             :     }
    1316             : 
    1317             :     fromLeft = -1;
    1318             :     adcch = 0;
    1319             :     found = 0;
    1320      624000 :     marked[4] = 19; // invalid channel
    1321      624000 :     marked[5] = 19; // invalid channel
    1322      624000 :     qTotal[19] = 0;
    1323    31190914 :     while ((adcch < 16) && (found < 3))
    1324             :     {
    1325     9980756 :       if (qTotal[adcch] > 0)
    1326             :       {
    1327             :         fromLeft = adcch;
    1328       13374 :         marked[2*found+1]=adcch;
    1329       13374 :         found++;
    1330       13374 :       }
    1331     9980756 :       adcch++;
    1332             :     }
    1333             : 
    1334             :     fromRight = -1;
    1335             :     adcch = 18;
    1336             :     found = 0;
    1337    31193512 :     while ((adcch > 2) && (found < 3))
    1338             :     {
    1339     9981644 :       if (qTotal[adcch] > 0)
    1340             :       {
    1341       13437 :         marked[2*found]=adcch;
    1342       13437 :         found++;
    1343             :         fromRight = adcch;
    1344       13437 :       }
    1345     9981644 :       adcch--;
    1346             :     }
    1347             : 
    1348     1872000 :     AliDebug(10,Form("Fromleft=%d, Fromright=%d",fromLeft, fromRight));
    1349             :     // here mask the hit candidates in the middle, if any
    1350      643477 :     if ((fromLeft >= 0) && (fromRight >= 0) && (fromLeft < fromRight))
    1351        1960 :       for (adcch = fromLeft+1; adcch < fromRight; adcch++)
    1352         910 :         qTotal[adcch] = 0;
    1353             : 
    1354             :     found = 0;
    1355    24960000 :     for (adcch = 0; adcch < 19; adcch++)
    1356    11872020 :       if (qTotal[adcch] > 0) found++;
    1357             :     // NOT READY
    1358             : 
    1359      624000 :     if (found > 4) // sorting like in the TRAP in case of 5 or 6 candidates!
    1360             :     {
    1361         150 :       if (marked[4] == marked[5]) marked[5] = 19;
    1362        1120 :       for (found=0; found<6; found++)
    1363             :       {
    1364         480 :         qMarked[found] = qTotal[marked[found]] >> 4;
    1365        1440 :         AliDebug(10,Form("ch_%d qTotal %d qTotals %d",marked[found],qTotal[marked[found]],qMarked[found]));
    1366             :       }
    1367             : 
    1368         160 :       Sort6To2Worst(marked[0], marked[3], marked[4], marked[1], marked[2], marked[5],
    1369          80 :                     qMarked[0],
    1370          80 :                     qMarked[3],
    1371          80 :                     qMarked[4],
    1372          80 :                     qMarked[1],
    1373          80 :                     qMarked[2],
    1374          80 :                     qMarked[5],
    1375             :                     &worse1, &worse2);
    1376             :       // Now mask the two channels with the smallest charge
    1377          80 :       if (worse1 < 19)
    1378             :       {
    1379          10 :         qTotal[worse1] = 0;
    1380          30 :         AliDebug(10,Form("Kill ch %d\n",worse1));
    1381             :       }
    1382          80 :       if (worse2 < 19)
    1383             :       {
    1384          80 :         qTotal[worse2] = 0;
    1385         240 :         AliDebug(10,Form("Kill ch %d\n",worse2));
    1386             :       }
    1387             :     }
    1388             : 
    1389    24960000 :     for (adcch = 0; adcch < 19; adcch++) {
    1390    11856000 :       if (qTotal[adcch] > 0) // the channel is marked for processing
    1391             :       {
    1392       15930 :         adcLeft  = fADCF[adcch  ][timebin];
    1393       15930 :         adcCentral  = fADCF[adcch+1][timebin];
    1394       15930 :         adcRight = fADCF[adcch+2][timebin];
    1395             :         // hit detected, in TRAP we have 4 units and a hit-selection, here we proceed all channels!
    1396             :         // subtract the pedestal TPFP, clipping instead of wrapping
    1397             : 
    1398       15930 :         Int_t regTPFP = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP, fDetector, fRobPos, fMcmPos);
    1399       47790 :         AliDebug(10, Form("Hit found, time=%d, adcch=%d/%d/%d, adc values=%d/%d/%d, regTPFP=%d, TPHT=%d\n",
    1400             :                timebin, adcch, adcch+1, adcch+2, adcLeft, adcCentral, adcRight, regTPFP,
    1401             :                fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT, fDetector, fRobPos, fMcmPos)));
    1402             : 
    1403       31860 :         if (adcLeft  < regTPFP) adcLeft  = 0; else adcLeft  -= regTPFP;
    1404       31860 :         if (adcCentral  < regTPFP) adcCentral  = 0; else adcCentral  -= regTPFP;
    1405       31860 :         if (adcRight < regTPFP) adcRight = 0; else adcRight -= regTPFP;
    1406             : 
    1407             :         // Calculate the center of gravity
    1408             :         // checking for adcCentral != 0 (in case of "bad" configuration)
    1409       15930 :         if (adcCentral == 0)
    1410           0 :           continue;
    1411       15930 :         ypos = 128*(adcRight - adcLeft) / adcCentral;
    1412       24092 :         if (ypos < 0) ypos = -ypos;
    1413             :         // make the correction using the position LUT
    1414       31860 :         ypos = ypos + fTrapConfig->GetTrapReg((AliTRDtrapConfig::TrapReg_t) (AliTRDtrapConfig::kTPL00 + (ypos & 0x7F)),
    1415       15930 :                                               fDetector, fRobPos, fMcmPos);
    1416       24100 :         if (adcLeft > adcRight) ypos = -ypos;
    1417             : 
    1418             :         // label calculation (up to 3)
    1419       15930 :         Int_t mcLabel[] = {-1, -1, -1};
    1420       15930 :         if (fDigitsManager) {
    1421             :           const Int_t maxLabels = 9;
    1422        8308 :           Int_t label[maxLabels] = { 0 }; // up to 9 different labels possible
    1423        8308 :           Int_t count[maxLabels] = { 0 };
    1424             :           Int_t nLabels = 0;
    1425        8308 :           Int_t padcol[3];
    1426        8308 :           padcol[0] = fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, adcch);
    1427        8308 :           padcol[1] = fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, adcch+1);
    1428        8308 :           padcol[2] = fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, adcch+2);
    1429        8308 :           Int_t padrow = fFeeParam->GetPadRowFromMCM(fRobPos, fMcmPos);
    1430       66464 :           for (Int_t iDict = 0; iDict < 3; iDict++) {
    1431       24924 :             if (!fDict[iDict])
    1432             :               continue;
    1433      199392 :             for (Int_t iPad = 0; iPad < 3; iPad++) {
    1434       74772 :               if (padcol[iPad] < 0)
    1435             :                 continue;
    1436       74724 :               Int_t currLabel = fDict[iDict]->GetData(padrow, padcol[iPad], timebin);
    1437      224172 :               AliDebug(10, Form("Read label: %4i for det: %3i, row: %i, col: %i, tb: %i\n", currLabel, fDetector, padrow, padcol[iPad], timebin));
    1438      310288 :               for (Int_t iLabel = 0; iLabel < nLabels; iLabel++) {
    1439       70439 :                 if (currLabel == label[iLabel]) {
    1440       18254 :                   count[iLabel]++;
    1441             :                   currLabel = -1;
    1442       18254 :                   break;
    1443             :                 }
    1444             :               }
    1445       74724 :               if (currLabel >= 0) {
    1446        9897 :                 label[nLabels] = currLabel;
    1447        9897 :                 count[nLabels] = 1;
    1448        9897 :                 nLabels++;
    1449        9897 :               }
    1450       74724 :             }
    1451       24924 :           }
    1452        8308 :           Int_t index[2*maxLabels];
    1453        8308 :           TMath::Sort(maxLabels, count, index);
    1454       36445 :           for (Int_t i = 0; i < 3; i++) {
    1455       17651 :             if (count[index[i]] <= 0)
    1456        7927 :               break;
    1457        9724 :             mcLabel[i] = label[index[i]];
    1458             :           }
    1459        8308 :         }
    1460             : 
    1461             :         // add the hit to the fitregister
    1462       15930 :         AddHitToFitreg(adcch, timebin, qTotal[adcch] >> fgkAddDigits, ypos, mcLabel);
    1463       15930 :       }
    1464             :     }
    1465             :   }
    1466             : 
    1467     1830400 :   for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
    1468      873600 :     if (fFitReg[iAdc].fNhits != 0) {
    1469      165510 :       AliDebug(2, Form("fitreg[%i]: nHits = %i, sumX = %i, sumY = %i, sumX2 = %i, sumY2 = %i, sumXY = %i", iAdc,
    1470             :                        fFitReg[iAdc].fNhits,
    1471             :                        fFitReg[iAdc].fSumX,
    1472             :                        fFitReg[iAdc].fSumY,
    1473             :                        fFitReg[iAdc].fSumX2,
    1474             :                        fFitReg[iAdc].fSumY2,
    1475             :                        fFitReg[iAdc].fSumXY
    1476             :                  ));
    1477             :     }
    1478             :   }
    1479       41600 : }
    1480             : 
    1481             : void AliTRDmcmSim::TrackletSelection()
    1482             : {
    1483             :   // Select up to 4 tracklet candidates from the fit registers
    1484             :   // and assign them to the CPUs.
    1485             : 
    1486             :   UShort_t adcIdx, i, j, ntracks, tmp;
    1487        3096 :   UShort_t trackletCand[18][2]; // store the adcch[0] and number of hits[1] for all tracklet candidates
    1488             : 
    1489             :   ntracks = 0;
    1490       58824 :   for (adcIdx = 0; adcIdx < 18; adcIdx++) // ADCs
    1491       30957 :     if ( (fFitReg[adcIdx].fNhits
    1492       27864 :           >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCL, fDetector, fRobPos, fMcmPos)) &&
    1493        3093 :          (fFitReg[adcIdx].fNhits+fFitReg[adcIdx+1].fNhits
    1494        3093 :           >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCT, fDetector, fRobPos, fMcmPos)))
    1495             :     {
    1496        1044 :       trackletCand[ntracks][0] = adcIdx;
    1497        1044 :       trackletCand[ntracks][1] = fFitReg[adcIdx].fNhits+fFitReg[adcIdx+1].fNhits;
    1498        3132 :       AliDebug(10,Form("%d  %2d %4d\n", ntracks, trackletCand[ntracks][0], trackletCand[ntracks][1]));
    1499        1044 :       ntracks++;
    1500        1044 :     };
    1501             : 
    1502        5184 :   for (i=0; i<ntracks;i++)
    1503        3132 :     AliDebug(10,Form("%d %d %d\n",i,trackletCand[i][0], trackletCand[i][1]));
    1504             : 
    1505        1548 :   if (ntracks > 4)
    1506             :   {
    1507             :     // primitive sorting according to the number of hits
    1508          40 :     for (j = 0; j < (ntracks-1); j++)
    1509             :     {
    1510         112 :       for (i = j+1; i < ntracks; i++)
    1511             :       {
    1512          50 :         if ( (trackletCand[j][1]  < trackletCand[i][1]) ||
    1513          36 :              ( (trackletCand[j][1] == trackletCand[i][1]) && (trackletCand[j][0] < trackletCand[i][0]) ) )
    1514             :         {
    1515             :           // swap j & i
    1516          24 :           tmp = trackletCand[j][1];
    1517          24 :           trackletCand[j][1] = trackletCand[i][1];
    1518          24 :           trackletCand[i][1] = tmp;
    1519          24 :           tmp = trackletCand[j][0];
    1520          24 :           trackletCand[j][0] = trackletCand[i][0];
    1521          24 :           trackletCand[i][0] = tmp;
    1522          24 :         }
    1523             :       }
    1524             :     }
    1525             :     ntracks = 4; // cut the rest, 4 is the max
    1526           4 :   }
    1527             :   // else is not necessary to sort
    1528             : 
    1529             :   // now sort, so that the first tracklet going to CPU0 corresponds to the highest adc channel - as in the TRAP
    1530        3816 :   for (j = 0; j < (ntracks-1); j++)
    1531             :   {
    1532        1668 :     for (i = j+1; i < ntracks; i++)
    1533             :     {
    1534         474 :       if (trackletCand[j][0] < trackletCand[i][0])
    1535             :       {
    1536             :         // swap j & i
    1537         460 :         tmp = trackletCand[j][1];
    1538         460 :         trackletCand[j][1] = trackletCand[i][1];
    1539         460 :         trackletCand[i][1] = tmp;
    1540         460 :         tmp = trackletCand[j][0];
    1541         460 :         trackletCand[j][0] = trackletCand[i][0];
    1542         460 :         trackletCand[i][0] = tmp;
    1543         460 :       }
    1544             :     }
    1545             :   }
    1546        5176 :   for (i = 0; i < ntracks; i++)  // CPUs with tracklets.
    1547        1040 :     fFitPtr[i] = trackletCand[i][0]; // pointer to the left channel with tracklet for CPU[i]
    1548       13400 :   for (i = ntracks; i < 4; i++)  // CPUs without tracklets
    1549        5152 :     fFitPtr[i] = 31;            // pointer to the left channel with tracklet for CPU[i] = 31 (invalid)
    1550        4644 :   AliDebug(10,Form("found %i tracklet candidates\n", ntracks));
    1551       15480 :   for (i = 0; i < 4; i++)
    1552       18576 :     AliDebug(10,Form("fitPtr[%i]: %i\n", i, fFitPtr[i]));
    1553             : 
    1554             :   // reject multiple tracklets
    1555        1548 :   if (AliTRDfeeParam::Instance()->GetRejectMultipleTracklets())
    1556             :     {
    1557             :       UShort_t counts = 0;
    1558           0 :       for(j = 0; j < (ntracks -1); j++)
    1559             :         {
    1560           0 :           if(fFitPtr[j] == 31)
    1561             :             continue;
    1562             : 
    1563           0 :           for(i = j+1; i < ntracks; i++)
    1564             :             {
    1565             :               // check if tracklets are from neighbouring ADC channels
    1566           0 :               if(TMath::Abs(fFitPtr[j] - fFitPtr[i]) > 1.)
    1567             :                 continue;
    1568             : 
    1569             :               // check which tracklet candidate has higher amount of hits
    1570           0 :               if((fFitReg[fFitPtr[j]].fNhits + fFitReg[fFitPtr[j]+1].fNhits) >=
    1571           0 :                  (fFitReg[fFitPtr[i]].fNhits + fFitReg[fFitPtr[i]+1].fNhits))
    1572             :                 {
    1573           0 :                   fFitPtr[i] = 31;
    1574           0 :                   counts++;
    1575             :                 }
    1576             :               else
    1577             :                 {
    1578           0 :                   fFitPtr[j] = 31;
    1579           0 :                   counts++;
    1580           0 :                   break;
    1581             :                 }
    1582           0 :             }
    1583             :         }
    1584           0 :       ntracks = ntracks - counts;
    1585             : 
    1586           0 :       AliDebug(10,Form("found %i tracklet candidates\n", ntracks));
    1587           0 :       for (i = 0; i < 4; i++)
    1588           0 :         AliDebug(10,Form("fitPtr[%i]: %i\n", i, fFitPtr[i]));
    1589           0 :     }
    1590        1548 : }
    1591             : 
    1592             : void AliTRDmcmSim::FitTracklet()
    1593             : {
    1594             :   // Perform the actual tracklet fit based on the fit sums
    1595             :   // which have been filled in the fit registers.
    1596             : 
    1597             :   // parameters in fitred.asm (fit program)
    1598             :   Int_t rndAdd = 0;
    1599             :   Int_t decPlaces = 5; // must be larger than 1 or change the following code
    1600             :   // if (decPlaces >  1)
    1601             :     rndAdd = (1 << (decPlaces-1)) + 1;
    1602             :   // else if (decPlaces == 1)
    1603             :   //   rndAdd = 1;
    1604             : 
    1605             :   Int_t ndriftDp = 5;  // decimal places for drift time
    1606             :   Long64_t shift = ((Long64_t) 1 << 32);
    1607             : 
    1608             :   // calculated in fitred.asm
    1609        3096 :   Int_t padrow = ((fRobPos >> 1) << 2) | (fMcmPos >> 2);
    1610        1548 :   Int_t yoffs = (((((fRobPos & 0x1) << 2) + (fMcmPos & 0x3)) * 18) << 8) -
    1611             :     ((18*4*2 - 18*2 - 1) << 7);
    1612             : 
    1613             :   // add corrections for mis-alignment
    1614        1548 :   if (AliTRDfeeParam::Instance()->GetUseMisalignCorr())
    1615             :     {
    1616           0 :       AliDebug(5,Form("using mis-alignment correction"));
    1617           0 :       yoffs += (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrYcorr, fDetector, fRobPos, fMcmPos);
    1618           0 :     }
    1619             : 
    1620        1548 :   yoffs = yoffs << decPlaces; // holds position of ADC channel 1
    1621        1548 :   Int_t layer = fDetector % 6;
    1622        1548 :   UInt_t scaleY = (UInt_t) ((0.635 + 0.03 * layer)/(256.0 * 160.0e-4) * shift);
    1623        1548 :   UInt_t scaleD = (UInt_t) ((0.635 + 0.03 * layer)/(256.0 * 140.0e-4) * shift);
    1624             : 
    1625        1548 :   Int_t deflCorr = (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrDeflCorr, fDetector, fRobPos, fMcmPos);
    1626        1548 :   Int_t ndrift   = (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrNdrift, fDetector, fRobPos, fMcmPos);
    1627             : 
    1628             :   // local variables for calculation
    1629             :   Long64_t mult, temp, denom; //???
    1630             :   UInt_t q0, q1, pid;             // charges in the two windows and total charge
    1631             :   UShort_t nHits;                 // number of hits
    1632             :   Int_t slope, offset;            // slope and offset of the tracklet
    1633             :   Int_t sumX, sumY, sumXY, sumX2; // fit sums from fit registers
    1634             :   Int_t sumY2;                // not used in the current TRAP program, now used for error calculation (simulation only)
    1635             :   Float_t fitError, fitSlope, fitOffset;
    1636             :   FitReg_t *fit0, *fit1;          // pointers to relevant fit registers
    1637             : 
    1638             : //  const uint32_t OneDivN[32] = {  // 2**31/N : exactly like in the TRAP, the simple division here gives the same result!
    1639             : //      0x00000000, 0x80000000, 0x40000000, 0x2AAAAAA0, 0x20000000, 0x19999990, 0x15555550, 0x12492490,
    1640             : //      0x10000000, 0x0E38E380, 0x0CCCCCC0, 0x0BA2E8B0, 0x0AAAAAA0, 0x09D89D80, 0x09249240, 0x08888880,
    1641             : //      0x08000000, 0x07878780, 0x071C71C0, 0x06BCA1A0, 0x06666660, 0x06186180, 0x05D17450, 0x0590B210,
    1642             : //      0x05555550, 0x051EB850, 0x04EC4EC0, 0x04BDA120, 0x04924920, 0x0469EE50, 0x04444440, 0x04210840};
    1643             : 
    1644       15480 :   for (Int_t cpu = 0; cpu < 4; cpu++) {
    1645        6192 :     if (fFitPtr[cpu] == 31)
    1646             :     {
    1647        5152 :       fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker();
    1648        5152 :     }
    1649             :     else
    1650             :     {
    1651        1040 :       fit0 = &fFitReg[fFitPtr[cpu]  ];
    1652        1040 :       fit1 = &fFitReg[fFitPtr[cpu]+1]; // next channel
    1653             : 
    1654             :       mult = 1;
    1655             :       mult = mult << (32 + decPlaces);
    1656             :       mult = -mult;
    1657             : 
    1658             :       // time offset for fit sums
    1659        2080 :       const Int_t t0 = AliTRDfeeParam::Instance()->GetUseTimeOffset() ?
    1660           0 :         (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrTimeOffset, fDetector, fRobPos, fMcmPos) : 0;
    1661             : 
    1662        3120 :       AliDebug(5,Form("using time offset t0 = %i",t0));
    1663             : 
    1664             :       // Merging
    1665        1040 :       nHits   = fit0->fNhits + fit1->fNhits; // number of hits
    1666        1040 :       sumX    = fit0->fSumX  + fit1->fSumX;
    1667        1040 :       sumX2   = fit0->fSumX2 + fit1->fSumX2;
    1668        1040 :       denom   = ((Long64_t) nHits)*((Long64_t) sumX2) - ((Long64_t) sumX)*((Long64_t) sumX);
    1669             : 
    1670        1040 :       mult    = mult / denom; // exactly like in the TRAP program
    1671        1040 :       q0      = fit0->fQ0    + fit1->fQ0;
    1672        1040 :       q1      = fit0->fQ1    + fit1->fQ1;
    1673        1040 :       sumY    = fit0->fSumY  + fit1->fSumY  + 256*fit1->fNhits;
    1674        1040 :       sumXY   = fit0->fSumXY + fit1->fSumXY + 256*fit1->fSumX;
    1675        1040 :       sumY2   = fit0->fSumY2 + fit1->fSumY2 + 512*fit1->fSumY + 256*256*fit1->fNhits;
    1676             : 
    1677        1040 :       slope   = nHits*sumXY - sumX*sumY;
    1678             :       //offset  = sumX2*sumY  - sumX*sumXY - t0 * sumX*sumY + t0 * nHits*sumXY;
    1679        1040 :       offset  = sumX2*sumY - sumX*sumXY;
    1680        1040 :       offset  = offset << 5;
    1681        1040 :       offset += t0 * nHits*sumXY - t0 * sumX*sumY;
    1682        1040 :       offset  = offset >> 5;
    1683             : 
    1684        1040 :       temp    = mult * slope;
    1685        1040 :       slope   = temp >> 32; // take the upper 32 bits
    1686        1040 :       slope   = -slope;
    1687        1040 :       temp    = mult * offset;
    1688        1040 :       offset  = temp >> 32; // take the upper 32 bits
    1689             : 
    1690        1040 :       offset = offset + yoffs;
    1691        3120 :       AliDebug(10, Form("slope = %i, slope * ndrift = %i, deflCorr: %i",
    1692             :                        slope, slope * ndrift, deflCorr));
    1693        1040 :       slope  = ((slope * ndrift) >> ndriftDp) + deflCorr;
    1694        1040 :       offset = offset - (fFitPtr[cpu] << (8 + decPlaces));
    1695             : 
    1696        1040 :       temp    = slope;
    1697        1040 :       temp    = temp * scaleD;
    1698        1040 :       slope   = (temp >> 32);
    1699        1040 :       temp    = offset;
    1700        1040 :       temp    = temp * scaleY;
    1701        1040 :       offset  = (temp >> 32);
    1702             : 
    1703             :       // rounding, like in the TRAP
    1704        1040 :       slope   = (slope  + rndAdd) >> decPlaces;
    1705        1040 :       offset  = (offset + rndAdd) >> decPlaces;
    1706             : 
    1707        3120 :       AliDebug(5, Form("Det: %3i, ROB: %i, MCM: %2i: deflection: %i, min: %i, max: %i",
    1708             :                        fDetector, fRobPos, fMcmPos, slope,
    1709             :                        (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrDeflCutStart     + 2*fFitPtr[cpu], fDetector, fRobPos, fMcmPos),
    1710             :                        (Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrDeflCutStart + 1 + 2*fFitPtr[cpu], fDetector, fRobPos, fMcmPos)));
    1711             : 
    1712        3120 :       AliDebug(5, Form("Fit sums: x = %i, X = %i, y = %i, Y = %i, Z = %i, q0 = %i, q1 = %i",
    1713             :                        sumX, sumX2, sumY, sumY2, sumXY, q0, q1));
    1714             : 
    1715        1040 :       fitSlope  = (Float_t) (nHits * sumXY - sumX * sumY) / (nHits * sumX2 - sumX*sumX);
    1716             : 
    1717        1040 :       fitOffset = (Float_t) (sumX2 * sumY - sumX * sumXY) / (nHits * sumX2 - sumX*sumX);
    1718             : 
    1719        1040 :       Float_t sx  = (Float_t) sumX;
    1720        1040 :       Float_t sx2 = (Float_t) sumX2;
    1721        1040 :       Float_t sy  = (Float_t) sumY;
    1722        1040 :       Float_t sy2 = (Float_t) sumY2;
    1723        1040 :       Float_t sxy = (Float_t) sumXY;
    1724        1040 :       fitError = sy2 - (sx2 * sy*sy - 2 * sx * sxy * sy + nHits * sxy*sxy) / (nHits * sx2 - sx*sx);
    1725             :       //fitError = (Float_t) sumY2 - (Float_t) (sumY*sumY) / nHits - fitSlope * ((Float_t) (sumXY - sumX*sumY) / nHits);
    1726             : 
    1727             :       Bool_t rejected = kFALSE;
    1728             :       // deflection range table from DMEM
    1729        1849 :       if ((slope < ((Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrDeflCutStart     + 2*fFitPtr[cpu], fDetector, fRobPos, fMcmPos))) ||
    1730         809 :           (slope > ((Int_t) fTrapConfig->GetDmemUnsigned(fgkDmemAddrDeflCutStart + 1 + 2*fFitPtr[cpu], fDetector, fRobPos, fMcmPos))))
    1731         321 :         rejected = kTRUE;
    1732             : 
    1733        1361 :       if (rejected && GetApplyCut())
    1734             :       {
    1735         321 :         fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker();
    1736         321 :       }
    1737             :       else
    1738             :       {
    1739         719 :         if (slope > 63 || slope < -64) { // wrapping in TRAP!
    1740           0 :           AliDebug(1,Form("Overflow in slope: %i, tracklet discarded!", slope));
    1741           0 :           fMCMT[cpu] = 0x10001000;
    1742           0 :           continue;
    1743             :         }
    1744             : 
    1745         719 :         slope   = slope  &   0x7F; // 7 bit
    1746             : 
    1747         719 :         if (offset > 0xfff || offset < -0xfff)
    1748           0 :           AliWarning("Overflow in offset");
    1749         719 :         offset  = offset & 0x1FFF; // 13 bit
    1750             : 
    1751         719 :         pid = GetPID(q0, q1);
    1752             : 
    1753         719 :         if (pid > 0xff)
    1754           0 :           AliWarning("Overflow in PID");
    1755         719 :         pid  = pid & 0xFF; // 8 bit, exactly like in the TRAP program
    1756             : 
    1757             :         // assemble and store the tracklet word
    1758         719 :         fMCMT[cpu] = (pid << 24) | (padrow << 20) | (slope << 13) | offset;
    1759             : 
    1760             :         // calculate number of hits and MC label
    1761         719 :         Int_t mcLabel[] = { -1, -1, -1};
    1762             :         Int_t nHits0 = 0;
    1763             :         Int_t nHits1 = 0;
    1764             : 
    1765             :         const Int_t maxLabels = 30;
    1766         719 :         Int_t label[maxLabels] = {0}; // up to 30 different labels possible
    1767         719 :         Int_t count[maxLabels] = {0};
    1768             :         Int_t nLabels = 0;
    1769             : 
    1770       34856 :         for (Int_t iHit = 0; iHit < fNHits; iHit++) {
    1771       29817 :           if ((fHits[iHit].fChannel - fFitPtr[cpu] < 0) ||
    1772       13108 :               (fHits[iHit].fChannel - fFitPtr[cpu] > 1))
    1773             :             continue;
    1774             : 
    1775             :           // counting contributing hits
    1776       19740 :           if (fHits[iHit].fTimebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0, fDetector, fRobPos, fMcmPos) &&
    1777        9870 :               fHits[iHit].fTimebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0, fDetector, fRobPos, fMcmPos))
    1778        3104 :             nHits0++;
    1779       15943 :           if (fHits[iHit].fTimebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1, fDetector, fRobPos, fMcmPos) &&
    1780        6073 :               fHits[iHit].fTimebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1, fDetector, fRobPos, fMcmPos))
    1781        6073 :             nHits1++;
    1782             : 
    1783             :           // label calculation only if there is a digitsmanager to get the labels from
    1784        9870 :           if (fDigitsManager) {
    1785       39520 :             for (Int_t i = 0; i < 3; i++) {
    1786       14820 :               Int_t currLabel = fHits[iHit].fLabel[i];
    1787       60790 :               for (Int_t iLabel = 0; iLabel < nLabels; iLabel++) {
    1788       16688 :                 if (currLabel == label[iLabel]) {
    1789        5682 :                   count[iLabel]++;
    1790             :                   currLabel = -1;
    1791        5682 :                   break;
    1792             :                 }
    1793             :               }
    1794       14820 :               if (currLabel >= 0 && nLabels < maxLabels) {
    1795         475 :                 label[nLabels] = currLabel;
    1796         475 :                 count[nLabels]++;
    1797         475 :                 nLabels++;
    1798         475 :               }
    1799             :             }
    1800        4940 :           }
    1801             : 
    1802        9870 :           if (fDigitsManager) {
    1803        4940 :             Int_t index[2*maxLabels];
    1804        4940 :             TMath::Sort(maxLabels, count, index);
    1805       22386 :             for (Int_t i = 0; i < 3; i++) {
    1806       10920 :               if (count[index[i]] <= 0)
    1807        4758 :                 break;
    1808        6162 :               mcLabel[i] = label[index[i]];
    1809             :             }
    1810        4940 :           }
    1811             :         }
    1812         719 :         new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletMCM((UInt_t) fMCMT[cpu], fDetector*2 + fRobPos%2, fRobPos, fMcmPos);
    1813         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetLabel(mcLabel);
    1814             : 
    1815             : 
    1816         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetNHits(fit0->fNhits + fit1->fNhits);
    1817         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetNHits0(nHits0);
    1818         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetNHits1(nHits1);
    1819         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetQ0(q0);
    1820         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetQ1(q1);
    1821         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetSlope(fitSlope);
    1822         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetOffset(fitOffset);
    1823         719 :         ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetError(TMath::Sqrt(TMath::Abs(fitError)/nHits));
    1824             : 
    1825             :         // store cluster information (if requested)
    1826         719 :         if (fgStoreClusters) {
    1827           0 :           Float_t *res = new Float_t[fNTimeBin];
    1828           0 :           Float_t *qtot = new Float_t[fNTimeBin];
    1829           0 :           for (Int_t iTimebin = 0; iTimebin < fNTimeBin; ++iTimebin) {
    1830           0 :             res[iTimebin] = 0;
    1831           0 :             qtot[iTimebin] = 0;
    1832             :           }
    1833           0 :           for (Int_t iHit = 0; iHit < fNHits; iHit++) {
    1834           0 :             Int_t timebin = fHits[iHit].fTimebin;
    1835             : 
    1836             :             // check if hit contributes
    1837           0 :             if (fHits[iHit].fChannel == fFitPtr[cpu]) {
    1838           0 :               res[timebin] = fHits[iHit].fYpos - (fitSlope * timebin + fitOffset);
    1839           0 :               qtot[timebin] = fHits[iHit].fQtot;
    1840           0 :             }
    1841           0 :             else if (fHits[iHit].fChannel == fFitPtr[cpu] + 1) {
    1842           0 :               res[timebin] = fHits[iHit].fYpos + 256 - (fitSlope * timebin + fitOffset);
    1843           0 :               qtot[timebin] = fHits[iHit].fQtot;
    1844           0 :             }
    1845             :           }
    1846           0 :           ((AliTRDtrackletMCM*) (*fTrackletArray)[fTrackletArray->GetEntriesFast()-1])->SetClusters(res, qtot, fNTimeBin);
    1847           0 :           delete [] res;
    1848           0 :           delete [] qtot;
    1849           0 :         }
    1850             : 
    1851         719 :         if (fitError < 0)
    1852           0 :           AliError(Form("Strange fit error: %f from Sx: %i, Sy: %i, Sxy: %i, Sx2: %i, Sy2: %i, nHits: %i",
    1853             :                         fitError, sumX, sumY, sumXY, sumX2, sumY2, nHits));
    1854        2157 :         AliDebug(3, Form("fit slope: %f, offset: %f, error: %f",
    1855             :                          fitSlope, fitOffset, TMath::Sqrt(TMath::Abs(fitError)/nHits)));
    1856         719 :       }
    1857        1040 :     }
    1858             :   }
    1859        1548 : }
    1860             : 
    1861             : void AliTRDmcmSim::Tracklet()
    1862             : {
    1863             :   // Run the tracklet calculation by calling sequentially:
    1864             :   // CalcFitreg(); TrackletSelection(); FitTracklet()
    1865             :   // and store the tracklets
    1866             : 
    1867       83200 :   if (!fInitialized) {
    1868           0 :     AliError("Called uninitialized! Nothing done!");
    1869           0 :     return;
    1870             :   }
    1871             : 
    1872       41600 :   fTrackletArray->Delete();
    1873             : 
    1874       41600 :   CalcFitreg();
    1875       41600 :   if (fNHits == 0)
    1876             :     return;
    1877        1548 :   TrackletSelection();
    1878        1548 :   FitTracklet();
    1879       43148 : }
    1880             : 
    1881             : Bool_t AliTRDmcmSim::StoreTracklets()
    1882             : {
    1883             :   // store the found tracklets via the loader
    1884             : 
    1885       41600 :   if (fTrackletArray->GetEntriesFast() == 0)
    1886       20538 :     return kTRUE;
    1887             : 
    1888         262 :   AliRunLoader *rl = AliRunLoader::Instance();
    1889             :   AliDataLoader *dl = 0x0;
    1890         262 :   if (rl)
    1891         262 :     dl = rl->GetLoader("TRDLoader")->GetDataLoader("tracklets");
    1892         262 :   if (!dl) {
    1893           0 :     AliError("Could not get the tracklets data loader!");
    1894           0 :     return kFALSE;
    1895             :   }
    1896             : 
    1897         262 :   TTree *trackletTree = dl->Tree();
    1898         262 :   if (!trackletTree) {
    1899           4 :     dl->MakeTree();
    1900           4 :     trackletTree = dl->Tree();
    1901           4 :   }
    1902             : 
    1903         262 :   AliTRDtrackletMCM *trkl = 0x0;
    1904         262 :   TBranch *trkbranch = trackletTree->GetBranch(fTrklBranchName.Data());
    1905         262 :   if (!trkbranch)
    1906           4 :     trkbranch = trackletTree->Branch(fTrklBranchName.Data(), "AliTRDtrackletMCM", &trkl, 32000);
    1907             : 
    1908        1244 :   for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
    1909         360 :     trkl = ((AliTRDtrackletMCM*) (*fTrackletArray)[iTracklet]);
    1910         360 :     trkbranch->SetAddress(&trkl);
    1911         360 :     trkbranch->Fill();
    1912             :   }
    1913             : 
    1914             :   return kTRUE;
    1915       21062 : }
    1916             : 
    1917             : void AliTRDmcmSim::WriteData(AliTRDarrayADC *digits)
    1918             : {
    1919             :   // write back the processed data configured by EBSF
    1920             :   // EBSF = 1: unfiltered data; EBSF = 0: filtered data
    1921             :   // zero-suppressed valued are written as -1 to digits
    1922             : 
    1923       41600 :   if( !CheckInitialized() )
    1924             :     return;
    1925             : 
    1926       20800 :   Int_t offset = (fMcmPos % 4 + 1) * 21 + (fRobPos % 2) * 84 - 1;
    1927             : 
    1928       20800 :   if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBSF, fDetector, fRobPos, fMcmPos) != 0) // store unfiltered data
    1929             :   {
    1930      915200 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
    1931      436800 :       if (~fZSMap[iAdc] == 0) {
    1932    24248392 :         for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    1933    11691189 :           digits->SetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin, -1);
    1934             :         }
    1935      433007 :       }
    1936        3793 :       else if (iAdc < 2 || iAdc == 20) {
    1937       25312 :         for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    1938       12204 :           digits->SetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin, (fADCR[iAdc][iTimeBin] >> fgkAddDigits) - fgAddBaseline);
    1939             :         }
    1940         452 :       }
    1941             :     }
    1942       20800 :   }
    1943             :   else {
    1944           0 :     for (Int_t iAdc = 0; iAdc < AliTRDfeeParam::GetNadcMcm(); iAdc++) {
    1945           0 :       if (~fZSMap[iAdc] != 0) {
    1946           0 :         for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    1947           0 :           digits->SetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin, (fADCF[iAdc][iTimeBin] >> fgkAddDigits) - fgAddBaseline);
    1948             :         }
    1949           0 :       }
    1950             :       else {
    1951           0 :         for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    1952           0 :           digits->SetDataByAdcCol(GetRow(), offset - iAdc, iTimeBin, -1);
    1953             :         }
    1954             :       }
    1955             :     }
    1956             :   }
    1957       41600 : }
    1958             : 
    1959             : 
    1960             : // ******************************
    1961             : // PID section
    1962             : //
    1963             : // Memory area for the LUT: 0xC100 to 0xC3FF
    1964             : //
    1965             : // The addresses for the parameters (the order is optimized for maximum calculation speed in the MCMs):
    1966             : // 0xC028: cor1
    1967             : // 0xC029: nBins(sF)
    1968             : // 0xC02A: cor0
    1969             : // 0xC02B: TableLength
    1970             : // Defined in AliTRDtrapConfig.h
    1971             : //
    1972             : // The algorithm implemented in the TRAP program of the MCMs (Venelin Angelov)
    1973             : //  1) set the read pointer to the beginning of the Parameters in DMEM
    1974             : //  2) shift right the FitReg with the Q0 + (Q1 << 16) to get Q1
    1975             : //  3) read cor1 with rpointer++
    1976             : //  4) start cor1*Q1
    1977             : //  5) read nBins with rpointer++
    1978             : //  6) start nBins*cor1*Q1
    1979             : //  7) read cor0 with rpointer++
    1980             : //  8) swap hi-low parts in FitReg, now is Q1 + (Q0 << 16)
    1981             : //  9) shift right to get Q0
    1982             : // 10) start cor0*Q0
    1983             : // 11) read TableLength
    1984             : // 12) compare cor0*Q0 with nBins
    1985             : // 13) if >=, clip cor0*Q0 to nBins-1
    1986             : // 14) add cor0*Q0 to nBins*cor1*Q1
    1987             : // 15) compare the result with TableLength
    1988             : // 16) if >=, clip to TableLength-1
    1989             : // 17) read from the LUT 8 bits
    1990             : 
    1991             : 
    1992             : Int_t AliTRDmcmSim::GetPID(Int_t q0, Int_t q1)
    1993             : {
    1994             :   // return PID calculated from charges accumulated in two time windows
    1995             : 
    1996             :    ULong64_t addrQ0;
    1997             :    ULong64_t addr;
    1998             : 
    1999        1438 :    UInt_t nBinsQ0 = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTnbins, fDetector, fRobPos, fMcmPos);  // number of bins in q0 / 4 !!
    2000         719 :    UInt_t pidTotalSize = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTLength, fDetector, fRobPos, fMcmPos);
    2001         719 :    if(nBinsQ0==0 || pidTotalSize==0)  // make sure we don't run into trouble if the value for Q0 is not configured
    2002         719 :      return 0;                        // Q1 not configured is ok for 1D LUT
    2003             : 
    2004           0 :    ULong_t corrQ0 = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTcor0, fDetector, fRobPos, fMcmPos);
    2005           0 :    ULong_t corrQ1 = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTcor1, fDetector, fRobPos, fMcmPos);
    2006           0 :    if(corrQ0==0)  // make sure we don't run into trouble if one of the values is not configured
    2007           0 :       return 0;
    2008             : 
    2009             :    addrQ0 = corrQ0;
    2010           0 :    addrQ0 = (((addrQ0*q0)>>16)>>16); // because addrQ0 = (q0 * corrQ0) >> 32; does not work for unknown reasons
    2011             : 
    2012           0 :    if(addrQ0 >= nBinsQ0) {  // check for overflow
    2013           0 :       AliDebug(5,Form("Overflow in q0: %llu/4 is bigger then %u", addrQ0, nBinsQ0));
    2014           0 :       addrQ0 = nBinsQ0 -1;
    2015           0 :    }
    2016             : 
    2017             :    addr = corrQ1;
    2018           0 :    addr = (((addr*q1)>>16)>>16);
    2019           0 :    addr = addrQ0 + nBinsQ0*addr; // because addr = addrQ0 + nBinsQ0* (((corrQ1*q1)>>32); does not work
    2020             : 
    2021           0 :    if(addr >= pidTotalSize) {
    2022           0 :       AliDebug(5,Form("Overflow in q1. Address %llu/4 is bigger then %u", addr, pidTotalSize));
    2023           0 :       addr = pidTotalSize -1;
    2024           0 :    }
    2025             : 
    2026             :    // For a LUT with 11 input and 8 output bits, the first memory address is set to  LUT[0] | (LUT[1] << 8) | (LUT[2] << 16) | (LUT[3] << 24)
    2027             :    // and so on
    2028           0 :    UInt_t result = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTStart+(addr/4), fDetector, fRobPos, fMcmPos);
    2029           0 :    return (result>>((addr%4)*8)) & 0xFF;
    2030         719 : }
    2031             : 
    2032             : 
    2033             : 
    2034             : // help functions, to be cleaned up
    2035             : 
    2036             : UInt_t AliTRDmcmSim::AddUintClipping(UInt_t a, UInt_t b, UInt_t nbits) const
    2037             : {
    2038             :   //
    2039             :   // This function adds a and b (unsigned) and clips to
    2040             :   // the specified number of bits.
    2041             :   //
    2042             : 
    2043    96096000 :   UInt_t sum = a + b;
    2044    48048000 :   if (nbits < 32)
    2045             :   {
    2046    48048000 :     UInt_t maxv = (1 << nbits) - 1;;
    2047    48048000 :     if (sum > maxv)
    2048           0 :       sum = maxv;
    2049    48048000 :   }
    2050             :   else
    2051             :   {
    2052           0 :     if ((sum < a) || (sum < b))
    2053           0 :       sum = 0xFFFFFFFF;
    2054             :   }
    2055    48048000 :   return sum;
    2056             : }
    2057             : 
    2058             : void AliTRDmcmSim::Sort2(UShort_t  idx1i, UShort_t  idx2i, \
    2059             :                             UShort_t  val1i, UShort_t  val2i, \
    2060             :                             UShort_t * const idx1o, UShort_t * const idx2o, \
    2061             :                             UShort_t * const val1o, UShort_t * const val2o) const
    2062             : {
    2063             :   // sorting for tracklet selection
    2064             : 
    2065         160 :     if (val1i > val2i)
    2066             :     {
    2067          76 :         *idx1o = idx1i;
    2068          76 :         *idx2o = idx2i;
    2069          76 :         *val1o = val1i;
    2070          76 :         *val2o = val2i;
    2071          76 :     }
    2072             :     else
    2073             :     {
    2074           4 :         *idx1o = idx2i;
    2075           4 :         *idx2o = idx1i;
    2076           4 :         *val1o = val2i;
    2077           4 :         *val2o = val1i;
    2078             :     }
    2079          80 : }
    2080             : 
    2081             : void AliTRDmcmSim::Sort3(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, \
    2082             :                             UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, \
    2083             :                             UShort_t * const idx1o, UShort_t * const idx2o, UShort_t * const idx3o, \
    2084             :                             UShort_t * const val1o, UShort_t * const val2o, UShort_t * const val3o)
    2085             : {
    2086             :   // sorting for tracklet selection
    2087             : 
    2088             :     Int_t sel;
    2089             : 
    2090             : 
    2091         610 :     if (val1i > val2i) sel=4; else sel=0;
    2092         420 :     if (val2i > val3i) sel=sel + 2;
    2093         278 :     if (val3i > val1i) sel=sel + 1;
    2094         240 :     switch(sel)
    2095             :     {
    2096             :         case 6 : // 1 >  2  >  3            => 1 2 3
    2097             :         case 0 : // 1 =  2  =  3            => 1 2 3 : in this case doesn't matter, but so is in hardware!
    2098          76 :             *idx1o = idx1i;
    2099          76 :             *idx2o = idx2i;
    2100          76 :             *idx3o = idx3i;
    2101          76 :             *val1o = val1i;
    2102          76 :             *val2o = val2i;
    2103          76 :             *val3o = val3i;
    2104          76 :             break;
    2105             : 
    2106             :         case 4 : // 1 >  2, 2 <= 3, 3 <= 1  => 1 3 2
    2107          44 :             *idx1o = idx1i;
    2108          44 :             *idx2o = idx3i;
    2109          44 :             *idx3o = idx2i;
    2110          44 :             *val1o = val1i;
    2111          44 :             *val2o = val3i;
    2112          44 :             *val3o = val2i;
    2113          44 :             break;
    2114             : 
    2115             :         case 2 : // 1 <= 2, 2 > 3, 3 <= 1   => 2 1 3
    2116          82 :             *idx1o = idx2i;
    2117          82 :             *idx2o = idx1i;
    2118          82 :             *idx3o = idx3i;
    2119          82 :             *val1o = val2i;
    2120          82 :             *val2o = val1i;
    2121          82 :             *val3o = val3i;
    2122          82 :             break;
    2123             : 
    2124             :         case 3 : // 1 <= 2, 2 > 3, 3  > 1   => 2 3 1
    2125          22 :             *idx1o = idx2i;
    2126          22 :             *idx2o = idx3i;
    2127          22 :             *idx3o = idx1i;
    2128          22 :             *val1o = val2i;
    2129          22 :             *val2o = val3i;
    2130          22 :             *val3o = val1i;
    2131          22 :             break;
    2132             : 
    2133             :         case 1 : // 1 <= 2, 2 <= 3, 3 > 1   => 3 2 1
    2134           6 :             *idx1o = idx3i;
    2135           6 :             *idx2o = idx2i;
    2136           6 :             *idx3o = idx1i;
    2137           6 :             *val1o = val3i;
    2138           6 :             *val2o = val2i;
    2139           6 :             *val3o = val1i;
    2140           6 :         break;
    2141             : 
    2142             :         case 5 : // 1 > 2, 2 <= 3, 3 >  1   => 3 1 2
    2143          10 :             *idx1o = idx3i;
    2144          10 :             *idx2o = idx1i;
    2145          10 :             *idx3o = idx2i;
    2146          10 :             *val1o = val3i;
    2147          10 :             *val2o = val1i;
    2148          10 :             *val3o = val2i;
    2149          10 :         break;
    2150             : 
    2151             :         default: // the rest should NEVER happen!
    2152           0 :             AliError("ERROR in Sort3!!!\n");
    2153           0 :         break;
    2154             :     }
    2155         240 : }
    2156             : 
    2157             : void AliTRDmcmSim::Sort6To4(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, UShort_t  idx4i, UShort_t  idx5i, UShort_t  idx6i, \
    2158             :                                UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, UShort_t  val4i, UShort_t  val5i, UShort_t  val6i, \
    2159             :                                UShort_t * const idx1o, UShort_t * const idx2o, UShort_t * const idx3o, UShort_t * const idx4o, \
    2160             :                                UShort_t * const val1o, UShort_t * const val2o, UShort_t * const val3o, UShort_t * const val4o)
    2161             : {
    2162             :   // sorting for tracklet selection
    2163             : 
    2164           0 :     UShort_t idx21s, idx22s, idx23s, dummy;
    2165           0 :     UShort_t val21s, val22s, val23s;
    2166           0 :     UShort_t idx23as, idx23bs;
    2167           0 :     UShort_t val23as, val23bs;
    2168             : 
    2169           0 :     Sort3(idx1i, idx2i, idx3i, val1i, val2i, val3i,
    2170             :                  idx1o, &idx21s, &idx23as,
    2171             :                  val1o, &val21s, &val23as);
    2172             : 
    2173           0 :     Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
    2174             :                  idx2o, &idx22s, &idx23bs,
    2175             :                  val2o, &val22s, &val23bs);
    2176             : 
    2177           0 :     Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, &dummy, &val23s, &dummy);
    2178             : 
    2179           0 :     Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
    2180             :                  idx3o, idx4o, &dummy,
    2181             :                  val3o, val4o, &dummy);
    2182             : 
    2183           0 : }
    2184             : 
    2185             : void AliTRDmcmSim::Sort6To2Worst(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, UShort_t  idx4i, UShort_t  idx5i, UShort_t  idx6i, \
    2186             :                                     UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, UShort_t  val4i, UShort_t  val5i, UShort_t  val6i, \
    2187             :                                     UShort_t * const idx5o, UShort_t * const idx6o)
    2188             : {
    2189             :   // sorting for tracklet selection
    2190             : 
    2191         160 :     UShort_t idx21s, idx22s, idx23s, dummy1, dummy2, dummy3, dummy4, dummy5;
    2192          80 :     UShort_t val21s, val22s, val23s;
    2193          80 :     UShort_t idx23as, idx23bs;
    2194          80 :     UShort_t val23as, val23bs;
    2195             : 
    2196          80 :     Sort3(idx1i, idx2i,   idx3i, val1i, val2i, val3i,
    2197             :                  &dummy1, &idx21s, &idx23as,
    2198             :                  &dummy2, &val21s, &val23as);
    2199             : 
    2200          80 :     Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
    2201             :                  &dummy1, &idx22s, &idx23bs,
    2202             :                  &dummy2, &val22s, &val23bs);
    2203             : 
    2204          80 :     Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, idx5o, &val23s, &dummy1);
    2205             : 
    2206          80 :     Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
    2207             :                  &dummy1, &dummy2, idx6o,
    2208             :                  &dummy3, &dummy4, &dummy5);
    2209          80 : }
    2210             : 
    2211             : 
    2212             : // ----- I/O implementation -----
    2213             : 
    2214             : ostream& AliTRDmcmSim::Text(ostream& os)
    2215             : {
    2216             :   // manipulator to activate output in text format (default)
    2217             : 
    2218           0 :   os.iword(fgkFormatIndex) = 0;
    2219           0 :   return os;
    2220             : }
    2221             : 
    2222             : ostream& AliTRDmcmSim::Cfdat(ostream& os)
    2223             : {
    2224             :   // manipulator to activate output in CFDAT format
    2225             :   // to send to the FEE via SCSN
    2226             : 
    2227           0 :   os.iword(fgkFormatIndex) = 1;
    2228           0 :   return os;
    2229             : }
    2230             : 
    2231             : ostream& AliTRDmcmSim::Raw(ostream& os)
    2232             : {
    2233             :   // manipulator to activate output as raw data dump
    2234             : 
    2235           0 :   os.iword(fgkFormatIndex) = 2;
    2236           0 :   return os;
    2237             : }
    2238             : 
    2239             : ostream& operator<<(ostream& os, const AliTRDmcmSim& mcm)
    2240             : {
    2241             :   // output implementation
    2242             : 
    2243             :   // no output for non-initialized MCM
    2244           0 :   if (!mcm.CheckInitialized())
    2245           0 :     return os;
    2246             : 
    2247             :   // ----- human-readable output -----
    2248           0 :   if (os.iword(AliTRDmcmSim::fgkFormatIndex) == 0) {
    2249             : 
    2250           0 :     os << "MCM " << mcm.fMcmPos << " on ROB " << mcm.fRobPos <<
    2251           0 :       " in detector " << mcm.fDetector << std::endl;
    2252             : 
    2253           0 :     os << "----- Unfiltered ADC data (10 bit) -----" << std::endl;
    2254           0 :     os << "ch    ";
    2255           0 :     for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++)
    2256           0 :       os << std::setw(5) << iChannel;
    2257           0 :     os << std::endl;
    2258           0 :     for (Int_t iTimeBin = 0; iTimeBin < mcm.fNTimeBin; iTimeBin++) {
    2259           0 :       os << "tb " << std::setw(2) << iTimeBin << ":";
    2260           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2261           0 :         os << std::setw(5) << (mcm.fADCR[iChannel][iTimeBin] >> mcm.fgkAddDigits);
    2262             :       }
    2263           0 :       os << std::endl;
    2264             :     }
    2265             : 
    2266           0 :     os << "----- Filtered ADC data (10+2 bit) -----" << std::endl;
    2267           0 :     os << "ch    ";
    2268           0 :     for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++)
    2269           0 :       os << std::setw(4) << iChannel
    2270           0 :          << ((~mcm.fZSMap[iChannel] != 0) ? "!" : " ");
    2271           0 :     os << std::endl;
    2272           0 :     for (Int_t iTimeBin = 0; iTimeBin < mcm.fNTimeBin; iTimeBin++) {
    2273           0 :       os << "tb " << std::setw(2) << iTimeBin << ":";
    2274           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2275           0 :         os << std::setw(4) << (mcm.fADCF[iChannel][iTimeBin])
    2276           0 :            << (((mcm.fZSMap[iChannel] & (1 << iTimeBin)) == 0) ? "!" : " ");
    2277             :       }
    2278           0 :       os << std::endl;
    2279             :     }
    2280           0 :   }
    2281             : 
    2282             :   // ----- CFDAT output -----
    2283           0 :   else if(os.iword(AliTRDmcmSim::fgkFormatIndex) == 1) {
    2284             :     Int_t dest       = 127;
    2285             :     Int_t addrOffset = 0x2000;
    2286             :     Int_t addrStep   = 0x80;
    2287             : 
    2288           0 :     for (Int_t iTimeBin = 0; iTimeBin < mcm.fNTimeBin; iTimeBin++) {
    2289           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2290           0 :         os << std::setw(5) << 10
    2291           0 :            << std::setw(5) << addrOffset + iChannel * addrStep + iTimeBin
    2292           0 :            << std::setw(5) << (mcm.fADCF[iChannel][iTimeBin])
    2293           0 :            << std::setw(5) << dest << std::endl;
    2294             :       }
    2295           0 :       os << std::endl;
    2296             :     }
    2297           0 :   }
    2298             : 
    2299             :   // ----- raw data ouptut -----
    2300           0 :   else if (os.iword(AliTRDmcmSim::fgkFormatIndex) == 2) {
    2301             :     Int_t   bufSize   = 300;
    2302           0 :     UInt_t *buf       = new UInt_t[bufSize];
    2303             : 
    2304           0 :     Int_t bufLength   = mcm.ProduceRawStream(&buf[0], bufSize);
    2305             : 
    2306           0 :     for (Int_t i = 0; i < bufLength; i++)
    2307           0 :       std::cout << "0x" << std::hex << buf[i] << std::dec << std::endl;
    2308             : 
    2309           0 :     delete [] buf;
    2310           0 :   }
    2311             : 
    2312             :   else {
    2313           0 :     os << "unknown format set" << std::endl;
    2314             :   }
    2315             : 
    2316           0 :   return os;
    2317           0 : }
    2318             : 
    2319             : 
    2320             : void AliTRDmcmSim::PrintFitRegXml(ostream& os) const
    2321             : {
    2322             :   // print fit registres in XML format
    2323             : 
    2324             :    bool tracklet=false;
    2325             : 
    2326           0 :   for (Int_t cpu = 0; cpu < 4; cpu++) {
    2327           0 :      if(fFitPtr[cpu] != 31)
    2328           0 :         tracklet=true;
    2329             :   }
    2330             : 
    2331           0 :   if(tracklet==true) {
    2332           0 :      os << "<nginject>" << std::endl;
    2333           0 :      os << "<ack roc=\""<< fDetector <<  "\" cmndid=\"0\">" << std::endl;
    2334           0 :      os << "<dmem-readout>" << std::endl;
    2335           0 :      os << "<d det=\"" << fDetector << "\">" << std::endl;
    2336           0 :      os << " <ro-board rob=\"" << fRobPos << "\">" << std::endl;
    2337           0 :      os << "  <m mcm=\"" << fMcmPos << "\">" << std::endl;
    2338             : 
    2339           0 :      for(int cpu=0; cpu<4; cpu++) {
    2340           0 :         os << "   <c cpu=\"" << cpu << "\">" << std::endl;
    2341           0 :         if(fFitPtr[cpu] != 31) {
    2342           0 :            for(int adcch=fFitPtr[cpu]; adcch<fFitPtr[cpu]+2; adcch++) {
    2343           0 :               os << "    <ch chnr=\"" << adcch << "\">"<< std::endl;
    2344           0 :               os << "     <hits>"   << fFitReg[adcch].fNhits << "</hits>"<< std::endl;
    2345           0 :               os << "     <q0>"     << fFitReg[adcch].fQ0 << "</q0>"<< std::endl;
    2346           0 :               os << "     <q1>"     << fFitReg[adcch].fQ1 << "</q1>"<< std::endl;
    2347           0 :               os << "     <sumx>"   << fFitReg[adcch].fSumX << "</sumx>"<< std::endl;
    2348           0 :               os << "     <sumxsq>" << fFitReg[adcch].fSumX2 << "</sumxsq>"<< std::endl;
    2349           0 :               os << "     <sumy>"   << fFitReg[adcch].fSumY << "</sumy>"<< std::endl;
    2350           0 :               os << "     <sumysq>" << fFitReg[adcch].fSumY2 << "</sumysq>"<< std::endl;
    2351           0 :               os << "     <sumxy>"  << fFitReg[adcch].fSumXY << "</sumxy>"<< std::endl;
    2352           0 :               os << "    </ch>" << std::endl;
    2353             :            }
    2354           0 :         }
    2355           0 :         os << "      </c>" << std::endl;
    2356             :      }
    2357           0 :      os << "    </m>" << std::endl;
    2358           0 :      os << "  </ro-board>" << std::endl;
    2359           0 :      os << "</d>" << std::endl;
    2360           0 :      os << "</dmem-readout>" << std::endl;
    2361           0 :      os << "</ack>" << std::endl;
    2362           0 :      os << "</nginject>" << std::endl;
    2363           0 :   }
    2364           0 : }
    2365             : 
    2366             : 
    2367             : void AliTRDmcmSim::PrintTrackletsXml(ostream& os) const
    2368             : {
    2369             :   // print tracklets in XML format
    2370             : 
    2371           0 :    os << "<nginject>" << std::endl;
    2372           0 :    os << "<ack roc=\""<< fDetector <<  "\" cmndid=\"0\">" << std::endl;
    2373           0 :    os << "<dmem-readout>" << std::endl;
    2374           0 :    os << "<d det=\"" << fDetector << "\">" << std::endl;
    2375           0 :    os << "  <ro-board rob=\"" << fRobPos << "\">" << std::endl;
    2376           0 :    os << "    <m mcm=\"" << fMcmPos << "\">" << std::endl;
    2377             : 
    2378             :    Int_t pid, padrow, slope, offset;
    2379           0 :    for(Int_t cpu=0; cpu<4; cpu++) {
    2380           0 :       if(fMCMT[cpu] == 0x10001000) {
    2381             :          pid=-1;
    2382             :          padrow=-1;
    2383             :          slope=-1;
    2384             :          offset=-1;
    2385           0 :       }
    2386             :       else {
    2387           0 :          pid    = (fMCMT[cpu] & 0xFF000000) >> 24;
    2388           0 :          padrow = (fMCMT[cpu] & 0xF00000  ) >> 20;
    2389           0 :          slope  = (fMCMT[cpu] & 0xFE000   ) >> 13;
    2390           0 :          offset = (fMCMT[cpu] & 0x1FFF    ) ;
    2391             : 
    2392             :       }
    2393           0 :       os << "      <trk> <pid>" << pid << "</pid>" << " <padrow>" << padrow << "</padrow>"
    2394           0 :          << " <slope>" << slope << "</slope>" << " <offset>" << offset << "</offset>" << "</trk>" << std::endl;
    2395             :    }
    2396             : 
    2397           0 :    os << "    </m>" << std::endl;
    2398           0 :    os << "  </ro-board>" << std::endl;
    2399           0 :    os << "</d>" << std::endl;
    2400           0 :    os << "</dmem-readout>" << std::endl;
    2401           0 :    os << "</ack>" << std::endl;
    2402           0 :    os << "</nginject>" << std::endl;
    2403           0 : }
    2404             : 
    2405             : 
    2406             : void AliTRDmcmSim::PrintAdcDatTxt(ostream& os) const
    2407             : {
    2408             :   // print ADC data in text format (suitable as Modelsim stimuli)
    2409             : 
    2410           0 :    os << "# MCM " << fMcmPos << " on ROB " << fRobPos <<
    2411           0 :       " in detector " << fDetector << std::endl;
    2412             : 
    2413           0 :    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    2414           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); ++iChannel) {
    2415           0 :          os << std::setw(5) << (fADCR[iChannel][iTimeBin] >> fgkAddDigits);
    2416             :       }
    2417           0 :       os << std::endl;
    2418             :    }
    2419           0 : }
    2420             : 
    2421             : 
    2422             : void AliTRDmcmSim::PrintAdcDatHuman(ostream& os) const
    2423             : {
    2424             :   // print ADC data in human-readable format
    2425             : 
    2426           0 :    os << "MCM " << fMcmPos << " on ROB " << fRobPos <<
    2427           0 :       " in detector " << fDetector << std::endl;
    2428             : 
    2429           0 :    os << "----- Unfiltered ADC data (10 bit) -----" << std::endl;
    2430           0 :    os << "ch    ";
    2431           0 :    for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++)
    2432           0 :       os << std::setw(5) << iChannel;
    2433           0 :    os << std::endl;
    2434           0 :    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    2435           0 :       os << "tb " << std::setw(2) << iTimeBin << ":";
    2436           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2437           0 :          os << std::setw(5) << (fADCR[iChannel][iTimeBin] >> fgkAddDigits);
    2438             :       }
    2439           0 :       os << std::endl;
    2440             :    }
    2441             : 
    2442           0 :    os << "----- Filtered ADC data (10+2 bit) -----" << std::endl;
    2443           0 :    os << "ch    ";
    2444           0 :    for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++)
    2445           0 :       os << std::setw(4) << iChannel
    2446           0 :          << ((~fZSMap[iChannel] != 0) ? "!" : " ");
    2447           0 :    os << std::endl;
    2448           0 :    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    2449           0 :       os << "tb " << std::setw(2) << iTimeBin << ":";
    2450           0 :       for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2451           0 :          os << std::setw(4) << (fADCF[iChannel][iTimeBin])
    2452           0 :             << (((fZSMap[iChannel] & (1 << iTimeBin)) == 0) ? "!" : " ");
    2453             :       }
    2454           0 :       os << std::endl;
    2455             :    }
    2456           0 : }
    2457             : 
    2458             : 
    2459             : void AliTRDmcmSim::PrintAdcDatXml(ostream& os) const
    2460             : {
    2461             :   // print ADC data in XML format
    2462             : 
    2463           0 :    os << "<nginject>" << std::endl;
    2464           0 :    os << "<ack roc=\""<< fDetector <<  "\" cmndid=\"0\">" << std::endl;
    2465           0 :    os << "<dmem-readout>" << std::endl;
    2466           0 :    os << "<d det=\"" << fDetector << "\">" << std::endl;
    2467           0 :    os << " <ro-board rob=\"" << fRobPos << "\">" << std::endl;
    2468           0 :    os << "  <m mcm=\"" << fMcmPos << "\">" << std::endl;
    2469             : 
    2470           0 :     for(Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2471           0 :        os << "   <ch chnr=\"" << iChannel << "\">" << std::endl;
    2472           0 :        for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    2473           0 :           os << "<tb>" << fADCF[iChannel][iTimeBin]/4 << "</tb>";
    2474             :        }
    2475           0 :        os << "   </ch>" << std::endl;
    2476             :     }
    2477             : 
    2478           0 :    os << "  </m>" << std::endl;
    2479           0 :    os << " </ro-board>" << std::endl;
    2480           0 :    os << "</d>" << std::endl;
    2481           0 :    os << "</dmem-readout>" << std::endl;
    2482           0 :    os << "</ack>" << std::endl;
    2483           0 :    os << "</nginject>" << std::endl;
    2484           0 : }
    2485             : 
    2486             : 
    2487             : 
    2488             : void AliTRDmcmSim::PrintAdcDatDatx(ostream& os, Bool_t broadcast, Int_t timeBinOffset) const
    2489             : {
    2490             :   // print ADC data in datx format (to send to FEE)
    2491             : 
    2492           0 :    fTrapConfig->PrintDatx(os, 2602, 1, 0, 127);  // command to enable the ADC clock - necessary to write ADC values to MCM
    2493           0 :    os << std::endl;
    2494             : 
    2495             :    Int_t addrOffset = 0x2000;
    2496             :    Int_t addrStep   = 0x80;
    2497             :    Int_t addrOffsetEBSIA = 0x20;
    2498             : 
    2499           0 :    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
    2500           0 :      for (Int_t iChannel = 0; iChannel < AliTRDfeeParam::GetNadcMcm(); iChannel++) {
    2501           0 :        if ((iTimeBin < timeBinOffset) || (iTimeBin >= fNTimeBin+timeBinOffset)) {
    2502           0 :          if(broadcast==kFALSE)
    2503           0 :            fTrapConfig->PrintDatx(os, addrOffset+iChannel*addrStep+addrOffsetEBSIA+iTimeBin, 10, GetRobPos(),  GetMcmPos());
    2504             :          else
    2505           0 :            fTrapConfig->PrintDatx(os, addrOffset+iChannel*addrStep+addrOffsetEBSIA+iTimeBin, 10, 0, 127);
    2506             :        }
    2507             :        else {
    2508           0 :          if(broadcast==kFALSE)
    2509           0 :            fTrapConfig->PrintDatx(os, addrOffset+iChannel*addrStep+addrOffsetEBSIA+iTimeBin, (fADCF[iChannel][iTimeBin-timeBinOffset]/4), GetRobPos(),  GetMcmPos());
    2510             :          else
    2511           0 :            fTrapConfig->PrintDatx(os, addrOffset+iChannel*addrStep+addrOffsetEBSIA+iTimeBin, (fADCF[iChannel][iTimeBin-timeBinOffset]/4), 0, 127);
    2512             :        }
    2513             :      }
    2514           0 :      os << std::endl;
    2515             :    }
    2516           0 : }
    2517             : 
    2518             : 
    2519             : void AliTRDmcmSim::PrintPidLutHuman()
    2520             : {
    2521             :   // print PID LUT in human readable format
    2522             : 
    2523             :    UInt_t result;
    2524             : 
    2525           0 :    UInt_t addrEnd = fgkDmemAddrLUTStart + fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTLength, fDetector, fRobPos, fMcmPos)/4; // /4 because each addr contains 4 values
    2526           0 :    UInt_t nBinsQ0 = fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTnbins, fDetector, fRobPos, fMcmPos);
    2527             : 
    2528           0 :    std::cout << "nBinsQ0: " << nBinsQ0 << std::endl;
    2529           0 :    std::cout << "LUT table length: " << fTrapConfig->GetDmemUnsigned(fgkDmemAddrLUTLength, fDetector, fRobPos, fMcmPos) << std::endl;
    2530             : 
    2531           0 :    if (nBinsQ0>0) {
    2532           0 :      for(UInt_t addr=fgkDmemAddrLUTStart; addr< addrEnd; addr++) {
    2533           0 :        result = fTrapConfig->GetDmemUnsigned(addr, fDetector, fRobPos, fMcmPos);
    2534           0 :        std::cout << addr << " # x: " << ((addr-fgkDmemAddrLUTStart)%((nBinsQ0)/4))*4 << ", y: " <<(addr-fgkDmemAddrLUTStart)/(nBinsQ0/4)
    2535           0 :                  << "  #  " <<((result>>0)&0xFF)
    2536           0 :                  << " | "  << ((result>>8)&0xFF)
    2537           0 :                  << " | "  << ((result>>16)&0xFF)
    2538           0 :                  << " | "  << ((result>>24)&0xFF) << std::endl;
    2539             :      }
    2540           0 :    }
    2541           0 : }
    2542             : 
    2543             : 
    2544             : Bool_t AliTRDmcmSim::ReadPackedConfig(AliTRDtrapConfig *cfg, Int_t hc, UInt_t *data, Int_t size)
    2545             : {
    2546             :   // Read the packed configuration from the passed memory block
    2547             :   //
    2548             :   // To be used to retrieve the TRAP configuration from the
    2549             :   // configuration as sent in the raw data.
    2550             : 
    2551           0 :   AliDebugClass(1, "Reading packed configuration");
    2552             : 
    2553           0 :   Int_t det = hc/2;
    2554             : 
    2555             :   Int_t idx = 0;
    2556             :   Int_t err = 0;
    2557             :   Int_t step, bwidth, nwords, exitFlag, bitcnt;
    2558             : 
    2559             :   UShort_t caddr;
    2560             :   UInt_t dat, msk, header, dataHi;
    2561             : 
    2562           0 :   while (idx < size && *data != 0x00000000) {
    2563             : 
    2564           0 :     Int_t rob = (*data >> 28) & 0x7;
    2565           0 :     Int_t mcm = (*data >> 24) & 0xf;
    2566             : 
    2567           0 :     AliDebugClass(1, Form("Config of det. %3i MCM %i:%02i (0x%08x)", det, rob, mcm, *data));
    2568           0 :     data++;
    2569             : 
    2570           0 :     while (idx < size && *data != 0x00000000) {
    2571             : 
    2572             :       header = *data;
    2573           0 :       data++;
    2574           0 :       idx++;
    2575             : 
    2576           0 :       AliDebugClass(5, Form("read: 0x%08x", header));
    2577             : 
    2578           0 :       if (header & 0x01) // single data
    2579             :         {
    2580           0 :           dat   = (header >>  2) & 0xFFFF;       // 16 bit data
    2581           0 :           caddr = (header >> 18) & 0x3FFF;    // 14 bit address
    2582             : 
    2583           0 :           if (caddr != 0x1FFF)  // temp!!! because the end marker was wrong
    2584             :             {
    2585           0 :               if (header & 0x02) // check if > 16 bits
    2586             :                 {
    2587           0 :                   dataHi = *data;
    2588           0 :                   AliDebugClass(5, Form("read: 0x%08x", dataHi));
    2589           0 :                   data++;
    2590           0 :                   idx++;
    2591           0 :                   err += ((dataHi ^ (dat | 1)) & 0xFFFF) != 0;
    2592           0 :                   dat = (dataHi & 0xFFFF0000) | dat;
    2593           0 :                 }
    2594           0 :               AliDebugClass(5, Form("addr=0x%04x (%s) data=0x%08x\n", caddr, cfg->GetRegName(cfg->GetRegByAddress(caddr)), dat));
    2595           0 :               if ( ! cfg->Poke(caddr, dat, det, rob, mcm) )
    2596           0 :                 AliDebugClass(5, Form("(single-write): non-existing address 0x%04x containing 0x%08x\n", caddr, header));
    2597           0 :               if (idx > size)
    2598             :                 {
    2599           0 :                   AliDebugClass(5, Form("(single-write): no more data, missing end marker\n"));
    2600           0 :                   return -err;
    2601             :                 }
    2602             :             }
    2603             :           else
    2604             :             {
    2605           0 :               AliDebugClass(5, Form("(single-write): address 0x%04x => old endmarker?\n", caddr));
    2606           0 :               return err;
    2607             :             }
    2608             :         }
    2609             : 
    2610             :       else               // block of data
    2611             :         {
    2612           0 :           step   =  (header >>  1) & 0x0003;
    2613           0 :           bwidth = ((header >>  3) & 0x001F) + 1;
    2614           0 :           nwords =  (header >>  8) & 0x00FF;
    2615           0 :           caddr  =  (header >> 16) & 0xFFFF;
    2616           0 :           exitFlag = (step == 0) || (step == 3) || (nwords == 0);
    2617             : 
    2618           0 :           if (exitFlag)
    2619             :             break;
    2620             : 
    2621           0 :           switch (bwidth)
    2622             :             {
    2623             :             case    15:
    2624             :             case    10:
    2625             :             case     7:
    2626             :             case     6:
    2627             :             case     5:
    2628             :               {
    2629           0 :                 msk = (1 << bwidth) - 1;
    2630             :                 bitcnt = 0;
    2631           0 :                 while (nwords > 0)
    2632             :                   {
    2633           0 :                     nwords--;
    2634           0 :                     bitcnt -= bwidth;
    2635           0 :                     if (bitcnt < 0)
    2636             :                       {
    2637           0 :                         header = *data;
    2638           0 :                         AliDebugClass(5, Form("read 0x%08x", header));
    2639           0 :                         data++;
    2640           0 :                         idx++;
    2641           0 :                         err += (header & 1);
    2642           0 :                         header = header >> 1;
    2643           0 :                         bitcnt = 31 - bwidth;
    2644           0 :                       }
    2645           0 :                     AliDebugClass(5, Form("addr=0x%04x (%s) data=0x%08x\n", caddr, cfg->GetRegName(cfg->GetRegByAddress(caddr)), header & msk));
    2646           0 :                     if ( ! cfg->Poke(caddr, header & msk, det, rob, mcm) )
    2647           0 :                       AliDebugClass(5, Form("(single-write): non-existing address 0x%04x containing 0x%08x\n", caddr, header));
    2648             : 
    2649           0 :                     caddr += step;
    2650           0 :                     header = header >> bwidth;
    2651           0 :                     if (idx >= size)
    2652             :                       {
    2653           0 :                         AliDebugClass(5, Form("(block-write): no end marker! %d words read\n", idx));
    2654           0 :                         return -err;
    2655             :                       }
    2656             :                   }
    2657             :                 break;
    2658             :               } // end case 5-15
    2659             :             case 31:
    2660             :               {
    2661           0 :                 while (nwords > 0)
    2662             :                   {
    2663           0 :                     header = *data;
    2664           0 :                     AliDebugClass(5, Form("read 0x%08x", header));
    2665           0 :                     data++;
    2666           0 :                     idx++;
    2667           0 :                     nwords--;
    2668           0 :                     err += (header & 1);
    2669             : 
    2670           0 :                     AliDebugClass(5, Form("addr=0x%04x (%s) data=0x%08x", caddr, cfg->GetRegName(cfg->GetRegByAddress(caddr)), header >> 1));
    2671           0 :                     if ( ! cfg->Poke(caddr, header >> 1, det, rob, mcm) )
    2672           0 :                       AliDebugClass(5, Form("(single-write): non-existing address 0x%04x containing 0x%08x\n", caddr, header));
    2673             : 
    2674           0 :                     caddr += step;
    2675           0 :                     if (idx >= size)
    2676             :                       {
    2677           0 :                         AliDebugClass(5, Form("no end marker! %d words read", idx));
    2678           0 :                         return -err;
    2679             :                       }
    2680             :                   }
    2681             :                 break;
    2682             :               }
    2683           0 :             default: return err;
    2684             :             } // end switch
    2685             :         } // end block case
    2686             :     }
    2687           0 :   } // end while
    2688           0 :   AliDebugClass(5, Form("no end marker! %d words read", idx));
    2689           0 :   return -err; // only if the max length of the block reached!
    2690           0 : }

Generated by: LCOV version 1.11