Revision of AliTRDmcmSim + coding rule violations
authorcblume <cblume@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 12 Mar 2009 14:56:21 +0000 (14:56 +0000)
committercblume <cblume@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 12 Mar 2009 14:56:21 +0000 (14:56 +0000)
TRD/AliTRDdigitizer.cxx
TRD/AliTRDdigitizer.h
TRD/AliTRDmcmSim.cxx
TRD/AliTRDmcmSim.h
TRD/AliTRDrawData.cxx
TRD/AliTRDtrackletMCM.cxx
TRD/AliTRDtrackletMCM.h
TRD/AliTRDtrapConfig.cxx [new file with mode: 0644]
TRD/AliTRDtrapConfig.h [new file with mode: 0644]
TRD/TRDbaseLinkDef.h
TRD/libTRDbase.pkg

index 5fe47bd..67c9633 100644 (file)
@@ -1310,8 +1310,8 @@ Bool_t AliTRDdigitizer::Signal2ADC(Int_t det, AliTRDarraySignal *signals)
     } // for: col
   } // for: row
 
-  // Do the Zero Suppression
-  ZS(digits);
+  // Run the digital processing in the MCM
+  RunDigitalProcessing(digits, det);
 
   return kTRUE;
 
@@ -1546,7 +1546,7 @@ Bool_t AliTRDdigitizer::ConvertSDigits()
       AliDebug(2,Form("No digits for det=%d",det));
       continue;
     }
-
+    
     // Convert the merged sdigits to digits
     if (!Signal2ADC(det,digitsIn)) {
       continue;
@@ -1566,6 +1566,7 @@ Bool_t AliTRDdigitizer::ConvertSDigits()
 
   } // for: detector numbers
 
+
   return kTRUE;
 
 }
@@ -1778,78 +1779,31 @@ Int_t AliTRDdigitizer::ExB(Float_t vdrift, Double_t driftlength, Double_t &lCol)
 }
 
 //_____________________________________________________________________________
-void AliTRDdigitizer::ZS(AliTRDarrayADC *digits)
+void AliTRDdigitizer::RunDigitalProcessing(AliTRDarrayADC *digits, Int_t det)
 {
   //
-  // Apply the ZS
+  // Run the digital processing in the TRAP
   //
 
-  // Create the temporary digits container
-  AliTRDarrayADC *tempDigits;
-  tempDigits = new AliTRDarrayADC();
-  Int_t dim4 = digits->GetNrow();
-  Int_t dim5 = digits->GetNcol()+2;  
-  Int_t dim6 = digits->GetNtime();
-  Int_t lim  = dim5-1;
-
-  tempDigits->Allocate(dim4,dim5,dim6);
-
-  for(Int_t row=0;row<dim4;row++)
-    {
-      for(Int_t col=0;col<dim5;col++)
-       {
-         for(Int_t time=0;time<dim6;time++)
-           {
-             if(col==0||col==lim)
-               {
-                 tempDigits->SetData(row,col,time,0);
-               }
-             else
-               {
-                 tempDigits->SetData(row,col,time,digits->GetData(row,col-1,time));         
-               }           
-           }
-       }
-    }
+  AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
 
   //Create and initialize the mcm object 
-  AliTRDmcmSim* mcmfast; 
-  mcmfast = new AliTRDmcmSim(); 
-  mcmfast->StartfastZS(dim5,dim6);
+  AliTRDmcmSim* mcmfast = new AliTRDmcmSim(); 
 
   //Call the methods in the mcm class using the temporary array as input  
-  for(Int_t row=0;row<dim4;row++)
+  for(Int_t rob = 0; rob < digits->GetNrow() / 4; rob++)
+  {
+    for(Int_t mcm = 0; mcm < 16; mcm++)
     {
-      for(Int_t col=0;col<dim5;col++)
-       {
-         for(Int_t time=0;time<dim6;time++)
-           {
-             mcmfast->SetData(col,time,tempDigits->GetData(row,col,time));
-           }
-       }
+      mcmfast->Init(det, rob, mcm); 
+      mcmfast->SetData(digits);
       mcmfast->Filter();
+      if (feeParam->GetTracklet())
+        mcmfast->Tracklet();
       mcmfast->ZSMapping();
-      mcmfast->FlagDigitsArray(tempDigits,row);
-      mcmfast->StartfastZS(dim5,dim6); 
-    }
-
-  //Modify the digits array to indicate suppressed values
-  for(Int_t irow=0; irow<dim4;irow++)
-    {
-      for(Int_t icol=1; icol<lim;icol++) 
-       {
-         for(Int_t itime=0; itime<dim6;itime++)
-           {
-             if(tempDigits->GetData(irow,icol,itime)==-1) // If supressed in temporary array
-               {
-                 digits->SetData(irow,icol-1,itime,-1); // Supressed values indicated by -1 in the digits array
-               }
-           }
-       }
+      mcmfast->WriteData(digits);
     }
+  }
 
-  // Delete objects
   delete mcmfast;
-  delete tempDigits;
-
 }
index 474c10e..42d596b 100644 (file)
@@ -81,7 +81,7 @@ class AliTRDdigitizer : public AliDigitizer {
           Int_t        Diffusion(Float_t vdrift, Double_t absdriftlength
                                , Double_t &lRow, Double_t &lCol, Double_t &lTime);
           Int_t        ExB(Float_t vdrift, Double_t driftlength, Double_t &lRow);
-         void         ZS(AliTRDarrayADC *digits);
+         void         RunDigitalProcessing(AliTRDarrayADC *digits, Int_t det = 0);
 
  protected:
 
index 41ed945..4f6f090 100644 (file)
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 //  TRD MCM (Multi Chip Module) simulator                                    //
+//  which simulated the TRAP processing after the AD-conversion              //
+//  The relevant parameters (i.e. configuration registers of the TRAP        //
+//  configuration are taken from AliTRDtrapConfig.                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-/* $Id$ */
+#include <fstream>  // needed for raw data dump
 
-/*
-
-  New release on 2007/08/17
-
-AliTRDmcmSim is now stably working and zero suppression function seems ok.
-From now, the default version of raw data is set to 3 in AliTRDfeeParam.
-
-The following internal parameters were abolished because it is useless and
-made trouble:
-
-   fColOfADCbeg
-   fColOfADCend
-
-GetCol member was modified accordingly. 
-
-New member function DumpData was prepared for diagnostics.
-
-ZSMapping member function was debugged. It was causing crash due to
-wrong indexing in 1 dimensional numbering. Also code was shaped up better.
-
-*/
-
-/*Semi-final version of TRD raw data simulation code with zero suppression (ZS)
-similar to TRD FEE. ZS is realized by the class group:
-
-  AliTRDfeeParam
-  AliTRDmcmSim
-  AliTRDrawData
-
-AliTRDfeeParam has been modified to have more parameters like raw data
-production version and so on. AliTRDmcmSim is new class and this is the core
-of MCM (PASA+TRAP) simulator. It has still very simple function and it will be
-another project to improve this to make it closer to the reall FEE.
-AliTRDrawData has been modified to use new class AliTRDmcmSim.
-
-These modifications were tested on Aug. 02 HEAD version that code itself
-compiles. I'm sure there must be still bugs and we need testing by as many as
-possible persons now. Especially it seems HLT part is impacted by problems
-because some parameters were moved from AliTRDrawData to AliTRDfeeParam (like
-fRawVersion disappeared from AliTRDrawData).
-
-In TRD definition, we have now 4 raw data versions.
-
-  0 very old offline version (by Bogdan)
-  1 test version (no zero suppression)
-  2 final version (no zero suppression)
-  3 test version (with zero suppression)
-
-The default is still set to 2 in AliTRDfeeParam::fgkRAWversion and it uses
-previously existing codes. If you set this to 3, AliTRDrawData changes behavior
-to use AliTRDmcmSim with ZS.
-
-Plan is after we make sure it works stably, we delete AliTRDmcm which is obsolete.
-However it still take time because tracklet part is not yet touched.
-The default raw version is 2.
-
-                                                                 Ken Oyama
-*/
-
-// if no histo is drawn, these are obsolete
-#include <TH1.h>
 #include <TCanvas.h>
-
-// only needed if I/O of tracklets is activated
-#include <TObject.h>
-#include <TFile.h>
-#include <TTree.h>
-#include <TSystem.h>
-
-#include <fstream>
-
+#include <TH1F.h>
+#include <TH2F.h>
+#include <TGraph.h>
+#include <TLine.h>
 #include <TMath.h>
+#include <TRandom.h>
+#include <TClonesArray.h>
 
 #include "AliLog.h"
+#include "AliRun.h"
+#include "AliRunLoader.h"
+#include "AliLoader.h"
+#include "AliTRDdigit.h"
 
-#include "AliTRDmcmSim.h"
 #include "AliTRDfeeParam.h"
+#include "AliTRDtrapConfig.h"
 #include "AliTRDSimParam.h"
-#include "AliTRDCommonParam.h"
 #include "AliTRDgeometry.h"
 #include "AliTRDcalibDB.h"
 #include "AliTRDdigitsManager.h"
 #include "AliTRDarrayADC.h"
-// additional for new tail filter and/or tracklet
-#include "AliTRDtrapAlu.h"
 #include "AliTRDpadPlane.h"
 #include "AliTRDtrackletMCM.h"
-
-#include "AliRun.h"
-#include "AliLoader.h"
+#include "AliTRDmcmSim.h"
 
 ClassImp(AliTRDmcmSim)
 
 //_____________________________________________________________________________
-AliTRDmcmSim::AliTRDmcmSim() :TObject()
+AliTRDmcmSim::AliTRDmcmSim() : TObject()
   ,fInitialized(kFALSE)
-  ,fNextEvent(-1)    
   ,fMaxTracklets(-1) 
-  ,fChaId(-1)
-  ,fSector(-1)
-  ,fStack(-1)
-  ,fLayer(-1)
+  ,fDetector(-1)
   ,fRobPos(-1)
   ,fMcmPos(-1)
-  ,fNADC(-1)
-  ,fNTimeBin(-1)
   ,fRow (-1)
-  ,fADCR(NULL)
-  ,fADCF(NULL)
-  ,fADCT(NULL)     
-  ,fPosLUT(NULL)    
-  ,fMCMT(NULL)      
-  ,fZSM(NULL)
-  ,fZSM1Dim(NULL)
-  ,fFeeParam(NULL)
-  ,fSimParam(NULL)
-  ,fCal(NULL)
-  ,fGeo(NULL)
-{
-  //
-  // AliTRDmcmSim default constructor
-  //
-
-  // By default, nothing is initialized.
-  // It is necessary to issue Init before use.
-}
-
-//_____________________________________________________________________________
-AliTRDmcmSim::AliTRDmcmSim(const AliTRDmcmSim &m) 
-  :TObject(m)
-  ,fInitialized(kFALSE) 
-  ,fNextEvent(-1)    
-  ,fMaxTracklets(-1) 
-  ,fChaId(-1)
-  ,fSector(-1)
-  ,fStack(-1)
-  ,fLayer(-1)
-  ,fRobPos(-1)
-  ,fMcmPos(-1)
   ,fNADC(-1)
   ,fNTimeBin(-1)
-  ,fRow(-1)
   ,fADCR(NULL)
   ,fADCF(NULL)
-  ,fADCT(NULL)      
-  ,fPosLUT(NULL)    
-  ,fMCMT(NULL)      
+  ,fMCMT(NULL)
+  ,fTrackletArray(NULL)      
   ,fZSM(NULL)
   ,fZSM1Dim(NULL)
   ,fFeeParam(NULL)
+  ,fTrapConfig(NULL)
   ,fSimParam(NULL)
   ,fCal(NULL)
   ,fGeo(NULL)
-  
+  ,fPedAcc(NULL)
+  ,fGainCounterA(NULL)
+  ,fGainCounterB(NULL)
+  ,fTailAmplLong(NULL)
+  ,fTailAmplShort(NULL)
+  ,fNHits(0)
+  ,fFitReg(NULL)
 {
   //
-  // AliTRDmcmSim copy constructor
-  //
-
+  // AliTRDmcmSim default constructor
   // By default, nothing is initialized.
   // It is necessary to issue Init before use.
 }
 
-//_____________________________________________________________________________
 AliTRDmcmSim::~AliTRDmcmSim() 
 {
   //
   // AliTRDmcmSim destructor
   //
 
-  if( fADCR != NULL ) {
+  if(fInitialized) {
     for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
       delete [] fADCR[iadc];
       delete [] fADCF[iadc];
-      delete [] fADCT[iadc];
       delete [] fZSM [iadc];
     }
     delete [] fADCR;
     delete [] fADCF;
-    delete [] fADCT;
     delete [] fZSM;
     delete [] fZSM1Dim;
-  }
-  if(fInitialized){
-    delete [] fPosLUT;
     delete [] fMCMT;
+    delete [] fPedAcc;
+    delete [] fGainCounterA;
+    delete [] fGainCounterB;
+    delete [] fTailAmplLong;
+    delete [] fTailAmplShort;
+    delete [] fFitReg;
+    
+    fTrackletArray->Delete();
+    delete fTrackletArray;
+    delete fGeo;
   }
-
-  delete fGeo;
-
-}
-
-//_____________________________________________________________________________
-AliTRDmcmSim &AliTRDmcmSim::operator=(const AliTRDmcmSim &m)
-{
-  //
-  // Assignment operator
-  //
-
-  if (this != &m) {
-    ((AliTRDmcmSim &) m).Copy(*this);
-  }
-  return *this;
-
-}
-
-//_____________________________________________________________________________
-void AliTRDmcmSim::Copy(TObject &m) const
-{
-  //
-  // Copy function
-  //
-  ((AliTRDmcmSim &) m).fNextEvent     = 0; //new
-  ((AliTRDmcmSim &) m).fMaxTracklets  = 0; //new
-  ((AliTRDmcmSim &) m).fInitialized   = 0;
-  ((AliTRDmcmSim &) m).fChaId         = 0;
-  ((AliTRDmcmSim &) m).fSector        = 0;
-  ((AliTRDmcmSim &) m).fStack         = 0;
-  ((AliTRDmcmSim &) m).fLayer         = 0;
-  ((AliTRDmcmSim &) m).fRobPos        = 0;
-  ((AliTRDmcmSim &) m).fMcmPos        = 0;
-  ((AliTRDmcmSim &) m).fNADC          = 0;
-  ((AliTRDmcmSim &) m).fNTimeBin      = 0;
-  ((AliTRDmcmSim &) m).fRow           = 0;
-  ((AliTRDmcmSim &) m).fADCR          = 0;
-  ((AliTRDmcmSim &) m).fADCF          = 0;
-  ((AliTRDmcmSim &) m).fADCT          = 0; //new
-  ((AliTRDmcmSim &) m).fPosLUT        = 0; //new
-  ((AliTRDmcmSim &) m).fMCMT          = 0; //new
-  ((AliTRDmcmSim &) m).fZSM           = 0;
-  ((AliTRDmcmSim &) m).fZSM1Dim       = 0;
-  ((AliTRDmcmSim &) m).fFeeParam      = 0;
-  ((AliTRDmcmSim &) m).fSimParam      = 0;
-  ((AliTRDmcmSim &) m).fCal           = 0;
-  ((AliTRDmcmSim &) m).fGeo           = 0;
-
 }
 
-//_____________________________________________________________________________
-
-//void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos ) 
-void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos, Bool_t newEvent = kFALSE ) // only for readout tree (new event)
+void AliTRDmcmSim::Init( Int_t det, Int_t robPos, Int_t mcmPos, Bool_t /* newEvent */ ) 
 {
   //
   // Initialize the class with new geometry information
   // fADC array will be reused with filled by zero
   //
    
-  fNextEvent     = 0; 
-  fFeeParam      = AliTRDfeeParam::Instance();
-  fSimParam      = AliTRDSimParam::Instance();
-  fCal           = AliTRDcalibDB::Instance();
-  fGeo           = new AliTRDgeometry();
-  fChaId         = chaId;
-  fSector        = fGeo->GetSector( fChaId );
-  fStack         = fGeo->GetStack( fChaId );
-  fLayer         = fGeo->GetLayer( fChaId );
+  if (!fInitialized) {
+    fFeeParam      = AliTRDfeeParam::Instance();
+    fTrapConfig    = AliTRDtrapConfig::Instance();
+    fSimParam      = AliTRDSimParam::Instance();
+    fCal           = AliTRDcalibDB::Instance();
+    fGeo           = new AliTRDgeometry();
+  }
+
+  fDetector      = det;
   fRobPos        = robPos;
   fMcmPos        = mcmPos;
   fNADC          = fFeeParam->GetNadcMcm();
   fNTimeBin      = fCal->GetNumberOfTimeBins();
   fRow           = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
-
-  fMaxTracklets  = fFeeParam->GetMaxNrOfTracklets();
-
-
+  fMaxTracklets  = fFeeParam->GetMaxNrOfTracklets();  
   
-  if (newEvent == kTRUE) {
-      fNextEvent = 1;
-  }
-
-
-
-  // Allocate ADC data memory if not yet done
-  if( fADCR == NULL ) {
+  if (!fInitialized) {
     fADCR    = new Int_t *[fNADC];
     fADCF    = new Int_t *[fNADC];
-    fADCT    = new Int_t *[fNADC]; //new
     fZSM     = new Int_t *[fNADC];
     fZSM1Dim = new Int_t  [fNADC];
+    fGainCounterA = new UInt_t[fNADC];
+    fGainCounterB = new UInt_t[fNADC];
     for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
       fADCR[iadc] = new Int_t[fNTimeBin];
       fADCF[iadc] = new Int_t[fNTimeBin];
-      fADCT[iadc] = new Int_t[fNTimeBin]; //new
       fZSM [iadc] = new Int_t[fNTimeBin];
     }
+    
+    // filter registers
+    fPedAcc = new UInt_t[fNADC]; // accumulator for pedestal filter
+    fTailAmplLong = new UShort_t[fNADC];
+    fTailAmplShort = new UShort_t[fNADC];
+    
+    // tracklet calculation
+    fFitReg = new FitReg_t[fNADC]; 
+    fTrackletArray = new TClonesArray("AliTRDtrackletMCM", fMaxTracklets);
+    
+    fMCMT = new UInt_t[fMaxTracklets];
   }
 
-  // Initialize ADC data
+  fInitialized = kTRUE;
+
+  Reset();
+}
+
+void AliTRDmcmSim::Reset()
+{
+  // Resets the data values and internal filter registers
+  // by re-initialising them
+
   for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
     for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
       fADCR[iadc][it] = 0;
       fADCF[iadc][it] = 0;
-      fADCT[iadc][it] = -1;  //new
       fZSM [iadc][it] = 1;   // Default unread = 1
     }
     fZSM1Dim[iadc] = 1;      // Default unread = 1
+    fGainCounterA[iadc] = 0;
+    fGainCounterB[iadc] = 0;
   }
   
-  //new:
-  fPosLUT = new Int_t[128];
-  for(Int_t i = 0; i<128; i++){
-    fPosLUT[i] = 0;
-  }
-  
-  fMCMT = new UInt_t[fMaxTracklets];
   for(Int_t i = 0; i < fMaxTracklets; i++) {
     fMCMT[i] = 0;
   }
+  
+  FilterPedestalInit();
+  FilterGainInit();
+  FilterTailInit(fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP)); //??? not really correct if gain filter is active
+}
 
+Bool_t AliTRDmcmSim::LoadMCM(AliRunLoader *runloader, Int_t det, Int_t rob, Int_t mcm) 
+{
+  // loads the ADC data as obtained from the digitsManager for the specified MCM
+
+  if (!CheckInitialized())
+    Init(det, rob, mcm);
+
+  if (!runloader) {
+    AliError("No Runloader given");
+    return kFALSE;
+  }
+
+  AliLoader *trdLoader = runloader->GetLoader("TRDLoader");
+  if (!trdLoader) {
+    AliError("Could not get TRDLoader");
+    return kFALSE;
+  }
+
+  trdLoader->LoadDigits();
+  AliTRDdigitsManager *digMgr = new AliTRDdigitsManager();
+  digMgr->SetSDigits(0);
+  digMgr->CreateArrays();
+  digMgr->ReadDigits(trdLoader->TreeD());
+  AliTRDarrayADC *digits = (AliTRDarrayADC*) digMgr->GetDigits(det);
+  if (!digits->HasData())
+    return kFALSE;
+  digits->Expand();
+
+  Int_t padrow = fFeeParam->GetPadRowFromMCM(rob, mcm);
+  Int_t padcol = 0;
+  for (Int_t ch = 0; ch < fNADC; ch++) {
+    for (Int_t tb = 0; tb < fNTimeBin; tb++) {
+      padcol = fFeeParam->GetPadColFromADC(rob, mcm, ch);
+      if (padcol < 0) {
+        fADCR[ch][tb] = 0;
+        fADCF[ch][tb] = 0;
+      }
+      else {
+        if (digits->GetData(padrow,padcol, tb) < 0) {
+          fADCR[ch][tb] = 0;
+          fADCF[ch][tb] = 0;
+        }
+        else {
+          fADCR[ch][tb] = digits->GetData(padrow, padcol, tb) << fgkAddDigits;
+          fADCF[ch][tb] = digits->GetData(padrow, padcol, tb) << fgkAddDigits;
+        }
+      }
+    }
+  }
+  digMgr->RemoveDigits(det);
+  delete digMgr;
 
-  fInitialized = kTRUE;
+  return kTRUE;
+}
+
+void AliTRDmcmSim::NoiseTest(Int_t nsamples, Int_t mean, Int_t sigma, Int_t inputGain, Int_t inputTail)
+{
+  // This function can be used to test the filters. 
+  // It feeds nsamples of ADC values with a gaussian distribution specified by mean and sigma.
+  // The filter chain implemented here consists of:
+  // Pedestal -> Gain -> Tail
+  // With inputGain and inputTail the input to the gain and tail filter, respectively, 
+  // can be chosen where 
+  // 0: noise input
+  // 1: pedestal output
+  // 2: gain output
+  // The input has to be chosen from a stage before. 
+  // The filter behaviour is controlled by the TRAP parameters from AliTRDtrapConfig in the 
+  // same way as in normal simulation.
+  // The functions produces four histograms with the values at the different stages.
+
+  TH1F *h   = new TH1F("noise", "Gaussian Noise;sample;ADC count",
+                       nsamples, 0, nsamples);
+  TH1F *hfp = new TH1F("pedf", "Noise #rightarrow Pedestal filter;sample;ADC count", nsamples, 0, nsamples);
+  TH1F *hfg = new TH1F("pedg", "Pedestal #rightarrow Gain;sample;ADC count", nsamples, 0, nsamples);
+  TH1F *hft = new TH1F("pedt", "Gain #rightarrow Tail;sample;ADC count", nsamples, 0, nsamples);
+  h->SetStats(kFALSE);
+  hfp->SetStats(kFALSE);
+  hfg->SetStats(kFALSE);
+  hft->SetStats(kFALSE);
+  
+  Int_t value;  // ADC count with noise (10 bit)
+  Int_t valuep; // pedestal filter output (12 bit)
+  Int_t valueg; // gain filter output (12 bit)
+  Int_t valuet; // tail filter value (12 bit)
+  
+  for (Int_t i = 0; i < nsamples; i++) {
+    value = (Int_t) gRandom->Gaus(mean, sigma);  // generate noise with gaussian distribution 
+    h->SetBinContent(i, value);
+
+    valuep = FilterPedestalNextSample(1, 0, ((Int_t) value) << 2);
+    
+    if (inputGain == 0)
+      valueg = FilterGainNextSample(1, ((Int_t) value) << 2);
+    else 
+      valueg = FilterGainNextSample(1, valuep); 
+    
+    if (inputTail == 0)
+      valuet = FilterTailNextSample(1, ((Int_t) value) << 2);
+    else if (inputTail == 1)
+      valuet = FilterTailNextSample(1, valuep); 
+    else
+      valuet = FilterTailNextSample(1, valueg); 
+
+    hfp->SetBinContent(i, valuep >> 2);
+    hfg->SetBinContent(i, valueg >> 2);
+    hft->SetBinContent(i, valuet >> 2);
+  }
+
+  TCanvas *c = new TCanvas; 
+  c->Divide(2,2);
+  c->cd(1);
+  h->Draw();
+  c->cd(2);
+  hfp->Draw();
+  c->cd(3);
+  hfg->Draw();
+  c->cd(4);
+  hft->Draw();
 }
 
-//_____________________________________________________________________________
 Bool_t AliTRDmcmSim::CheckInitialized()
 {
   //
@@ -350,126 +329,123 @@ Bool_t AliTRDmcmSim::CheckInitialized()
   return fInitialized;
 }
 
-//_____________________________________________________________________________
-
-
-void AliTRDmcmSim::SetPosLUT() {
-  Double_t iHi  = (Double_t)fCal->GetPRFhi();
-  Double_t iLo  = (Double_t)fCal->GetPRFlo();
-  Int_t   nBin  = fCal->GetPRFbin();
-  Int_t   iOff  = fLayer * nBin;
-  Int_t kNlayer = fGeo->Nlayer();
-
-  Float_t  *sPRFsmp   = new Float_t[nBin*kNlayer];
-  Double_t *sPRFlayer = new Double_t[nBin];
-  
-  
-  for(Int_t i = 0; i<nBin*kNlayer; i++){
-    
-    //printf("%f\n",fCal->GetSampledPRF()[i]);
-    sPRFsmp[i] = fCal->GetSampledPRF()[i]; 
-  
+void AliTRDmcmSim::Print(Option_t* option) const
+{
+  // Prints the data stored and/or calculated for this MCM.
+  // The output is controlled by option which can be a sequence of any of 
+  // the following characters:
+  // R - prints raw ADC data
+  // F - prints filtered data 
+  // H - prints detected hits
+  // T - prints found tracklets
+  // The later stages are only useful when the corresponding calculations 
+  // have been performed.
+
+  printf("MCM %i on ROB %i in detector %i\n", fMcmPos, fRobPos, fDetector);
+
+  TString opt = option;
+  if (opt.Contains("U")) {
+    printf("Raw ADC data (10 bit):\n");
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      for (Int_t iChannel = 0; iChannel < fNADC; iChannel++) {
+        printf("%5i", fADCR[iChannel][iTimeBin] >> fgkAddDigits);
+      }
+      printf("\n");
+    }
   }
 
-  Double_t sWidth = (iHi-iLo)/((Double_t) nBin);
-  Int_t   sPad    = (Int_t) (1.0/sWidth);
-  
-  // get the PRF for actual layer (interpolated to ibin data-points; 61 measured)
-  for(Int_t iBin = 0; iBin < nBin; iBin++){
-    sPRFlayer[iBin] = (Double_t)sPRFsmp[iOff+iBin];
+  if (opt.Contains("F")) {
+    printf("Filtered data (12 bit):\n");
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      for (Int_t iChannel = 0; iChannel < fNADC; iChannel++) {
+        printf("%5i", fADCF[iChannel][iTimeBin]);
+      }
+      printf("\n");
+    }
   }
 
-  Int_t bin0 = (Int_t)(-iLo / sWidth - 0.5);                           // bin-nr. for pad-position 0
-  
-  Int_t bin1 = (Int_t)((Double_t)(0.5 - iLo) / sWidth - 0.5);          // bin-nr. for pad-position 0.5
-  bin1 = bin1 + 1;
-  bin0 = bin0 + 1;  //avoid negative values in aYest (start right of symmetry center)
-  while (bin0-sPad<0) {
-    bin0 = bin0 + 1;
-  }
-  while (bin1+sPad>=nBin) {
-    bin1 = bin1 - 1;
+  if (opt.Contains("H")) {
+    printf("Found %i hits:\n", fNHits);
+    for (Int_t iHit = 0; iHit < fNHits; iHit++) {
+      printf("Hit %3i in timebin %2i, ADC %2i has charge %3i and position %3i\n",
+             iHit,  fHits[iHit].timebin, fHits[iHit].channel, fHits[iHit].qtot, fHits[iHit].ypos);
+    }
   }
-  
-  Double_t* aYest = new Double_t[bin1-bin0+1];
 
-  /*TH1F* hist1 = new TH1F("h1","yest(y)",128,0,0.5);
-  TH1F* hist2 = new TH1F("h2","y(yest)",128,0,0.5);
-  TH1F* hist3 = new TH1F("h3","y(yest)-yest",128,0,0.5);
-  TH1F* hist4 = new TH1F("h4","y(yest)-yest,discrete",128,0,0.5);
-  TCanvas *c1 = new TCanvas("c1","c1",800,1000);
-  hist1->Draw();
-  TCanvas *c2 = new TCanvas("c2","c2",800,1000);
-  hist2->Draw();
-  TCanvas *c3 = new TCanvas("c3","c3",800,1000);
-  hist3->Draw();
-  TCanvas *c4 = new TCanvas("c4","c4",800,1000);
-  hist4->Draw();*/
-  
-  for(Int_t iBin = bin0; iBin <= bin1; iBin++){
-    aYest[iBin-bin0] = 0.5*(sPRFlayer[iBin-sPad] - sPRFlayer[iBin+sPad])/(sPRFlayer[iBin]); // estimated position from PRF; between 0 and 1
-    //Double_t position = ((Double_t)(iBin)+0.5)*sWidth+iLo;
-    //  hist1->Fill(position,aYest[iBin-bin0]);
+  if (opt.Contains("T")) {
+    printf("Tracklets:\n");
+    for (Int_t iTrkl = 0; iTrkl < fTrackletArray->GetEntriesFast(); iTrkl++) {
+      printf("tracklet %i: 0x%08x\n", iTrkl, ((AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl])->GetTrackletWord());
+    }
   }
-  
-
-
-  Double_t aY[128]; // reversed function
+}
 
-  AliTRDtrapAlu a;
-  a.Init(1,8,0,31);
-  
-  for(Int_t j = 0; j<128; j++) { // loop over all Yest; LUT has 128 entries; 
-    Double_t yest = ((Double_t)j)/256; 
-    
-    Int_t iBin = 0;
-    while (yest>aYest[iBin] && iBin<(bin1-bin0)) {
-      iBin = iBin+1;
-    }
-    if((iBin == bin1 - bin0)&&(yest>aYest[iBin])) {
-      aY[j] = 0.5;                      // yest too big
-      //hist2->Fill(yest,aY[j]);
-      
+void AliTRDmcmSim::Draw(Option_t* option) 
+{
+  // Plots the data stored in a 2-dim. timebin vs. ADC channel plot.
+  // The option selects what data is plotted and can be a sequence of 
+  // the following characters:
+  // R - plot raw data (default)
+  // F - plot filtered data (meaningless if R is specified)
+  // In addition to the ADC values:
+  // H - plot hits 
+  // T - plot tracklets
+
+  TString opt = option;
+
+  TH2F *hist = new TH2F("mcmdata", Form("Data of MCM %i on ROB %i in detector %i", \
+                                        fMcmPos, fRobPos, fDetector), \
+                        fNADC, -0.5, fNADC-.5, fNTimeBin, -.5, fNTimeBin-.5);
+  hist->GetXaxis()->SetTitle("ADC Channel");
+  hist->GetYaxis()->SetTitle("Timebin");
+  hist->SetStats(kFALSE);
+
+  if (opt.Contains("R")) {
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+        hist->SetBinContent(iAdc+1, iTimeBin+1, fADCR[iAdc][iTimeBin] >> fgkAddDigits);
+      }
     }
-    else {
-      Int_t bin_d = iBin + bin0 - 1;
-      Int_t bin_u = iBin + bin0;
-      Double_t y_d = ((Double_t)bin_d + 0.5)*sWidth + iLo; // lower y
-      Double_t y_u = ((Double_t)bin_u + 0.5)*sWidth + iLo; // upper y
-      Double_t yest_d = aYest[iBin-1];                     // lower estimated y
-      Double_t yest_u = aYest[iBin];                       // upper estimated y
-      
-      aY[j] = ((yest-yest_d)/(yest_u-yest_d))*(y_u-y_d) + y_d;
-      //hist2->Fill(yest,aY[j]);
-     
+  }
+  else {
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+        hist->SetBinContent(iAdc+1, iTimeBin+1, fADCF[iAdc][iTimeBin] >> fgkAddDigits);
+      }
     }
-    aY[j] = aY[j] - yest;
-    //hist3->Fill(yest,aY[j]);
-    // formatting
-    a.AssignDouble(aY[j]);
-    //a.WriteWord();
-    fPosLUT[j] = a.GetValue(); // 1+8Bit value;128 entries;LUT is steered by abs(Q(i+1)-Q(i-1))/Q(i)=COG and gives the correction to COG/2
-    //hist4->Fill(yest,fPosLUT[j]);
-    
   }
-   
-  
-  delete [] sPRFsmp;
-  delete [] sPRFlayer;
-  delete [] aYest;
-  
-}
+  hist->Draw("colz");
 
+  if (opt.Contains("H")) {
+    TGraph *grHits = new TGraph();
+    for (Int_t iHit = 0; iHit < fNHits; iHit++) {
+      grHits->SetPoint(iHit, 
+                       fHits[iHit].channel + 1 + fHits[iHit].ypos/256., 
+                       fHits[iHit].timebin);
+    }
+    grHits->Draw("*");
+  }
 
-//_____________________________________________________________________________
-Int_t* AliTRDmcmSim::GetPosLUT(){
-  return fPosLUT;
+  if (opt.Contains("T")) {
+    TLine *trklLines = new TLine[4];
+    for (Int_t iTrkl = 0; iTrkl < 4; iTrkl++) {
+      if (fMCMT[iTrkl] == 0x10001000)
+        break;
+      AliTRDpadPlane *pp = fGeo->GetPadPlane(fDetector);
+      AliTRDtrackletMCM *trkl = (AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl];
+      Float_t offset = pp->GetColPos(fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, 19)) + 19 * pp->GetWidthIPad();
+      trklLines[iTrkl].SetX1((offset -  trkl->GetY()) / pp->GetWidthIPad());
+      trklLines[iTrkl].SetY1(0);
+      trklLines[iTrkl].SetX2((offset - (trkl->GetY() + ((Float_t) trkl->GetdY())*140e-4)) / pp->GetWidthIPad());
+      trklLines[iTrkl].SetY2(fNTimeBin - 1);
+      trklLines[iTrkl].SetLineColor(2);
+      trklLines[iTrkl].SetLineWidth(2);
+      printf("Tracklet %i: y = %f, dy = %f, offset = %f\n", iTrkl, trkl->GetY(), (trkl->GetdY() * 140e-4), offset);
+      trklLines[iTrkl].Draw();
+    }
+  }
 }
 
-
-
 void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
 {
   //
@@ -479,16 +455,16 @@ void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
   if( !CheckInitialized() ) return;
 
   if( iadc < 0 || iadc >= fNADC ) {
-    //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
+                       //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
     return;
   }
 
   for( int it = 0 ;  it < fNTimeBin ; it++ ) {
-    fADCR[iadc][it] = (Int_t)(adc[it]);
+    fADCR[iadc][it] = (Int_t) (adc[it]) << fgkAddDigits;
+    fADCF[iadc][it] = (Int_t) (adc[it]) << fgkAddDigits;
   }
 }
 
-//_____________________________________________________________________________
 void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
 {
   //
@@ -502,10 +478,51 @@ void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
     return;
   }
 
-  fADCR[iadc][it] = adc;
+  fADCR[iadc][it] = adc << fgkAddDigits;
+  fADCF[iadc][it] = adc << fgkAddDigits;
+}
+
+void AliTRDmcmSim::SetData(AliTRDarrayADC *adcArray)
+{
+  if (!fInitialized) {
+    AliError("Called uninitialized! Aborting!");
+    return;
+  }
+
+  Int_t firstAdc = 0;
+  Int_t lastAdc = fNADC-1;
+
+  if (GetCol(firstAdc) > 143) {
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      fADCR[firstAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
+      fADCF[firstAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
+    }
+    firstAdc = 1;
+  }
+
+  if (GetCol(lastAdc) < 0) {
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+      fADCR[lastAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
+      fADCF[lastAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
+    }
+    lastAdc = fNADC - 2;
+  }
+
+  for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+    for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
+      Int_t value = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin);
+      if (value < 0) {
+        fADCR[iAdc][iTimeBin] = 0;
+        fADCF[iAdc][iTimeBin] = 0;
+      }
+      else {
+        fADCR[iAdc][iTimeBin] = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin) << fgkAddDigits;
+        fADCF[iAdc][iTimeBin] = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin) << fgkAddDigits;
+      }
+    }
+  }
 }
 
