a34a9f2a6fbb9a81d46322483af173bd5f2cd833
[u/mrichter/AliRoot.git] / TRD / AliTRDRawStream.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // This class provides access to TRD digits in raw data.                     //
21 //                                                                           //
22 // It loops over all TRD digits in the raw data given by the AliRawReader.   //
23 // The Next method goes to the next digit. If there are no digits left       //
24 // it returns kFALSE.                                                        //
25 // Several getters provide information about the current digit.              //
26 //                                                                           //
27 // Author: C. Lippmann (C.Lippmann@gsi.de)                                   //
28 //                                                                           //
29 ///////////////////////////////////////////////////////////////////////////////
30
31 #include "AliLog.h"
32 #include "AliRawReader.h"
33 #include "AliTRDRawStream.h"
34 #include "AliTRDgeometry.h"
35 #include "AliTRDCommonParam.h"
36 #include "AliTRDcalibDB.h"
37
38 ClassImp(AliTRDRawStream)
39
40 //_____________________________________________________________________________
41 AliTRDRawStream::AliTRDRawStream() 
42   :TObject()
43   ,fSig()
44   ,fADC(0)
45   ,fTB(0)
46   ,fEv(0)
47   ,fROB(0)
48   ,fMCM(0)
49   ,fSM(0)
50   ,fLAYER(0)
51   ,fSTACK(0)
52   ,fROC(0)
53   ,fSIDE(0)
54   ,fDCS(0)
55   ,fROW(0)
56   ,fCOL(0)
57   ,fDET(0)
58   ,fBCctr(0)
59   ,fPTctr(0)
60   ,fPTphase(0)
61   ,fRVmajor(0)
62   ,fRVminor(0)
63   ,fHCHWords(0)
64   ,fTBins(0)
65   ,fTCon(0)
66   ,fPEDon(0)
67   ,fGAINon(0)
68   ,fXTon(0)
69   ,fNonLinOn(0)
70   ,fBypass(0)
71   ,fCommonAdditive(0)
72   ,fZeroSuppressed(0)
73   ,fHCHctr1(0)
74   ,fHCHctr2(0)
75   ,fMCMHctr1(0)
76   ,fMCMHctr2(0)
77   ,fGTUctr1(0)
78   ,fGTUctr2(0)
79   ,fHCdataCtr(0)
80   ,fTracklPID(0.)
81   ,fTracklDefL(0.)
82   ,fTracklPadPos(0.)
83   ,fTracklPadRow(0)
84   ,fGTUlinkMask()
85   ,fRawReader(NULL)
86   ,fRawVersion(2)
87   ,fNextStatus(0)
88   ,fTbSwitch(0)
89   ,fTbSwitchCtr(0)
90   ,fTimeWords(0)
91   ,fWordCtr(0)
92   ,fRowMax(0)
93   ,fColMax(0)
94   ,fADCmask()
95   ,fChamberDone()
96   ,fRetVal(0)
97   ,fEqID(0)
98   ,fDataSize(0)
99   ,fSizeOK(kFALSE)
100   ,fCountBytes(0)
101   ,fBufSize(0)
102   ,fkBufferSet(kFALSE)
103   ,fPos(NULL)
104   ,fDataWord(NULL)
105   ,fTimeBinsCalib(0)
106   ,fGeo(NULL) 
107   ,fCommonParam(NULL)
108   ,fCalibration(NULL)
109 {
110   //
111   // Default constructor
112   //
113
114   for (Int_t i = 0; i < 540; i++) {
115     fChamberDone[i] = 0;
116   }
117
118 }
119
120 //_____________________________________________________________________________
121 AliTRDRawStream::AliTRDRawStream(AliRawReader *rawReader) 
122   :TObject()
123   ,fSig()
124   ,fADC(0)
125   ,fTB(0)
126   ,fEv(0)
127   ,fROB(0)
128   ,fMCM(0)
129   ,fSM(0)
130   ,fLAYER(0)
131   ,fSTACK(0)
132   ,fROC(0)
133   ,fSIDE(0)
134   ,fDCS(0)
135   ,fROW(0)
136   ,fCOL(0)
137   ,fDET(0)
138   ,fBCctr(0)
139   ,fPTctr(0)
140   ,fPTphase(0)
141   ,fRVmajor(0)
142   ,fRVminor(0)
143   ,fHCHWords(0)
144   ,fTBins(0)
145   ,fTCon(0)
146   ,fPEDon(0)
147   ,fGAINon(0)
148   ,fXTon(0)
149   ,fNonLinOn(0)
150   ,fBypass(0)
151   ,fCommonAdditive(0)
152   ,fZeroSuppressed(0)
153   ,fHCHctr1(0)
154   ,fHCHctr2(0)
155   ,fMCMHctr1(0)
156   ,fMCMHctr2(0)
157   ,fGTUctr1(0)
158   ,fGTUctr2(0)
159   ,fHCdataCtr(0)
160   ,fTracklPID(0.)
161   ,fTracklDefL(0.)
162   ,fTracklPadPos(0.)
163   ,fTracklPadRow(0)
164   ,fGTUlinkMask()
165   ,fRawReader(rawReader)
166   ,fRawVersion(2)
167   ,fNextStatus(0)
168   ,fTbSwitch(0)
169   ,fTbSwitchCtr(0)
170   ,fTimeWords(0)
171   ,fWordCtr(0)
172   ,fRowMax(0)
173   ,fColMax(0)
174   ,fADCmask()
175   ,fChamberDone()
176   ,fRetVal(0)
177   ,fEqID(0)
178   ,fDataSize(0)
179   ,fSizeOK(kFALSE)
180   ,fCountBytes(0)
181   ,fBufSize(0)
182   ,fkBufferSet(kFALSE)
183   ,fPos(NULL)
184   ,fDataWord(NULL)
185   ,fTimeBinsCalib(0)
186   ,fGeo(NULL) 
187   ,fCommonParam(NULL)
188   ,fCalibration(NULL)
189 {
190   //
191   // Create an object to read TRD raw digits
192   //
193
194   fRawReader->Select("TRD");
195
196   for (Int_t i = 0; i < 540; i++) {
197     fChamberDone[i] = 0;
198   }
199
200 }
201
202 //_____________________________________________________________________________
203 AliTRDRawStream::AliTRDRawStream(const AliTRDRawStream& stream)
204   :TObject(stream)
205   ,fSig()
206   ,fADC(-1)
207   ,fTB(-1)
208   ,fEv(-1)
209   ,fROB(-1)
210   ,fMCM(-1)
211   ,fSM(-1)
212   ,fLAYER(-1)
213   ,fSTACK(-1)
214   ,fROC(-1)
215   ,fSIDE(-1)
216   ,fDCS(-1)
217   ,fROW(-1)
218   ,fCOL(-1)
219   ,fDET(0)
220   ,fBCctr(-1)
221   ,fPTctr(-1)
222   ,fPTphase(-1)
223   ,fRVmajor(-1)
224   ,fRVminor(-1)
225   ,fHCHWords(-1)
226   ,fTBins(-1)
227   ,fTCon(0)
228   ,fPEDon(0)
229   ,fGAINon(0)
230   ,fXTon(0)
231   ,fNonLinOn(-1)
232   ,fBypass(-1)
233   ,fCommonAdditive(-1)
234   ,fZeroSuppressed(0)
235   ,fHCHctr1(-1)
236   ,fHCHctr2(-1)
237   ,fMCMHctr1(-1)
238   ,fMCMHctr2(-1)
239   ,fGTUctr1(-1)
240   ,fGTUctr2(-1)
241   ,fHCdataCtr(-1)
242   ,fTracklPID(-1.)
243   ,fTracklDefL(-1.)
244   ,fTracklPadPos(-1.)
245   ,fTracklPadRow(-1)
246   ,fGTUlinkMask()
247   ,fRawReader(NULL)
248   ,fRawVersion(-1)
249   ,fNextStatus(0)
250   ,fTbSwitch(0)
251   ,fTbSwitchCtr(0)
252   ,fTimeWords(0)
253   ,fWordCtr(0)
254   ,fRowMax(-1)
255   ,fColMax(-1)
256   ,fADCmask()
257   ,fChamberDone()
258   ,fRetVal(0)
259   ,fEqID(0)
260   ,fDataSize(0)
261   ,fSizeOK(kFALSE)
262   ,fCountBytes(0)
263   ,fBufSize(0)
264   ,fkBufferSet(kFALSE)
265   ,fPos(NULL)
266   ,fDataWord(NULL)
267   ,fTimeBinsCalib(0)
268   ,fGeo(NULL)
269   ,fCommonParam(NULL)
270   ,fCalibration(NULL)
271 {
272   //
273   // Copy constructor
274   //
275
276   AliFatal("Copy constructor not implemented");
277
278 }
279
280 //_____________________________________________________________________________
281 AliTRDRawStream& AliTRDRawStream::operator = (const AliTRDRawStream& 
282                                               /* stream */)
283 {
284   //
285   // Assigment operator
286   //
287
288   Fatal("operator =", "assignment operator not implemented");
289   return *this;
290
291 }
292
293 //_____________________________________________________________________________
294 AliTRDRawStream::~AliTRDRawStream()
295 {
296   //
297   // Destructor
298   //
299   
300   delete fGeo;
301 }
302
303 //_____________________________________________________________________________
304 void AliTRDRawStream::SetRawReader(AliRawReader *rawReader) 
305 {
306   if (rawReader)
307     {
308       fRawReader = rawReader;
309     }
310 }
311 //_____________________________________________________________________________
312 Bool_t AliTRDRawStream::SetRawVersion(Int_t rv)
313 {
314   //
315   // Set the raw data version
316   //
317
318   if ( rv >= 0 && rv <= 3 ) {
319     fRawVersion = rv;
320     return kTRUE;
321   }
322
323   return kFALSE;
324
325 }
326
327
328 //____________________________________________________________________________
329 Int_t AliTRDRawStream::Init()
330 {
331   //
332   // Initialization
333   //
334
335   fCommonParam = AliTRDCommonParam::Instance();
336   if (!fCommonParam) {
337     AliError("Could not get common parameters");
338     return 0;
339   }
340
341   fCalibration = AliTRDcalibDB::Instance();
342   if (!fCalibration) {
343     AliError("Could not get calibration object");
344     return 0;
345   }
346
347   if (!fGeo)
348     {
349       fGeo = new AliTRDgeometry();
350     }
351   
352   fTimeBinsCalib = fCalibration->GetNumberOfTimeBins();
353   AliDebug(2, Form("Number of Timebins read from CDB: %d", fTimeBinsCalib));
354
355   // The number of data words needed for this number of time bins (there
356   // are 3 time bins in one word)
357   fTimeWords = (fTimeBinsCalib-1)/3 + 1;
358
359   fTbSwitch    = 3;
360   fTbSwitchCtr = 0;
361
362   fHCHctr1 = fHCHctr2 =  0;
363   fGTUctr1 = fGTUctr2 = -1;
364
365   fHCdataCtr = 0;
366   fWordCtr   = 0;  
367
368   fDET     = 0;
369   fRetVal = 0;
370   fEqID     = 0;
371   fDataSize = 0;
372   fSizeOK = kFALSE;
373   
374   fNextStatus = fkStart;
375
376   fCountBytes = 0;
377   fBufSize = 0;
378   fDataWord = NULL;
379   fPos = NULL;
380   fWordCtr = 0;
381   fkBufferSet = kFALSE;
382   return kTRUE;
383 }
384
385 //____________________________________________________________________________
386 Int_t AliTRDRawStream::NextData()
387 {
388   //
389   // Updates the next data word pointer
390   //
391
392   if (fCountBytes + kSizeWord >= fBufSize)
393     {
394       fkBufferSet = fRawReader->ReadNextData(fPos);
395       if (fkBufferSet == kTRUE)
396         {
397           fBufSize = fRawReader->GetDataSize();
398           fCountBytes = 0;        
399           fDataWord = (UInt_t*)fPos;
400           fNextStatus = fkNextSM;
401           fWordCtr = 0;
402           return fkNextSM;
403         }
404       else
405         {
406           fNextStatus = fkStop;
407           return fkNoMoreData;
408         }
409     }
410   else
411     {
412
413       fPos += kSizeWord;
414       fCountBytes += kSizeWord;   
415       fDataWord = (UInt_t*)fPos;
416       fWordCtr++;
417       return fkWordOK;
418     }
419 }
420
421 //____________________________________________________________________________
422 Bool_t AliTRDRawStream::Next()
423 {
424   //
425   // Updates the next data word pointer
426   //
427
428   if (fNextStatus == fkStart)
429     {
430       Init();
431     }
432
433   while (fNextStatus != fkStop)
434     { // !fkStop
435       NextData();
436             
437       if (fNextStatus == fkNextMCM || fNextStatus == fkNextData)
438         {
439           fHCdataCtr += 4;
440
441         if( ((*fDataWord & 0x80000000) == 0x0) && ((*fDataWord & 0x0000000f) == 0xC) )
442           { // MCM Header
443             DecodeMCMheader();
444             if ( fMCM < 0 || fMCM > 15 || fROB < 0 || fROB > 7 ) 
445               {
446                 AliWarning("Wrong fMCM or fROB. Skip this data");
447                 fRawReader->AddMajorErrorLog(kWrongMCMorROB,Form("MCM=%d, ROB=%d",fMCM,fROB));
448                 fNextStatus = fkNextHC;
449                 continue;
450               }
451             fTbSwitch    = 3;  // For first adc channel we expect: (*fDataWord & 3) = 3
452             fTbSwitchCtr = 0;  // 
453             fADC = fTB   = 0;  // Reset Counter
454             fNextStatus = fkNextData;
455             continue;
456           }
457     
458         if ( *fDataWord == kEndofrawdatamarker ) 
459           {  // End of half-chamber data, finished
460             fGTUctr1 = -1;
461             fNextStatus = fkNextHC;
462             continue;
463           }
464
465         if (fNextStatus == fkNextData )
466           {       // MCM header is set, ADC data is valid.
467     
468             // Found some data. Decode it now:
469             fRetVal = DecodeDataWord();
470             if ( fRetVal ==  0 ) continue;
471             if ( fRetVal == -1 ) 
472               {
473                 fNextStatus = fkNextHC;
474                 continue;
475               }
476             if ( fADC > 1 && fADC < (Int_t)fGeo->ADCmax()-1 ) 
477               {       
478                 // Write Digits
479                 if ( fCOL >= 0 && fCOL < fColMax && fROW >= 0 && fROW < fRowMax ) 
480                   {  // A real pad
481                     fTB += 3;           
482                     return kTRUE;
483                   }            
484               }
485             else 
486               {
487                 fCOL = -1;             
488               }
489           }// fkNextData  
490         
491         continue;
492         } //next mcm
493
494       if ( fNextStatus == fkNextHC )
495         {
496           //
497           // 1) Find end_of_tracklet_marker
498           //
499           // GTU Link Mask?
500           if ( (*fDataWord & 0xfffff000) ==  0xe0000000 ) 
501             {
502               DecodeGTUlinkMask();
503               continue;
504             }
505           
506           // endoftrackletmarker?
507           if ( *fDataWord == kEndoftrackletmarker ) 
508             {
509               AliDebug(3, "end-of-tracklet-marker found");
510               fNextStatus = fkSeekNonEoTracklet;
511               continue;
512             } 
513           else 
514             {
515               // Tracklets found
516               AliDebug(3, "Tracklet found");
517               DecodeTracklet();
518               continue;
519             }
520         } //if next HC
521
522       if (fNextStatus == fkSeekNonEoTracklet)
523         {
524           //
525           // 2) Look for non-end_of_tracklet_marker
526           //
527           //printf("Word %d: 0x%08x\n", fWordCtr, *fDataWord); 
528
529           if ( *fDataWord != kEndoftrackletmarker ) 
530             {
531               fNextStatus = fkDecodeHC;
532               AliDebug(3, "NON end-of-tracklet-marker found");
533               //// no do not continue - this should be the hcheader
534             }
535           else
536             {
537               //just go on and find the non-end_of_tracklet_marker
538               continue;
539             }
540         }
541
542       if ( fNextStatus == fkDecodeHC )
543         {
544           AliDebug(3, "Decode HC");
545
546           //
547           // 3) This Word must be Half Chamber Header
548           //
549           if ( (*fDataWord & 0x00000003) == 1 ) 
550             { // HC header
551               DecodeHCheader(fTimeBinsCalib); // This is the new header!
552               fDET    = fGeo->GetDetector(fLAYER, fSTACK, fSM);
553               fRowMax = fCommonParam->GetRowMax(fLAYER,fSTACK,fSM);
554               fColMax = fCommonParam->GetColMax(fROC);
555               
556               fMCMHctr2 = 0;
557               fHCdataCtr = 0;
558               
559               fChamberDone[fDET]++;
560               fNextStatus = fkNextMCM;
561               AliDebug(3, "Decode HC OK");            
562               continue;
563             } //HC header
564           else
565             {
566               AliDebug(3, "Decode HC NOT OK");        
567               fNextStatus = fkNextSM;
568               continue;
569             }
570         } // if decode HC
571
572       if (fNextStatus == fkNextSM)
573         {
574           
575           fDET     = 0;
576           fRetVal = 0;
577           fEqID     = 0;
578           fDataSize = 0;
579           fSizeOK = kFALSE;
580           
581           // After reading the first word check for size of this data and get Eq. ID
582           if ( fWordCtr == 1 ) 
583             {
584               fDataSize = fRawReader->GetDataSize()/4;  // Size of this payload in 32bit words
585               fEqID     = fRawReader->GetEquipmentId(); // Get Equipment ID
586               if ( fDataSize > 0 ) fSizeOK = kTRUE;
587             }
588           
589           // GTU Link Mask?
590           if ( (*fDataWord & 0xfffff000) ==  0xe0000000 ) 
591             {
592               DecodeGTUlinkMask();
593               fNextStatus = fkNextHC;
594               continue;
595             } 
596           else 
597             {
598               AliWarning(Form("Equipment %d: First data word is not GTU Link Mask!", fEqID));
599               fRawReader->AddMajorErrorLog(kGTULinkMaskMissing,Form("Equipment %d",fEqID));
600               fNextStatus = fkStop;
601             }       
602         }// if nextSM
603
604     } // not fkStop
605
606   AliDebug(1, Form("That's all folks! %d", fSM));
607   return kFALSE;
608 }
609
610 //============================================================================
611 // Decoding functions
612 //============================================================================
613
614
615 //____________________________________________________________________________
616 void AliTRDRawStream::DecodeHCheader(Int_t timeBins)
617 {
618   //
619   // Decode the HC header (fRawVersion == 2, 3, 4, ???)
620   //
621
622   fRVmajor = (*fDataWord >> 24) & 0x7f;
623   fRVminor = (*fDataWord >> 17) & 0x7f;
624
625   if (fRVmajor < 2 || fRVmajor > 4)
626     AliError(Form(" Unsupported raw version: %d", fRawVersion))
627   
628   if ( fRawVersion != fRVmajor ) {
629     
630     AliWarning("===============================================================================");
631     AliWarning(Form("Mismatch between fRawVersion (%d) and fRVmajor from HC header (%d)"
632                     ,fRawVersion,fRVmajor));
633     AliWarning(Form("Setting fRawVersion to %d", fRVmajor));
634     AliWarning("===============================================================================");
635     fRawVersion = fRVmajor;
636
637   }
638
639   //
640   // check for zero suppression
641   if ( fRawVersion >= 3 || fRawVersion <= 4 ) fZeroSuppressed = kTRUE;
642   else                                        fZeroSuppressed = kFALSE;
643   
644   // 1st word (h[0])
645   if ( (*fDataWord & 0x3) == 1 ) {
646
647     fHCHWords = (*fDataWord >> 14) & 0x7;
648     fSM       = (*fDataWord >>  9) & 0x1f;
649     fLAYER    = (*fDataWord >>  6) & 0x7;
650     fSTACK    = (*fDataWord >>  3) & 0x7;
651     fSIDE     = (*fDataWord >>  2) & 0x1;
652
653     fROC      = fGeo->GetDetectorSec(fLAYER, fSTACK);
654
655     AliDebug(3, Form("0x%08x: HC header: sm=%d; roc=%d; side=%x", *fDataWord, fSM, fROC, fSIDE+10));
656
657     if ((fSM    <  0) || 
658         (fSM    > 17) || 
659         (fLAYER <  0) || 
660         (fLAYER >  5) || 
661         (fSTACK <  0) || 
662         (fSTACK >  4) || 
663         (fSIDE  <  0) || 
664         (fSIDE  >  1)) {
665       AliWarning(Form("0x%08x: Strange HC header: dcs=%d; sm=%d; layer=%d; stack=%d.",
666                      *fDataWord, fDCS, fSM, fLAYER, fSTACK));
667       fRawReader->AddMajorErrorLog(kHCHeaderCorrupt,Form("0x%08x:dcs=%d; sm=%d; layer=%d; stack=%d.",
668                                                          *fDataWord, fDCS, fSM, fLAYER, fSTACK));
669     } 
670     else {
671       fHCHctr1++;
672       fHCHctr2++;
673     }
674   } 
675   else { 
676     AliWarning(Form("0x%08x: No HC header when it was expected.", *fDataWord)); 
677     fRawReader->AddMajorErrorLog(kHCHeaderMissing,Form("0x%08x", *fDataWord));
678   }
679
680   // 2nd word (h[1])
681   if ( fHCHWords >= 1 ) {
682     // read one more word
683     if (NextData() != fkWordOK)
684       {
685         AliWarning("Next HC word missing");
686         fRawReader->AddMajorErrorLog(kHCWordMissing,"Next HC word missing"); 
687         fNextStatus = fkNextHC;
688         return;
689       }
690     if ( (*fDataWord & 0x3) == 1 ) {
691       
692       fBCctr   =  (*fDataWord >> 16);
693       fPTctr   =  (*fDataWord >> 12) & 0xf;
694       fPTphase =  (*fDataWord >>  8) & 0xf;
695       fTBins   = ((*fDataWord >>  2) & 0x3f) + 1;
696
697       AliDebug(3, Form("0x%08x: HC header 2: BCctr=%d PTctr=%d PTph=%d TB=%d"
698                       , *fDataWord, fBCctr, fPTctr, fPTphase, fTBins));
699
700       if( fTBins != timeBins ) {
701
702         AliWarning("===============================================================================");
703         AliError(Form("Mismatch between nNTB from CDB (%d) and from HC header (%d)"
704                       , timeBins, fTBins));
705         AliWarning(Form("We will use the value from the raw data (HC header): %d", fTBins));
706         AliWarning("===============================================================================");
707
708         fTimeWords = (fTBins - 1)/3 + 1;        
709       }
710
711     }
712
713   }
714
715   // 3nd word (h[2])
716   if ( fHCHWords >= 2 ) {
717     // read one more word
718     if (NextData() != fkWordOK)
719       {
720         AliWarning("Next HC word missing");
721         fRawReader->AddMajorErrorLog(kHCWordMissing,"Next HC word missing"); 
722         fNextStatus = fkNextHC;
723         return;
724       }
725     if ( (*fDataWord & 0x3) == 1 ) {
726        
727       fTCon     = (*fDataWord >> 29) & 0x1;
728       fPEDon    = (*fDataWord >> 31) & 0x1;
729       fGAINon   = (*fDataWord >> 30) & 0x1;
730       fXTon     = (*fDataWord >> 28) & 0x1;
731       fNonLinOn = (*fDataWord >> 27) & 0x1;
732       fBypass   = (*fDataWord >> 26) & 0x1;
733
734       fCommonAdditive = (*fDataWord >> 20) & 0x3f;
735
736       AliDebug(3, Form("0x%08x: HC header 3: TC=%d, PED=%d, GAIN=%d, XT=%d, NonLin=%d, Bypass=%d, Add=%d"
737                       , fTCon, fPEDon, fGAINon, fXTon, fNonLinOn, fBypass, fCommonAdditive));
738     }
739   }
740
741 }  
742
743 //____________________________________________________________________________
744 void AliTRDRawStream::DecodeMCMheader()
745 {
746
747   //
748   // Decode the MCM header
749   //
750
751   if ( fRawVersion < 1 || fRawVersion > 3 ) 
752     {
753       AliError(Form(" Unsupported raw version: %d", fRawVersion));      
754     }
755
756   fMCM  = (*fDataWord & 0xff000000) >> 24;
757   fEv   = (*fDataWord & 0x00fffff0) >> 4;
758
759   fROB  = fMCM / 16;
760   fMCM  = fMCM % 16;
761
762   fROW  = fGeo->GetPadRowFromMCM(fROB, fMCM);
763
764   AliDebug(4, Form("0x%08x: SM%d L%dS%d. MCM Header: fROB=%d fMCM=%02d fEv=%02d"
765                   , *fDataWord, fSM, fLAYER, fSTACK, fROB, fMCM, fEv));
766
767   if ( fROB % 2 == 0 && fSIDE == 1 ) {
768     AliWarning(Form("SM%d L%dS%d: Mismatch between fROB (%d) and fSIDE (%d): fMCM=%02d"
769                    , fSM, fLAYER, fSTACK, fROB, fSIDE, fMCM ));
770     fRawReader->AddMajorErrorLog(kROBSideMismatch,Form("SM%d L%dS%d: fROB (%d) fSIDE (%d): fMCM=%02d"
771                                                        , fSM, fLAYER, fSTACK, fROB, fSIDE, fMCM ));
772   }
773   if ( fROB % 2 != 0 && fSIDE == 0 ) {
774     AliWarning(Form("SM%d L%dS%d: Mismatch between fROB (%d) and fSIDE (%d): fMCM=%02d"
775                    , fSM, fLAYER, fSTACK, fROB, fSIDE, fMCM ));
776     fRawReader->AddMajorErrorLog(kROBSideMismatch,Form("SM%d L%dS%d: fROB (%d) fSIDE (%d): fMCM=%02d"
777                                                        , fSM, fLAYER, fSTACK, fROB, fSIDE, fMCM ));
778   }
779   if ( (fSTACK == 2 && fROW >= fGeo->RowmaxC0()) ||
780        (fSTACK != 2 && fROW >= fGeo->RowmaxC1()) || fROW < 0 ) {
781     AliWarning(Form("SM%d L%dS%d: Wrong Padrow (%d) fROB=%d, fSIDE=%d, fMCM=%02d"
782                    , fSM, fLAYER, fSTACK, fROW, fROB, fSIDE, fMCM ));
783     fRawReader->AddMajorErrorLog(kWrongPadrow,Form("SM%d L%dS%d: Padrow (%d) fROB=%d, fSIDE=%d, fMCM=%02d"
784                                                   , fSM, fLAYER, fSTACK, fROW, fROB, fSIDE, fMCM ));
785   }
786   
787   fMCMHctr1++;
788   fMCMHctr2++;
789
790   // AdcMask for Zero supressed data
791   if ( fRawVersion == 3 ) {
792     // read one more word
793     if (NextData() != fkWordOK)
794       {
795         AliWarning("MCM ADC mask missing");
796         fRawReader->AddMajorErrorLog(kMCMADCMaskMissing,"Missing"); 
797         fNextStatus = fkNextHC;
798         return;
799       }
800     if ( (*fDataWord & 0x000007ff) == 0xC ) {     // at the moment bits 4-10 are empty
801       
802       for ( Int_t ctr = 0; ctr < fGeo->ADCmax(); ctr++ ) {
803         if ( (*fDataWord >> (11+ctr)) == 0x1 ) fADCmask[ctr] = kTRUE;
804         else                                  fADCmask[ctr] = kFALSE;
805       }
806
807       AliDebug(4, Form("0x%08x: ADC mask", *fDataWord));
808
809     }
810     else {
811       AliWarning("Expected ADC mask but did not find one!");
812       fRawReader->AddMajorErrorLog(kMCMADCMaskMissing,"Decode error"); 
813     }
814
815   }
816
817 }
818
819 //____________________________________________________________________________
820 void AliTRDRawStream::DecodeTracklet()
821 {
822
823   //
824   // Decode the Tracklet
825   //
826   // this function is not tested yet on real tracklets
827   //
828
829   if ( fRawVersion < 1 || fRawVersion > 3 ) 
830     {
831       AliError(Form(" Unsupported raw version: %d", fRawVersion));      
832     }
833
834   fTracklPID    = (*fDataWord >> 24) & 0xff;
835   fTracklPadRow = (*fDataWord >> 20) & 0xf;    // 0:15
836   fTracklDefL   = (*fDataWord >> 13) & 0x7f;
837   fTracklPadPos = (*fDataWord)       & 0x1fff;
838
839   fTracklPID    /= (Float_t)((1<<8) - 1);                      // 0:1 (steps of 0.39%)
840   fTracklDefL    = (fTracklDefL  - ((1<< 7)-1)/2.) * 140.e-4;  // -0.889:0.889cm 
841   fTracklPadPos  = (fTracklPadPos - ((1<<13)-1)/2.) * 160.e-4; // -65.528:65.528 cm
842
843   //AliDebug(4, Form("0x%08x: Tracklet found: SM%d L%dS%d side %x: PadRow=%d PadPos=%f DefL=%f PID=%f"
844   //              , *fDataWord, fSM, fLAYER, fSTACK, fSIDE+10
845   //                , fTracklPadRow, fTracklPadPos, fTracklDefL, fTracklPID));
846
847   if( (fSTACK == 2) && (fTracklPadRow >= (Int_t) fGeo->RowmaxC0()) ||
848       (fSTACK != 2) && (fTracklPadRow >= (Int_t) fGeo->RowmaxC1()) ) {
849     AliWarning(Form("Strange Row read from Tracklet Word: %d", fTracklPadRow));
850     fRawReader->AddMajorErrorLog(kTrackletRowMismatch,Form("Word: %d", fTracklPadRow));
851   }
852
853 }
854
855 //____________________________________________________________________________
856 void AliTRDRawStream::DecodeGTUlinkMask()
857 {
858
859   //
860   // Decode the link masks sent by the GTU. These marke the active optical links
861   // between GTU and Super Module. Up to now only fully active links are found
862   // (0xfff = 12 active links).
863   //
864
865   if ( fRawVersion < 1 || fRawVersion > 3 ) 
866     {
867       AliError(Form(" Unsupported raw version: %d", fRawVersion));      
868     }
869
870   if ( fGTUctr1 == -1 ) fGTUctr2++;
871   fGTUctr1++;
872
873   if ( (fGTUctr1 >= 0) && (fGTUctr1 < 5) && (fGTUctr2 >= 0) && (fGTUctr2 < 18) ) {
874     fGTUlinkMask[fGTUctr2][fGTUctr1] = (*fDataWord & 0xfff);
875   }
876
877 }
878
879 //____________________________________________________________________________
880 Int_t  AliTRDRawStream::DecodeDataWord()
881 {
882
883   //
884   // Decode the Data
885   //
886
887   if      ( fRawVersion >= 1 && fRawVersion <= 2 ) {
888     return DecodeDataWordV1V2();
889   }
890   else if ( fRawVersion >= 3 && fRawVersion <= 3 ) {
891     return DecodeDataWordV3();
892   }
893
894   AliError(Form(" Unsupported raw version: %d", fRawVersion));
895   return -1;
896
897 }
898
899 //____________________________________________________________________________
900 Int_t  AliTRDRawStream::DecodeDataWordV1V2()
901 {
902
903   //
904   // Decode the Data (full raw data. No zero suppression. 21 adc channels)
905   //
906   // return  0 means continue to next data word
907   // return -1 means break data loop
908   //
909
910   if ( (*fDataWord & 0x00000003) != 0x2 && (*fDataWord & 0x00000003) != 0x3) {
911     AliWarning(Form("Data %08x : Data Word ends neither with b11 nor b10", (Int_t)*fDataWord));
912     fRawReader->AddMinorErrorLog(kDataMaskError,Form("Data %08x", (Int_t)*fDataWord));
913     return -1;
914   }
915
916   if ( (*fDataWord & 0x00000003) != fTbSwitch ) {    // Next ADC channel found
917     fTbSwitch = (fTbSwitch & 2) | !(fTbSwitch & 1);   // 0x3 <--> 0x2
918     fTbSwitchCtr = 0;
919     fADC++;
920     fTB=0;
921   }
922
923   fTbSwitchCtr++; // Just read one word
924
925   // We have only timeTotal time bins
926   if ( fTbSwitchCtr > fTimeWords ) {
927     AliWarning(Form("Data is strange. Already found %d words for this ADC channel", (Int_t)fTbSwitchCtr));
928     fRawReader->AddMinorErrorLog(kADCNumberOverflow,Form("%d words", (Int_t)fTbSwitchCtr));
929     return 0;
930   }
931
932   // We have only 21 ADC channels.
933   if ( fADC > (Int_t)fGeo->ADCmax()-1 ) {
934     AliWarning(Form("Data %08x : Data is strange. fADC is already %d", (Int_t)*fDataWord, (Int_t)fADC));
935     fRawReader->AddMinorErrorLog(kADCChannelOverflow,Form("Data %08x : fADC=%d", (Int_t)*fDataWord, (Int_t)fADC));
936     return 0;
937   }
938
939   // There are 18 pads connected to each MCM ADC channels 2...19. The other channels cross to other
940   // MCMs and are good for online tracking in the MCM.
941   if ( fADC > 1 && fADC < (Int_t)fGeo->ADCmax()-1 ) {
942
943     // Get Pad column
944     fCOL = fGeo->GetPadColFromADC(fROB, fMCM, fADC);
945
946     // We have only 144 Pad Columns
947     if ( fCOL > fColMax-1 || fCOL < 0 ) {
948       AliWarning(Form("SM%d L%dS%d: Wrong Pad column (%d) fROB=%d, fSIDE=%d, fMCM=%02d", fSM,
949                     fLAYER, fSTACK, fCOL, fROB, fSIDE, fMCM ));
950       fRawReader->AddMajorErrorLog(kWrongPadcolumn,Form("SM%d L%dS%d: column (%d) fROB=%d, fSIDE=%d, fMCM=%02d", fSM,
951                     fLAYER, fSTACK, fCOL, fROB, fSIDE, fMCM ));
952     }
953
954     // Decode 32 bit data words with information from 3 time bins and copy the data
955     fSig[0] = (*fDataWord & 0x00000ffc) >> 2;
956     fSig[1] = (*fDataWord & 0x003ff000) >> 12;
957     fSig[2] = (*fDataWord & 0xffc00000) >> 22;
958
959     // Print data to screen:
960     // Do NOT switch on for default production, it is VERY slow
961     //    AliDebug(5, Form("SM%d L%dS%d: ROB%d MCM=%d ADC=%d (ROW=%d COL=%d): Data %04d %04d %04d\n",
962     //               fSM, fLAYER, fSTACK, fROB, fMCM, fADC, fROW, fCOL, fSig[0], fSig[1], fSig[2]));
963     
964   }
965   else {
966     
967     fCOL = -1;
968     
969   }
970
971   return 1;
972
973 }
974
975 //____________________________________________________________________________
976 Int_t  AliTRDRawStream::DecodeDataWordV3()
977 {
978
979   //
980   // Decode the data (Zero suppresses data. 21 adc channels)
981   //
982   // return  0 means continue to next data word
983   // return -1 means break data loop
984   //
985   // NOT TESTED YET!!!!!!!!
986   //
987
988   if ( (*fDataWord & 0x00000003) != 0x2 && (*fDataWord & 0x00000003) != 0x3) {
989     AliWarning(Form("Data %08x : Data Word ends neither with b11 nor b10", (Int_t)*fDataWord));
990     fRawReader->AddMinorErrorLog(kDataMaskError,Form("Data %08x", (Int_t)*fDataWord));
991     return -1;
992   }
993
994   if ( (*fDataWord & 0x00000003) != fTbSwitch ) {    // Next ADC channel found
995     fTbSwitch = (fTbSwitch & 2) | !(fTbSwitch & 1);   // 0x3 <--> 0x2
996     fTbSwitchCtr = 0;
997     //
998     // Jump to next ADC channel that is not masked
999     do {
1000       fADC++;
1001     } while ( ((fADC < fGeo->ADCmax()) && (fADCmask[fADC] == kFALSE)) || (fADC >= fGeo->ADCmax()) );
1002     fTB=0;
1003   }
1004
1005   fTbSwitchCtr++; // Just read one word
1006
1007   // We have only timeTotal time bins
1008   if ( fTbSwitchCtr > fTimeWords ) {
1009     AliWarning(Form("Data is strange. Already found %d words for this ADC channel", (Int_t)fTbSwitchCtr));
1010     fRawReader->AddMinorErrorLog(kADCNumberOverflow,Form("%d words", (Int_t)fTbSwitchCtr));
1011     return 0;
1012   }
1013
1014   // We have only 21 ADC channels.
1015   if ( fADC > (Int_t)fGeo->ADCmax()-1 ) {
1016     AliWarning(Form("Data %08x : Data is strange. fADC is already %d", (Int_t)*fDataWord, (Int_t)fADC));
1017     fRawReader->AddMinorErrorLog(kADCChannelOverflow,Form("Data %08x : fADC=%d", (Int_t)*fDataWord, (Int_t)fADC));
1018     return 0;
1019   }
1020
1021   // There are 18 pads connected to each MCM ADC channels 2...19. The other channels cross to other
1022   // MCMs and are good for online tracking in the MCM.
1023   if ( fADC > 1 && fADC < (Int_t)fGeo->ADCmax()-1 ) {
1024
1025     // Get Pad column
1026     fCOL = fGeo->GetPadColFromADC(fROB, fMCM, fADC);
1027
1028     // We have only 144 Pad Columns
1029     if ( fCOL > fColMax-1 || fCOL < 0 ) {
1030       AliWarning(Form("SM%d L%dS%d: Wrong Pad column (%d) fROB=%d, fSIDE=%d, fMCM=%02d", fSM,
1031                     fLAYER, fSTACK, fCOL, fROB, fSIDE, fMCM ));
1032       fRawReader->AddMajorErrorLog(kWrongPadcolumn,Form("SM%d L%dS%d: column (%d) fROB=%d, fSIDE=%d, fMCM=%02d", fSM,
1033                     fLAYER, fSTACK, fCOL, fROB, fSIDE, fMCM ));
1034     }
1035
1036     // Decode 32 bit data words with information from 3 time bins and copy the data
1037     fSig[0] = (*fDataWord & 0x00000ffc) >> 2;
1038     fSig[1] = (*fDataWord & 0x003ff000) >> 12;
1039     fSig[2] = (*fDataWord & 0xffc00000) >> 22;
1040
1041     // Print data to screen:
1042     AliDebug(5, Form("SM%d L%dS%d: ROB%d MCM=%d ADC=%d (ROW=%d COL=%d): Data %04d %04d %04d\n",
1043                      fSM, fLAYER, fSTACK, fROB, fMCM, fADC, fROW, fCOL, fSig[0], fSig[1], fSig[2]));
1044     
1045   }
1046   else {
1047     
1048     fCOL = -1;
1049     
1050   }
1051
1052   return 1;
1053
1054 }