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