-//_____________________________________________________________________________
 void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
 {
   //
@@ -520,11 +537,11 @@ void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
   }
 
   for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
-    fADCR[iadc][it] = fSimParam->GetADCbaseline();
+    fADCR[iadc][it] = fSimParam->GetADCbaseline() << fgkAddDigits;
+    fADCF[iadc][it] = fSimParam->GetADCbaseline() << fgkAddDigits;
   }
 }
 
-//_____________________________________________________________________________
 Int_t AliTRDmcmSim::GetCol( Int_t iadc )
 {
   //
@@ -536,82 +553,7 @@ Int_t AliTRDmcmSim::GetCol( Int_t iadc )
   return fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, iadc);
 }
 
-//_____________________________________________________________________________
-Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize )
-{
-  //
-  // Produce raw data stream from this MCM and put in buf
-  // Returns number of words filled, or negative value 
-  // with -1 * number of overflowed words
-  //
-
-  UInt_t  x;
-  UInt_t  iEv = 0;
-  Int_t   nw  = 0;  // Number of written words
-  Int_t   of  = 0;  // Number of overflowed words
-  Int_t   rawVer   = fFeeParam->GetRAWversion();
-  Int_t **adc;
-
-  if( !CheckInitialized() ) return 0;
-
-  if( fFeeParam->GetRAWstoreRaw() ) {
-    adc = fADCR;
-  } else {
-    adc = fADCF;
-  }
-
-  // Produce MCM header
-  x = ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
-  if (nw < maxSize) {
-    buf[nw++] = x;
-  }
-  else {
-    of++;
-  }
-
-  // Produce ADC mask
-  if( rawVer >= 3 ) {
-    x = 0;
-    for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
-      if( fZSM1Dim[iAdc] == 0 ) { //  0 means not suppressed
-       x = x | (1 << iAdc);
-      }
-    }
-    if (nw < maxSize) {
-      buf[nw++] = x;
-    }
-    else {
-      of++;
-    }
-  }
-
-  // Produce ADC data. 3 timebins are packed into one 32 bits word
-  // In this version, different ADC channel will NOT share the same word
-
-  UInt_t aa=0, a1=0, a2=0, a3=0;
-
-  for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
-    if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // suppressed
-    aa = !(iAdc & 1) + 2;
-    for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
-      a1 = ((iT    ) < fNTimeBin ) ? adc[iAdc][iT  ] : 0;
-      a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
-      a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
-      x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
-      if (nw < maxSize) {
-       buf[nw++] = x;
-      }
-      else {
-       of++;
-      }
-    }
-  }
-
-  if( of != 0 ) return -of; else return nw;
-}
-
-//_____________________________________________________________________________
-Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
+Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize, UInt_t iEv)
 {
   //
   // Produce raw data stream from this MCM and put in buf
@@ -620,7 +562,6 @@ Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
   //
 
   UInt_t  x;
-  //UInt_t  iEv = 0;
   Int_t   nw  = 0;  // Number of written words
   Int_t   of  = 0;  // Number of overflowed words
   Int_t   rawVer   = fFeeParam->GetRAWversion();
@@ -635,13 +576,9 @@ Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
     adc = fADCF;
   }
 
-  // Produce MCM header : xrrr mmmm eeee eeee eeee eeee eeee 1100
-  //                      x : 0 before , 1 since 10.2007
-  //                      r : Readout board position (Alice numbering)
-  //                      m : MCM posi
-  //                      e : Event counter from 1
-  //x = (1<<31) | ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
+  // Produce MCM header
   x = (1<<31) | (fRobPos << 28) | (fMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC;
+
   if (nw < maxSize) {
     buf[nw++] = x;
        //printf("\nMCM header: %X ",x);
@@ -679,18 +616,18 @@ Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
 
   for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
     if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // Zero Suppression, 0 means not suppressed
-    aa = !(iAdc & 1) + 2;      // 3 for the even ADC channel , 2 for the odd ADC channel
+    aa = !(iAdc & 1) + 2;
     for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
-      a1 = ((iT    ) < fNTimeBin ) ? adc[iAdc][iT  ] : 0;
-      a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
-      a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
+      a1 = ((iT    ) < fNTimeBin ) ? adc[iAdc][iT  ] >> fgkAddDigits : 0;
+      a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] >> fgkAddDigits : 0;
+      a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] >> fgkAddDigits : 0;
       x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
       if (nw < maxSize) {
-       buf[nw++] = x;
-       //printf("%08X ",x);
+        buf[nw++] = x;
+        //printf("%08X ",x);
       }
       else {
-       of++;
+        of++;
       }
     }
   }
@@ -698,7 +635,6 @@ Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
   if( of != 0 ) return -of; else return nw;
 }
 
-//_____________________________________________________________________________
 Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t maxSize )
 {
   //
@@ -731,124 +667,264 @@ Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t maxSize )
   if( of != 0 ) return -of; else return nw;
 }
 
-
-//_____________________________________________________________________________
 void AliTRDmcmSim::Filter()
 {
   //
-  // Apply digital filter
+  // Filter the raw ADC values. The active filter stages and their
+  // parameters are taken from AliTRDtrapConfig.
+  // The raw data is stored separate from the filtered data. Thus, 
+  // it is possible to run the filters on a set of raw values 
+  // sequentially for parameter tuning.
   //
 
-  if( !CheckInitialized() ) return;
-
-  // Initialize filtered data array with raw data
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
-    for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
-      fADCF[iadc][it] = fADCR[iadc][it]; 
-    }
+  if( !CheckInitialized() ) {
+    AliError("got called before initialization! Nothing done!");
+    return;
   }
 
-  // Then apply fileters one by one to filtered data array
-  if( fFeeParam->IsPFon() ) FilterPedestal();
-  if( fFeeParam->IsGFon() ) FilterGain();
-  if( fFeeParam->IsTFon() ) FilterTail();
+  // Apply filters sequentially. Bypass is handled by filters
+  // since counters and internal registers may be updated even 
+  // if the filter is bypassed.
+  // The first filter takes the data from fADCR and 
+  // outputs to fADCF. 
+  
+  // Non-linearity filter not implemented.
+  FilterPedestal();
+  FilterGain();
+  FilterTail();
+  // Crosstalk filter not implemented.
 }
 
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterPedestal()
+void AliTRDmcmSim::FilterPedestalInit() 
+{
+  // Initializes the pedestal filter assuming that the input has 
+  // been constant for a long time (compared to the time constant).
+
+//  UShort_t    fpnp = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP); // 0..511 -> 0..127.75, pedestal at the output
+  UShort_t    fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC); // 0..3, 0 - fastest, 3 - slowest
+  UShort_t    shifts[4] = {11, 14, 17, 21}; //??? where to take shifts from?
+
+  for (Int_t iAdc = 0; iAdc < fNADC; iAdc++)
+    fPedAcc[iAdc] = (fSimParam->GetADCbaseline() << 2) * (1<<shifts[fptc]);
+}
+
+UShort_t AliTRDmcmSim::FilterPedestalNextSample(Int_t adc, Int_t timebin, UShort_t value)
 {
+  // Returns the output of the pedestal filter given the input value.
+  // The output depends on the internal registers and, thus, the 
+  // history of the filter.
+
+  UShort_t    fpnp = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP); // 0..511 -> 0..127.75, pedestal at the output
+  UShort_t    fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC); // 0..3, 0 - fastest, 3 - slowest
+  UShort_t    fpby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPBY); // 0..1 the bypass, active low
+  UShort_t    shifts[4] = {11, 14, 17, 21}; //??? where to come from
+
+  UShort_t accumulatorShifted;
+  Int_t correction;
+  UShort_t inpAdd;
+  
+  inpAdd = value + fpnp;
+
+  if (fpby == 0) //??? before or after update of accumulator
+    return value;
+
+  accumulatorShifted = (fPedAcc[adc] >> shifts[fptc]) & 0x3FF;   // 10 bits
+  if (timebin == 0) // the accumulator is disabled in the drift time
+  {
+    correction = (value & 0x3FF) - accumulatorShifted;
+    fPedAcc[adc] = (fPedAcc[adc] + correction) & 0x7FFFFFFF;             // 31 bits
+  }
+  
+  if (inpAdd <= accumulatorShifted)
+    return 0;
+  else
+  {
+    inpAdd = inpAdd - accumulatorShifted;
+    if (inpAdd > 0xFFF) 
+      return 0xFFF;
+    else 
+      return inpAdd;
+  }
+}
 
-     
+void AliTRDmcmSim::FilterPedestal()
+{
   //
   // Apply pedestal filter
   //
+  // As the first filter in the chain it reads data from fADCR 
+  // and outputs to fADCF. 
+  // It has only an effect if previous samples have been fed to 
+  // find the pedestal. Currently, the simulation assumes that 
+  // the input has been stable for a sufficiently long time.
 
-  Int_t ap = fSimParam->GetADCbaseline();      // ADC instrinsic pedestal
-  Int_t ep = fFeeParam->GetPFeffectPedestal(); // effective pedestal
-  //Int_t tc = fFeeParam->GetPFtimeConstant();   // this makes no sense yet
-
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
-    for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
-      fADCF[iadc][it] = fADCF[iadc][it] - ap + ep;
+  for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+    for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+      fADCF[iAdc][iTimeBin] = FilterPedestalNextSample(iAdc, iTimeBin, fADCR[iAdc][iTimeBin]);
     }
   }
 }
 
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterGain()
+void AliTRDmcmSim::FilterGainInit()
 {
-  //
-  // Apply gain filter (not implemented)
-  // Later it will be implemented because gain digital filiter will
-  // increase noise level.
-  //
+  // Initializes the gain filter. In this case, only threshold 
+  // counters are reset.
 
+  for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+    // these are counters which in hardware continue 
+    // until maximum or reset
+    fGainCounterA[iAdc] = 0;
+    fGainCounterB[iAdc] = 0;
+  }
 }
 
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterTail()
+UShort_t AliTRDmcmSim::FilterGainNextSample(Int_t adc, UShort_t value)
 {
-  //
-  // Apply exponential tail filter (Bogdan's version)
-  //
+  // Apply the gain filter to the given value.
+  // BEGIN_LATEX O_{i}(t) = #gamma_{i} * I_{i}(t) + a_{i} END_LATEX
+  // The output depends on the internal registers and, thus, the 
+  // history of the filter.
 
-  Double_t *dtarg  = new Double_t[fNTimeBin];
-  Int_t    *itarg  = new Int_t[fNTimeBin];
-  Int_t     nexp   = fFeeParam->GetTFnExp();
-  Int_t     tftype = fFeeParam->GetTFtype();
+  UShort_t    fgby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGBY); // bypass, active low
+  UShort_t    fgf  = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGF0 + adc)); // 0x700 + (0 & 0x1ff);
+  UShort_t    fga  = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGA0 + adc)); // 40;
+  UShort_t    fgta = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTA); // 20;
+  UShort_t    fgtb = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTB); // 2060;
 
-  switch( tftype ) {
-    
-  case 0: // Exponential Filter Analog Bogdan
-    for (Int_t iCol = 0; iCol < fNADC; iCol++) {
-      FilterSimDeConvExpA( fADCF[iCol], dtarg, fNTimeBin, nexp);
-      for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
-       fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
-      }
-    }
-    break;
+  UInt_t tmp;
 
-  case 1: // Exponential filter digital Bogdan
-    for (Int_t iCol = 0; iCol < fNADC; iCol++) {
-      FilterSimDeConvExpD( fADCF[iCol], itarg, fNTimeBin, nexp);
-      for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
-       fADCF[iCol][iTime] = itarg[iTime];
-      }
-    }
-    break;
-    
-  case 2: // Exponential filter Marian special
-    for (Int_t iCol = 0; iCol < fNADC; iCol++) {
-      FilterSimDeConvExpMI( fADCF[iCol], dtarg, fNTimeBin);
-      for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
-       fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
-      }
-    }
-    break;
-
-    //new
-  case 3: // Exponential filter using AliTRDtrapAlu class
-    for (Int_t iCol = 0; iCol < fNADC; iCol++) {
-      FilterSimDeConvExpEl( fADCF[iCol], itarg, fNTimeBin, nexp);
-      for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
-       fADCF[iCol][iTime] = itarg[iTime]>>2; // to be used for raw-data
-       fADCT[iCol][iTime] = itarg[iTime];    // 12bits; to be used for tracklet; tracklet will have own container; 
-      }
+  value &= 0xFFF;
+  tmp = (value * fgf) >> 11;
+  if (tmp > 0xFFF) tmp = 0xFFF;
+
+  if (fgby == 1)
+    value = AddUintClipping(tmp, fga, 12);
+
+  // Update threshold counters 
+  // not really useful as they are cleared with every new event
+  if ((fGainCounterA[adc] == 0x3FFFFFF) || (fGainCounterB[adc] == 0x3FFFFFF))
+  {
+    if (value >= fgtb) 
+      fGainCounterB[adc]++;
+    else if (value >= fgta) 
+      fGainCounterA[adc]++;
+  }
+
+  return value;
+}
+
+void AliTRDmcmSim::FilterGain()
+{
+  // Read data from fADCF and apply gain filter.
+
+  for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+    for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+        fADCF[iAdc][iTimeBin] = FilterGainNextSample(iAdc, fADCF[iAdc][iTimeBin]);
     }
-    break;
+  }
+}
 
-    
-  default:
-    AliError(Form("Invalid filter type %d ! \n", tftype ));
-    break;
+void AliTRDmcmSim::FilterTailInit(Int_t baseline)
+{
+  // Initializes the tail filter assuming that the input has 
+  // been at the baseline value (configured by FTFP) for a 
+  // sufficiently long time.
+
+  // exponents and weight calculated from configuration
+  UShort_t    alphaLong = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL); // the weight of the long component
+  UShort_t    lambdaLong = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL) & 0x1FF); // the multiplier
+  UShort_t    lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS) & 0x1FF); // the multiplier
+
+  Float_t lambdaL = lambdaLong  * 1.0 / (1 << 11);
+  Float_t lambdaS = lambdaShort * 1.0 / (1 << 11);
+  Float_t alphaL  = alphaLong   * 1.0 / (1 << 11);
+  Float_t qup, qdn;
+  qup = (1 - lambdaL) * (1 - lambdaS);
+  qdn = 1 - lambdaS * alphaL - lambdaL * (1 - alphaL);
+  Float_t kdc = qup/qdn;
+
+  Float_t kt, ql, qs;
+  UShort_t aout;
+  
+  kt = kdc * baseline;
+  aout = baseline - (UShort_t) kt;
+  ql = lambdaL * (1 - lambdaS) *      alphaL;
+  qs = lambdaS * (1 - lambdaL) * (1 - alphaL);
+
+  for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+    fTailAmplLong[iAdc]  = (UShort_t) (aout * ql / (ql + qs));
+    fTailAmplShort[iAdc] = (UShort_t) (aout * qs / (ql + qs));
+  }
+}
+
+UShort_t AliTRDmcmSim::FilterTailNextSample(Int_t adc, UShort_t value)
+{
+  // Returns the output of the tail filter for the given input value. 
+  // The output depends on the internal registers and, thus, the 
+  // history of the filter.
+
+  // exponents and weight calculated from configuration
+  UShort_t    alphaLong = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL); // the weight of the long component
+  UShort_t    lambdaLong = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL) & 0x1FF); // the multiplier
+  UShort_t    lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS) & 0x1FF); // the multiplier
+
+  Float_t lambdaL = lambdaLong  * 1.0 / (1 << 11);
+  Float_t lambdaS = lambdaShort * 1.0 / (1 << 11);
+  Float_t alphaL  = alphaLong   * 1.0 / (1 << 11);
+  Float_t qup, qdn;
+  qup = (1 - lambdaL) * (1 - lambdaS);
+  qdn = 1 - lambdaS * alphaL - lambdaL * (1 - alphaL);
+//  Float_t kdc = qup/qdn;
+
+  UInt_t aDiff;
+  UInt_t alInpv;
+  UShort_t aQ;
+  UInt_t tmp;
+  
+  UShort_t inp_volt = value & 0xFFF;    // 12 bits
+      
+  if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTBY) == 0) // bypass mode, active low
+    return value;
+  else
+  {   
+    // add the present generator outputs
+    aQ = AddUintClipping(fTailAmplLong[adc], fTailAmplShort[adc], 12);
+
+    // calculate the difference between the input the generated signal
+    if (inp_volt > aQ) 
+      aDiff = inp_volt - aQ;
+    else                
+      aDiff = 0;
+
+    // the inputs to the two generators, weighted
+    alInpv = (aDiff * alphaLong) >> 11;
+
+    // the new values of the registers, used next time
+    // long component
+    tmp = AddUintClipping(fTailAmplLong[adc], alInpv, 12);
+    tmp =  (tmp * lambdaLong) >> 11;
+    fTailAmplLong[adc] = tmp & 0xFFF;
+    // short component
+    tmp = AddUintClipping(fTailAmplShort[adc], aDiff - alInpv, 12);
+    tmp =  (tmp * lambdaShort) >> 11;
+    fTailAmplShort[adc] = tmp & 0xFFF;
+
+    // the output of the filter
+    return aDiff;
   }
+}
 
-  delete [] dtarg;
-  delete [] itarg;
+void AliTRDmcmSim::FilterTail()
+{
+  // Apply tail filter
 
+  for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+    for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
+      fADCF[iAdc][iTimeBin] = FilterTailNextSample(iAdc, fADCF[iAdc][iTimeBin]);
+    }
+  }
 }
 
-//_____________________________________________________________________________
 void AliTRDmcmSim::ZSMapping()
 {
   //
@@ -858,23 +934,29 @@ void AliTRDmcmSim::ZSMapping()
   // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
   //
 
-  Int_t eBIS = fFeeParam->GetEBsglIndThr();       // TRAP default = 0x4  (Tis=4)
-  Int_t eBIT = fFeeParam->GetEBsumIndThr();       // TRAP default = 0x28 (Tit=40)
-  Int_t eBIL = fFeeParam->GetEBindLUT();          // TRAP default = 0xf0
-                                                  // (lookup table accept (I2,I1,I0)=(111)
-                                                  // or (110) or (101) or (100))
-  Int_t eBIN = fFeeParam->GetEBignoreNeighbour(); // TRAP default = 1 (no neighbor sensitivity)
+  //??? values should come from TRAPconfig
+  Int_t eBIS = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIS); // TRAP default = 0x4  (Tis=4)
+  Int_t eBIT = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIT); // TRAP default = 0x28 (Tit=40)
+  Int_t eBIL = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIL); // TRAP default = 0xf0
+                                                                 // (lookup table accept (I2,I1,I0)=(111)
+                                                                 // or (110) or (101) or (100))
+  Int_t eBIN = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIN); // TRAP default = 1 (no neighbor sensitivity)
   Int_t ep   = AliTRDfeeParam::GetPFeffectPedestal();
 
-  if( !CheckInitialized() ) return;
+  Int_t **adc = fADCF;
 
-  for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
-    for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
+  if( !CheckInitialized() ) {
+    AliError("got called uninitialized! Aborting!");    
+    return;
+  }
+
+  for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
+    for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
 
       // Get ADC data currently in filter buffer
-      Int_t ap = fADCF[iadc-1][it] - ep; // previous
-      Int_t ac = fADCF[iadc  ][it] - ep; // current
-      Int_t an = fADCF[iadc+1][it] - ep; // next
+      Int_t ap = adc[iadc-1][it] - ep; // previous
+      Int_t ac = adc[iadc  ][it] - ep; // current
+      Int_t an = adc[iadc+1][it] - ep; // next
 
       // evaluate three conditions
       Int_t i0 = ( ac >=  ap && ac >=  an ) ? 0 : 1; // peak center detection
@@ -890,7 +972,6 @@ void AliTRDmcmSim::ZSMapping()
        fZSM[iadc-1][it] &= d;
        fZSM[iadc+1][it] &= d;
       }
-
     }
   }
 
@@ -903,7 +984,6 @@ void AliTRDmcmSim::ZSMapping()
 
 }
 
-//_____________________________________________________________________________
 void AliTRDmcmSim::DumpData( char *f, char *target )
 {
   //
@@ -922,7 +1002,8 @@ void AliTRDmcmSim::DumpData( char *f, char *target )
 
   std::ofstream of( f, std::ios::out | std::ios::app );
   of << Form("AliTRDmcmSim::DumpData det=%03d sm=%02d stack=%d layer=%d rob=%d mcm=%02d\n",
-            fChaId, fSector, fStack, fLayer, fRobPos, fMcmPos );
+            fDetector, fGeo->GetSector(fDetector), fGeo->GetStack(fDetector), 
+             fGeo->GetSector(fDetector), fRobPos, fMcmPos );
 
   for( int t=0 ; target[t] != 0 ; t++ ) {
     switch( target[t] ) {
@@ -972,1794 +1053,670 @@ void AliTRDmcmSim::DumpData( char *f, char *target )
   }
 }
 
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterSimDeConvExpA(Int_t *source, Double_t *target
-                                     , Int_t n, Int_t nexp) 
-{
-  //
-  // Exponential filter "analog"
-  // source will not be changed
-  //
-
-  Int_t    i = 0;
-  Int_t    k = 0;
-  Double_t reminder[2];
-  Double_t correction;
-  Double_t result;
-  Double_t rates[2];
-  Double_t coefficients[2];
-
-  // Initialize (coefficient = alpha, rates = lambda)
-  // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
-
-  Double_t r1 = (Double_t)fFeeParam->GetTFr1();
-  Double_t r2 = (Double_t)fFeeParam->GetTFr2();
-  Double_t c1 = (Double_t)fFeeParam->GetTFc1();
-  Double_t c2 = (Double_t)fFeeParam->GetTFc2();
-  
-  coefficients[0] = c1;
-  coefficients[1] = c2;
-
-  Double_t dt = 0.1;
-  rates[0] = TMath::Exp(-dt/(r1));
-  rates[1] = TMath::Exp(-dt/(r2));
-
-  // Attention: computation order is important
-  correction = 0.0;
-  for (k = 0; k < nexp; k++) {
-    reminder[k] = 0.0;
-  }
-    
-  for (i = 0; i < n; i++) {
-
-    result    = ((Double_t)source[i] - correction);    // no rescaling
-    target[i] = result;
-    
-    for (k = 0; k < nexp; k++) {
-      reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
-    }
-      
-    correction = 0.0;
-    for (k = 0; k < nexp; k++) {
-      correction += reminder[k];
-    }
-  }
-}
-
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n
-                                     , Int_t nexp) 
+void AliTRDmcmSim::AddHitToFitreg(Int_t adc, UShort_t timebin, UShort_t qtot, Short_t ypos, Int_t label) 
 {
-  //
-  // Exponential filter "digital"
-  // source will not be changed
-  //
-
-  Int_t i        = 0;
-  Int_t fAlphaL  = 0;
-  Int_t fAlphaS  = 0;
-  Int_t fTailPed = 0;
-  Int_t iAlphaL  = 0;
-  Int_t iAlphaS  = 0;
-
-  // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
-  // initialize (coefficient = alpha, rates = lambda)
-
-  Double_t dt = 0.1;
-  Double_t r1 = (Double_t)fFeeParam->GetTFr1();
-  Double_t r2 = (Double_t)fFeeParam->GetTFr2();
-  Double_t c1 = (Double_t)fFeeParam->GetTFc1();
-  Double_t c2 = (Double_t)fFeeParam->GetTFc2();
-
-  Int_t fLambdaL = (Int_t)((TMath::Exp(-dt/r1) - 0.75) * 2048.0);
-  Int_t fLambdaS = (Int_t)((TMath::Exp(-dt/r2) - 0.25) * 2048.0);
-  Int_t iLambdaL = fLambdaL & 0x01FF; iLambdaL |= 0x0600; //  9 bit paramter + fixed bits
-  Int_t iLambdaS = fLambdaS & 0x01FF; iLambdaS |= 0x0200; //  9 bit paramter + fixed bits
-
-  if (nexp == 1) {
-    fAlphaL = (Int_t) (c1 * 2048.0);
-    iAlphaL = fAlphaL & 0x03FF;                                // 10 bit paramter
-  }
-  if (nexp == 2) {
-    fAlphaL = (Int_t) (c1 * 2048.0);
-    fAlphaS = (Int_t) ((c2 - 0.5) * 2048.0);
-    iAlphaL = fAlphaL & 0x03FF;                                // 10 bit paramter
-    iAlphaS = fAlphaS & 0x03FF; iAlphaS |= 0x0400;             // 10 bit paramter + fixed bits
-  }
-  
-  Double_t iAl = iAlphaL  / 2048.0;           // alpha  L: correspondence to floating point numbers
-  Double_t iAs = iAlphaS  / 2048.0;           // alpha  S: correspondence to floating point numbers
-  Double_t iLl = iLambdaL / 2048.0;           // lambda L: correspondence to floating point numbers
-  Double_t iLs = iLambdaS / 2048.0;           // lambda S: correspondence to floating point numbers
-
-  Int_t h1;
-  Int_t h2;
-  Int_t rem1;
-  Int_t rem2;
-  Int_t correction;
-  Int_t result;
-  Int_t iFactor = ((Int_t) fFeeParam->GetPFeffectPedestal() ) << 2;
-
-  Double_t xi = 1 - (iLl*iAs + iLs*iAl);            // Calculation of equilibrium values of the
-  rem1 = (Int_t) ((iFactor/xi) * ((1-iLs)*iLl*iAl)); // Internal registers to prevent switch on effects.
-  rem2 = (Int_t) ((iFactor/xi) * ((1-iLl)*iLs*iAs));
-  
-  // further initialization
-  if ((rem1 + rem2) > 0x0FFF) {
-    correction = 0x0FFF;
-  } 
-  else {
-    correction = (rem1 + rem2) & 0x0FFF;
-  }
-
-  fTailPed = iFactor - correction;
-
-  for (i = 0; i < n; i++) {
-
-    result = (source[i]  - correction);
-    if (result < 0) { // Too much undershoot
-      result = 0;
-    }
-
-    target[i] = result;
-                                                        
-    h1 = (rem1 + ((iAlphaL * result) >> 11));
-    if (h1 > 0x0FFF) {
-      h1 = 0x0FFF;
-    } 
-    else {
-      h1 &= 0x0FFF;
-    }
-
-    h2 = (rem2 + ((iAlphaS * result) >> 11));
-    if (h2 > 0x0FFF) {
-      h2 = 0x0FFF;
-    } 
-    else {
-      h2 &= 0x0FFF;
-    }
-  
-    rem1 = (iLambdaL * h1 ) >> 11;
-    rem2 = (iLambdaS * h2 ) >> 11;
-    
-    if ((rem1 + rem2) > 0x0FFF) {
-      correction = 0x0FFF;
-    } 
-    else {
-      correction = (rem1 + rem2) & 0x0FFF;
-    }
-
-  }
-
-}
-
-//_____________________________________________________________________________
-void AliTRDmcmSim::FilterSimDeConvExpMI(Int_t *source, Double_t *target
-                                      , Int_t n) 
-{
-  //
-  // Exponential filter (M. Ivanov)
-  // source will not be changed
-  //
-
-  Int_t i = 0;
-  Double_t sig1[100];
-  Double_t sig2[100];
-  Double_t sig3[100];
-
-  for (i = 0; i < n; i++) {
-    sig1[i] = (Double_t)source[i];
-  }
-
-  Float_t dt      = 0.1;
-  Float_t lambda0 = (1.0 / fFeeParam->GetTFr2()) * dt;
-  Float_t lambda1 = (1.0 / fFeeParam->GetTFr1()) * dt;
-
-  FilterSimTailMakerSpline( sig1, sig2, lambda0, n);
-  FilterSimTailCancelationMI( sig2, sig3, 0.7, lambda1, n);
-
-  for (i = 0; i < n; i++) {
-    target[i] = sig3[i];
-  }
-
-}
-
-//______________________________________________________________________________
-void AliTRDmcmSim::FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout
-                                          , Double_t lambda, Int_t n) 
-{
-  //
-  // Special filter (M. Ivanov)
-  //
-
-  Int_t    i = 0;
-  Double_t l = TMath::Exp(-lambda*0.5);
-  Double_t in[1000];
-  Double_t out[1000];
-
-  // Initialize in[] and out[] goes 0 ... 2*n+19
-  for (i = 0; i < n*2+20; i++) {
-    in[i] = out[i] = 0;
-  }
-
-  // in[] goes 0, 1
-  in[0] = ampin[0];
-  in[1] = (ampin[0] + ampin[1]) * 0.5;
-   
-  // Add charge to the end
-  for (i = 0; i < 22; i++) {
-    in[2*(n-1)+i] = ampin[n-1]; // in[] goes 2*n-2, 2*n-1, ... , 2*n+19 
-  }
-
-  // Use arithmetic mean
-  for (i = 1; i < n-1; i++) {
-    in[2*i]   = ampin[i];    // in[] goes 2, 3, ... , 2*n-4, 2*n-3
-    in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.;
-  }
-
-  Double_t temp;
-  out[2*n]    = in[2*n];
-  temp        = 0;
-  for (i = 2*n; i >= 0; i--) {
-    out[i]    = in[i] + temp;
-    temp      = l*(temp+in[i]);
-  }
-
-  for (i = 0; i < n; i++){
-    //ampout[i] = out[2*i+1];  // org
-    ampout[i] = out[2*i];
-  }
-
+  // Add the given hit to the fit register which is lateron used for 
+  // the tracklet calculation. 
+  // In addition to the fit sums in the fit register MC information 
+  // is stored.
+
+  if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0)) && 
+      (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0)))
+    fFitReg[adc].Q0 += qtot;
+  
+  if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1)) && 
+      (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1)))
+    fFitReg[adc].Q1 += qtot;
+  
+  if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS) ) && 
+      (timebin <  fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE)))
+  {
+    fFitReg[adc].SumX  += timebin;
+    fFitReg[adc].SumX2 += timebin*timebin;
+    fFitReg[adc].Nhits++;
+    fFitReg[adc].SumY  += ypos;
+    fFitReg[adc].SumY2 += ypos*ypos;
+    fFitReg[adc].SumXY += timebin*ypos;
+  }
+
+  // register hits (MC info)
+  fHits[fNHits].channel = adc;
+  fHits[fNHits].qtot = qtot;
+  fHits[fNHits].ypos = ypos;
+  fHits[fNHits].timebin = timebin;
+  fHits[fNHits].label = label;
+  fNHits++;
 }
 
-//______________________________________________________________________________
-void AliTRDmcmSim::FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout
-                                            , Double_t norm, Double_t lambda
-                                            , Int_t n) 
+void AliTRDmcmSim::CalcFitreg() 
 {
-  //
-  // Special filter (M. Ivanov)
-  //
-
-  Int_t    i = 0;
-
-  Double_t l = TMath::Exp(-lambda*0.5);
-  Double_t k = l*(1.0 - norm*lambda*0.5);
-  Double_t in[1000];
-  Double_t out[1000];
-
-  // Initialize in[] and out[] goes 0 ... 2*n+19
-  for (i = 0; i < n*2+20; i++) {
-    in[i] = out[i] = 0;
-  }
-
-  // in[] goes 0, 1
-  in[0] = ampin[0];
-  in[1] = (ampin[0]+ampin[1])*0.5;
-
-  // Add charge to the end
-  for (i =-2; i < 22; i++) {
-    // in[] goes 2*n-4, 2*n-3, ... , 2*n+19 
-    in[2*(n-1)+i] = ampin[n-1];
-  }
-
-  for (i = 1; i < n-2; i++) {
-    // in[] goes 2, 3, ... , 2*n-6, 2*n-5
-    in[2*i]    = ampin[i];
-    in[2*i+1]  = (9.0 * (ampin[i]+ampin[i+1]) - (ampin[i-1]+ampin[i+2])) / 16.0;
-    //in[2*i+1]  = ((ampin[i]+ampin[i+1]))/2.0;
-  }
-
-  Double_t temp;
-  out[0] = in[0];
-  temp   = in[0];
-  for (i = 1; i <= 2*n; i++) {
-    out[i] = in[i] + (k-l)*temp;
-    temp   = in[i] +  k   *temp;
-  }
-
-  for (i = 0; i < n; i++) {
-    //ampout[i] = out[2*i+1];  // org
-    //ampout[i] = TMath::Max(out[2*i+1],0.0);  // org
-    ampout[i] = TMath::Max(out[2*i],0.0);
-  }
-}
-
-
-//_____________________________________________________________________________________
-//the following filter uses AliTRDtrapAlu-class
-
-void AliTRDmcmSim::FilterSimDeConvExpEl(Int_t *source, Int_t *target, Int_t n, Int_t nexp) {
-  //static Int_t count = 0;
-  Double_t dt = 0.1;
-  Double_t r1 = (Double_t)fFeeParam->GetTFr1();
-  Double_t r2 = (Double_t)fFeeParam->GetTFr2();
-  Double_t c1 = (Double_t)fFeeParam->GetTFc1();
-  Double_t c2 = (Double_t)fFeeParam->GetTFc2();
-  
-  nexp = 1;
-
-  //it is assumed that r1,r2,c1,c2 are given such, that the configuration values are in the ranges according to TRAP-manual
-  //parameters need to be adjusted
-  AliTRDtrapAlu lambdaL;
-  AliTRDtrapAlu lambdaS;
-  AliTRDtrapAlu alphaL;
-  AliTRDtrapAlu alphaS;
-  
-  AliTRDtrapAlu correction;
-  AliTRDtrapAlu result;
-  AliTRDtrapAlu bufL;
-  AliTRDtrapAlu bufS;
-  AliTRDtrapAlu bSource;
-  
-  lambdaL.Init(1,11);
-  lambdaS.Init(1,11);
-  alphaL.Init(1,11);
-  alphaS.Init(1,11);
-  
-  //count=count+1;
-
-  lambdaL.AssignDouble(TMath::Exp(-dt/r1));
-  lambdaS.AssignDouble(TMath::Exp(-dt/r2));
-  alphaL.AssignDouble(c1); // in AliTRDfeeParam the number of exponentials is set and also the according time constants
-  alphaS.AssignDouble(c2); // later it should be: alphaS=1-alphaL
-  
-  //data is enlarged to 12 bits, including 2 bits after the comma; class AliTRDtrapAlu is used to handle arithmetics correctly
-  correction.Init(10,2);
-  result.Init(10,2);
-  bufL.Init(10,2);
-  bufS.Init(10,2);
-  bSource.Init(10,2);
-  
-  for(Int_t i = 0; i < n; i++) {
-    bSource.AssignInt(source[i]);
-    result = bSource - correction; // subtraction can produce an underflow
-    if(result.GetSign() == kTRUE) {
-      result.AssignInt(0);
-    }
-    
-    //target[i] = result.GetValuePre();  // later, target and source should become AliTRDtrapAlu,too in order to simulate the 10+2Bits through the filter properly
-    
-    target[i] = result.GetValue(); // 12 bit-value; to get the corresponding integer value, target must be shifted: target>>2 
-
-    //printf("target-Wert zur Zeit %d : %d",i,target[i]);
-    //printf("\n");
-    
-    bufL  =  bufL + (result * alphaL);
-    bufL  =  bufL * lambdaL; 
-    
-    bufS  =  bufS + (result * alphaS);
-    bufS  =  bufS * lambdaS;  // eventually this should look like:
-    // bufS = (bufS + (result - result * alphaL)) * lambdaS // alphaS=1-alphaL; then alphaS-variable is not needed any more
-
-    correction = bufL + bufS; //check for overflow intrinsic; if overflowed, correction is set to 0x03FF
-  }
-  
-}
-
-
-
-
-
-
-
-//__________________________________________________________________________________
-
-
-// in order to use the Tracklets, please first 
-// -- set AliTRDfeeParam::fgkTracklet to kTRUE, in order to switch on Tracklet-calculation
-// -- set AliTRDfeeParam::fgkTFtype   to 3, in order to use the new tail cancellation filter
-//    currently tracklets from filtered digits are only given when setting fgkTFtype (AliTRDfeeParam) to 3
-// -- set AliTRDfeeParam::fgkMCTrackletOutput to kTRUE, if you want to use the Tracklet output container with          information about the Tracklet position (MCM, channel number)
-
-// The code is designed such that the less possible calculations with AliTRDtrapAlu class-objects are performed; whenever possible calculations are done with doubles or integers and the results are transformed into the right format
-
-void AliTRDmcmSim::Tracklet(){
-    // tracklet calculation
-    // if you use this code after a simulation, please make sure the same filter-settings as in the simulation are set in AliTRDfeeParam
-
-  if(!CheckInitialized()){ return; }
-  
-  Bool_t filtered = kTRUE;
-  
-  
-  
-  AliTRDtrapAlu data;
-  data.Init(10,2);
-  if(fADCT[0][0]==-1){                      // check if filter was applied
-    filtered = kFALSE;
-    for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
-      for( Int_t iT = 0 ; iT < fNTimeBin ; iT++ ) {
-       data.AssignInt(fADCR[iadc][iT]);
-       fADCT[iadc][iT] = data.GetValue(); // all incoming values are positive 10+2 bit values; if el.filter was called, this is done correctly
+  // Preprocessing.
+  // Detect the hits and fill the fit registers.
+  // Requires 12-bit data from fADCF which means Filter() 
+  // has to be called before even if all filters are bypassed.
+
+  //???
+  // TRAP parameters:
+  const uint16_t LUT_POS[128] = {   // move later to some other file
+    0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
+    16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26,
+    27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 26,
+    26, 26, 26, 25, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 18, 18, 17, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  7};
+  
+  //??? to be clarified:
+  UInt_t adc_mask = 0xfffff;
+  
+  UShort_t timebin, adcch, adc_left, adc_cent, adc_right, hit_qual, timebin1, timebin2, Qtot_tmp;
+  Short_t ypos, fromLeft, fromRight, found;
+  UShort_t Qtot[19]; // the last is dummy
+  UShort_t marked[6], Qmarked[6], worse1, worse2;
+  
+  timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS); 
+  if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0) 
+      < timebin1)
+    timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0);
+  timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE); 
+  if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1) 
+      > timebin2)
+    timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1);
+
+  // reset the fit registers
+  fNHits = 0; 
+  for (adcch = 0; adcch < fNADC-2; adcch++) // due to border channels
+  {
+    fFitReg[adcch].Nhits = 0;
+    fFitReg[adcch].Q0    = 0;
+    fFitReg[adcch].Q1    = 0;
+    fFitReg[adcch].SumX  = 0;
+    fFitReg[adcch].SumY  = 0;
+    fFitReg[adcch].SumX2 = 0;
+    fFitReg[adcch].SumY2 = 0;
+    fFitReg[adcch].SumXY = 0;
+  }
+  
+  for (timebin = timebin1; timebin < timebin2; timebin++)
+  {
+    // first find the hit candidates and store the total cluster charge in Qtot array
+    // in case of not hit store 0 there.
+    for (adcch = 0; adcch < fNADC-2; adcch++) {
+      if ( ( (adc_mask >> adcch) & 7) == 7) //??? all 3 channels are present in case of ZS
+      {
+        adc_left  = fADCF[adcch  ][timebin];
+        adc_cent  = fADCF[adcch+1][timebin];
+        adc_right = fADCF[adcch+2][timebin];
+        if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVBY) == 1) 
+          hit_qual = ( (adc_left * adc_right) < 
+                       (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVT) * adc_cent) );
+        else            
+          hit_qual = 1;
+        // The accumulated charge is with the pedestal!!!
+        Qtot_tmp = adc_left + adc_cent + adc_right;
+        if ( (hit_qual) &&
+             (Qtot_tmp >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT)) &&
+             (adc_left <= adc_cent) &&
+             (adc_cent > adc_right) )
+          Qtot[adcch] = Qtot_tmp;
+        else
+          Qtot[adcch] = 0;
+        //printf("ch %2d   Qtot %5d\n",adcch, Qtot[adcch]);
       }
+      else
+        Qtot[adcch] = 0; //jkl
     }
-   
-  }
-  
-  // the online ordering of mcm's is reverse to the TRAP-manual-ordering! reverse fADCT (to be consistent to TRAP), then do all calculations
-  // reverse fADCT:
-  Int_t** rev0 = new Int_t *[fNADC];
-  Int_t** rev1 = new Int_t *[fNADC];
-  
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
-    rev0[iadc] = new Int_t[fNTimeBin];
-    rev1[iadc] = new Int_t[fNTimeBin];
-    for( Int_t iT = 0; iT < fNTimeBin; iT++) {
-      if( iadc <= fNADC-iadc-1 ) {
-       rev0[iadc][iT]  = fADCT[fNADC-iadc-1][iT];
-       rev1[iadc][iT]  = fADCT[iadc][iT];
-       fADCT[iadc][iT] = rev0[iadc][iT];
-      }
-      else {
-       rev0[iadc][iT]  = rev1[fNADC-iadc-1][iT];
-       fADCT[iadc][iT] = rev0[iadc][iT];
+
+    fromLeft = -1;
+    adcch = 0;
+    found = 0;
+    marked[4] = 19; // invalid channel
+    marked[5] = 19; // invalid channel
+    Qtot[19] = 0;
+    while ((adcch < 16) && (found < 3))
+    {
+      if (Qtot[adcch] > 0)
+      {
+        fromLeft = adcch;
+        marked[2*found+1]=adcch;
+        found++;
       }
+      adcch++;
     }
-  }
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
-    delete[] rev0[iadc];
-    delete[] rev1[iadc];
-  }
-  
-  delete[] rev0;
-  delete[] rev1;
-  
-  rev0 = NULL;
-  rev1 = NULL;
     
-  // get the filtered pedestal; supports only electronic tail-cancellation filter
-  AliTRDtrapAlu filPed;
-  Int_t ep = 0;
-  Int_t *ieffped = new Int_t[fNTimeBin];
-  for(Int_t iT = 0; iT < fNTimeBin; iT++){
-    ieffped[iT] = ep; 
-  }
-  if( filtered == kTRUE ) {
-    if( fFeeParam->IsPFon() ){
-      ep = fFeeParam->GetPFeffectPedestal();
-    }
-    Int_t      nexp  = fFeeParam->GetTFnExp();
-    Int_t  *isource  = new Int_t[fNTimeBin];
-    filPed.Init(10,2);
-    filPed.AssignInt(ep);           
-    Int_t epf = filPed.GetValue();  
-    for(Int_t iT = 0; iT < fNTimeBin; iT++){
-      isource[iT] = ep;                  
-      ieffped[iT] = epf;
-    }
-    if( fFeeParam->IsTFon() ) {
-      FilterSimDeConvExpEl( isource, ieffped, fNTimeBin, nexp);
+    fromRight = -1;
+    adcch = 18;
+    found = 0;
+    while ((adcch > 2) && (found < 3))
+    {
+      if (Qtot[adcch] > 0)
+      {
+        marked[2*found]=adcch;
+        found++;
+        fromRight = adcch;
+      }
+      adcch--;
     }
-  
-    delete[] isource;
-  }
-  
-  //the following values should go to AliTRDfeeParam once they are defined; then they have to be read in properly
-  //naming follows conventions in TRAP-manual
-  
-  
-  Bool_t bVBY = kTRUE;                         // cluster-verification bypass
-
-  Double_t cQTParam = 0;                      // cluster quality threshold; granularity 2^-10; range: 0<=cQT/2^-10<=2^-4 - 2^-10
-  AliTRDtrapAlu cQTAlu; 
-  cQTAlu.Init(1,10,0,63);
-  cQTAlu.AssignDouble(cQTParam);
-  Int_t cQT = cQTAlu.GetValue();
 
-  // linear fit 
-  Int_t tFS = fFeeParam->GetLinearFitStart();  // linear fit start
-  Int_t tFE = fFeeParam->GetLinearFitEnd();    // linear fit stop
-   
-  // charge accumulators
-  Int_t tQS0 = fFeeParam->GetQacc0Start();     // start-time for charge-accumulator 0
-  Int_t tQE0 = fFeeParam->GetQacc0End();       // stop-time for charge-accumulator 0
-  Int_t tQS1 = fFeeParam->GetQacc1Start();     // start-time for charge-accumulator 1 
-  Int_t tQE1 = fFeeParam->GetQacc1End();       // stop-time for charge-accumulator 1
-  // values set such that tQS0=tFS; tQE0=tQS1-1; tFE=tQE1; want to do (QS0+QS1)/N
-  Double_t cTHParam = (Double_t)fFeeParam->GetMinClusterCharge(); // cluster charge threshold
-  AliTRDtrapAlu cTHAlu;  
-  cTHAlu.Init(12,2);
-  cTHAlu.AssignDouble(cTHParam);
-  Int_t cTH = cTHAlu.GetValue();                                 // cTH used for comparison
-
-  struct List_t {
-    List_t *next;
-    Int_t iadc;
-    Int_t value;
-  };
-  
-  List_t selection[7];            // list with 7 elements
-  List_t *list = NULL;
-  List_t *listLeft = NULL;
+    //printf("Fromleft=%d, Fromright=%d\n",fromLeft, fromRight);
+    // here mask the hit candidates in the middle, if any
+    if ((fromLeft >= 0) && (fromRight >= 0) && (fromLeft < fromRight))
+      for (adcch = fromLeft+1; adcch < fromRight; adcch++)
+        Qtot[adcch] = 0;
     
-  Int_t* qsum = new Int_t[fNADC];
-   
-  // fit sums
-  AliTRDtrapAlu qsumAlu;
-  qsumAlu.Init(12,2);           // charge sum will be 12+2 bits
-  AliTRDtrapAlu dCOGAlu; 
-  dCOGAlu.Init(1,7,0,127);      // COG will be 1+7 Bits; maximum 1 - 2^-7 for LUT
-  AliTRDtrapAlu yrawAlu;
-  yrawAlu.Init(1,8,-1,255);
-  AliTRDtrapAlu yAlu;
-  yAlu.Init(1,16,-1,0xFF00);    // only first 8 past-comma bits filled;additional 8 bits for accuracy;maximum 1 - 2^-8; sign is given by + or -
-  AliTRDtrapAlu xAlu;
-  xAlu.Init(5,8);               // 8 past-comma bits because value will be added/multiplied to another value with this accuracy
-  AliTRDtrapAlu xxAlu;
-  xxAlu.Init(10,0);            
-  AliTRDtrapAlu yyAlu;
-  yyAlu.Init(1,16,0,0xFFFF);    // maximum is 2^16-1; 16Bit for past-commas
-  AliTRDtrapAlu xyAlu;
-  xyAlu.Init(6,8);
-  AliTRDtrapAlu XAlu;
-  XAlu.Init(9,0);
-  AliTRDtrapAlu XXAlu;
-  XXAlu.Init(14,0);
-  AliTRDtrapAlu YAlu;
-  YAlu.Init(5,8);               // 14 bit, 1 is sign-bit; therefore only 13 bit 
-  AliTRDtrapAlu YYAlu;
-  YYAlu.Init(5,16);
-  AliTRDtrapAlu XYAlu;
-  XYAlu.Init(8,8);              // 17 bit, 1 is sign-bit; therefore only 16 bit        
-  AliTRDtrapAlu qtruncAlu;
-  qtruncAlu.Init(12,0);
-  AliTRDtrapAlu QT0Alu;
-  QT0Alu.Init(15,0);
-  AliTRDtrapAlu QT1Alu;
-  QT1Alu.Init(16,0);
-
-  AliTRDtrapAlu oneAlu;
-  oneAlu.Init(1,8);
-  
-  AliTRDtrapAlu inverseNAlu;
-  inverseNAlu.Init(1,8);        // simulates the LUT for 1/N
-  AliTRDtrapAlu MeanChargeAlu;  // mean charge in ADC counts
-  MeanChargeAlu.Init(8,0);
-  AliTRDtrapAlu TotalChargeAlu;
-  TotalChargeAlu.Init(17,8);
-  //nr of post comma bits should be the same for inverseN and TotalCharge
-  
-  
-  SetPosLUT();                    // initialize the position correction LUT for this MCM;
-
-
-  // fit-sums; remapping!; 0,1,2->0; 1,2,3->1; ... 18,19,20->18
-  Int_t *X   = new Int_t[fNADC-2];
-  Int_t *XX  = new Int_t[fNADC-2];
-  Int_t *Y   = new Int_t[fNADC-2];
-  Int_t *YY  = new Int_t[fNADC-2];
-  Int_t *XY  = new Int_t[fNADC-2];
-  Int_t *N   = new Int_t[fNADC-2];
-  Int_t *QT0 = new Int_t[fNADC-2]; // accumulated charge
-  Int_t *QT1 = new Int_t[fNADC-2]; // accumulated charge
-  
-  for (Int_t iCol = 0; iCol < fNADC-2; iCol++) { 
-      
-      // initialize fit-sums 
-      X[iCol]   = 0;
-      XX[iCol]  = 0;
-      Y[iCol]   = 0;
-      YY[iCol]  = 0;
-      XY[iCol]  = 0;
-      N[iCol]   = 0;
-      QT0[iCol] = 0;
-      QT1[iCol] = 0;
-  }
-  
+    found = 0;
+    for (adcch = 0; adcch < 19; adcch++)
+      if (Qtot[adcch] > 0) found++;
+    // NOT READY
 
-  filPed.Init(7,2);                         // convert filtered pedestal into 7+2Bits
-  
-  for(Int_t iT = 0; iT < fNTimeBin; iT++){
-    
-    if(iT<tFS || iT>=tFE) continue;         // linear fit yes/no? 
-
-    // reset
-    Int_t portChannel[4]   = {-1,-1,-1,-1};   
-    Int_t clusterCharge[4] = {0,0,0,0};
-    Int_t leftCharge[4]    = {0,0,0,0};
-    Int_t centerCharge[4]  = {0,0,0,0}; 
-    Int_t rightCharge[4]   = {0,0,0,0};
-    
-    Int_t mark = 0;
-    
-    filPed.AssignFormatted(ieffped[iT]);   // no size-checking when using AssignFormatted; ieffped>=0
-    filPed = filPed;                       // this checks the size
-    
-    ieffped[iT] = filPed.GetValue();
-        
-    for(Int_t i = 0; i<7; i++){
-      selection[i].next       = NULL;
-      selection[i].iadc       =   -1;     // value of -1: invalid adc
-      selection[i].value      =    0;
-   
-    }
-    // selection[0] is starting list-element; just for pointing
-
-    // loop over inner adc's 
-    for (Int_t iCol = 1; iCol < fNADC-1; iCol++) { 
-      
-      Int_t left   = fADCT[iCol-1][iT]; 
-      Int_t center = fADCT[iCol][iT];
-      Int_t right  = fADCT[iCol+1][iT];  
-
-      Int_t sum = left + center + right;            // cluster charge sum
-      qsumAlu.AssignFormatted(sum);    
-      qsumAlu = qsumAlu;                        // size-checking; redundant
-      qsum[iCol] = qsumAlu.GetValue(); 
-      
-      //hit detection and masking
-      if(center>=left){
-       if(center>right){
-         if(qsum[iCol]>=(cTH + 3*ieffped[iT])){    // effective pedestal of all three channels must be added to cTH(+20); this is not parallel to TRAP manual; maybe cTH has to be adjusted in fFeeParam; therefore channels are not yet reduced by their pedestal
-           mark |= 1;                              // marker
-         }
-       }
+    if (found > 4) // sorting like in the TRAP in case of 5 or 6 candidates!
+    {
+      if (marked[4] == marked[5]) marked[5] = 19;
+      for (found=0; found<6; found++)
+      {
+        Qmarked[found] = Qtot[marked[found]] >> 4;
+        //printf("ch_%d Qtot %d Qtots %d |",marked[found],Qtot[marked[found]],Qmarked[found]);
       }
-      mark = mark<<1;                
-    }
-    mark = mark>>1;
-
-       
-    // get selection of 6 adc's and sort,starting with greatest values
-
-    //read three from right side and sort (primitive sorting algorithm)
-    Int_t i = 0; // adc number
-    Int_t j = 1; // selection number
-    while(i<fNADC-2 && j<=3){
-      i = i + 1;
-      if( ((mark>>(i-1)) & 1) == 1) {
-       selection[j].iadc  = fNADC-1-i;
-       selection[j].value = qsum[fNADC-1-i]>>6;   // for hit-selection only the first 8 out of the 14 Bits are used for comparison
-       
-       // insert into sorted list
-       listLeft = &selection[0];
-       list = listLeft->next;
-       
-       if(list!=NULL) {
-         while((list->next != NULL) && (selection[j].value <= list->value)){
-           listLeft = list;
-           list = list->next;
-         }
-         
-         if(selection[j].value<=list->value){
-           selection[j].next = list->next;
-           list->next = &selection[j];
-         }
-         else {
-           listLeft->next = &selection[j];
-           selection[j].next = list;
-         }
-       }
-       else{
-         listLeft->next = &selection[j];
-         selection[j].next = list;
-       }
-       
-       j = j + 1;
+      //printf("\n");
+      
+      Sort6To2Worst(marked[0], marked[3], marked[4], marked[1], marked[2], marked[5],
+                    Qmarked[0],
+                    Qmarked[3],
+                    Qmarked[4],
+                    Qmarked[1],
+                    Qmarked[2],
+                    Qmarked[5],
+                    &worse1, &worse2);
+      // Now mask the two channels with the smallest charge
+      if (worse1 < 19)
+      {
+        Qtot[worse1] = 0;
+        //printf("Kill ch %d\n",worse1);
       }
-    }
-
-
-    // read three from left side
-    Int_t k = fNADC-2;
-    while(k>i && j<=6) {
-      if( ((mark>>(k-1)) & 1) == 1) {
-       selection[j].iadc  = fNADC-1-k;
-       selection[j].value = qsum[fNADC-1-k]>>6;
-       
-       listLeft = &selection[0];
-       list = listLeft->next;
-       
-       if(list!=NULL){
-         while((list->next != NULL) && (selection[j].value <= list->value)){
-           listLeft = list;
-           list = list->next;
-         }
-       
-         if(selection[j].value<=list->value){
-           selection[j].next = list->next;
-           list->next = &selection[j];
-         }
-         else {
-           listLeft->next = &selection[j];
-           selection[j].next = list;
-         }
-       }
-       else{
-         listLeft->next = &selection[j];
-         selection[j].next = list;
-       }
-
-       j = j + 1;
+      if (worse2 < 19)
+      {
+        Qtot[worse2] = 0;
+        //printf("Kill ch %d\n",worse2);
       }
-      k = k - 1;
     }
-
-    // get the four with greatest charge-sum
-    list = &selection[0];
-    for(i = 0; i<4; i++){
-      if(list->next == NULL) continue;
-      list = list->next;
-      if(list->iadc == -1) continue;
-      Int_t adc = list->iadc;                              // channel number with selected hit
-      
-      // the following arrays contain the four chosen channels in 1 time-bin
-      portChannel[i]   = adc; 
-      clusterCharge[i] = qsum[adc];
-      leftCharge[i]    = fADCT[adc-1][iT] - ieffped[iT]; // reduce by filtered pedestal (pedestal is part of the signal)
-      centerCharge[i]  = fADCT[adc][iT] - ieffped[iT];           
-      rightCharge[i]   = fADCT[adc+1][iT] - ieffped[iT];         
-    }
-
-    // arithmetic unit
     
-    // cluster verification
-    if(!bVBY){
-      for(i = 0; i<4; i++){
-       Int_t lr = leftCharge[i]*rightCharge[i]*1024;
-       Int_t cc = centerCharge[i]*centerCharge[i]*cQT;
-       if (lr>=cc){
-         portChannel[i]   = -1;                                 // set to invalid address 
-         clusterCharge[i] = 0;
-       }
-      }
-    }
-
-    // fit-sums of valid channels
-    // local hit position
-    for(i = 0; i<4; i++){
-      if (centerCharge[i] ==  0) {
-       portChannel[i] = -1; 
-      }// prevent division by 0
-      
-      if (portChannel[i]  == -1) continue;
-      
-      Double_t dCOG = (Double_t)(rightCharge[i]-leftCharge[i])/centerCharge[i];
-       
-      Bool_t sign = (dCOG>=0.0) ? kFALSE : kTRUE;
-      dCOG = (sign == kFALSE) ? dCOG : -dCOG;     // AssignDouble doesn't allow for signed doubles
-      dCOGAlu.AssignDouble(dCOG);
-      Int_t iLUTpos = dCOGAlu.GetValue();       // steers position in LUT
-            
-      dCOG = dCOG/2;
-      yrawAlu.AssignDouble(dCOG);
-      Int_t iCOG = yrawAlu.GetValue();
-      Int_t y = iCOG + fPosLUT[iLUTpos % 128];    // local position in pad-units
-      yrawAlu.AssignFormatted(y);               // 0<y<1           
-      yAlu  = yrawAlu;                        // convert to 16 past-comma bits
-      
-      if(sign == kTRUE) yAlu.SetSign(-1);       // buffer width of 9 bits; sign on real (not estimated) position
-      xAlu.AssignInt(iT);                       // buffer width of 5 bits 
-      
-
-      xxAlu = xAlu * xAlu;                  // buffer width of 10 bits -> fulfilled by x*x       
-      
-      yyAlu = yAlu * yAlu;                  // buffer width of 16 bits
-   
-      xyAlu = xAlu * yAlu;                  // buffer width of 14 bits
-                  
-      Int_t adc = portChannel[i]-1;              // remapping! port-channel contains channel-nr. of inner adc's (1..19; mapped to 0..18)
-
-      // calculate fit-sums recursively
-      // interpretation of their bit-length is given as comment
-      
-      // be aware that the accuracy of the result of a calculation is always determined by the accuracy of the less accurate value
-
-      XAlu.AssignFormatted(X[adc]);
-      XAlu = XAlu + xAlu;                   // buffer width of 9 bits 
-      X[adc] = XAlu.GetValue();
-             
-      XXAlu.AssignFormatted(XX[adc]);
-      XXAlu = XXAlu + xxAlu;                // buffer width of 14 bits    
-      XX[adc] = XXAlu.GetValue();
-
-      if (Y[adc] < 0) {
-       YAlu.AssignFormatted(-Y[adc]);          // make sure that only positive values are assigned; sign-setting must be done by hand
-       YAlu.SetSign(-1);
-      }
-      else {
-       YAlu.AssignFormatted(Y[adc]);
-       YAlu.SetSign(1);
-      }
-       
-      YAlu = YAlu + yAlu;                   // buffer width of 14 bits (8 past-comma);     
-      Y[adc] = YAlu.GetSignedValue();
-            
-      YYAlu.AssignFormatted(YY[adc]);
-      YYAlu = YYAlu + yyAlu;                // buffer width of 21 bits (16 past-comma) 
-      YY[adc] = YYAlu.GetValue();
-           
-      if (XY[adc] < 0) {
-       XYAlu.AssignFormatted(-XY[adc]);
-       XYAlu.SetSign(-1);
-      }
-      else {
-       XYAlu.AssignFormatted(XY[adc]);
-       XYAlu.SetSign(1);
-      }
-
-      XYAlu = XYAlu + xyAlu;                // buffer allows 17 bits (8 past-comma) 
-      XY[adc] = XYAlu.GetSignedValue();
-            
-      N[adc]  = N[adc] + 1;
-   
-
-      // accumulated charge
-      qsumAlu.AssignFormatted(qsum[adc+1]); // qsum was not remapped!
-      qtruncAlu = qsumAlu;
-
-      if(iT>=tQS0 && iT<=tQE0){
-       QT0Alu.AssignFormatted(QT0[adc]);
-       QT0Alu = QT0Alu + qtruncAlu;
-       QT0[adc] = QT0Alu.GetValue();
-       //interpretation of QT0 as 12bit-value (all pre-comma); is this as it should be done?; buffer allows 15 Bit
-      }
-      
-      if(iT>=tQS1 && iT<=tQE1){
-       QT1Alu.AssignFormatted(QT1[adc]);
-       QT1Alu = QT1Alu + qtruncAlu;
-       QT1[adc] = QT1Alu.GetValue();
-       //interpretation of QT1 as 12bit-value; buffer allows 16 Bit
+    for (adcch = 0; adcch < 19; adcch++) {
+      if (Qtot[adcch] > 0) // the channel is marked for processing
+      {
+        adc_left  = fADCF[adcch  ][timebin];
+        adc_cent  = fADCF[adcch+1][timebin];
+        adc_right = fADCF[adcch+2][timebin];
+        // hit detected, in TRAP we have 4 units and a hit-selection, here we proceed all channels!
+        // subtract the pedestal TPFP, clipping instead of wrapping
+        
+        Int_t TPFP = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP);
+//        printf("Hit found, time=%d, adcch=%d/%d/%d, adc values=%d/%d/%d, TPFP=%d, TPHT=%d\n",
+//               timebin, adcch, adcch+1, adcch+2, adc_left, adc_cent, adc_right, TPFP, 
+//               fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT));
+
+        if (adc_left  < TPFP) adc_left  = 0; else adc_left  -= TPFP;
+        if (adc_cent  < TPFP) adc_cent  = 0; else adc_cent  -= TPFP;
+        if (adc_right < TPFP) adc_right = 0; else adc_right -= TPFP;
+        // Calculate the center of gravity
+        ypos = 128*(adc_left - adc_right) / adc_cent;
+        if (ypos < 0) ypos = -ypos;
+        // make the correction using the LUT
+        ypos = ypos + LUT_POS[ypos & 0x7F];
+        if (adc_left > adc_right) ypos = -ypos;
+        AddHitToFitreg(adcch, timebin, Qtot[adcch], ypos, -1);
       }
-    }// i
-      
-    // remapping is done!!
-     
-  }//iT
-  
-    
-  // tracklet-assembly
-  
-  // put into AliTRDfeeParam and take care that values are in proper range
-  const Int_t cTCL = 1;      // left adc: number of hits; 8<=TCL<=31 (?? 1<=cTCL<+8 ??) 
-  const Int_t cTCT = 8;      // joint number of hits;     8<=TCT<=31; note that according to TRAP manual this number cannot be lower than 8; however it should be adjustable to the number of hits in the fit time range (40%)
-  
-  Int_t mPair   = 0;         // marker for possible tracklet pairs
-  Int_t* hitSum = new Int_t[fNADC-3];
-  // hitSum[0] means: hit sum of remapped channels 0 and 1; hitSum[17]: 17 and 18; 
-  
-  // check for all possible tracklet-pairs of adjacent channels (two are merged); mark the left channel of the chosen pairs
-  for (Int_t iCol = 0; iCol < fNADC-3; iCol++) {
-    hitSum[iCol] = N[iCol] + N[iCol+1];
-    if ((N[iCol]>=cTCL) && (hitSum[iCol]>=cTCT)) {
-       mPair |= 1;         // mark as possible channel-pair
-     
     }
-    mPair = mPair<<1;
   }
-  mPair = mPair>>1;
-  
-  List_t* selectPair = new List_t[fNADC-2];      // list with 18 elements (0..18) containing the left channel-nr and hit sums
-                                                 // selectPair[18] is starting list-element just for pointing
-  for(Int_t k = 0; k<fNADC-2; k++){
-      selectPair[k].next       = NULL;
-      selectPair[k].iadc       =   -1;           // invalid adc
-      selectPair[k].value      =    0;
-   
-    }
+}
 
- list = NULL;
- listLeft = NULL;
-  
-  // read marker and sort according to hit-sum
-  
-  Int_t adcL  = 0;            // left adc-channel-number (remapped)
-  Int_t selNr = 0;            // current number in list
-  
-  // insert marked channels into list and sort according to hit-sum
-  while(adcL < fNADC-3 && selNr < fNADC-3){
-     
-    if( ((mPair>>((fNADC-4)-(adcL))) & 1) == 1) {
-      selectPair[selNr].iadc  = adcL;
-      selectPair[selNr].value = hitSum[adcL];   
-      
-      listLeft = &selectPair[fNADC-3];
-      list = listLeft->next;
-       
-      if(list!=NULL) {
-       while((list->next != NULL) && (selectPair[selNr].value <= list->value)){
-         listLeft = list;
-         list = list->next;
-       }
-       
-       if(selectPair[selNr].value <= list->value){
-         selectPair[selNr].next = list->next;
-         list->next = &selectPair[selNr];
-       }
-       else {
-         listLeft->next = &selectPair[selNr];
-         selectPair[selNr].next = list;
-       }
-       
-      }
-      else{
-       listLeft->next = &selectPair[selNr];
-       selectPair[selNr].next = list;
+void AliTRDmcmSim::TrackletSelection() 
+{
+  // Select up to 4 tracklet candidates from the fit registers  
+  // and assign them to the CPUs.
+
+  UShort_t adc_idx, i, j, ntracks, tmp;
+  UShort_t track_p[18][2]; // store the adcch[0] and number of hits[1] for all tracklet candidates
+
+  ntracks = 0;
+  for (adc_idx = 0; adc_idx < 18; adc_idx++) // ADCs
+    if ( (fFitReg[adc_idx].Nhits 
+          >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCL)) &&
+         (fFitReg[adc_idx].Nhits+fFitReg[adc_idx+1].Nhits
+          >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCT)))
+    {
+      track_p[ntracks][0] = adc_idx;
+      track_p[ntracks][1] = fFitReg[adc_idx].Nhits+fFitReg[adc_idx+1].Nhits;
+      //printf("%d  %2d %4d\n", ntracks, track_p[ntracks][0], track_p[ntracks][1]);
+      ntracks++;
+    };
+
+  // for (i=0; i<ntracks;i++) printf("%d %d %d\n",i,track_p[i][0], track_p[i][1]);
+
+  if (ntracks > 4)
+  {
+    // primitive sorting according to the number of hits
+    for (j = 0; j < (ntracks-1); j++)
+    {
+      for (i = j+1; i < ntracks; i++)
+      {
+        if ( (track_p[j][1]  < track_p[i][1]) ||
+             ( (track_p[j][1] == track_p[i][1]) && (track_p[j][0] < track_p[i][0]) ) )
+        {
+          // swap j & i
+          tmp = track_p[j][1];
+          track_p[j][1] = track_p[i][1];
+          track_p[i][1] = tmp;
+          tmp = track_p[j][0];
+          track_p[j][0] = track_p[i][0];
+          track_p[i][0] = tmp;
+        }
       }
-      
-      selNr = selNr + 1;
     }
-    adcL = adcL + 1;
+    ntracks = 4; // cut the rest, 4 is the max
   }
+  // else is not necessary to sort
   
-  //select up to 4 channels with maximum number of hits
-  Int_t lpairChannel[4] = {-1,-1,-1,-1}; // save the left channel-numbers of pairs with most hit-sum
-  Int_t rpairChannel[4] = {-1,-1,-1,-1}; // save the right channel, too; needed for detecting double tracklets
-  list = &selectPair[fNADC-3];
-  
-  for (Int_t i = 0; i<4; i++) {
-    if(list->next == NULL) continue;
-    list = list->next;
-    if(list->iadc == -1) continue;
-    lpairChannel[i] = list->iadc;        // channel number with selected hit
-    rpairChannel[i] = lpairChannel[i]+1;
-  }
-  
-  // avoid submission of double tracklets  
-  for (Int_t i = 3; i>0; i--) {
-    for (Int_t j = i-1; j>-1; j--) {
-      if(lpairChannel[i] == rpairChannel[j]) {
-       lpairChannel[i] = -1;
-       rpairChannel[i] = -1;
-       break;
+  // now sort, so that the first tracklet going to CPU0 corresponds to the highest adc channel - as in the TRAP
+  for (j = 0; j < (ntracks-1); j++)
+  {
+    for (i = j+1; i < ntracks; i++)
+    {
+      if (track_p[j][0] < track_p[i][0])
+      {
+        // swap j & i
+        tmp = track_p[j][1];
+        track_p[j][1] = track_p[i][1];
+        track_p[i][1] = tmp;
+        tmp = track_p[j][0];
+        track_p[j][0] = track_p[i][0];
+        track_p[i][0] = tmp;
       }
-      /* if(rpairChannel[i] == lpairChannel[j]) {
-       lpairChannel[i] = -1;
-       rpairChannel[i] = -1;
-       break;
-       }*/
     }
   }
-  
-  // merging of the fit-sums of the remainig channels
-  // assume same data-word-width as for fit-sums for 1 channel
-  // relative scales!
-  Int_t mADC[4];                      
-  Int_t mN[4];
-  Int_t mQT0[4];
-  Int_t mQT1[4];
-  Int_t mX[4];
-  Int_t mXX[4];
-  Int_t mY[4];
-  Int_t mYY[4];
-  Int_t mXY[4];
-  Int_t mOffset[4];
-  Int_t mSlope[4];
-  Int_t mMeanCharge[4]; 
-  Int_t inverseN = 0;
-  Double_t invN = 0;
-  Int_t one = 0;
-
-  for (Int_t i = 0; i<4; i++){
-    mADC[i] = -1;                        // set to invalid number
-    mN[i]   =  0;
-    mQT0[i] =  0;
-    mQT1[i] =  0;
-    mX[i]   =  0;
-    mXX[i]  =  0;
-    mY[i]   =  0;
-    mYY[i]  =  0;
-    mXY[i]  =  0;
-    mOffset[i] = 0;
-    mSlope[i]  = 0;
-    mMeanCharge[i] = 0;
-  }
-  
-  oneAlu.AssignInt(1);
-  one = oneAlu.GetValue();              // one with 8 past comma bits
-  for (Int_t i = 0; i<4; i++){
-          
-
-    mADC[i] = lpairChannel[i];          // mapping of merged sums to left channel nr. (0,1->0; 1,2->1; ... 17,18->17)
-                                        // the adc and pad-mapping should now be one to one: adc i is linked to pad i; TRAP-numbering
-    Int_t madc = mADC[i];
-    if (madc == -1) continue;
-    
-    YAlu.AssignInt(N[rpairChannel[i]]);
-    Int_t wpad  = YAlu.GetValue();       // enlarge hit counter of right channel by 8 past-comma bits; YAlu can have 5 pre-comma bits (values up to 63); hit counter<=nr of time bins (24)
-
-    mN[i]    = hitSum[madc];
-  
-    // don't merge fit sums in case of a stand-alone tracklet (consisting of only 1 channel); in that case only left channel makes up the fit sums
-    if (N[madc+1] == 0) {
-       mQT0[i] = QT0[madc];
-       mQT1[i] = QT1[madc];
-       
-    }
-    else {
+  for (i = 0; i < ntracks; i++)  // CPUs with tracklets.
+    fFitPtr[i] = track_p[i][0]; // pointer to the left channel with tracklet for CPU[i]
+  for (i = ntracks; i < 4; i++)  // CPUs without tracklets
+    fFitPtr[i] = 31;            // pointer to the left channel with tracklet for CPU[i] = 31 (invalid)
+//  printf("found %i tracklet candidates\n", ntracks);
+}
 
-       // is it ok to do the size-checking for the merged fit-sums with the same format as for single-channel fit-sums?
-       
-       mQT0[i]   = QT0[madc] + QT0[madc+1];
-       QT0Alu.AssignFormatted(mQT0[i]);   
-       QT0Alu  = QT0Alu;                // size-check
-       mQT0[i]   = QT0Alu.GetValue();     // write back
-       
-       mQT1[i]   = QT1[madc] + QT1[madc+1];
-       QT1Alu.AssignFormatted(mQT1[i]);
-       QT1Alu  = QT1Alu;
-       mQT1[i]   = QT1Alu.GetValue();
-    }
-    
-    // calculate the mean charge in adc values; later to be replaced by electron likelihood
-    mMeanCharge[i] = mQT0[i] + mQT1[i]; // total charge
-    mMeanCharge[i] = mMeanCharge[i]>>2; // losing of accuracy; accounts for high mean charge
-    // simulate LUT for 1/N; LUT is fed with the double-accurate pre-calculated value of 1/N; accuracy of entries has to be adjusted to real TRAP
-    invN = 1.0/(mN[i]);
-    inverseNAlu.AssignDouble(invN);
-    inverseN = inverseNAlu.GetValue();
-    mMeanCharge[i] = mMeanCharge[i] * inverseN;  // now to be interpreted with 8 past-comma bits
-    TotalChargeAlu.AssignFormatted(mMeanCharge[i]);
-    TotalChargeAlu = TotalChargeAlu;
-    MeanChargeAlu = TotalChargeAlu;
-    mMeanCharge[i] = MeanChargeAlu.GetValue();
-    
-    // this check is not necessary; it is just for efficiency reasons
-    if (N[madc+1] == 0) {
-       mX[i]     =   X[madc];
-       mXX[i]    =  XX[madc];
-       mY[i]     =   Y[madc];
-       mXY[i]    =  XY[madc];
-       mYY[i]    =  YY[madc];
-    }
-    else {
-       
-       mX[i]     =   X[madc] +  X[madc+1];
-       XAlu.AssignFormatted(mX[i]);
-       XAlu      = XAlu;
-       mX[i]     = XAlu.GetValue();
-       
-       mXX[i]    =  XX[madc] + XX[madc+1];
-       XXAlu.AssignFormatted(mXX[i]);
-       XXAlu     = XXAlu;
-       mXX[i]    = XXAlu.GetValue();
-    
-       mY[i]     =   Y[madc] + Y[madc+1] + wpad;
-       if (mY[i] < 0) {
-           YAlu.AssignFormatted(-mY[i]);
-           YAlu.SetSign(-1);
-       }
-       else {
-           YAlu.AssignFormatted(mY[i]);
-           YAlu.SetSign(1);
-       }
-       YAlu    = YAlu;
-       mY[i]     = YAlu.GetSignedValue();
-       
-       mXY[i]    = XY[madc] + XY[madc+1] + X[madc+1]*one;    // multiplication by one to maintain the data format
-       
-       if (mXY[i] < 0) {
-           XYAlu.AssignFormatted(-mXY[i]);
-           XYAlu.SetSign(-1);
-       }
-       else {
-           XYAlu.AssignFormatted(mXY[i]);
-           XYAlu.SetSign(1);
-       }
-       XYAlu   = XYAlu;
-       mXY[i]    = XYAlu.GetSignedValue();
-    
-       mYY[i]    = YY[madc] + YY[madc+1] + 2*Y[madc+1]*one+ wpad*one;
-       if (mYY[i] < 0) {
-           YYAlu.AssignFormatted(-mYY[i]);
-           YYAlu.SetSign(-1);
-       }
-       else {
-           YYAlu.AssignFormatted(mYY[i]);
-           YYAlu.SetSign(1);
-       }
-       
-       YYAlu   = YYAlu;
-       mYY[i]    = YYAlu.GetSignedValue();
+void AliTRDmcmSim::FitTracklet()
+{
+  // Perform the actual tracklet fit based on the fit sums 
+  // which have been filled in the fit registers. 
+
+  // parameters in fitred.asm (fit program)
+  Int_t decPlaces = 5;
+  Int_t rndAdd = 0;
+  if (decPlaces >  1) 
+    rndAdd = (1 << (decPlaces-1)) + 1;
+  else if (decPlaces == 1)
+    rndAdd = 1;
+
+  // should come from trapConfig (DMEM) 
+  AliTRDpadPlane *pp = fGeo->GetPadPlane(fDetector);
+  Long64_t shift = ((Long64_t) 1 << 32);
+  UInt_t scale_y = (UInt_t) (shift * (pp->GetWidthIPad() / (256 * 160e-4)));
+  UInt_t scale_d = (UInt_t) (shift * (pp->GetWidthIPad() / (256 * 140e-4)));
+  int padrow = fFeeParam->GetPadRowFromMCM(fRobPos, fMcmPos);
+  int yoffs  = (fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, 19) - fFeeParam->GetNcol()/2) << (8 + decPlaces); 
+  int ndrift = 20; //??? value in simulation?
+  int defl_cor = 0; // -370;
+  int minslope = -10000; // no pt-cut so far
+  int maxslope =  10000; // no pt-cut so far
+
+  // local variables for calculation
+  Long64_t mult, temp, denom; //???
+  UInt_t q0, q1, qTotal;          // charges in the two windows and total charge
+  UShort_t nHits;                 // number of hits
+  Int_t slope, offset;            // slope and offset of the tracklet
+  Int_t sumX, sumY, sumXY, sumX2; // fit sums from fit registers
+  //int32_t SumY2;                // not used in the current TRAP program
+  FitReg_t *fit0, *fit1;          // pointers to relevant fit registers
+  
+//  const uint32_t OneDivN[32] = {  // 2**31/N : exactly like in the TRAP, the simple division here gives the same result!
+//      0x00000000, 0x80000000, 0x40000000, 0x2AAAAAA0, 0x20000000, 0x19999990, 0x15555550, 0x12492490,
+//      0x10000000, 0x0E38E380, 0x0CCCCCC0, 0x0BA2E8B0, 0x0AAAAAA0, 0x09D89D80, 0x09249240, 0x08888880,
+//      0x08000000, 0x07878780, 0x071C71C0, 0x06BCA1A0, 0x06666660, 0x06186180, 0x05D17450, 0x0590B210,
+//      0x05555550, 0x051EB850, 0x04EC4EC0, 0x04BDA120, 0x04924920, 0x0469EE50, 0x04444440, 0x04210840};
+
+  for (Int_t cpu = 0; cpu < 4; cpu++) {
+    if (fFitPtr[cpu] == 31)
+    {
+      fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker(); 
     }
-  
-  }
-    
-  // calculation of offset and slope from the merged fit-sums; 
-  // YY is needed for some error measure only; still to be done
-  // be aware that all values are relative values (scale: timebin-width; pad-width) and are integer values on special scale
-  
-  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  // !!important note: the offset is calculated from hits in the time bin range between tFS and tFE; it corresponds to the value at the height of the time bin tFS which does NOT need to correspond to the upper side of the drift   !!
-  // !!volume (cathode wire plane). The offset cannot be rescaled as long as it is unknown which is the first time bin that contains hits from the drift region and thus to which distance from the cathode plane tFS corresponds.    !!
-  // !!This has to be taken into account by the GTU. Furthermore a Lorentz correction might have to be applied to the offset (see below).                                                                                             !!
-  // !!In this implementation it is assumed that no miscalibration containing changing drift velocities in the amplification region is used.                                                                                          !!
-  // !!The corrections to the offset (e.g. no ExB correction applied as offset is supposed to be on top of drift region; however not at anode wire, so some inclination of drifting clusters due to Lorentz angle exists) are only    !!
-  // !!valid (in approximation) if tFS is close to the beginning of the drift region.                                                                                                                                                 !!
-  // !!The slope however can be converted to a deflection length between electrode and cathode wire plane as it is clear that the drift region is sampled 20 times                                                                    !!
-  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-  // which formats should be chosen?
-  AliTRDtrapAlu denomAlu;
-  denomAlu.Init(20,8);       
-  AliTRDtrapAlu numAlu;
-  numAlu.Init(20,8);     
-  // is this enough pre-comma place? covers the range of the 13 bit-word of the transmitted offset
-  // offset measured in coord. of left channel must be between -0.5 and 1.5; 14 pre-comma bits because numerator can be big
-
-  for (Int_t i = 0; i<4; i++) {
-    if (mADC[i] == -1) continue;
+    else
+    {
+      fit0 = &fFitReg[fFitPtr[cpu]  ];
+      fit1 = &fFitReg[fFitPtr[cpu]+1]; // next channel
+
+      mult = 1;
+      mult = mult << (32 + decPlaces);
+      mult = -mult;
+
+      // Merging
+      nHits   = fit0->Nhits + fit1->Nhits; // number of hits
+      sumX    = fit0->SumX  + fit1->SumX;
+      sumX2   = fit0->SumX2 + fit1->SumX2;
+      denom   = nHits*sumX2 - sumX*sumX;
+
+      mult    = mult / denom; // exactly like in the TRAP program
+      q0      = fit0->Q0    + fit1->Q0;
+      q1      = fit0->Q1    + fit1->Q1;
+      sumY    = fit0->SumY  + fit1->SumY  + 256*fit1->Nhits;
+      sumXY   = fit0->SumXY + fit1->SumXY + 256*fit1->SumX;
+
+      slope   = nHits*sumXY - sumX * sumY;
+      offset  = sumX2*sumY  - sumX * sumXY;
+      temp    = mult * slope;
+      slope   = temp >> 32; // take the upper 32 bits
+      temp    = mult * offset;
+      offset  = temp >> 32; // take the upper 32 bits
+
+      offset = offset + yoffs + (18 << (8 + decPlaces)); 
+      slope  = slope * ndrift + defl_cor;
+      offset = offset - (fFitPtr[cpu] << (8 + decPlaces));
       
-    Int_t num0  = (mN[i]*mXX[i]-mX[i]*mX[i]);
-    if (num0 < 0) {
-      denomAlu.AssignInt(-num0);    // num0 does not have to be interpreted as having past-comma bits -> AssignInt
-      denomAlu.SetSign(-1);
-    }
-    else {
-      denomAlu.AssignInt(num0);
-      denomAlu.SetSign(1);
-    }
-    
-    Int_t num1  = mN[i]*mXY[i] - mX[i]*mY[i];
-    if (num1 < 0) {
-      numAlu.AssignFormatted(-num1); // value of num1 is already formatted to have 8 past-comma bits
-      numAlu.SetSign(-1);
-    }
-    else {
-      numAlu.AssignFormatted(num1);
-      numAlu.SetSign(1);
-    }
-    numAlu    = numAlu/denomAlu;
-    mSlope[i]   = numAlu.GetSignedValue();
-   
-    Int_t num2  = mXX[i]*mY[i] - mX[i]*mXY[i];
-   
-    if (num2 < 0) {
-      numAlu.AssignFormatted(-num2);
-      numAlu.SetSign(-1);
-    }
-    else {
-      numAlu.AssignFormatted(num2);
-      numAlu.SetSign(1);
+      if ((slope < minslope) || (slope > maxslope))
+      {
+        fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker();
+      }
+      else
+      {
+        temp    = slope;
+        temp    = temp * scale_d;
+        slope   = (temp >> 32);
+        
+        temp    = offset;
+        temp    = temp * scale_y;
+        offset  = (temp >> 32);
+        
+        // rounding, like in the TRAP
+        slope   = (slope  + rndAdd) >> decPlaces;
+        offset  = (offset + rndAdd) >> decPlaces;
+
+        if (slope > 0x3f || slope < -0x3f)
+          AliWarning("Overflow in slope");
+        slope   = slope  &   0x7F; // 7 bit
+
+        if (offset > 0xfff || offset < 0xfff)
+          AliWarning("Overflow in offset");
+        offset  = offset & 0x1FFF; // 13 bit
+
+        qTotal  = (q1 / nHits) >> 1;
+        if (qTotal > 0xff)
+          AliWarning("Overflow in charge");
+        qTotal  = qTotal & 0xFF; // 8 bit, exactly like in the TRAP program
+
+        // assemble and store the tracklet word
+        fMCMT[cpu] = (qTotal << 24) | (padrow << 20) | (slope << 13) | offset;
+        new ((*fTrackletArray)[cpu]) AliTRDtrackletMCM((UInt_t) fMCMT[cpu], fDetector*2 + fRobPos%2, fRobPos, fMcmPos);
+      }
     }
-   
-    numAlu    = numAlu/denomAlu;
-   
-    
-    mOffset[i]  = numAlu.GetSignedValue();
-    numAlu.SetSign(1);
-    denomAlu.SetSign(1);
-       
-                                 
-    //numAlu.AssignInt(mADC[i]+1);   // according to TRAP-manual but trafo not to middle of chamber (0.5 channels away)             
-    numAlu.AssignDouble((Double_t)mADC[i] + 1.5);      // numAlu has enough pre-comma place for that; correct trafo, best values
-    mOffset[i]  = mOffset[i] + numAlu.GetValue();      // transform offset to a coord.system relative to chip; +1 to avoid neg. values 
-    
-    // up to here: adc-mapping according to TRAP manual and in line with pad-col mapping
-    // reverse adc-counting to be again in line with the online mapping
-    mADC[i]     = fNADC - 4 - mADC[i];                 // fNADC-4-mADC[i]: 0..17; remapping necessary;
-    mADC[i]     = mADC[i] + 2; 
-    // +2: mapping onto original ADC-online-counting: inner adc's corresponding to a chip's pasa: number 2..19
   }
+}
 
-  // adc-counting is corresponding to online mapping; use AliTRDfeeParam::GetPadColFromADC to get the pad to which adc is connected; 
-  // pad-column mapping is reverse to adc-online mapping; TRAP adc-mapping is in line with pad-mapping (increase in same direction);
-  
-  // transform parameters to the local coordinate-system of a stack (used by GTU)
-  AliTRDpadPlane* padPlane = fGeo->CreatePadPlane(fLayer,fStack);
-  
-  Double_t padWidthI = padPlane->GetWidthIPad()*10.0; // get values in cm; want them in mm
-  //Double_t padWidthO = padPlane->GetWidthOPad()*10; // difference between outer pad-widths not included; in real TRAP??
-  
-  // difference between width of inner and outer pads of a row is not accounted for;
-  
-  Double_t magField = 0.4;                           // z-component of magnetic field in Tesla; adjust to current simulation!!; magnetic field can hardly be evaluated for the position of each mcm 
-  Double_t eCharge  = 0.3;                           // unit charge in (GeV/c)/m*T
-  Double_t ptMin   = 2.3;                            // minimum transverse momentum (GeV/c); to be adjusted(?)
-  
-  Double_t granularityOffset = 0.160;                // granularity for offset in mm
-  Double_t granularitySlope  = 0.140;                // granularity for slope  in mm     
-    
-  // get the coordinates in SM-system; parameters: 
-  
-  Double_t zPos       =  (padPlane->GetRowPos(fRow))*10.0;  // z-position of the MCM; fRow is counted on a chamber; SM consists of 5 
-  // zPos is position of pad-borders;
-  Double_t zOffset = 0.0;
-  if ( fRow == 0 || fRow == 15 ) {
-      zOffset = padPlane->GetLengthOPad();
-  }
-  else {
-      zOffset = padPlane->GetLengthIPad();
-  }
-  zOffset = (-1.0) * zOffset/2.0;
-  // turn zPos to be z-coordinate at middle of pad-row
-  zPos = zPos + zOffset;
-
-      
-  Double_t xPos       =  0.0;                               // x-position of the upper border of the drift-chamber of actual layer
-  Int_t    icol       =  0;                                 // column-number of adc-channel
-  Double_t yPos[4];                                         // y-position of the pad to which ADC is connected
-  Double_t dx         = 30.0;                               // height of drift-chamber in mm; maybe retrieve from AliTRDGeometry
-  Double_t freqSample = fFeeParam->GetSamplingFrequency();  // retrieve the sampling frequency (10.019750 MHz)
-  Double_t vdrift     = fCal->GetVdriftAverage(fChaId);     // averaged drift velocity for this detector (1.500000 cm/us)
-  Int_t    nrOfDriftTimeBins = Int_t(dx/10.0*freqSample/vdrift); // the number of time bins in the drift region (20)
-  Int_t    nrOfAmplTimeBins  = 2;                           // the number of time bins between anode wire and cathode wires in ampl.region (3.5mm)(guess)(suppose v_drift+3.5cm/us there=>all clusters arrive at anode wire within one time bin (100ns))
-  Int_t    nrOfOffsetCorrTimeBins = tFS - nrOfAmplTimeBins - 1; // -1 is  to be conservative; offset correction will not remove the shift but is supposed to improve it; if tFS = 5, 2 drift time bins before tFS are assumed
-  if(nrOfOffsetCorrTimeBins < 0) nrOfOffsetCorrTimeBins = 0;// don't apply offset correction if no drift time bins before tFS can be assumed 
-  Double_t lorTan     = AliTRDCommonParam::Instance()->GetOmegaTau(vdrift); // tan of the Lorentz-angle for this detector; could be evaluated and set as a parameter for each mcm
-  //Double_t lorAngle   =  7.0;                             // Lorentz-angle in degrees
-  Double_t tiltAngle  = padPlane->GetTiltingAngle();        // sign-respecting tilting angle of pads in actual layer
-  Double_t tiltTan    = TMath::Tan(TMath::Pi()/180.0 * tiltAngle);
-  //Double_t lorTan     = TMath::Tan(TMath::Pi()/180.0 * lorAngle);
-
-  Double_t alphaMax[4];                            // maximum deflection from the direction to the primary vertex; granularity of hit pads
-  Double_t slopeMin[4];                            // local limits for the deflection
-  Double_t slopeMax[4];
-  Int_t   mslopeMin[4];                            // in granularity units; to be compared to mSlope[i]
-  Int_t   mslopeMax[4];
-
-
-  // x coord. of upper side of drift chambers in local SM-system (in mm)
-  // obtained by evaluating the x-range of the hits; should be crosschecked; only drift, not amplification region taken into account (30mm);
-  // the y-deflection is given as difference of y between lower and upper side of drift-chamber, not pad-plane;
-  switch(fLayer) 
-    {
-    case 0: 
-      xPos = 3003.0;
-      break;
-    case 1:
-      xPos = 3129.0;
-      break;
-    case 2:
-      xPos = 3255.0;
-      break;
-    case 3:
-      xPos = 3381.0;
-      break;
-    case 4:
-      xPos = 3507.0;
-      break;
-    case 5:
-      xPos = 3633.0;
-      break;
-    }
-  // calculation of offset-correction n: 
-
-  Int_t nCorrectOffset = (fRobPos % 2 == 0) ? ((fMcmPos % 4)) : ( 4 + (fMcmPos % 4));  
-  nCorrectOffset = (nCorrectOffset - 4)*18 - 1;
-  if (nCorrectOffset < 0) {
-    numAlu.AssignInt(-nCorrectOffset);
-    numAlu.SetSign(-1);
-  }
-  else {
-    numAlu.AssignInt(nCorrectOffset);
-    numAlu.SetSign(1);
+void AliTRDmcmSim::Tracklet()
+{
+  if (!fInitialized) {
+    AliError("Called uninitialized! Aborting!");
+    return;
   }
-  nCorrectOffset = numAlu.GetSignedValue();   
 
-  // the Lorentz correction to the offset
-  Double_t lorCorrectOffset = lorTan *(Double_t)nrOfOffsetCorrTimeBins*vdrift*10.0/freqSample; // Lorentz offset correction in mm
-  
+  fTrackletArray->Delete();
 
-  lorCorrectOffset = lorCorrectOffset/padWidthI; // Lorentz correction in pad width units
-  
-  if(lorCorrectOffset < 0) {
-      numAlu.AssignDouble(-lorCorrectOffset);
-      numAlu.SetSign(-1);
-  }
-  else{
-      numAlu.AssignDouble(lorCorrectOffset);
-      numAlu.SetSign(1);
-  }
-  
-  Int_t mlorCorrectOffset = numAlu.GetSignedValue();
-  
-  
-  Double_t mCorrectOffset = padWidthI/granularityOffset; // >= 0.0
-  // calculation of slope-correction
+  CalcFitreg();
+  TrackletSelection();
+  FitTracklet();
 
-  // this is only true for tracks coming (approx.) from primary vertex
-  // everything is evaluated for a tracklet covering the whole drift chamber
-  Double_t cCorrectSlope = (-lorTan*dx + zPos/xPos*dx*tiltTan)/granularitySlope;
-  // Double_t cCorrectSlope =  zPos/xPos*dx*tiltTan/granularitySlope;
-  // zPos can be negative! for track from primary vertex: zOut-zIn > 0 <=> zPos > 0
-  
-  if (cCorrectSlope < 0) {
-      numAlu.AssignDouble(-cCorrectSlope);
-      numAlu.SetSign(-1);
+  AliRunLoader *rl = AliRunLoader::Instance();
+  AliDataLoader *dl = 0x0;
+  if (rl)
+    dl = rl->GetLoader("TRDLoader")->GetDataLoader("tracklets");
+  if (!dl) {
+    AliError("Could not get the tracklets data loader!");
   }
   else {
-      numAlu.AssignDouble(cCorrectSlope);
-      numAlu.SetSign(1);
-  }
-  cCorrectSlope = numAlu.GetSignedValue();
-  // convert slope to deflection between upper and lower drift-chamber position (slope is given in pad-unit/time-bins)
-  // different pad-width of outer pads of a pad-plane not taken into account
-  // note that the fit was only done in the range tFS to tFE, however this range does not need to cover the whole drift region (neither start nor end of it)
-  // however the tracklets are supposed to be a fit in the drift region thus the linear function is stretched to fit the drift region of 30 mm
-  
-  
-  Double_t mCorrectSlope = (Double_t)(nrOfDriftTimeBins)*padWidthI/granularitySlope;  // >= 0.0
-
-  AliTRDtrapAlu correctAlu;
-  correctAlu.Init(20,8);
-  
-  AliTRDtrapAlu offsetAlu;
-  offsetAlu.Init(13,0,-0x1000,0x0FFF);          // 13 bit-word; 2-complement (1 sign-bit); asymmetric range
-  
-  AliTRDtrapAlu slopeAlu;
-  slopeAlu.Init(7,0,-0x40,0x3F);                // 7 bit-word;  2-complement (1 sign-bit);
-
-  for (Int_t i = 0; i<4; i++) {
-    
-    if (mADC[i] == -1) continue;
-    
-    icol = fFeeParam->GetPadColFromADC(fRobPos,fMcmPos,mADC[i]); // be aware that mADC[i] contains the ADC-number according to online-mapping
-    yPos[i]   = (padPlane->GetColPos(icol))*10.0;
-    
-    
-    // offset:
-    
-    correctAlu.AssignDouble(mCorrectOffset);     // done because max. accuracy is 8 bit
-    mCorrectOffset = correctAlu.GetValueWhole(); // cut offset correction to 8 past-comma bit accuracy
-    mOffset[i]  = (Int_t)((mCorrectOffset)*(Double_t)(mOffset[i] + nCorrectOffset - mlorCorrectOffset)); 
-    //mOffset[i]  = mOffset[i]*(-1);                   // adjust to direction of y-axes in online simulation
-    
-    if (mOffset[i] < 0) {
-      numAlu.AssignFormatted(-mOffset[i]);
-      numAlu.SetSign(-1);
-    }
-    else {
-      numAlu.AssignFormatted(mOffset[i]);
-      numAlu.SetSign(1);
-    }
-
-    offsetAlu = numAlu; 
-    mOffset[i]  = offsetAlu.GetSignedValue();  
+    TTree *trackletTree = dl->Tree();
+    if (!trackletTree)
+      dl->MakeTree();
+    trackletTree = dl->Tree();
 
-    
-    // slope:
-    
-    correctAlu.AssignDouble(mCorrectSlope);
-    mCorrectSlope = correctAlu.GetValueWhole();
-    
-    mSlope[i]   = (Int_t)((mCorrectSlope*(Double_t)mSlope[i]) + cCorrectSlope);
+    AliTRDtrackletMCM *trkl = 0x0;
+    TBranch *trkbranch = trackletTree->GetBranch("mcmtrklbranch");
+    if (!trkbranch)
+      trkbranch = trackletTree->Branch("mcmtrklbranch", "AliTRDtrackletMCM", &trkl, 32000);
+//      trkbranch = trackletTree->Branch("mcmtrklbranch", &fTrackletArray, 32000, 2);
 
-    if (mSlope[i] < 0) {
-      numAlu.AssignFormatted(-mSlope[i]);
-      numAlu.SetSign(-1);
+    for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
+      trkl = ((AliTRDtrackletMCM*) (*fTrackletArray)[iTracklet]);
+      trkbranch->SetAddress(&trkl);
+//      printf("filling tracklet 0x%08x\n", trkl->GetTrackletWord());
+      trkbranch->Fill();
     }
-    else {
-      numAlu.AssignFormatted(mSlope[i]);
-      numAlu.SetSign(1);
-    }
-
-    slopeAlu  = numAlu;     // here all past-comma values are cut, not rounded; alternatively add +0.5 before cutting (means rounding)
-    mSlope[i]   = slopeAlu.GetSignedValue(); 
-       
-    // local (LTU) limits for the deflection 
-    // ATan returns angles in radian
-    alphaMax[i]  = TMath::ASin(eCharge*magField/(2.0*ptMin)*(TMath::Sqrt(xPos*xPos + yPos[i]*yPos[i]))/1000.0); // /1000: mm->m
-    slopeMin[i]  = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) - alphaMax[i]))/granularitySlope;
-    slopeMax[i]  = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) + alphaMax[i]))/granularitySlope;
-    
-    if (slopeMin[i] < 0) {
-      slopeAlu.AssignDouble(-slopeMin[i]);
-      slopeAlu.SetSign(-1);
-    }
-    else { 
-      slopeAlu.AssignDouble(slopeMin[i]);
-      slopeAlu.SetSign(1);
-    }
-    mslopeMin[i] = slopeAlu.GetSignedValue();  // the borders should lie inside the range of mSlope -> usage of slopeAlu again
-   
-    if (slopeMax[i] < 0) {
-      slopeAlu.AssignDouble(-slopeMax[i]);
-      slopeAlu.SetSign(-1);
-    }
-    else {
-      slopeAlu.AssignDouble(slopeMax[i]);
-      slopeAlu.SetSign(1);
-    }
-    mslopeMax[i] = slopeAlu.GetSignedValue();
+    dl->WriteData("OVERWRITE");
   }
+}
 
-  // suppress submission of tracks with low stiffness
-  // put parameters in 32bit-word and submit (write to file as root-file; sort after SM, stack, layer, chamber) 
+void AliTRDmcmSim::WriteData(AliTRDarrayADC *digits)
+{
+  // write back the processed data configured by EBSF
+  // EBSF = 1: unfiltered data; EBSF = 0: filtered data
+  // zero-suppressed valued are written as -1 to digits
 
-  // sort tracklet-words in ascending y-order according to the offset (according to mADC would also be possible)
-  // up to now they are sorted according to maximum hit sum
-  // is the sorting really done in the TRAP-chip?
-  
-  Int_t order[4] = {-1,-1,-1,-1};
-  Int_t wordnr = 0;   // number of tracklet-words
-  
-  for(Int_t j = 0; j < fMaxTracklets; j++) {
-      //if( mADC[j] == -1) continue; 
-      if( (mADC[j] == -1) || (mSlope[j] < mslopeMin[j]) || (mSlope[j] > mslopeMax[j])) continue; // this applies a pt-cut
-      wordnr++;
-      if( wordnr-1 == 0) {
-         order[0] = j;
-         continue;
-      }
-      // wordnr-1>0, wordnr-1<4
-      order[wordnr-1] = j;
-      for( Int_t k = 0; k < wordnr-1; k++) {
-         if( mOffset[j] < mOffset[order[k]] ) {
-             for( Int_t l = wordnr-1; l > k; l-- ) {
-                 order[l] = order[l-1];
-             }
-             order[k] = j;
-             break;
-         }
-         
-      }
+  if (!fInitialized) {
+    AliError("Called uninitialized! Aborting!");
+    return;
   }
-        
-  // fill the bit-words in ascending order and without gaps
-  UInt_t bitWord[4] = {0,0,0,0};                 // attention: unsigned int to have real 32 bits (no 2-complement)
-  for(Int_t j = 0; j < wordnr; j++) { // only "wordnr" tracklet-words
-      //Bool_t rem1 = kTRUE;
-    
-    Int_t i = order[j];
-    //bit-word is 2-complement and therefore without sign
-    bitWord[j] =   1; // this is the starting 1 of the bit-word (at 33rd position); the 1 must be ignored
-    //printf("\n");
-    UInt_t shift  = 0;
-    UInt_t shift2 = 0;
-       
-       
-
-
-    /*printf("mean charge: %d\n",mMeanCharge[i]);
-    printf("row: %d\n",fRow);
-    printf("slope: %d\n",mSlope[i]);
-    printf("pad position: %d\n",mOffset[i]);
-    printf("channel: %d\n",mADC[i]);*/
-
-    // electron probability (currently not implemented; the mean charge is just scaled)
-    shift = (UInt_t)mMeanCharge[i];
-    for(Int_t iBit = 0; iBit < 8; iBit++) {
-      bitWord[j]  = bitWord[j]<<1;
-      bitWord[j] |= (shift>>(7-iBit))&1;               
-      //printf("0");
-    }
-
-    // pad row
-    shift = (UInt_t)fRow;
-    for(Int_t iBit = 0; iBit < 4; iBit++) {
-      bitWord[j]  = bitWord[j]<<1;
-      bitWord[j] |= (shift>>(3-iBit))&1;
-      //printf("%d", (fRow>>(3-iBit))&1);
-    }
-    
-    // deflection length
-    if(mSlope[i] < 0) {
-       shift = (UInt_t)(-mSlope[i]);
-       // shift2 is 2-complement of shift
-       shift2 = 1;
-       for(Int_t iBit = 1; iBit < 7; iBit++) {
-           shift2  = shift2<<1;
-           shift2 |= (1- (((shift)>>(6-iBit))&1) );
-           //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
-       }
-       shift2 = shift2 + 1;
-       //printf("1");
-       for(Int_t iBit = 0; iBit < 7; iBit++) {
-           bitWord[j]  = bitWord[j]<<1;
-           bitWord[j] |= (shift2>>(6-iBit))&1;
-           //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
-       }
-    }
-    else {
-       shift = (UInt_t)(mSlope[i]);
-       bitWord[j]  = bitWord[j]<<1;
-       bitWord[j]   |= 0;
-       //printf("0");
-       for(Int_t iBit = 1; iBit < 7; iBit++) {
-           bitWord[j]  = bitWord[j]<<1;
-           bitWord[j] |= (shift>>(6-iBit))&1;
-           //printf("%d",(mSlope[i]>>(6-iBit))&1);
-       }
-    }
 
-    // pad position
-    if(mOffset[i] < 0) {
-       shift = (UInt_t)(-mOffset[i]);
-       shift2 = 1;
-       for(Int_t iBit = 1; iBit < 13; iBit++) {
-           shift2  = shift2<<1;
-           shift2 |= (1-(((shift)>>(12-iBit))&1));
-           //printf("%d",(1-((-mOffset[i])>>(12-iBit))&1));
-       }
-       shift2 = shift2 + 1;
-       //printf("1");
-       for(Int_t iBit = 0; iBit < 13; iBit++) {
-           bitWord[j]  = bitWord[j]<<1;
-           bitWord[j] |= (shift2>>(12-iBit))&1;
-           //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
-       }
-    }
-    else {
-       shift = (UInt_t)mOffset[i];
-       bitWord[j] = bitWord[j]<<1;
-       bitWord[j]   |= 0; 
-       //printf("0");
-       for(Int_t iBit = 1; iBit < 13; iBit++) {
-           bitWord[j]  = bitWord[j]<<1;
-           bitWord[j] |= (shift>>(12-iBit))&1;
-           //printf("%d",(mOffset[i]>>(12-iBit))&1);
-       }
-    }
+  Int_t firstAdc = 0;
+  Int_t lastAdc = fNADC - 1;
 
+  if (GetCol(firstAdc) > 143)
+    firstAdc = 1;
 
-        
-    //printf("bitWord: %u\n",bitWord[j]);
-    //printf("adc: %d\n",mADC[i]);
-    fMCMT[j] = bitWord[j];
-  }
-    
-  //printf("\n");
+  if (GetCol(lastAdc) < 0) 
+    lastAdc = fNADC - 2;
 
-  
-  delete [] qsum;
-  delete [] ieffped;
-
-  delete [] X;
-  delete [] XX;
-  delete [] Y;
-  delete [] YY;
-  delete [] XY;
-  delete [] N;
-  delete [] QT0;
-  delete [] QT1;
-
-  delete [] hitSum;
-  delete [] selectPair;
-
-  delete padPlane;
-
-//if you want to activate the MC tracklet output, set fgkMCTrackletOutput=kTRUE in AliTRDfeeParam
-       
-  if (!fFeeParam->GetMCTrackletOutput()) 
-      return;
-  AliLog::SetClassDebugLevel("AliTRDmcmSim", 10);
-  AliLog::SetFileOutput("../log/tracklet.log");
-  
-  // testing for wordnr in order to speed up the simulation
-  if (wordnr == 0) 
-    return;
-   
-  UInt_t       *trackletWord = new UInt_t[fMaxTracklets];
-  Int_t        *adcChannel   = new Int_t[fMaxTracklets];
-  Int_t        *trackRef     = new Int_t[fMaxTracklets];
-
-  Int_t u = 0;
-
-  AliTRDdigitsManager *digman = new AliTRDdigitsManager();
-  digman->ReadDigits(AliRunLoader::Instance()->GetLoader("TRDLoader")->TreeD());
-  digman->SetUseDictionaries(kTRUE);
-  AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
-
-  for (Int_t j = 0; j < fMaxTracklets; j++) {
-      Int_t i = order[j];
-      trackletWord[j] = 0;
-      adcChannel[j] = -1;
-      if (bitWord[j]!=0) {
-         trackletWord[u] = bitWord[j];
-         adcChannel[u]   = mADC[i];   // mapping onto the original adc-array to be in line with the digits-adc-ordering (21 channels in total on 1 mcm, 18 belonging to pads); mADC[i] should be >-1 in case bitWord[i]>0
-
-// Finding label of MC track
-         TH1F *hTrkRef = new TH1F("trackref", "trackref", 100000, 0, 100000);
-         Int_t track[3];
-         Int_t padcol = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u]);
-         Int_t padcol_ngb = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u] - 1);
-         Int_t padrow = 4 * (fRobPos / 2) + fMcmPos / 4;
-         Int_t det = 30 * fSector + 6 * fStack + fLayer;
-         for(Int_t iTimebin = feeParam->GetLinearFitStart(); iTimebin < feeParam->GetLinearFitEnd(); iTimebin++) {
-             track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
-             track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
-             track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
-             hTrkRef->Fill(track[0]);
-             if (track[1] != track[0] && track[1] != -1)
-                 hTrkRef->Fill(track[1]);
-             if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
-                 hTrkRef->Fill(track[2]);
-             if (padcol_ngb >= 0) {
-                 track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
-                 track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
-                 track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
-                 hTrkRef->Fill(track[0]);
-                 if (track[1] != track[0] && track[1] != -1)
-                     hTrkRef->Fill(track[1]);
-                 if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
-                     hTrkRef->Fill(track[2]);
-             }
-         }
-         trackRef[u] = hTrkRef->GetMaximumBin() - 1;
-         delete hTrkRef;
-         u = u + 1;
+  if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBSF) != 0) // store unfiltered data
+  {
+    for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
+      if (fZSM1Dim[iAdc] == 1) {
+        for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+          digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, -1);
+//          printf("suppressed: %i, %i, %i, %i, now: %i\n", fDetector, GetRow(), GetCol(iAdc), iTimeBin, 
+//                 digits->GetData(GetRow(), GetCol(iAdc), iTimeBin));
+        }
       }
-  }
-
-  AliDataLoader *dl = AliRunLoader::Instance()->GetLoader("TRDLoader")->GetDataLoader("tracklets");
-  if (!dl) {
-    AliError("Could not get the tracklets data loader!");
+    }
   }
   else {
-    TTree *trackletTree = dl->Tree();
-    if (!trackletTree)
-      dl->MakeTree();
-    trackletTree = dl->Tree();
-
-   AliTRDtrackletMCM *trkl = new AliTRDtrackletMCM(); 
-   TBranch *trkbranch = trackletTree->GetBranch("mcmtrklbranch");
-   if (!trkbranch)
-       trkbranch = trackletTree->Branch("mcmtrklbranch", "AliTRDtrackletMCM", &trkl, 32000);
-    trkbranch->SetAddress(&trkl);
-
-    for (Int_t iTracklet = 0; iTracklet < fMaxTracklets; iTracklet++) {
-       if (trackletWord[iTracklet] == 0)
-           continue;
-       trkl->SetTrackletWord(trackletWord[iTracklet]);
-       trkl->SetDetector(30*fSector + 6*fStack + fLayer);
-       trkl->SetROB(fRobPos);
-       trkl->SetMCM(fMcmPos);
-       trkl->SetLabel(trackRef[iTracklet]);
-       trackletTree->Fill();
+    for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
+      if (fZSM1Dim[iAdc] == 0) {
+        for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+          digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, fADCF[iAdc][iTimeBin] >> fgkAddDigits);
+        }
+      }
+      else {
+        for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
+          digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, -1);
+//          printf("suppressed: %i, %i, %i, %i\n", fDetector, GetRow(), GetCol(iAdc), iTimeBin);
+        }
+      }
     }
-    delete trkl;
-    dl->WriteData("OVERWRITE");
   }
+}
 
-  delete [] trackletWord;
-  delete [] adcChannel; 
-  delete [] trackRef;
-  delete digman;
+// help functions, to be cleaned up
 
-  // to be done:
-  // error measure for quality of fit (not necessarily needed for the trigger)
-  // cluster quality threshold (not yet set)
-  // electron probability
+UInt_t AliTRDmcmSim::AddUintClipping(UInt_t a, UInt_t b, UInt_t nbits)
+{
+  // 
+  // This function adds a and b (unsigned) and clips to 
+  // the specified number of bits. 
+  //  
+
+  UInt_t sum = a + b;
+  if (nbits < 32)
+  {
+    UInt_t maxv = (1 << nbits) - 1;;
+    if (sum > maxv) 
+      sum = maxv;
+  }
+  else
+  {
+    if ((sum < a) || (sum < b)) 
+      sum = 0xFFFFFFFF;
+  }
+  return sum;
 }
-//_____________________________________________________________________________________
-void AliTRDmcmSim::GeneratefZSM1Dim()
+
+void AliTRDmcmSim::Sort2(uint16_t  idx1i, uint16_t  idx2i, \
+                            uint16_t  val1i, uint16_t  val2i, \
+                            uint16_t *idx1o, uint16_t *idx2o, \
+                            uint16_t *val1o, uint16_t *val2o)
 {
-  //
-  // Generate the array fZSM1Dim necessary
-  // for the method ProduceRawStream
-  //
 
-  // Fill the mapping
-  // Supressed zeros indicated by -1 in digits array
-  for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) 
+    if (val1i > val2i)
     {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         
-         if(fADCF[iadc][it]==-1)  // If is a supressed value
-           {
-             fZSM[iadc][it]=1;
-           }
-         else                    // Not suppressed
-           {
-             fZSM[iadc][it]=0;
-           }
-       }
+        *idx1o = idx1i;
+        *idx2o = idx2i;
+        *val1o = val1i;
+        *val2o = val2i;
     }
-
-  // Make the 1 dim projection
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) 
+    else
     {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         fZSM1Dim[iadc] &= fZSM[iadc][it];
-       }
+        *idx1o = idx2i;
+        *idx2o = idx1i;
+        *val1o = val2i;
+        *val2o = val1i;
     }
 }
-//_______________________________________________________________________________________
-void AliTRDmcmSim::CopyArrays()
-{
-  //
-  // Initialize filtered data array with raw data
-  // Method added for internal consistency
-  //
 
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) 
-    {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         fADCF[iadc][it] = fADCR[iadc][it]; 
-       }
-    }
-}
-//_______________________________________________________________________________________
-void AliTRDmcmSim::StartfastZS(Int_t pads, Int_t timebins)
+void AliTRDmcmSim::Sort3(uint16_t  idx1i, uint16_t  idx2i, uint16_t  idx3i, \
+                            uint16_t  val1i, uint16_t  val2i, uint16_t  val3i, \
+                            uint16_t *idx1o, uint16_t *idx2o, uint16_t *idx3o, \
+                            uint16_t *val1o, uint16_t *val2o, uint16_t *val3o)
 {
-  //
-  // Initialize just the necessary elements to perform
-  // the zero suppression in the digitizer
-  //
-   
-  fFeeParam  = AliTRDfeeParam::Instance();
-  fSimParam  = AliTRDSimParam::Instance();
-  fNADC      = pads;      
-  fNTimeBin  = timebins; 
+    int sel;
 
-  if( fADCR == NULL ) 
-    {
-      fADCR    = new Int_t *[fNADC];
-      fADCF    = new Int_t *[fNADC];
-      fADCT    = new Int_t *[fNADC]; 
-      fZSM     = new Int_t *[fNADC];
-      fZSM1Dim = new Int_t  [fNADC];
-    for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
-      {
-       fADCR[iadc] = new Int_t[fNTimeBin];
-       fADCF[iadc] = new Int_t[fNTimeBin];
-       fADCT[iadc] = new Int_t[fNTimeBin]; 
-       fZSM [iadc] = new Int_t[fNTimeBin];
-      }
-    }
 
-  for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) 
+    if (val1i > val2i) sel=4; else sel=0;
+    if (val2i > val3i) sel=sel + 2;
+    if (val3i > val1i) sel=sel + 1;
+    //printf("input channels %d %d %d, charges %d %d %d sel=%d\n",idx1i, idx2i, idx3i, val1i, val2i, val3i, sel);
+    switch(sel)
     {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         fADCR[iadc][it] =  0;
-         fADCF[iadc][it] =  0;
-         fADCT[iadc][it] = -1;  
-         fZSM [iadc][it] =  1;   
-       }
-      fZSM1Dim[iadc] = 1;      
-    }
-  
-  fInitialized = kTRUE;
+        case 6 : // 1 >  2  >  3            => 1 2 3
+        case 0 : // 1 =  2  =  3            => 1 2 3 : in this case doesn't matter, but so is in hardware!
+            *idx1o = idx1i;
+            *idx2o = idx2i;
+            *idx3o = idx3i;
+            *val1o = val1i;
+            *val2o = val2i;
+            *val3o = val3i;
+            break;
+
+        case 4 : // 1 >  2, 2 <= 3, 3 <= 1  => 1 3 2
+            *idx1o = idx1i;
+            *idx2o = idx3i;
+            *idx3o = idx2i;
+            *val1o = val1i;
+            *val2o = val3i;
+            *val3o = val2i;
+            break;
+
+        case 2 : // 1 <= 2, 2 > 3, 3 <= 1   => 2 1 3
+            *idx1o = idx2i;
+            *idx2o = idx1i;
+            *idx3o = idx3i;
+            *val1o = val2i;
+            *val2o = val1i;
+            *val3o = val3i;
+            break;
+
+        case 3 : // 1 <= 2, 2 > 3, 3  > 1   => 2 3 1
+            *idx1o = idx2i;
+            *idx2o = idx3i;
+            *idx3o = idx1i;
+            *val1o = val2i;
+            *val2o = val3i;
+            *val3o = val1i;
+            break;
+
+        case 1 : // 1 <= 2, 2 <= 3, 3 > 1   => 3 2 1
+            *idx1o = idx3i;
+            *idx2o = idx2i;
+            *idx3o = idx1i;
+            *val1o = val3i;
+            *val2o = val2i;
+            *val3o = val1i;
+        break;
+
+        case 5 : // 1 > 2, 2 <= 3, 3 >  1   => 3 1 2
+            *idx1o = idx3i;
+            *idx2o = idx1i;
+            *idx3o = idx2i;
+            *val1o = val3i;
+            *val2o = val1i;
+            *val3o = val2i;
+        break;
+
+        default: // the rest should NEVER happen!
+            printf("ERROR in Sort3!!!\n");
+        break;
+    }
+//    printf("output channels %d %d %d, charges %d %d %d \n",*idx1o, *idx2o, *idx3o, *val1o, *val2o, *val3o);
 }
-//_______________________________________________________________________________________
-void AliTRDmcmSim::FlagDigitsArray(AliTRDarrayADC *tempdigs, Int_t valrow)
+
+void AliTRDmcmSim::Sort6To4(uint16_t  idx1i, uint16_t  idx2i, uint16_t  idx3i, uint16_t  idx4i, uint16_t  idx5i, uint16_t  idx6i, \
+                               uint16_t  val1i, uint16_t  val2i, uint16_t  val3i, uint16_t  val4i, uint16_t  val5i, uint16_t  val6i, \
+                               uint16_t *idx1o, uint16_t *idx2o, uint16_t *idx3o, uint16_t *idx4o, \
+                               uint16_t *val1o, uint16_t *val2o, uint16_t *val3o, uint16_t *val4o)
 {
-  //
-  // Modify the digits array to flag suppressed values
-  //
 
-  for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) 
-    {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         if(fZSM[iadc][it]==1)
-           {
-             tempdigs->SetData(valrow,iadc,it,-1);
-           }
-       }
-    }
+    uint16_t idx21s, idx22s, idx23s, dummy;
+    uint16_t val21s, val22s, val23s;
+    uint16_t idx23as, idx23bs;
+    uint16_t val23as, val23bs;
+
+    Sort3(idx1i, idx2i, idx3i, val1i, val2i, val3i,
+                 idx1o, &idx21s, &idx23as,
+                 val1o, &val21s, &val23as);
+
+    Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
+                 idx2o, &idx22s, &idx23bs,
+                 val2o, &val22s, &val23bs);
+
+    Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, &dummy, &val23s, &dummy);
+
+    Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
+                 idx3o, idx4o, &dummy,
+                 val3o, val4o, &dummy);
+
 }
-//_______________________________________________________________________________________
-void AliTRDmcmSim::RestoreZeros()
+
+void AliTRDmcmSim::Sort6To2Worst(uint16_t  idx1i, uint16_t  idx2i, uint16_t  idx3i, uint16_t  idx4i, uint16_t  idx5i, uint16_t  idx6i, \
+                                    uint16_t  val1i, uint16_t  val2i, uint16_t  val3i, uint16_t  val4i, uint16_t  val5i, uint16_t  val6i, \
+                                    uint16_t *idx5o, uint16_t *idx6o)
 {
-  //
-  // Restore the zero-suppressed values (set as -1) to the value 0
-  //
 
-  for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) 
-    {
-      for( Int_t it = 0 ; it < fNTimeBin ; it++ ) 
-       {
-         
-         if(fADCF[iadc][it]==-1)  //if is a supressed zero, reset to zero
-           {
-             fADCF[iadc][it]=0;
-             fADCR[iadc][it]=0;
-           }     
-       }
-    }
+    uint16_t idx21s, idx22s, idx23s, dummy1, dummy2, dummy3, dummy4, dummy5;
+    uint16_t val21s, val22s, val23s;
+    uint16_t idx23as, idx23bs;
+    uint16_t val23as, val23bs;
+
+    Sort3(idx1i, idx2i,   idx3i, val1i, val2i, val3i,
+                 &dummy1, &idx21s, &idx23as,
+                 &dummy2, &val21s, &val23as);
+
+    Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
+                 &dummy1, &idx22s, &idx23bs,
+                 &dummy2, &val22s, &val23bs);
+
+    Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, idx5o, &val23s, &dummy1);
 
+    Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
+                 &dummy1, &dummy2, idx6o,
+                 &dummy3, &dummy4, &dummy5);
+//    printf("idx21s=%d, idx23as=%d, idx22s=%d, idx23bs=%d, idx5o=%d, idx6o=%d\n",
+//            idx21s,    idx23as,    idx22s,    idx23bs,    *idx5o,    *idx6o);
 }
 
index 5422768..5cddbed 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef ALITRDMCMSIM_H
-#define ALITRDMCMSIM_H
+#ifndef ALITRDMCMSIMNEW_H
+#define ALITRDMCMSIMNEW_H
 /* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
  * See cxx source for full Copyright notice                               */
 
 ///////////////////////////////////////////////////////
 
 #include <TObject.h>
+#include <TClonesArray.h>
 
+class AliRunLoader;
 class AliTRDfeeParam;
 class AliTRDSimParam;
+class AliTRDtrapConfig;
 class AliTRDcalibDB;
 class AliTRDgeometry;
-class AliTRDtrapAlu;
 class AliTRDpadPlane;
 class AliTRDarrayADC;
 
 class AliTRDmcmSim : public TObject {
-
  public:
-
                     AliTRDmcmSim();
-                    AliTRDmcmSim(const AliTRDmcmSim &m);
   virtual          ~AliTRDmcmSim();
-  AliTRDmcmSim      &operator=(const AliTRDmcmSim &m);
 
-  virtual void      Copy(TObject &m) const;
+          void      Init( Int_t cha, Int_t rob, Int_t mcm, Bool_t newEvent = kFALSE );   // Initialize MCM by the position parameters
+         void      Reset();                                   // clears filter registers and internal data
+
+         Bool_t    LoadMCM(AliRunLoader *runloader, Int_t det, Int_t rob, Int_t mcm);
+         void      NoiseTest(Int_t nsamples, Int_t mean, Int_t sigma, Int_t inputGain = 1, Int_t inputTail = 2);
 
-          void      Init( Int_t cha, Int_t rob, Int_t mcm, Bool_t newEvent );   // Initialize MCM by the position parameters
-  //void      Init( Int_t cha, Int_t rob, Int_t mcm );   // Initialize MCM by the position parameters
           void      SetData(Int_t iadc, Int_t *adc);           // Set ADC data with array 
           void      SetData(Int_t iadc, Int_t it, Int_t adc ); // Set ADC data
+         void      SetData(AliTRDarrayADC *adcArray);         // Set ADC data from adcArray
           void      SetDataPedestal(Int_t iadc );              // Fill ADC data with pedestal values
 
-          Int_t     GetChaId() const  { return fChaId;  };     // Returns Chamber ID (0-539)
+          Int_t     GetDetector() const  { return fDetector;  };     // Returns Chamber ID (0-539)
           Int_t     GetRobPos() const { return fRobPos; };     // Returns ROB position (0-7)
           Int_t     GetMcmPos() const { return fMcmPos; };     // Returns MCM position (0-17) (16,17 are mergers)
           Int_t     GetRow() const    { return fRow;    };     // Returns Row number on chamber where the MCM is sitting
          Int_t     GetCol( Int_t iadc );                      // Get corresponding column (0-143) from for ADC channel iadc = [0:20]
          // for the ADC/Col mapping, see: http://wiki.kip.uni-heidelberg.de/ti/TRD/index.php/Image:ROB_MCM_numbering.pdf
 
-         Int_t*    GetPosLUT();
+         void WriteData(AliTRDarrayADC *digits);
 
-         Int_t     ProduceRawStream( UInt_t *buf, Int_t bufsize );   // Produce raw data stream from this MCM - old
-         Int_t     ProduceRawStreamV2( UInt_t *buf, Int_t bufsize, UInt_t iEv ); // Produce raw data stream - Read data format
+         Int_t     ProduceRawStream( UInt_t *buf, Int_t bufsize, UInt_t iEv = 0 ); // Produce raw data stream - Read data format
          Int_t     ProduceTrackletStream( UInt_t *buf, Int_t bufsize ); // produce the tracklet stream for this MCM
-         void      Filter();                                  // Apply digital filters for existing data
+               
+         // different stages of processing in the TRAP
+         void      Filter();                                  // Apply digital filters for existing data (according to configuration)
          void      ZSMapping();                               // Do ZS mapping for existing data
-         void      DumpData( char *f, char *target );         // Dump data stored (only for debugging)
-         void      Tracklet();
-         void      SetPosLUT();
-         void      CopyArrays();                              // Copy arrays between containers, internal consistency
-         void      GeneratefZSM1Dim();                        // Generate the ZSM1Dim based on digits array info
-         void      StartfastZS(Int_t pads, Int_t timebis);                    // For ZS in the digitizer
-         void      FlagDigitsArray(AliTRDarrayADC *tempdigs, Int_t valrow);   //Set flags on the digits array
-         void      RestoreZeros(); 
+         void      Tracklet();                                // Run tracklet preprocessor and perform tracklet fit
 
- protected:
+         // apply individual filters to all channels and timebins
+         void      FilterPedestal();                   // Apply pedestal filter
+         void      FilterGain();                       // Apply gain filter
+         void      FilterTail();                       // Apply tail filter
 
-          Bool_t    fInitialized;                       // Status whether the class is initialized or not
-         Int_t    fNextEvent;                         // 0, if new event; 1 if not
-         Int_t     fMaxTracklets;                      // maximum number of tracklet-words submitted per mcm **new**
-         Int_t     fChaId;                             // Chamber ID
-         Int_t     fSector;                            // Sector number of the supermodule
-         Int_t     fStack;                             // Chamber stack ID
-         Int_t     fLayer;                             // Chamber layer ID
-          Int_t     fRobPos;                            // ROB Position on chamber
-          Int_t     fMcmPos;                            // MCM Position on chamber
-         Int_t     fNADC;                              // Number of ADC (usually 21)
-         Int_t     fNTimeBin;                          // Number of Timebins (variable)
-          Int_t     fRow;                               // Pad row number (0-11 or 0-15) of the MCM on chamber
-         Int_t   **fADCR;                              // Array with MCM ADC values (Raw)
-          Int_t   **fADCF;                              // Array with MCM ADC values (Filtered)
-         Int_t   **fADCT;                              // Array with MCM ADC values (filtered) for tracklet (12bits) //***NEW***
-         Int_t    *fPosLUT;                            // position lookup table **new**
-         UInt_t   *fMCMT;                              // tracklet word for one mcm/trap-chip **new**
-         Int_t   **fZSM;                               // Zero suppression map
-          Int_t    *fZSM1Dim;                           // Zero suppression map (1 dimensional projection)
+         // filter initialization (resets internal registers)
+         void      FilterPedestalInit();
+         void      FilterGainInit();
+         void      FilterTailInit(Int_t baseline); //??? automatic baseline??
 
-       
-       
+         // feed single sample to individual filter
+         // this changes the internal registers
+         // all filters operate on 12-bit values!
+         UShort_t  FilterPedestalNextSample(Int_t adc, Int_t timebin, UShort_t value);
+         UShort_t  FilterGainNextSample(Int_t adc, UShort_t value);
+         UShort_t  FilterTailNextSample(Int_t adc, UShort_t value);
 
+         // tracklet calculation
+         void      AddHitToFitreg(Int_t adc, UShort_t timebin, UShort_t qtot, Short_t ypos, Int_t label);
+         void      CalcFitreg();
+         void      TrackletSelection();
+         void      FitTracklet();
 
-         // Parameter classes
-         AliTRDfeeParam *fFeeParam;                    // FEE parameters
-         AliTRDSimParam *fSimParam;                    // Simulation parameters
-         AliTRDcalibDB  *fCal;                         // Calibration interface
-         AliTRDgeometry *fGeo;                         // Geometry
+         TClonesArray* GetTrackletArray() { return fTrackletArray; }
 
-         Bool_t    CheckInitialized();                 // Check whether the class is initialized
-         void      FilterPedestal();                   // Apply pedestal filter
-         void      FilterGain();                       // Apply gain filter
-         void      FilterTail();                       // Apply tail filter
+         // data display
+         void      Print(Option_t* option="") const;   // print stored data to stdout
+         void      Draw(Option_t *option ="");         // draw data (ADC data, hits and tracklets)
+         void      DumpData( char *f, char *target );  // Dump data stored (only for debugging)
 
-         // Here are the several sub functions used only in FilterTail
-         void      FilterSimDeConvExpA(Int_t *source, Double_t *target, Int_t n, Int_t nexp);
-         void      FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n, Int_t nexp);
-         void      FilterSimDeConvExpMI(Int_t *source, Double_t *target, Int_t n);
-         void      FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout, Double_t lambda, Int_t n);
-         void      FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout, Double_t norm, Double_t lambda, Int_t n);
-         void      FilterSimDeConvExpEl(Int_t *source, Int_t *target, Int_t n, Int_t nexp);
+ protected:
+         Bool_t    CheckInitialized();                 // Check whether the class is initialized
+         
+         Bool_t    fInitialized;                       // Status whether the class is initialized or not
+         Int_t     fMaxTracklets;                      // maximum number of tracklet-words submitted per mcm **new** //???
+         Int_t     fDetector;                             // Chamber ID
+         Int_t     fRobPos;                            // ROB Position on chamber 
+         Int_t     fMcmPos;                            // MCM Position on chamber 
+         Int_t     fRow;                               // Pad row number (0-11 or 0-15) of the MCM on chamber
+         Int_t     fNADC;                              // Number of ADC (usually 21) //??? static const
+         Int_t     fNTimeBin;                          // Number of Timebins (variable)  //??? why stored here? taken from TRAPconfig
+         Int_t   **fADCR;                              // Array with MCM ADC values (Raw, 12 bit)
+         Int_t   **fADCF;                              // Array with MCM ADC values (Filtered, 12 bit)
+         UInt_t   *fMCMT;                              // tracklet word for one mcm/trap-chip **new** //??? needed?
+         TClonesArray *fTrackletArray;                 // Array of AliTRDtrackletMCM which contains MC information in addition to the tracklet word
+         Int_t   **fZSM;                               // Zero suppression map
+         Int_t    *fZSM1Dim;                           // Zero suppression map (1 dimensional projection)
 
-  ClassDef(AliTRDmcmSim,3)
+         static const Int_t fgkAddDigits = 2;          // additional digits used for internal representation
+                                                       // all internal data as after data control block (i.e. 12 bit), s. TRAP manual
+         static const Int_t fgkNCPU = 4;               // Number of CPUs in the TRAP
+         Int_t     fFitPtr[fgkNCPU];                   // pointer to the tracklet to be calculated by CPU i
+         static const Int_t fgkNHitsMC = 100;          // maximum number of hits for which MC information is kept
 
+         // Parameter classes
+         AliTRDfeeParam    *fFeeParam;                 // FEE parameters
+         AliTRDtrapConfig  *fTrapConfig;               // TRAP config
+         AliTRDSimParam    *fSimParam;                 // Simulation parameters
+         AliTRDcalibDB     *fCal;                      // Calibration interface
+         AliTRDgeometry    *fGeo;                      // Geometry
+
+         // internal filter registers
+         UInt_t*   fPedAcc;                            // Accumulator for pedestal filter
+         UInt_t*   fGainCounterA;                      // Counter for values above FGTA in the gain filter
+         UInt_t*   fGainCounterB;                      // Counter for values above FGTB in the gain filter
+         UShort_t* fTailAmplLong;                      // Amplitude of the long component in the tail filter
+         UShort_t* fTailAmplShort;                     // Amplitude of the short component in the tail filter
+
+         // hit detection
+         // individual hits can be stored as MC info
+         struct Hit_t {
+           Int_t channel;
+           Int_t timebin;
+           Int_t qtot;
+           Int_t ypos;
+           Int_t label;
+         } fHits[fgkNHitsMC];                          // Array of detected hits (only available in MC)
+         Int_t fNHits;                                 // Number of detected hits
+
+         // tracklet calculation
+         struct FitReg_t {
+           Int_t   Nhits;
+           UInt_t Q0;
+           UInt_t Q1;
+           UInt_t SumX;
+           Int_t SumY;
+           UInt_t SumX2;
+           UInt_t SumY2;
+           Int_t SumXY;
+         } *fFitReg;                                   // pointer to the 18 fit registers 
+
+         //??? cleaning up
+         void Sort2(UShort_t  idx1i, UShort_t  idx2i, UShort_t  val1i, UShort_t  val2i, 
+                    UShort_t *idx1o, UShort_t *idx2o, UShort_t *val1o, UShort_t *val2o);
+         void Sort3(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, 
+                    UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, 
+                    UShort_t *idx1o, UShort_t *idx2o, UShort_t *idx3o, 
+                    UShort_t *val1o, UShort_t *val2o, UShort_t *val3o);
+         void Sort6To4(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, UShort_t  idx4i, UShort_t  idx5i, UShort_t  idx6i, 
+                       UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, UShort_t  val4i, UShort_t  val5i, UShort_t  val6i, 
+                       UShort_t *idx1o, UShort_t *idx2o, UShort_t *idx3o, UShort_t *idx4o, 
+                       UShort_t *val1o, UShort_t *val2o, UShort_t *val3o, UShort_t *val4o);
+         void Sort6To2Worst(UShort_t  idx1i, UShort_t  idx2i, UShort_t  idx3i, UShort_t  idx4i, UShort_t  idx5i, UShort_t  idx6i, 
+                            UShort_t  val1i, UShort_t  val2i, UShort_t  val3i, UShort_t  val4i, UShort_t  val5i, UShort_t  val6i, 
+                            UShort_t *idx5o, UShort_t *idx6o);
+
+         UInt_t AddUintClipping(UInt_t a, UInt_t b, UInt_t nbits);  // Add a and b (unsigned) with clipping to the maximum value representable by nbits
+
+ private:
+         AliTRDmcmSim(const AliTRDmcmSim &m);             // not implemented
+         AliTRDmcmSim &operator=(const AliTRDmcmSim &m);  // not implemented
+
+
+  ClassDef(AliTRDmcmSim,4)
 };
 
 #endif
index 90096fd..e75b117 100644 (file)
@@ -544,11 +544,11 @@ Int_t AliTRDrawData::ProduceHcData(AliTRDarrayADC *digits, Int_t side, Int_t det
                }
 
                // Simulate process in MCM
-               //              mcm[entry]->Filter();     // Apply filter
-               //              mcm[entry]->ZSMapping();  // Calculate zero suppression mapping
-               mcm[entry]->CopyArrays();
-               mcm[entry]->GeneratefZSM1Dim();
-               mcm[entry]->RestoreZeros();
+               mcm[entry]->Filter();     // Apply filter
+               mcm[entry]->ZSMapping();  // Calculate zero suppression mapping
+//jkl          mcm[entry]->CopyArrays();
+//jkl          mcm[entry]->GeneratefZSM1Dim();
+//jkl          mcm[entry]->RestoreZeros();
 
                if (tracklet_on) {
                    mcm[entry]->Tracklet(); 
@@ -563,7 +563,7 @@ Int_t AliTRDrawData::ProduceHcData(AliTRDarrayADC *digits, Int_t side, Int_t det
                    }
                } else { // no tracklets: write raw-data already in this loop 
                    // Write MCM data to buffer
-                   Int_t tempNw =  mcm[entry]->ProduceRawStreamV2( &buf[nw], maxSize - nw, fEventCounter );
+                   Int_t tempNw =  mcm[entry]->ProduceRawStream( &buf[nw], maxSize - nw, fEventCounter );
                    if( tempNw < 0 ) {
                                of += tempNw;
                                nw += maxSize - nw;
@@ -593,7 +593,7 @@ Int_t AliTRDrawData::ProduceHcData(AliTRDarrayADC *digits, Int_t side, Int_t det
                        Int_t entry = iRobRow*(fGeo->MCMmax()) + iMcm; 
                      
                        // Write MCM data to buffer
-                       Int_t tempNw =  mcm[entry]->ProduceRawStreamV2( &buf[nw], maxSize - nw, fEventCounter );
+                       Int_t tempNw =  mcm[entry]->ProduceRawStream( &buf[nw], maxSize - nw, fEventCounter );
                        if( tempNw < 0 ) {
                                        of += tempNw;
                                        nw += maxSize - nw;
@@ -891,11 +891,11 @@ Int_t AliTRDrawData::ProduceHcDataV3(AliTRDarrayADC *digits, Int_t side , Int_t
        }
 
        // Simulate process in MCM
-       //      mcm[entry]->Filter();     // Apply filter
-       //      mcm[entry]->ZSMapping();  // Calculate zero suppression mapping
-       mcm[entry]->CopyArrays();
-       mcm[entry]->GeneratefZSM1Dim();
-       mcm[entry]->RestoreZeros();
+       mcm[entry]->Filter();     // Apply filter
+       mcm[entry]->ZSMapping();  // Calculate zero suppression mapping
+//jkl  mcm[entry]->CopyArrays();
+//jkl  mcm[entry]->GeneratefZSM1Dim();
+//jkl  mcm[entry]->RestoreZeros();
 
        if (tracklet_on) {
            mcm[entry]->Tracklet(); 
index 77d2712..907f19a 100644 (file)
@@ -52,6 +52,18 @@ AliTRDtrackletMCM::AliTRDtrackletMCM(UInt_t trackletWord, Int_t hcid) :
     fGeo = new AliTRDgeometry();
 }
 
+AliTRDtrackletMCM::AliTRDtrackletMCM(UInt_t trackletWord, Int_t hcid, Int_t rob, Int_t mcm) :
+  AliTRDtrackletBase(),
+  fGeo(0x0),
+  fHCId(hcid),
+  fTrackletWord(trackletWord), 
+  fMCM(mcm),
+  fROB(rob),
+  fLabel(-1)
+{ 
+    fGeo = new AliTRDgeometry();
+}
+
 AliTRDtrackletMCM::AliTRDtrackletMCM(const AliTRDtrackletMCM &rhs) :
   AliTRDtrackletBase(rhs),
   fGeo(0x0),
index 3541f67..aaf126f 100644 (file)
@@ -20,6 +20,7 @@ class AliTRDtrackletMCM : public AliTRDtrackletBase {
  public:
   AliTRDtrackletMCM(UInt_t trackletWord = 0);
   AliTRDtrackletMCM(UInt_t trackletWword, Int_t hcid);
+  AliTRDtrackletMCM(UInt_t trackletWword, Int_t hcid, Int_t rob, Int_t mcm);
   AliTRDtrackletMCM(const AliTRDtrackletMCM &rhs);
   ~AliTRDtrackletMCM();
 
diff --git a/TRD/AliTRDtrapConfig.cxx b/TRD/AliTRDtrapConfig.cxx
new file mode 100644 (file)
index 0000000..cd1140f
--- /dev/null
@@ -0,0 +1,609 @@
+#include "AliLog.h"
+
+#include "AliTRDtrapConfig.h"
+
+ClassImp(AliTRDtrapConfig)
+
+AliTRDtrapConfig* AliTRDtrapConfig::fgInstance = 0x0;
+
+AliTRDtrapConfig::AliTRDtrapConfig() : 
+  TObject()
+{
+  // default constructor, initializing array of TRAP registers
+
+  //                              Name          Address  Nbits   Reset Value
+  fRegs[kSML0]    =   SimpleReg_t("SML0",        0x0A00, 15,     0x4050     );  // Global state machine
+  fRegs[kSML1]    =   SimpleReg_t("SML1",        0x0A01, 15,     0x4200     );
+  fRegs[kSML2]    =   SimpleReg_t("SML2",        0x0A02, 15,     0x4384     );
+  fRegs[kSMMODE]  =   SimpleReg_t("SMMODE",      0x0A03, 16,     0xF0E2     );
+  fRegs[kNITM0]   =   SimpleReg_t("NITM0",       0x0A08, 14,     0x3FFF     );
+  fRegs[kNITM1]   =   SimpleReg_t("NITM1",       0x0A09, 14,     0x3FFF     );
+  fRegs[kNITM2]   =   SimpleReg_t("NITM2",       0x0A0A, 14,     0x3FFF     );
+  fRegs[kNIP4D]   =   SimpleReg_t("NIP4D",       0x0A0B, 7,      0x7F       );
+  fRegs[kCPU0CLK] =   SimpleReg_t("CPU0CLK",     0x0A20, 5,      0x07       );
+  fRegs[kCPU1CLK] =   SimpleReg_t("CPU1CLK",     0x0A22, 5,      0x07       );
+  fRegs[kCPU2CLK] =   SimpleReg_t("CPU2CLK",     0x0A24, 5,      0x07       );
+  fRegs[kCPU3CLK] =   SimpleReg_t("CPU3CLK",     0x0A26, 5,      0x07       );
+  fRegs[kNICLK]   =   SimpleReg_t("NICLK",       0x0A28, 5,      0x07       );
+  fRegs[kFILCLK]  =   SimpleReg_t("FILCLK",      0x0A2A, 5,      0x07       );
+  fRegs[kPRECLK]  =   SimpleReg_t("PRECLK",      0x0A2C, 5,      0x07       );
+  fRegs[kADCEN]   =   SimpleReg_t("ADCEN",       0x0A2E, 5,      0x07       );
+  fRegs[kNIODE]   =   SimpleReg_t("NIODE",       0x0A30, 5,      0x07       );
+  fRegs[kNIOCE]   =   SimpleReg_t("NIOCE",       0x0A32, 6,      0x21       );  // bit 5 is status bit (read-only)!
+  fRegs[kNIIDE]   =   SimpleReg_t("NIIDE",       0x0A34, 5,      0x07       );
+  fRegs[kNIICE]   =   SimpleReg_t("NIICE",       0x0A36, 5,      0x07       );
+  fRegs[kARBTIM]  =   SimpleReg_t("ARBTIM",      0x0A3F, 4,      0x0        );  // Arbiter
+  fRegs[kIA0IRQ0] =   SimpleReg_t("IA0IRQ0",     0x0B00, 12,     0x000      );  // IVT of CPU0
+  fRegs[kIA0IRQ1] =   SimpleReg_t("IA0IRQ1",     0x0B01, 12,     0x000      );
+  fRegs[kIA0IRQ2] =   SimpleReg_t("IA0IRQ2",     0x0B02, 12,     0x000      );
+  fRegs[kIA0IRQ3] =   SimpleReg_t("IA0IRQ3",     0x0B03, 12,     0x000      );
+  fRegs[kIA0IRQ4] =   SimpleReg_t("IA0IRQ4",     0x0B04, 12,     0x000      );
+  fRegs[kIA0IRQ5] =   SimpleReg_t("IA0IRQ5",     0x0B05, 12,     0x000      );
+  fRegs[kIA0IRQ6] =   SimpleReg_t("IA0IRQ6",     0x0B06, 12,     0x000      );
+  fRegs[kIA0IRQ7] =   SimpleReg_t("IA0IRQ7",     0x0B07, 12,     0x000      );
+  fRegs[kIA0IRQ8] =   SimpleReg_t("IA0IRQ8",     0x0B08, 12,     0x000      );
+  fRegs[kIA0IRQ9] =   SimpleReg_t("IA0IRQ9",     0x0B09, 12,     0x000      );
+  fRegs[kIA0IRQA] =   SimpleReg_t("IA0IRQA",     0x0B0A, 12,     0x000      );
+  fRegs[kIA0IRQB] =   SimpleReg_t("IA0IRQB",     0x0B0B, 12,     0x000      );
+  fRegs[kIA0IRQC] =   SimpleReg_t("IA0IRQC",     0x0B0C, 12,     0x000      );
+  fRegs[kIRQSW0]  =   SimpleReg_t("IRQSW0",      0x0B0D, 13,     0x1FFF     );
+  fRegs[kIRQHW0]  =   SimpleReg_t("IRQHW0",      0x0B0E, 13,     0x0000     );
+  fRegs[kIRQHL0]  =   SimpleReg_t("IRQHL0",      0x0B0F, 13,     0x0000     );
+  fRegs[kIA1IRQ0] =   SimpleReg_t("IA1IRQ0",     0x0B20, 12,     0x000      );  // IVT of CPU1
+  fRegs[kIA1IRQ1] =   SimpleReg_t("IA1IRQ1",     0x0B21, 12,     0x000      );
+  fRegs[kIA1IRQ2] =   SimpleReg_t("IA1IRQ2",     0x0B22, 12,     0x000      );
+  fRegs[kIA1IRQ3] =   SimpleReg_t("IA1IRQ3",     0x0B23, 12,     0x000      );
+  fRegs[kIA1IRQ4] =   SimpleReg_t("IA1IRQ4",     0x0B24, 12,     0x000      );
+  fRegs[kIA1IRQ5] =   SimpleReg_t("IA1IRQ5",     0x0B25, 12,     0x000      );
+  fRegs[kIA1IRQ6] =   SimpleReg_t("IA1IRQ6",     0x0B26, 12,     0x000      );
+  fRegs[kIA1IRQ7] =   SimpleReg_t("IA1IRQ7",     0x0B27, 12,     0x000      );
+  fRegs[kIA1IRQ8] =   SimpleReg_t("IA1IRQ8",     0x0B28, 12,     0x000      );
+  fRegs[kIA1IRQ9] =   SimpleReg_t("IA1IRQ9",     0x0B29, 12,     0x000      );
+  fRegs[kIA1IRQA] =   SimpleReg_t("IA1IRQA",     0x0B2A, 12,     0x000      );
+  fRegs[kIA1IRQB] =   SimpleReg_t("IA1IRQB",     0x0B2B, 12,     0x000      );
+  fRegs[kIA1IRQC] =   SimpleReg_t("IA1IRQC",     0x0B2C, 12,     0x000      );
+  fRegs[kIRQSW1]  =   SimpleReg_t("IRQSW1",      0x0B2D, 13,     0x1FFF     );
+  fRegs[kIRQHW1]  =   SimpleReg_t("IRQHW1",      0x0B2E, 13,     0x0000     );
+  fRegs[kIRQHL1]  =   SimpleReg_t("IRQHL1",      0x0B2F, 13,     0x0000     );
+  fRegs[kIA2IRQ0] =   SimpleReg_t("IA2IRQ0",     0x0B40, 12,     0x000      );  // IVT of CPU2
+  fRegs[kIA2IRQ1] =   SimpleReg_t("IA2IRQ1",     0x0B41, 12,     0x000      );
+  fRegs[kIA2IRQ2] =   SimpleReg_t("IA2IRQ2",     0x0B42, 12,     0x000      );
+  fRegs[kIA2IRQ3] =   SimpleReg_t("IA2IRQ3",     0x0B43, 12,     0x000      );
+  fRegs[kIA2IRQ4] =   SimpleReg_t("IA2IRQ4",     0x0B44, 12,     0x000      );
+  fRegs[kIA2IRQ5] =   SimpleReg_t("IA2IRQ5",     0x0B45, 12,     0x000      );
+  fRegs[kIA2IRQ6] =   SimpleReg_t("IA2IRQ6",     0x0B46, 12,     0x000      );
+  fRegs[kIA2IRQ7] =   SimpleReg_t("IA2IRQ7",     0x0B47, 12,     0x000      );
+  fRegs[kIA2IRQ8] =   SimpleReg_t("IA2IRQ8",     0x0B48, 12,     0x000      );
+  fRegs[kIA2IRQ9] =   SimpleReg_t("IA2IRQ9",     0x0B49, 12,     0x000      );
+  fRegs[kIA2IRQA] =   SimpleReg_t("IA2IRQA",     0x0B4A, 12,     0x000      );
+  fRegs[kIA2IRQB] =   SimpleReg_t("IA2IRQB",     0x0B4B, 12,     0x000      );
+  fRegs[kIA2IRQC] =   SimpleReg_t("IA2IRQC",     0x0B4C, 12,     0x000      );
+  fRegs[kIRQSW2]  =   SimpleReg_t("IRQSW2",      0x0B4D, 13,     0x1FFF     );
+  fRegs[kIRQHW2]  =   SimpleReg_t("IRQHW2",      0x0B4E, 13,     0x0000     );
+  fRegs[kIRQHL2]  =   SimpleReg_t("IRQHL2",      0x0B4F, 13,     0x0000     );
+  fRegs[kIA3IRQ0] =   SimpleReg_t("IA3IRQ0",     0x0B60, 12,     0x000      );  // IVT of CPU3
+  fRegs[kIA3IRQ1] =   SimpleReg_t("IA3IRQ1",     0x0B61, 12,     0x000      );
+  fRegs[kIA3IRQ2] =   SimpleReg_t("IA3IRQ2",     0x0B62, 12,     0x000      );
+  fRegs[kIA3IRQ3] =   SimpleReg_t("IA3IRQ3",     0x0B63, 12,     0x000      );
+  fRegs[kIA3IRQ4] =   SimpleReg_t("IA3IRQ4",     0x0B64, 12,     0x000      );
+  fRegs[kIA3IRQ5] =   SimpleReg_t("IA3IRQ5",     0x0B65, 12,     0x000      );
+  fRegs[kIA3IRQ6] =   SimpleReg_t("IA3IRQ6",     0x0B66, 12,     0x000      );
+  fRegs[kIA3IRQ7] =   SimpleReg_t("IA3IRQ7",     0x0B67, 12,     0x000      );
+  fRegs[kIA3IRQ8] =   SimpleReg_t("IA3IRQ8",     0x0B68, 12,     0x000      );
+  fRegs[kIA3IRQ9] =   SimpleReg_t("IA3IRQ9",     0x0B69, 12,     0x000      );
+  fRegs[kIA3IRQA] =   SimpleReg_t("IA3IRQA",     0x0B6A, 12,     0x000      );
+  fRegs[kIA3IRQB] =   SimpleReg_t("IA3IRQB",     0x0B6B, 12,     0x000      );
+  fRegs[kIA3IRQC] =   SimpleReg_t("IA3IRQC",     0x0B6C, 12,     0x000      );
+  fRegs[kIRQSW3]  =   SimpleReg_t("IRQSW3",      0x0B6D, 13,     0x1FFF     );
+  fRegs[kIRQHW3]  =   SimpleReg_t("IRQHW3",      0x0B6E, 13,     0x0000     );
+  fRegs[kIRQHL3]  =   SimpleReg_t("IRQHL3",      0x0B6F, 13,     0x0000     );
+  fRegs[kCTGDINI] =   SimpleReg_t("CTGDINI",     0x0B80, 32,     0x00000000 );  // Global Counter/Timer
+  fRegs[kCTGCTRL] =   SimpleReg_t("CTGCTRL",     0x0B81, 12,     0xE3F      );
+  fRegs[kC08CPU0] =   SimpleReg_t("C08CPU0",     0x0C00, 32,     0x00000000 );  // CPU constants
+  fRegs[kC09CPU0] =   SimpleReg_t("C09CPU0",     0x0C01, 32,     0x00000000 );
+  fRegs[kC10CPU0] =   SimpleReg_t("C10CPU0",     0x0C02, 32,     0x00000000 );
+  fRegs[kC11CPU0] =   SimpleReg_t("C11CPU0",     0x0C03, 32,     0x00000000 );
+  fRegs[kC12CPUA] =   SimpleReg_t("C12CPUA",     0x0C04, 32,     0x00000000 );
+  fRegs[kC13CPUA] =   SimpleReg_t("C13CPUA",     0x0C05, 32,     0x00000000 );
+  fRegs[kC14CPUA] =   SimpleReg_t("C14CPUA",     0x0C06, 32,     0x00000000 );
+  fRegs[kC15CPUA] =   SimpleReg_t("C15CPUA",     0x0C07, 32,     0x00000000 );
+  fRegs[kC08CPU1] =   SimpleReg_t("C08CPU1",     0x0C08, 32,     0x00000000 );
+  fRegs[kC09CPU1] =   SimpleReg_t("C09CPU1",     0x0C09, 32,     0x00000000 );
+  fRegs[kC10CPU1] =   SimpleReg_t("C10CPU1",     0x0C0A, 32,     0x00000000 );
+  fRegs[kC11CPU1] =   SimpleReg_t("C11CPU1",     0x0C0B, 32,     0x00000000 );
+  fRegs[kC08CPU2] =   SimpleReg_t("C08CPU2",     0x0C10, 32,     0x00000000 );
+  fRegs[kC09CPU2] =   SimpleReg_t("C09CPU2",     0x0C11, 32,     0x00000000 );
+  fRegs[kC10CPU2] =   SimpleReg_t("C10CPU2",     0x0C12, 32,     0x00000000 );
+  fRegs[kC11CPU2] =   SimpleReg_t("C11CPU2",     0x0C13, 32,     0x00000000 );
+  fRegs[kC08CPU3] =   SimpleReg_t("C08CPU3",     0x0C18, 32,     0x00000000 );
+  fRegs[kC09CPU3] =   SimpleReg_t("C09CPU3",     0x0C19, 32,     0x00000000 );
+  fRegs[kC10CPU3] =   SimpleReg_t("C10CPU3",     0x0C1A, 32,     0x00000000 );
+  fRegs[kC11CPU3] =   SimpleReg_t("C11CPU3",     0x0C1B, 32,     0x00000000 );
+  fRegs[kNMOD]    =   SimpleReg_t("NMOD",        0x0D40, 6,      0x08       );  // NI interface
+  fRegs[kNDLY]    =   SimpleReg_t("NDLY",        0x0D41, 30,     0x24924924 );
+  fRegs[kNED]     =   SimpleReg_t("NED",         0x0D42, 16,     0xA240     );
+  fRegs[kNTRO]    =   SimpleReg_t("NTRO",        0x0D43, 18,     0x3FFFC    );
+  fRegs[kNRRO]    =   SimpleReg_t("NRRO",        0x0D44, 18,     0x3FFFC    );
+  fRegs[kNES]     =   SimpleReg_t("NES",         0x0D45, 32,     0x00000000 );
+  fRegs[kNTP]     =   SimpleReg_t("NTP",         0x0D46, 32,     0x0000FFFF );
+  fRegs[kNBND]    =   SimpleReg_t("NBND",        0x0D47, 16,     0x6020     );
+  fRegs[kNP0]     =   SimpleReg_t("NP0",         0x0D48, 11,     0x44C      );
+  fRegs[kNP1]     =   SimpleReg_t("NP1",         0x0D49, 11,     0x44C      );
+  fRegs[kNP2]     =   SimpleReg_t("NP2",         0x0D4A, 11,     0x44C      );
+  fRegs[kNP3]     =   SimpleReg_t("NP3",         0x0D4B, 11,     0x44C      );
+  fRegs[kNCUT]    =   SimpleReg_t("NCUT",        0x0D4C, 32,     0xFFFFFFFF );
+  fRegs[kTPPT0]   =   SimpleReg_t("TPPT0",       0x3000, 7,      0x01       );  // Filter and Preprocessor
+  fRegs[kTPFS]    =   SimpleReg_t("TPFS",        0x3001, 7,      0x05       );
+  fRegs[kTPFE]    =   SimpleReg_t("TPFE",        0x3002, 7,      0x14       );
+  fRegs[kTPPGR]   =   SimpleReg_t("TPPGR",       0x3003, 7,      0x15       );
+  fRegs[kTPPAE]   =   SimpleReg_t("TPPAE",       0x3004, 7,      0x1E       );
+  fRegs[kTPQS0]   =   SimpleReg_t("TPQS0",       0x3005, 7,      0x00       );
+  fRegs[kTPQE0]   =   SimpleReg_t("TPQE0",       0x3006, 7,      0x0A       );
+  fRegs[kTPQS1]   =   SimpleReg_t("TPQS1",       0x3007, 7,      0x0B       );
+  fRegs[kTPQE1]   =   SimpleReg_t("TPQE1",       0x3008, 7,      0x14       );
+  fRegs[kEBD]     =   SimpleReg_t("EBD",         0x3009, 3,      0x0        );
+  fRegs[kEBAQA]   =   SimpleReg_t("EBAQA",       0x300A, 7,      0x00       );
+  fRegs[kEBSIA]   =   SimpleReg_t("EBSIA",       0x300B, 7,      0x20       );
+  fRegs[kEBSF]    =   SimpleReg_t("EBSF",        0x300C, 1,      0x1        );
+  fRegs[kEBSIM]   =   SimpleReg_t("EBSIM",       0x300D, 1,      0x1        );
+  fRegs[kEBPP]    =   SimpleReg_t("EBPP",        0x300E, 1,      0x1        );
+  fRegs[kEBPC]    =   SimpleReg_t("EBPC",        0x300F, 1,      0x1        );
+  fRegs[kEBIS]    =   SimpleReg_t("EBIS",        0x3014, 10,     0x005      );
+  fRegs[kEBIT]    =   SimpleReg_t("EBIT",        0x3015, 12,     0x028      );
+  fRegs[kEBIL]    =   SimpleReg_t("EBIL",        0x3016, 8,      0xF0       );
+  fRegs[kEBIN]    =   SimpleReg_t("EBIN",        0x3017, 1,      0x1        );
+  fRegs[kFLBY]    =   SimpleReg_t("FLBY",        0x3018, 1,      0x0        );
+  fRegs[kFPBY]    =   SimpleReg_t("FPBY",        0x3019, 1,      0x0        );
+  fRegs[kFGBY]    =   SimpleReg_t("FGBY",        0x301A, 1,      0x0        );
+  fRegs[kFTBY]    =   SimpleReg_t("FTBY",        0x301B, 1,      0x0        );
+  fRegs[kFCBY]    =   SimpleReg_t("FCBY",        0x301C, 1,      0x0        );
+  fRegs[kFPTC]    =   SimpleReg_t("FPTC",        0x3020, 2,      0x3        );
+  fRegs[kFPNP]    =   SimpleReg_t("FPNP",        0x3021, 9,      0x078      );
+  fRegs[kFPCL]    =   SimpleReg_t("FPCL",        0x3022, 1,      0x1        );
+  fRegs[kFGTA]    =   SimpleReg_t("FGTA",        0x3028, 12,     0x014      );
+  fRegs[kFGTB]    =   SimpleReg_t("FGTB",        0x3029, 12,     0x80C      );
+  fRegs[kFGCL]    =   SimpleReg_t("FGCL",        0x302A, 1,      0x1        );
+  fRegs[kFTAL]    =   SimpleReg_t("FTAL",        0x3030, 10,     0x0F6      );
+  fRegs[kFTLL]    =   SimpleReg_t("FTLL",        0x3031, 9,      0x11D      );
+  fRegs[kFTLS]    =   SimpleReg_t("FTLS",        0x3032, 9,      0x0D3      );
+  fRegs[kFCW1]    =   SimpleReg_t("FCW1",        0x3038, 8,      0x1E       );
+  fRegs[kFCW2]    =   SimpleReg_t("FCW2",        0x3039, 8,      0xD4       );
+  fRegs[kFCW3]    =   SimpleReg_t("FCW3",        0x303A, 8,      0xE6       );
+  fRegs[kFCW4]    =   SimpleReg_t("FCW4",        0x303B, 8,      0x4A       );
+  fRegs[kFCW5]    =   SimpleReg_t("FCW5",        0x303C, 8,      0xEF       );
+  fRegs[kTPFP]    =   SimpleReg_t("TPFP",        0x3040, 9,      0x037      );
+  fRegs[kTPHT]    =   SimpleReg_t("TPHT",        0x3041, 14,     0x00A0     );
+  fRegs[kTPVT]    =   SimpleReg_t("TPVT",        0x3042, 6,      0x00       );
+  fRegs[kTPVBY]   =   SimpleReg_t("TPVBY",       0x3043, 1,      0x0        );
+  fRegs[kTPCT]    =   SimpleReg_t("TPCT",        0x3044, 5,      0x08       );
+  fRegs[kTPCL]    =   SimpleReg_t("TPCL",        0x3045, 5,      0x01       );
+  fRegs[kTPCBY]   =   SimpleReg_t("TPCBY",       0x3046, 1,      0x1        );
+  fRegs[kTPD]     =   SimpleReg_t("TPD",         0x3047, 4,      0xF        );
+  fRegs[kTPCI0]   =   SimpleReg_t("TPCI0",       0x3048, 5,      0x00       );
+  fRegs[kTPCI1]   =   SimpleReg_t("TPCI1",       0x3049, 5,      0x00       );
+  fRegs[kTPCI2]   =   SimpleReg_t("TPCI2",       0x304A, 5,      0x00       );
+  fRegs[kTPCI3]   =   SimpleReg_t("TPCI3",       0x304B, 5,      0x00       );
+  fRegs[kADCMSK]  =   SimpleReg_t("ADCMSK",      0x3050, 21,     0x1FFFFF   );
+  fRegs[kADCINB]  =   SimpleReg_t("ADCINB",      0x3051, 2,      0x2        );
+  fRegs[kADCDAC]  =   SimpleReg_t("ADCDAC",      0x3052, 5,      0x10       );
+  fRegs[kADCPAR]  =   SimpleReg_t("ADCPAR",      0x3053, 18,     0x195EF    );
+  fRegs[kADCTST]  =   SimpleReg_t("ADCTST",      0x3054, 2,      0x0        );
+  fRegs[kSADCAZ]  =   SimpleReg_t("SADCAZ",      0x3055, 1,      0x1        );
+  fRegs[kFGF0]    =   SimpleReg_t("FGF0",        0x3080, 9,      0x000      );
+  fRegs[kFGF1]    =   SimpleReg_t("FGF1",        0x3081, 9,      0x000      );
+  fRegs[kFGF2]    =   SimpleReg_t("FGF2",        0x3082, 9,      0x000      );
+  fRegs[kFGF3]    =   SimpleReg_t("FGF3",        0x3083, 9,      0x000      );
+  fRegs[kFGF4]    =   SimpleReg_t("FGF4",        0x3084, 9,      0x000      );
+  fRegs[kFGF5]    =   SimpleReg_t("FGF5",        0x3085, 9,      0x000      );
+  fRegs[kFGF6]    =   SimpleReg_t("FGF6",        0x3086, 9,      0x000      );
+  fRegs[kFGF7]    =   SimpleReg_t("FGF7",        0x3087, 9,      0x000      );
+  fRegs[kFGF8]    =   SimpleReg_t("FGF8",        0x3088, 9,      0x000      );
+  fRegs[kFGF9]    =   SimpleReg_t("FGF9",        0x3089, 9,      0x000      );
+  fRegs[kFGF10]   =   SimpleReg_t("FGF10",       0x308A, 9,      0x000      );
+  fRegs[kFGF11]   =   SimpleReg_t("FGF11",       0x308B, 9,      0x000      );
+  fRegs[kFGF12]   =   SimpleReg_t("FGF12",       0x308C, 9,      0x000      );
+  fRegs[kFGF13]   =   SimpleReg_t("FGF13",       0x308D, 9,      0x000      );
+  fRegs[kFGF14]   =   SimpleReg_t("FGF14",       0x308E, 9,      0x000      );
+  fRegs[kFGF15]   =   SimpleReg_t("FGF15",       0x308F, 9,      0x000      );
+  fRegs[kFGF16]   =   SimpleReg_t("FGF16",       0x3090, 9,      0x000      );
+  fRegs[kFGF17]   =   SimpleReg_t("FGF17",       0x3091, 9,      0x000      );
+  fRegs[kFGF18]   =   SimpleReg_t("FGF18",       0x3092, 9,      0x000      );
+  fRegs[kFGF19]   =   SimpleReg_t("FGF19",       0x3093, 9,      0x000      );
+  fRegs[kFGF20]   =   SimpleReg_t("FGF20",       0x3094, 9,      0x000      );
+  fRegs[kFGA0]    =   SimpleReg_t("FGA0",        0x30A0, 6,      0x00       );
+  fRegs[kFGA1]    =   SimpleReg_t("FGA1",        0x30A1, 6,      0x00       );
+  fRegs[kFGA2]    =   SimpleReg_t("FGA2",        0x30A2, 6,      0x00       );
+  fRegs[kFGA3]    =   SimpleReg_t("FGA3",        0x30A3, 6,      0x00       );
+  fRegs[kFGA4]    =   SimpleReg_t("FGA4",        0x30A4, 6,      0x00       );
+  fRegs[kFGA5]    =   SimpleReg_t("FGA5",        0x30A5, 6,      0x00       );
+  fRegs[kFGA6]    =   SimpleReg_t("FGA6",        0x30A6, 6,      0x00       );
+  fRegs[kFGA7]    =   SimpleReg_t("FGA7",        0x30A7, 6,      0x00       );
+  fRegs[kFGA8]    =   SimpleReg_t("FGA8",        0x30A8, 6,      0x00       );
+  fRegs[kFGA9]    =   SimpleReg_t("FGA9",        0x30A9, 6,      0x00       );
+  fRegs[kFGA10]   =   SimpleReg_t("FGA10",       0x30AA, 6,      0x00       );
+  fRegs[kFGA11]   =   SimpleReg_t("FGA11",       0x30AB, 6,      0x00       );
+  fRegs[kFGA12]   =   SimpleReg_t("FGA12",       0x30AC, 6,      0x00       );
+  fRegs[kFGA13]   =   SimpleReg_t("FGA13",       0x30AD, 6,      0x00       );
+  fRegs[kFGA14]   =   SimpleReg_t("FGA14",       0x30AE, 6,      0x00       );
+  fRegs[kFGA15]   =   SimpleReg_t("FGA15",       0x30AF, 6,      0x00       );
+  fRegs[kFGA16]   =   SimpleReg_t("FGA16",       0x30B0, 6,      0x00       );
+  fRegs[kFGA17]   =   SimpleReg_t("FGA17",       0x30B1, 6,      0x00       );
+  fRegs[kFGA18]   =   SimpleReg_t("FGA18",       0x30B2, 6,      0x00       );
+  fRegs[kFGA19]   =   SimpleReg_t("FGA19",       0x30B3, 6,      0x00       );
+  fRegs[kFGA20]   =   SimpleReg_t("FGA20",       0x30B4, 6,      0x00       );
+  fRegs[kFLL00]   =   SimpleReg_t("FLL00",       0x3100, 6,      0x00       );  // non-linearity table, 64 x 6 bits
+  fRegs[kFLL01]   =   SimpleReg_t("FLL01",       0x3101, 6,      0x00       );
+  fRegs[kFLL02]   =   SimpleReg_t("FLL02",       0x3102, 6,      0x00       );
+  fRegs[kFLL03]   =   SimpleReg_t("FLL03",       0x3103, 6,      0x00       );
+  fRegs[kFLL04]   =   SimpleReg_t("FLL04",       0x3104, 6,      0x00       );
+  fRegs[kFLL05]   =   SimpleReg_t("FLL05",       0x3105, 6,      0x00       );
+  fRegs[kFLL06]   =   SimpleReg_t("FLL06",       0x3106, 6,      0x00       );
+  fRegs[kFLL07]   =   SimpleReg_t("FLL07",       0x3107, 6,      0x00       );
+  fRegs[kFLL08]   =   SimpleReg_t("FLL08",       0x3108, 6,      0x00       );
+  fRegs[kFLL09]   =   SimpleReg_t("FLL09",       0x3109, 6,      0x00       );
+  fRegs[kFLL0A]   =   SimpleReg_t("FLL0A",       0x310A, 6,      0x00       );
+  fRegs[kFLL0B]   =   SimpleReg_t("FLL0B",       0x310B, 6,      0x00       );
+  fRegs[kFLL0C]   =   SimpleReg_t("FLL0C",       0x310C, 6,      0x00       );
+  fRegs[kFLL0D]   =   SimpleReg_t("FLL0D",       0x310D, 6,      0x00       );
+  fRegs[kFLL0E]   =   SimpleReg_t("FLL0E",       0x310E, 6,      0x00       );
+  fRegs[kFLL0F]   =   SimpleReg_t("FLL0F",       0x310F, 6,      0x00       );
+  fRegs[kFLL10]   =   SimpleReg_t("FLL10",       0x3110, 6,      0x00       );
+  fRegs[kFLL11]   =   SimpleReg_t("FLL11",       0x3111, 6,      0x00       );
+  fRegs[kFLL12]   =   SimpleReg_t("FLL12",       0x3112, 6,      0x00       );
+  fRegs[kFLL13]   =   SimpleReg_t("FLL13",       0x3113, 6,      0x00       );
+  fRegs[kFLL14]   =   SimpleReg_t("FLL14",       0x3114, 6,      0x00       );
+  fRegs[kFLL15]   =   SimpleReg_t("FLL15",       0x3115, 6,      0x00       );
+  fRegs[kFLL16]   =   SimpleReg_t("FLL16",       0x3116, 6,      0x00       );
+  fRegs[kFLL17]   =   SimpleReg_t("FLL17",       0x3117, 6,      0x00       );
+  fRegs[kFLL18]   =   SimpleReg_t("FLL18",       0x3118, 6,      0x00       );
+  fRegs[kFLL19]   =   SimpleReg_t("FLL19",       0x3119, 6,      0x00       );
+  fRegs[kFLL1A]   =   SimpleReg_t("FLL1A",       0x311A, 6,      0x00       );
+  fRegs[kFLL1B]   =   SimpleReg_t("FLL1B",       0x311B, 6,      0x00       );
+  fRegs[kFLL1C]   =   SimpleReg_t("FLL1C",       0x311C, 6,      0x00       );
+  fRegs[kFLL1D]   =   SimpleReg_t("FLL1D",       0x311D, 6,      0x00       );
+  fRegs[kFLL1E]   =   SimpleReg_t("FLL1E",       0x311E, 6,      0x00       );
+  fRegs[kFLL1F]   =   SimpleReg_t("FLL1F",       0x311F, 6,      0x00       );
+  fRegs[kFLL20]   =   SimpleReg_t("FLL20",       0x3120, 6,      0x00       );
+  fRegs[kFLL21]   =   SimpleReg_t("FLL21",       0x3121, 6,      0x00       );
+  fRegs[kFLL22]   =   SimpleReg_t("FLL22",       0x3122, 6,      0x00       );
+  fRegs[kFLL23]   =   SimpleReg_t("FLL23",       0x3123, 6,      0x00       );
+  fRegs[kFLL24]   =   SimpleReg_t("FLL24",       0x3124, 6,      0x00       );
+  fRegs[kFLL25]   =   SimpleReg_t("FLL25",       0x3125, 6,      0x00       );
+  fRegs[kFLL26]   =   SimpleReg_t("FLL26",       0x3126, 6,      0x00       );
+  fRegs[kFLL27]   =   SimpleReg_t("FLL27",       0x3127, 6,      0x00       );
+  fRegs[kFLL28]   =   SimpleReg_t("FLL28",       0x3128, 6,      0x00       );
+  fRegs[kFLL29]   =   SimpleReg_t("FLL29",       0x3129, 6,      0x00       );
+  fRegs[kFLL2A]   =   SimpleReg_t("FLL2A",       0x312A, 6,      0x00       );
+  fRegs[kFLL2B]   =   SimpleReg_t("FLL2B",       0x312B, 6,      0x00       );
+  fRegs[kFLL2C]   =   SimpleReg_t("FLL2C",       0x312C, 6,      0x00       );
+  fRegs[kFLL2D]   =   SimpleReg_t("FLL2D",       0x312D, 6,      0x00       );
+  fRegs[kFLL2E]   =   SimpleReg_t("FLL2E",       0x312E, 6,      0x00       );
+  fRegs[kFLL2F]   =   SimpleReg_t("FLL2F",       0x312F, 6,      0x00       );
+  fRegs[kFLL30]   =   SimpleReg_t("FLL30",       0x3130, 6,      0x00       );
+  fRegs[kFLL31]   =   SimpleReg_t("FLL31",       0x3131, 6,      0x00       );
+  fRegs[kFLL32]   =   SimpleReg_t("FLL32",       0x3132, 6,      0x00       );
+  fRegs[kFLL33]   =   SimpleReg_t("FLL33",       0x3133, 6,      0x00       );
+  fRegs[kFLL34]   =   SimpleReg_t("FLL34",       0x3134, 6,      0x00       );
+  fRegs[kFLL35]   =   SimpleReg_t("FLL35",       0x3135, 6,      0x00       );
+  fRegs[kFLL36]   =   SimpleReg_t("FLL36",       0x3136, 6,      0x00       );
+  fRegs[kFLL37]   =   SimpleReg_t("FLL37",       0x3137, 6,      0x00       );
+  fRegs[kFLL38]   =   SimpleReg_t("FLL38",       0x3138, 6,      0x00       );
+  fRegs[kFLL39]   =   SimpleReg_t("FLL39",       0x3139, 6,      0x00       );
+  fRegs[kFLL3A]   =   SimpleReg_t("FLL3A",       0x313A, 6,      0x00       );
+  fRegs[kFLL3B]   =   SimpleReg_t("FLL3B",       0x313B, 6,      0x00       );
+  fRegs[kFLL3C]   =   SimpleReg_t("FLL3C",       0x313C, 6,      0x00       );
+  fRegs[kFLL3D]   =   SimpleReg_t("FLL3D",       0x313D, 6,      0x00       );
+  fRegs[kFLL3E]   =   SimpleReg_t("FLL3E",       0x313E, 6,      0x00       );
+  fRegs[kFLL3F]   =   SimpleReg_t("FLL3F",       0x313F, 6,      0x00       );
+  fRegs[kPASADEL] =   SimpleReg_t("PASADEL",     0x3158, 8,      0xFF       );  // end of non-lin table
+  fRegs[kPASAPHA] =   SimpleReg_t("PASAPHA",     0x3159, 6,      0x3F       );
+  fRegs[kPASAPRA] =   SimpleReg_t("PASAPRA",     0x315A, 6,      0x0F       );
+  fRegs[kPASADAC] =   SimpleReg_t("PASADAC",     0x315B, 8,      0x80       );
+  fRegs[kPASACHM] =   SimpleReg_t("PASACHM",     0x315C, 19,     0x7FFFF    );
+  fRegs[kPASASTL] =   SimpleReg_t("PASASTL",     0x315D, 8,      0xFF       );
+  fRegs[kPASAPR1] =   SimpleReg_t("PASAPR1",     0x315E, 1,      0x0        );
+  fRegs[kPASAPR0] =   SimpleReg_t("PASAPR0",     0x315F, 1,      0x0        );
+  fRegs[kSADCTRG] =   SimpleReg_t("SADCTRG",     0x3161, 1,      0x0        );
+  fRegs[kSADCRUN] =   SimpleReg_t("SADCRUN",     0x3162, 1,      0x0        );
+  fRegs[kSADCPWR] =   SimpleReg_t("SADCPWR",     0x3163, 3,      0x7        );
+  fRegs[kL0TSIM]  =   SimpleReg_t("L0TSIM",      0x3165, 14,     0x0050     );
+  fRegs[kSADCEC]  =   SimpleReg_t("SADCEC",      0x3166, 7,      0x00       );
+  fRegs[kSADCMC]  =   SimpleReg_t("SADCMC",      0x3170, 8,      0xC0       );
+  fRegs[kSADCOC]  =   SimpleReg_t("SADCOC",      0x3171, 8,      0x19       );
+  fRegs[kSADCGTB] =   SimpleReg_t("SADCGTB",     0x3172, 32,     0x37737700 );
+  fRegs[kSEBDEN]  =   SimpleReg_t("SEBDEN",      0x3178, 3,      0x0        );
+  fRegs[kSEBDOU]  =   SimpleReg_t("SEBDOU",      0x3179, 3,      0x0        );
+  fRegs[kTPL00]   =   SimpleReg_t("TPL00",       0x3180, 5,      0x00       );  // pos table, 128 x 5 bits
+  fRegs[kTPL01]   =   SimpleReg_t("TPL01",       0x3181, 5,      0x00       );
+  fRegs[kTPL02]   =   SimpleReg_t("TPL02",       0x3182, 5,      0x00       );
+  fRegs[kTPL03]   =   SimpleReg_t("TPL03",       0x3183, 5,      0x00       );
+  fRegs[kTPL04]   =   SimpleReg_t("TPL04",       0x3184, 5,      0x00       );
+  fRegs[kTPL05]   =   SimpleReg_t("TPL05",       0x3185, 5,      0x00       );
+  fRegs[kTPL06]   =   SimpleReg_t("TPL06",       0x3186, 5,      0x00       );
+  fRegs[kTPL07]   =   SimpleReg_t("TPL07",       0x3187, 5,      0x00       );
+  fRegs[kTPL08]   =   SimpleReg_t("TPL08",       0x3188, 5,      0x00       );
+  fRegs[kTPL09]   =   SimpleReg_t("TPL09",       0x3189, 5,      0x00       );
+  fRegs[kTPL0A]   =   SimpleReg_t("TPL0A",       0x318A, 5,      0x00       );
+  fRegs[kTPL0B]   =   SimpleReg_t("TPL0B",       0x318B, 5,      0x00       );
+  fRegs[kTPL0C]   =   SimpleReg_t("TPL0C",       0x318C, 5,      0x00       );
+  fRegs[kTPL0D]   =   SimpleReg_t("TPL0D",       0x318D, 5,      0x00       );
+  fRegs[kTPL0E]   =   SimpleReg_t("TPL0E",       0x318E, 5,      0x00       );
+  fRegs[kTPL0F]   =   SimpleReg_t("TPL0F",       0x318F, 5,      0x00       );
+  fRegs[kTPL10]   =   SimpleReg_t("TPL10",       0x3190, 5,      0x00       );
+  fRegs[kTPL11]   =   SimpleReg_t("TPL11",       0x3191, 5,      0x00       );
+  fRegs[kTPL12]   =   SimpleReg_t("TPL12",       0x3192, 5,      0x00       );
+  fRegs[kTPL13]   =   SimpleReg_t("TPL13",       0x3193, 5,      0x00       );
+  fRegs[kTPL14]   =   SimpleReg_t("TPL14",       0x3194, 5,      0x00       );
+  fRegs[kTPL15]   =   SimpleReg_t("TPL15",       0x3195, 5,      0x00       );
+  fRegs[kTPL16]   =   SimpleReg_t("TPL16",       0x3196, 5,      0x00       );
+  fRegs[kTPL17]   =   SimpleReg_t("TPL17",       0x3197, 5,      0x00       );
+  fRegs[kTPL18]   =   SimpleReg_t("TPL18",       0x3198, 5,      0x00       );
+  fRegs[kTPL19]   =   SimpleReg_t("TPL19",       0x3199, 5,      0x00       );
+  fRegs[kTPL1A]   =   SimpleReg_t("TPL1A",       0x319A, 5,      0x00       );
+  fRegs[kTPL1B]   =   SimpleReg_t("TPL1B",       0x319B, 5,      0x00       );
+  fRegs[kTPL1C]   =   SimpleReg_t("TPL1C",       0x319C, 5,      0x00       );
+  fRegs[kTPL1D]   =   SimpleReg_t("TPL1D",       0x319D, 5,      0x00       );
+  fRegs[kTPL1E]   =   SimpleReg_t("TPL1E",       0x319E, 5,      0x00       );
+  fRegs[kTPL1F]   =   SimpleReg_t("TPL1F",       0x319F, 5,      0x00       );
+  fRegs[kTPL20]   =   SimpleReg_t("TPL20",       0x31A0, 5,      0x00       );
+  fRegs[kTPL21]   =   SimpleReg_t("TPL21",       0x31A1, 5,      0x00       );
+  fRegs[kTPL22]   =   SimpleReg_t("TPL22",       0x31A2, 5,      0x00       );
+  fRegs[kTPL23]   =   SimpleReg_t("TPL23",       0x31A3, 5,      0x00       );
+  fRegs[kTPL24]   =   SimpleReg_t("TPL24",       0x31A4, 5,      0x00       );
+  fRegs[kTPL25]   =   SimpleReg_t("TPL25",       0x31A5, 5,      0x00       );
+  fRegs[kTPL26]   =   SimpleReg_t("TPL26",       0x31A6, 5,      0x00       );
+  fRegs[kTPL27]   =   SimpleReg_t("TPL27",       0x31A7, 5,      0x00       );
+  fRegs[kTPL28]   =   SimpleReg_t("TPL28",       0x31A8, 5,      0x00       );
+  fRegs[kTPL29]   =   SimpleReg_t("TPL29",       0x31A9, 5,      0x00       );
+  fRegs[kTPL2A]   =   SimpleReg_t("TPL2A",       0x31AA, 5,      0x00       );
+  fRegs[kTPL2B]   =   SimpleReg_t("TPL2B",       0x31AB, 5,      0x00       );
+  fRegs[kTPL2C]   =   SimpleReg_t("TPL2C",       0x31AC, 5,      0x00       );
+  fRegs[kTPL2D]   =   SimpleReg_t("TPL2D",       0x31AD, 5,      0x00       );
+  fRegs[kTPL2E]   =   SimpleReg_t("TPL2E",       0x31AE, 5,      0x00       );
+  fRegs[kTPL2F]   =   SimpleReg_t("TPL2F",       0x31AF, 5,      0x00       );
+  fRegs[kTPL30]   =   SimpleReg_t("TPL30",       0x31B0, 5,      0x00       );
+  fRegs[kTPL31]   =   SimpleReg_t("TPL31",       0x31B1, 5,      0x00       );
+  fRegs[kTPL32]   =   SimpleReg_t("TPL32",       0x31B2, 5,      0x00       );
+  fRegs[kTPL33]   =   SimpleReg_t("TPL33",       0x31B3, 5,      0x00       );
+  fRegs[kTPL34]   =   SimpleReg_t("TPL34",       0x31B4, 5,      0x00       );
+  fRegs[kTPL35]   =   SimpleReg_t("TPL35",       0x31B5, 5,      0x00       );
+  fRegs[kTPL36]   =   SimpleReg_t("TPL36",       0x31B6, 5,      0x00       );
+  fRegs[kTPL37]   =   SimpleReg_t("TPL37",       0x31B7, 5,      0x00       );
+  fRegs[kTPL38]   =   SimpleReg_t("TPL38",       0x31B8, 5,      0x00       );
+  fRegs[kTPL39]   =   SimpleReg_t("TPL39",       0x31B9, 5,      0x00       );
+  fRegs[kTPL3A]   =   SimpleReg_t("TPL3A",       0x31BA, 5,      0x00       );
+  fRegs[kTPL3B]   =   SimpleReg_t("TPL3B",       0x31BB, 5,      0x00       );
+  fRegs[kTPL3C]   =   SimpleReg_t("TPL3C",       0x31BC, 5,      0x00       );
+  fRegs[kTPL3D]   =   SimpleReg_t("TPL3D",       0x31BD, 5,      0x00       );
+  fRegs[kTPL3E]   =   SimpleReg_t("TPL3E",       0x31BE, 5,      0x00       );
+  fRegs[kTPL3F]   =   SimpleReg_t("TPL3F",       0x31BF, 5,      0x00       );
+  fRegs[kTPL40]   =   SimpleReg_t("TPL40",       0x31C0, 5,      0x00       );
+  fRegs[kTPL41]   =   SimpleReg_t("TPL41",       0x31C1, 5,      0x00       );
+  fRegs[kTPL42]   =   SimpleReg_t("TPL42",       0x31C2, 5,      0x00       );
+  fRegs[kTPL43]   =   SimpleReg_t("TPL43",       0x31C3, 5,      0x00       );
+  fRegs[kTPL44]   =   SimpleReg_t("TPL44",       0x31C4, 5,      0x00       );
+  fRegs[kTPL45]   =   SimpleReg_t("TPL45",       0x31C5, 5,      0x00       );
+  fRegs[kTPL46]   =   SimpleReg_t("TPL46",       0x31C6, 5,      0x00       );
+  fRegs[kTPL47]   =   SimpleReg_t("TPL47",       0x31C7, 5,      0x00       );
+  fRegs[kTPL48]   =   SimpleReg_t("TPL48",       0x31C8, 5,      0x00       );
+  fRegs[kTPL49]   =   SimpleReg_t("TPL49",       0x31C9, 5,      0x00       );
+  fRegs[kTPL4A]   =   SimpleReg_t("TPL4A",       0x31CA, 5,      0x00       );
+  fRegs[kTPL4B]   =   SimpleReg_t("TPL4B",       0x31CB, 5,      0x00       );
+  fRegs[kTPL4C]   =   SimpleReg_t("TPL4C",       0x31CC, 5,      0x00       );
+  fRegs[kTPL4D]   =   SimpleReg_t("TPL4D",       0x31CD, 5,      0x00       );
+  fRegs[kTPL4E]   =   SimpleReg_t("TPL4E",       0x31CE, 5,      0x00       );
+  fRegs[kTPL4F]   =   SimpleReg_t("TPL4F",       0x31CF, 5,      0x00       );
+  fRegs[kTPL50]   =   SimpleReg_t("TPL50",       0x31D0, 5,      0x00       );
+  fRegs[kTPL51]   =   SimpleReg_t("TPL51",       0x31D1, 5,      0x00       );
+  fRegs[kTPL52]   =   SimpleReg_t("TPL52",       0x31D2, 5,      0x00       );
+  fRegs[kTPL53]   =   SimpleReg_t("TPL53",       0x31D3, 5,      0x00       );
+  fRegs[kTPL54]   =   SimpleReg_t("TPL54",       0x31D4, 5,      0x00       );
+  fRegs[kTPL55]   =   SimpleReg_t("TPL55",       0x31D5, 5,      0x00       );
+  fRegs[kTPL56]   =   SimpleReg_t("TPL56",       0x31D6, 5,      0x00       );
+  fRegs[kTPL57]   =   SimpleReg_t("TPL57",       0x31D7, 5,      0x00       );
+  fRegs[kTPL58]   =   SimpleReg_t("TPL58",       0x31D8, 5,      0x00       );
+  fRegs[kTPL59]   =   SimpleReg_t("TPL59",       0x31D9, 5,      0x00       );
+  fRegs[kTPL5A]   =   SimpleReg_t("TPL5A",       0x31DA, 5,      0x00       );
+  fRegs[kTPL5B]   =   SimpleReg_t("TPL5B",       0x31DB, 5,      0x00       );
+  fRegs[kTPL5C]   =   SimpleReg_t("TPL5C",       0x31DC, 5,      0x00       );
+  fRegs[kTPL5D]   =   SimpleReg_t("TPL5D",       0x31DD, 5,      0x00       );
+  fRegs[kTPL5E]   =   SimpleReg_t("TPL5E",       0x31DE, 5,      0x00       );
+  fRegs[kTPL5F]   =   SimpleReg_t("TPL5F",       0x31DF, 5,      0x00       );
+  fRegs[kTPL60]   =   SimpleReg_t("TPL60",       0x31E0, 5,      0x00       );
+  fRegs[kTPL61]   =   SimpleReg_t("TPL61",       0x31E1, 5,      0x00       );
+  fRegs[kTPL62]   =   SimpleReg_t("TPL62",       0x31E2, 5,      0x00       );
+  fRegs[kTPL63]   =   SimpleReg_t("TPL63",       0x31E3, 5,      0x00       );
+  fRegs[kTPL64]   =   SimpleReg_t("TPL64",       0x31E4, 5,      0x00       );
+  fRegs[kTPL65]   =   SimpleReg_t("TPL65",       0x31E5, 5,      0x00       );
+  fRegs[kTPL66]   =   SimpleReg_t("TPL66",       0x31E6, 5,      0x00       );
+  fRegs[kTPL67]   =   SimpleReg_t("TPL67",       0x31E7, 5,      0x00       );
+  fRegs[kTPL68]   =   SimpleReg_t("TPL68",       0x31E8, 5,      0x00       );
+  fRegs[kTPL69]   =   SimpleReg_t("TPL69",       0x31E9, 5,      0x00       );
+  fRegs[kTPL6A]   =   SimpleReg_t("TPL6A",       0x31EA, 5,      0x00       );
+  fRegs[kTPL6B]   =   SimpleReg_t("TPL6B",       0x31EB, 5,      0x00       );
+  fRegs[kTPL6C]   =   SimpleReg_t("TPL6C",       0x31EC, 5,      0x00       );
+  fRegs[kTPL6D]   =   SimpleReg_t("TPL6D",       0x31ED, 5,      0x00       );
+  fRegs[kTPL6E]   =   SimpleReg_t("TPL6E",       0x31EE, 5,      0x00       );
+  fRegs[kTPL6F]   =   SimpleReg_t("TPL6F",       0x31EF, 5,      0x00       );
+  fRegs[kTPL70]   =   SimpleReg_t("TPL70",       0x31F0, 5,      0x00       );
+  fRegs[kTPL71]   =   SimpleReg_t("TPL71",       0x31F1, 5,      0x00       );
+  fRegs[kTPL72]   =   SimpleReg_t("TPL72",       0x31F2, 5,      0x00       );
+  fRegs[kTPL73]   =   SimpleReg_t("TPL73",       0x31F3, 5,      0x00       );
+  fRegs[kTPL74]   =   SimpleReg_t("TPL74",       0x31F4, 5,      0x00       );
+  fRegs[kTPL75]   =   SimpleReg_t("TPL75",       0x31F5, 5,      0x00       );
+  fRegs[kTPL76]   =   SimpleReg_t("TPL76",       0x31F6, 5,      0x00       );
+  fRegs[kTPL77]   =   SimpleReg_t("TPL77",       0x31F7, 5,      0x00       );
+  fRegs[kTPL78]   =   SimpleReg_t("TPL78",       0x31F8, 5,      0x00       );
+  fRegs[kTPL79]   =   SimpleReg_t("TPL79",       0x31F9, 5,      0x00       );
+  fRegs[kTPL7A]   =   SimpleReg_t("TPL7A",       0x31FA, 5,      0x00       );
+  fRegs[kTPL7B]   =   SimpleReg_t("TPL7B",       0x31FB, 5,      0x00       );
+  fRegs[kTPL7C]   =   SimpleReg_t("TPL7C",       0x31FC, 5,      0x00       );
+  fRegs[kTPL7D]   =   SimpleReg_t("TPL7D",       0x31FD, 5,      0x00       );
+  fRegs[kTPL7E]   =   SimpleReg_t("TPL7E",       0x31FE, 5,      0x00       );
+  fRegs[kTPL7F]   =   SimpleReg_t("TPL7F",       0x31FF, 5,      0x00       );
+  fRegs[kMEMRW]   =   SimpleReg_t("MEMRW",       0xD000, 7,      0x79       );  // end of pos table
+  fRegs[kMEMCOR]  =   SimpleReg_t("MEMCOR",      0xD001, 9,      0x000      );
+  fRegs[kDMDELA]  =   SimpleReg_t("DMDELA",      0xD002, 4,      0x8        );
+  fRegs[kDMDELS]  =   SimpleReg_t("DMDELS",      0xD003, 4,      0x8        );
+
+  for (Int_t iReg = 0; iReg < kLastReg; iReg++) {
+    fRegisterValue[iReg].globalValue = GetRegResetValue((TrapReg_t) iReg);
+    fRegisterValue[iReg].state = RegValue_t::kGlobal;
+//    printf("%-8s: 0x%08x\n", GetRegName((TrapReg_t) iReg), fRegisterValue[iReg].globalValue);
+  }
+}
+
+AliTRDtrapConfig* AliTRDtrapConfig::Instance()
+{
+  // return a pointer to an instance of this class
+
+  if (!fgInstance)
+    fgInstance = new AliTRDtrapConfig();
+  return fgInstance;
+}
+
+Int_t AliTRDtrapConfig::GetTrapReg(TrapReg_t reg, Int_t det, Int_t rob, Int_t mcm)
+{
+  // get the value of an individual TRAP register 
+  // if it is individual for TRAPs a valid TRAP has to be specified
+
+  if ((reg < 0) || (reg >= kLastReg)) {
+    AliError("Non-existing register requested");
+    return -1;
+  }
+  else {
+    if (fRegisterValue[reg].state == RegValue_t::kGlobal) {
+      return fRegisterValue[reg].globalValue;
+    }
+    else if (fRegisterValue[reg].state == RegValue_t::kIndividual) {
+      if ((det < 0) || (det > 539) || (rob < 0) || (rob > 7) || (mcm < 0) || (mcm > 15)) {
+        AliError("Invalid MCM specified!");
+        return -1;
+      }
+      else {
+        Int_t mcmid = 0;
+        return fRegisterValue[reg].individualValue[mcmid];
+      }
+    }
+  }
+  return -1;
+}
+
+Bool_t AliTRDtrapConfig::SetTrapReg(TrapReg_t reg, Int_t value, Int_t det, Int_t rob, Int_t mcm)
+{
+  // set the value for the given TRAP register 
+  // if no MCM is specified the value is stored as global,
+  // i.e. the same for all TRAPs
+
+  if ((det == -1) && (rob == -1) && (mcm == -1)) {
+    if (fRegisterValue[reg].state == RegValue_t::kGlobal) {
+      fRegisterValue[reg].globalValue = value;
+    } 
+    else if (fRegisterValue[reg].state == RegValue_t::kIndividual) {
+      delete [] fRegisterValue[reg].individualValue;
+      fRegisterValue[reg].state = RegValue_t::kGlobal;
+      fRegisterValue[reg].globalValue = value;
+    }
+    else {
+      return kFALSE;
+    }
+  }
+  else if ((det < 0) || (det > 539) || (rob < 0) || (rob > 7) || (mcm < 0) || (mcm > 7)) {
+    AliError("Invalid MCM specified");
+    return kFALSE;
+  }
+  else {
+    if (fRegisterValue[reg].state == RegValue_t::kGlobal) {
+      fRegisterValue[reg].state = RegValue_t::kIndividual;
+      fRegisterValue[reg].individualValue = new Int_t[540*38*16];
+      fRegisterValue[reg].individualValue[det*38*16 + rob*16 + mcm] = value;
+    }
+    else if (fRegisterValue[reg].state == RegValue_t::kIndividual) {
+      fRegisterValue[reg].individualValue[det*38*16 + rob*16 + mcm] = value;
+    }
+    else {
+      return kFALSE;
+    }
+  }
+  return kTRUE;
+}
+
+Bool_t AliTRDtrapConfig::LoadConfig()
+{
+  // load a set of TRAP register values (configuration)
+  // so far only a default set is implemented for testing
+  // for a detailed description of the registers see the TRAP manual
+
+
+  // pedestal filter
+  SetTrapReg(kFPNP, 4*10);
+  SetTrapReg(kFPTC, 0);
+  SetTrapReg(kFPBY, 1);
+  
+  // gain filter
+  for (Int_t adc = 0; adc < 20; adc++) {
+    SetTrapReg(TrapReg_t(kFGA0+adc), 40);
+    SetTrapReg(TrapReg_t(kFGF0+adc), 15);
+  }
+  SetTrapReg(kFGTA, 20);
+  SetTrapReg(kFGTB, 2060);
+  SetTrapReg(kFGBY, 0);  // bypassed!
+
+  // tail cancellation
+  SetTrapReg(kFTAL, 270);
+  SetTrapReg(kFTLL, 348);
+  SetTrapReg(kFTLS, 449);
+  SetTrapReg(kFTBY, 1);
+
+  // tracklet calculation
+  SetTrapReg(kTPQS0, 5);
+  SetTrapReg(kTPQE0, 10);
+  SetTrapReg(kTPQS1, 11);
+  SetTrapReg(kTPQE1, 20);
+  SetTrapReg(kTPFS, 5);
+  SetTrapReg(kTPFE, 20);
+  SetTrapReg(kTPVBY, 0);
+  SetTrapReg(kTPVT, 10);
+  SetTrapReg(kTPHT, 100);
+  SetTrapReg(kTPFP, 40);
+  SetTrapReg(kTPCL, 3);
+  SetTrapReg(kTPCT, 5);
+  
+  // event buffer
+  SetTrapReg(kEBSF, 1);  // 0: store filtered; 1: store unfiltered
+  // zs applied to data stored in event buffer (sel. by EBSF)
+  SetTrapReg(kEBIS, 5 << 2); // single indicator threshold (plus two digits)
+  SetTrapReg(kEBIT, 5 << 2); // sum indicator threshold (plus two digits)
+  SetTrapReg(kEBIL, 0xf0);   // lookup table
+  SetTrapReg(kEBIN, 1);      // no neighbour sensitivity
+
+  return kTRUE;
+}
+
+void AliTRDtrapConfig::PrintTrapReg(TrapReg_t reg, Int_t det, Int_t rob, Int_t mcm)
+{
+  // print the information about the given register
+  // if it is individual a valid MCM has to be specified
+
+  if (fRegisterValue[reg].state == RegValue_t::kGlobal) {
+    printf("%s (%i bits) at 0x%08x is 0x%08x and resets to: 0x%08x\n", 
+           GetRegName((TrapReg_t) reg),
+           GetRegNBits((TrapReg_t) reg),
+           GetRegAddress((TrapReg_t) reg),
+           fRegisterValue[reg].globalValue,
+           GetRegResetValue((TrapReg_t) reg));
+  }
+  else if (fRegisterValue[reg].state == RegValue_t::kIndividual) {
+    if ((det < 0) || (det > 539) || (rob < 0) || (rob > 7) || (mcm < 0) || (mcm > 7)) {
+      AliError("Register value is MCM-specific but an invalid MCM is specified");
+    }
+    else {
+      printf("%s (%i bits) at 0x%08x is 0x%08x and resets to: 0x%08x\n", 
+             GetRegName((TrapReg_t) reg),
+             GetRegNBits((TrapReg_t) reg),
+             GetRegAddress((TrapReg_t) reg),
+             fRegisterValue[reg].individualValue[det*38*16 + rob*16 + mcm],
+             GetRegResetValue((TrapReg_t) reg));
+    }
+  }
+}
diff --git a/TRD/AliTRDtrapConfig.h b/TRD/AliTRDtrapConfig.h
new file mode 100644 (file)
index 0000000..680a4b1
--- /dev/null
@@ -0,0 +1,514 @@
+#ifndef ALITRDTRAPCONFIG_H
+#define ALITRDTRAPCONFIG_H
+
+#include <TObject.h>
+#include <TClonesArray.h>
+
+class AliTRDtrapConfig : public TObject
+{
+ public:
+  static AliTRDtrapConfig* Instance();
+
+  enum TrapReg_t { kSML0, 
+                 kSML1, 
+                 kSML2,
+                 kSMMODE,
+                 kNITM0,
+                 kNITM1,
+                 kNITM2,
+                 kNIP4D,
+                 kCPU0CLK,
+                 kCPU1CLK,
+                 kCPU2CLK,
+                 kCPU3CLK,
+                 kNICLK,
+                 kFILCLK,
+                 kPRECLK,
+                 kADCEN,
+                 kNIODE,
+                 kNIOCE,
+                 kNIIDE,
+                 kNIICE,
+                 kARBTIM,      
+                 kIA0IRQ0,     
+                 kIA0IRQ1,     
+                 kIA0IRQ2,     
+                 kIA0IRQ3,     
+                 kIA0IRQ4,     
+                 kIA0IRQ5,     
+                 kIA0IRQ6,     
+                 kIA0IRQ7,     
+                 kIA0IRQ8,     
+                 kIA0IRQ9,     
+                 kIA0IRQA,     
+                 kIA0IRQB,     
+                 kIA0IRQC,     
+                 kIRQSW0,      
+                 kIRQHW0,      
+                 kIRQHL0,      
+                 kIA1IRQ0,     
+                 kIA1IRQ1,     
+                 kIA1IRQ2,     
+                 kIA1IRQ3,     
+                 kIA1IRQ4,     
+                 kIA1IRQ5,     
+                 kIA1IRQ6,     
+                 kIA1IRQ7,     
+                 kIA1IRQ8,     
+                 kIA1IRQ9,     
+                 kIA1IRQA,     
+                 kIA1IRQB,     
+                 kIA1IRQC,     
+                 kIRQSW1,      
+                 kIRQHW1,      
+                 kIRQHL1,      
+                 kIA2IRQ0,     
+                 kIA2IRQ1,     
+                 kIA2IRQ2,     
+                 kIA2IRQ3,     
+                 kIA2IRQ4,     
+                 kIA2IRQ5,     
+                 kIA2IRQ6,     
+                 kIA2IRQ7,     
+                 kIA2IRQ8,     
+                 kIA2IRQ9,     
+                 kIA2IRQA,     
+                 kIA2IRQB,     
+                 kIA2IRQC,     
+                 kIRQSW2,      
+                 kIRQHW2,      
+                 kIRQHL2,      
+                 kIA3IRQ0,     
+                 kIA3IRQ1,     
+                 kIA3IRQ2,     
+                 kIA3IRQ3,     
+                 kIA3IRQ4,     
+                 kIA3IRQ5,     
+                 kIA3IRQ6,     
+                 kIA3IRQ7,     
+                 kIA3IRQ8,     
+                 kIA3IRQ9,     
+                 kIA3IRQA,     
+                 kIA3IRQB,     
+                 kIA3IRQC,     
+                 kIRQSW3,      
+                 kIRQHW3,      
+                 kIRQHL3,      
+                 kCTGDINI,     
+                 kCTGCTRL,     
+                 kC08CPU0,     
+                 kC09CPU0,     
+                 kC10CPU0,     
+                 kC11CPU0,     
+                 kC12CPUA,     
+                 kC13CPUA,     
+                 kC14CPUA,     
+                 kC15CPUA,     
+                 kC08CPU1,     
+                 kC09CPU1,     
+                 kC10CPU1,     
+                 kC11CPU1,     
+                 kC08CPU2,     
+                 kC09CPU2,     
+                 kC10CPU2,     
+                 kC11CPU2,     
+                 kC08CPU3,     
+                 kC09CPU3,     
+                 kC10CPU3,     
+                 kC11CPU3,     
+                 kNMOD,        
+                 kNDLY,        
+                 kNED,         
+                 kNTRO,        
+                 kNRRO,        
+                 kNES,         
+                 kNTP,         
+                 kNBND,        
+                 kNP0,         
+                 kNP1,         
+                 kNP2,         
+                 kNP3,         
+                 kNCUT,        
+                 kTPPT0,       
+                 kTPFS,        
+                 kTPFE,        
+                 kTPPGR,       
+                 kTPPAE,       
+                 kTPQS0,       
+                 kTPQE0,       
+                 kTPQS1,       
+                 kTPQE1,       
+                 kEBD,         
+                 kEBAQA,       
+                 kEBSIA,       
+                 kEBSF,        
+                 kEBSIM,       
+                 kEBPP,        
+                 kEBPC,        
+                 kEBIS,        
+                 kEBIT,        
+                 kEBIL,        
+                 kEBIN,        
+                 kFLBY,        
+                 kFPBY,        
+                 kFGBY,        
+                 kFTBY,        
+                 kFCBY,        
+                 kFPTC,        
+                 kFPNP,        
+                 kFPCL,        
+                 kFGTA,        
+                 kFGTB,        
+                 kFGCL,        
+                 kFTAL,        
+                 kFTLL,        
+                 kFTLS,        
+                 kFCW1,        
+                 kFCW2,        
+                 kFCW3,        
+                 kFCW4,        
+                 kFCW5,        
+                 kTPFP,        
+                 kTPHT,        
+                 kTPVT,        
+                 kTPVBY,       
+                 kTPCT,        
+                 kTPCL,        
+                 kTPCBY,       
+                 kTPD,         
+                 kTPCI0,       
+                 kTPCI1,       
+                 kTPCI2,       
+                 kTPCI3,       
+                 kADCMSK,      
+                 kADCINB,      
+                 kADCDAC,      
+                 kADCPAR,      
+                 kADCTST,      
+                 kSADCAZ,      
+                 kFGF0,        
+                 kFGF1,        
+                 kFGF2,        
+                 kFGF3,        
+                 kFGF4,        
+                 kFGF5,        
+                 kFGF6,        
+                 kFGF7,        
+                 kFGF8,        
+                 kFGF9,        
+                 kFGF10,       
+                 kFGF11,       
+                 kFGF12,       
+                 kFGF13,       
+                 kFGF14,       
+                 kFGF15,       
+                 kFGF16,       
+                 kFGF17,       
+                 kFGF18,       
+                 kFGF19,       
+                 kFGF20,       
+                 kFGA0,        
+                 kFGA1,        
+                 kFGA2,        
+                 kFGA3,        
+                 kFGA4,        
+                 kFGA5,        
+                 kFGA6,        
+                 kFGA7,        
+                 kFGA8,        
+                 kFGA9,        
+                 kFGA10,       
+                 kFGA11,       
+                 kFGA12,       
+                 kFGA13,       
+                 kFGA14,       
+                 kFGA15,       
+                 kFGA16,       
+                 kFGA17,       
+                 kFGA18,       
+                 kFGA19,       
+                 kFGA20,       
+                 kFLL00,       
+                 kFLL01,       
+                 kFLL02,       
+                 kFLL03,       
+                 kFLL04,       
+                 kFLL05,       
+                 kFLL06,       
+                 kFLL07,       
+                 kFLL08,       
+                 kFLL09,       
+                 kFLL0A,       
+                 kFLL0B,       
+                 kFLL0C,       
+                 kFLL0D,       
+                 kFLL0E,       
+                 kFLL0F,       
+                 kFLL10,       
+                 kFLL11,       
+                 kFLL12,       
+                 kFLL13,       
+                 kFLL14,       
+                 kFLL15,       
+                 kFLL16,       
+                 kFLL17,       
+                 kFLL18,       
+                 kFLL19,       
+                 kFLL1A,       
+                 kFLL1B,       
+                 kFLL1C,       
+                 kFLL1D,       
+                 kFLL1E,       
+                 kFLL1F,       
+                 kFLL20,       
+                 kFLL21,       
+                 kFLL22,       
+                 kFLL23,       
+                 kFLL24,       
+                 kFLL25,       
+                 kFLL26,       
+                 kFLL27,       
+                 kFLL28,       
+                 kFLL29,       
+                 kFLL2A,       
+                 kFLL2B,       
+                 kFLL2C,       
+                 kFLL2D,       
+                 kFLL2E,       
+                 kFLL2F,       
+                 kFLL30,       
+                 kFLL31,       
+                 kFLL32,       
+                 kFLL33,       
+                 kFLL34,       
+                 kFLL35,       
+                 kFLL36,       
+                 kFLL37,       
+                 kFLL38,       
+                 kFLL39,       
+                 kFLL3A,       
+                 kFLL3B,       
+                 kFLL3C,       
+                 kFLL3D,       
+                 kFLL3E,       
+                 kFLL3F,       
+                 kPASADEL,     
+                 kPASAPHA,     
+                 kPASAPRA,     
+                 kPASADAC,     
+                 kPASACHM,     
+                 kPASASTL,     
+                 kPASAPR1,     
+                 kPASAPR0,     
+                 kSADCTRG,     
+                 kSADCRUN,     
+                 kSADCPWR,     
+                 kL0TSIM,      
+                 kSADCEC,      
+                 kSADCMC,      
+                 kSADCOC,      
+                 kSADCGTB,     
+                 kSEBDEN,      
+                 kSEBDOU,      
+                 kTPL00,       
+                 kTPL01,       
+                 kTPL02,       
+                 kTPL03,       
+                 kTPL04,       
+                 kTPL05,       
+                 kTPL06,       
+                 kTPL07,       
+                 kTPL08,       
+                 kTPL09,       
+                 kTPL0A,       
+                 kTPL0B,       
+                 kTPL0C,       
+                 kTPL0D,       
+                 kTPL0E,       
+                 kTPL0F,       
+                 kTPL10,       
+                 kTPL11,       
+                 kTPL12,       
+                 kTPL13,       
+                 kTPL14,       
+                 kTPL15,       
+                 kTPL16,       
+                 kTPL17,       
+                 kTPL18,       
+                 kTPL19,       
+                 kTPL1A,       
+                 kTPL1B,       
+                 kTPL1C,       
+                 kTPL1D,       
+                 kTPL1E,       
+                 kTPL1F,       
+                 kTPL20,       
+                 kTPL21,       
+                 kTPL22,       
+                 kTPL23,       
+                 kTPL24,       
+                 kTPL25,       
+                 kTPL26,       
+                 kTPL27,       
+                 kTPL28,       
+                 kTPL29,       
+                 kTPL2A,       
+                 kTPL2B,       
+                 kTPL2C,       
+                 kTPL2D,       
+                 kTPL2E,       
+                 kTPL2F,       
+                 kTPL30,       
+                 kTPL31,       
+                 kTPL32,       
+                 kTPL33,       
+                 kTPL34,       
+                 kTPL35,       
+                 kTPL36,       
+                 kTPL37,       
+                 kTPL38,       
+                 kTPL39,       
+                 kTPL3A,       
+                 kTPL3B,       
+                 kTPL3C,       
+                 kTPL3D,       
+                 kTPL3E,       
+                 kTPL3F,       
+                 kTPL40,       
+                 kTPL41,       
+                 kTPL42,       
+                 kTPL43,       
+                 kTPL44,       
+                 kTPL45,       
+                 kTPL46,       
+                 kTPL47,       
+                 kTPL48,       
+                 kTPL49,       
+                 kTPL4A,       
+                 kTPL4B,       
+                 kTPL4C,       
+                 kTPL4D,       
+                 kTPL4E,       
+                 kTPL4F,       
+                 kTPL50,       
+                 kTPL51,       
+                 kTPL52,       
+                 kTPL53,       
+                 kTPL54,       
+                 kTPL55,       
+                 kTPL56,       
+                 kTPL57,       
+                 kTPL58,       
+                 kTPL59,       
+                 kTPL5A,       
+                 kTPL5B,       
+                 kTPL5C,       
+                 kTPL5D,       
+                 kTPL5E,       
+                 kTPL5F,       
+                 kTPL60,       
+                 kTPL61,       
+                 kTPL62,       
+                 kTPL63,       
+                 kTPL64,       
+                 kTPL65,       
+                 kTPL66,       
+                 kTPL67,       
+                 kTPL68,       
+                 kTPL69,       
+                 kTPL6A,       
+                 kTPL6B,       
+                 kTPL6C,       
+                 kTPL6D,       
+                 kTPL6E,       
+                 kTPL6F,       
+                 kTPL70,       
+                 kTPL71,       
+                 kTPL72,       
+                 kTPL73,       
+                 kTPL74,       
+                 kTPL75,       
+                 kTPL76,       
+                 kTPL77,       
+                 kTPL78,       
+                 kTPL79,       
+                 kTPL7A,       
+                 kTPL7B,       
+                 kTPL7C,       
+                 kTPL7D,       
+                 kTPL7E,       
+                 kTPL7F,       
+                 kMEMRW,       
+                 kMEMCOR,      
+                 kDMDELA,      
+                 kDMDELS,      
+                 kLastReg };   // enum of all TRAP registers, to be used for access to them
+
+  inline const char* GetRegName(TrapReg_t reg)       { return fRegs[reg].name; }
+  inline UShort_t    GetRegAddress(TrapReg_t reg)    { return fRegs[reg].addr; }
+  inline UShort_t    GetRegNBits(TrapReg_t reg)      { return fRegs[reg].nbits; }
+  inline UInt_t      GetRegResetValue(TrapReg_t reg) { return fRegs[reg].res_val; }
+
+  Int_t GetTrapReg(TrapReg_t reg, Int_t det = -1, Int_t rob = -1, Int_t mcm = -1);
+  void PrintTrapReg(TrapReg_t reg, Int_t det = -1, Int_t rob = -1, Int_t mcm = -1);
+
+  Bool_t SetTrapReg(TrapReg_t reg, Int_t value, Int_t det = -1, Int_t rob = -1, Int_t mcm = -1);
+
+  Bool_t LoadConfig();
+
+ protected:
+  static AliTRDtrapConfig *fgInstance;  // pointer to instance (singleton)
+
+  struct SimpleReg_t {
+    char      *name;   // Name of the register
+    UShort_t  addr;    // Address in GIO of TRAP
+    UShort_t  nbits;   // Number of bits, from 1 to 32
+    UInt_t    res_val; // reset value
+    SimpleReg_t(char *nnn = 0, UShort_t a = 0, UShort_t n = 0, UInt_t r = 0) : 
+      name(nnn), addr(a), nbits(n), res_val(r) {}
+  };
+
+  struct RegValue_t {
+    enum {
+      kInvalid = 0,
+      kGlobal,
+      kIndividual
+    } state;
+    union {
+      Int_t globalValue;
+      Int_t *individualValue;
+    };
+  };
+
+  SimpleReg_t fRegs[kLastReg];          // array of TRAP registers
+  RegValue_t fRegisterValue[kLastReg];  // array of TRAP register values in use
+
+/* not yet used
+  struct BlockDescr_t {
+    UShort_t addr;
+    UShort_t nregs;
+    UShort_t nbits;
+    UShort_t step;
+  };
+
+  struct CmdReg_t {
+    char *name;
+    UShort_t addr;
+  };
+
+  enum DbankProp_t { kDBankEmpty = 0,
+                   kDBankHeader,
+                   kDBankData,
+                   kDBankNoB,
+                   kDBankCRC,
+                   kDBankEHeader,
+                   kDBankSCSNData };
+*/
+
+ private:
+  AliTRDtrapConfig();
+
+  ClassDef(AliTRDtrapConfig, 1);
+};
+
+#endif
index 73055e1..1d17895 100644 (file)
@@ -73,6 +73,7 @@
 #pragma link C++ class  AliTRDmcmTracklet+;
 #pragma link C++ class  AliTRDmcmSim+;
 #pragma link C++ class  AliTRDmcm+;
+#pragma link C++ class  AliTRDtrapConfig+;
 #pragma link C++ class  AliTRDtrigParam;
 #pragma link C++ class  AliTRDtrackletBase+;
 #pragma link C++ class  AliTRDtrackletGTU+;
index d51c96d..27c563a 100644 (file)
@@ -48,6 +48,7 @@ SRCS= AliTRDarraySignal.cxx \
       AliTRDSensorArray.cxx \
       AliTRDalignment.cxx \
       AliTRDmcmTracklet.cxx \
+      AliTRDtrapConfig.cxx \
       AliTRDmcmSim.cxx \
       AliTRDmcm.cxx \
       AliTRDtrigParam.cxx \