Fix for 64-bit platforms
[u/mrichter/AliRoot.git] / RAW / AliAltroRawStream.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 Altro digits in raw data.
21 ///
22 /// It loops over all Altro 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 ///////////////////////////////////////////////////////////////////////////////
28
29 #include "AliAltroRawStream.h"
30 #include "AliRawReader.h"
31 #include "AliLog.h"
32
33 ClassImp(AliAltroRawStream)
34
35
36 //_____________________________________________________________________________
37 AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
38   fNoAltroMapping(kTRUE),
39   fIsOldRCUFormat(kFALSE),
40   fIsShortDataHeader(kFALSE),
41   fDDLNumber(-1),
42   fPrevDDLNumber(-1),
43   fRCUId(-1),
44   fPrevRCUId(-1),
45   fHWAddress(-1),
46   fPrevHWAddress(-1),
47   fTime(-1),
48   fPrevTime(-1),
49   fSignal(-1),
50   fTimeBunch(-1),
51   fRawReader(rawReader),
52   fData(NULL),
53   fPosition(0),
54   fCount(0),
55   fBunchLength(0),
56   fRCUTrailerData(NULL),
57   fRCUTrailerSize(0)
58 {
59 // create an object to read Altro raw digits
60   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
61 }
62
63 //_____________________________________________________________________________
64 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
65   TObject(stream),
66   fNoAltroMapping(stream.fNoAltroMapping),
67   fIsOldRCUFormat(stream.fIsOldRCUFormat),
68   fIsShortDataHeader(stream.fIsShortDataHeader),
69   fDDLNumber(stream.fDDLNumber),
70   fPrevDDLNumber(stream.fPrevDDLNumber),
71   fRCUId(stream.fRCUId),
72   fPrevRCUId(stream.fPrevRCUId),
73   fHWAddress(stream.fHWAddress),
74   fPrevHWAddress(stream.fPrevHWAddress),
75   fTime(stream.fTime),
76   fPrevTime(stream.fPrevTime),
77   fSignal(stream.fSignal),
78   fTimeBunch(stream.fTimeBunch),
79   fRawReader(stream.fRawReader),
80   fData(stream.fData),
81   fPosition(stream.fPosition),
82   fCount(stream.fCount),
83   fBunchLength(stream.fBunchLength),
84   fRCUTrailerData(stream.fRCUTrailerData),
85   fRCUTrailerSize(stream.fRCUTrailerSize)
86 {
87   fSegmentation[0]   = stream.fSegmentation[0];
88   fSegmentation[1]   = stream.fSegmentation[1];
89   fSegmentation[2]   = stream.fSegmentation[2];
90 }
91
92 //_____________________________________________________________________________
93 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
94 {
95   if(&stream == this) return *this;
96
97   fNoAltroMapping    = stream.fNoAltroMapping;
98   fIsOldRCUFormat    = stream.fIsOldRCUFormat;
99   fIsShortDataHeader = stream.fIsShortDataHeader;
100   fDDLNumber         = stream.fDDLNumber;
101   fPrevDDLNumber     = stream.fPrevDDLNumber;
102   fRCUId             = stream.fRCUId;
103   fPrevRCUId         = stream.fPrevRCUId;
104   fHWAddress         = stream.fHWAddress;
105   fPrevHWAddress     = stream.fPrevHWAddress;
106   fTime              = stream.fTime;
107   fPrevTime          = stream.fPrevTime;
108   fSignal            = stream.fSignal;
109   fTimeBunch         = stream.fTimeBunch;
110   fRawReader         = stream.fRawReader;
111   fData              = stream.fData;
112   fPosition          = stream.fPosition;
113   fCount             = stream.fCount;
114   fBunchLength       = stream.fBunchLength;
115   fRCUTrailerData    = stream.fRCUTrailerData;
116   fRCUTrailerSize    = stream.fRCUTrailerSize;
117
118   fSegmentation[0]   = stream.fSegmentation[0];
119   fSegmentation[1]   = stream.fSegmentation[1];
120   fSegmentation[2]   = stream.fSegmentation[2];
121
122   return *this;
123 }
124
125 //_____________________________________________________________________________
126 AliAltroRawStream::~AliAltroRawStream()
127 {
128 // clean up
129
130 }
131
132 //_____________________________________________________________________________
133 void AliAltroRawStream::Reset()
134 {
135 // reset altro raw stream params
136
137   fPosition = fCount = fBunchLength = 0;
138
139   fRCUTrailerData = NULL;
140   fRCUTrailerSize = 0;
141
142   fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
143
144   if (fRawReader) fRawReader->Reset();
145
146   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
147 }
148
149 //_____________________________________________________________________________
150 Bool_t AliAltroRawStream::Next()
151 {
152 // read the next raw digit
153 // returns kFALSE if there is no digit left
154
155   fPrevDDLNumber = fDDLNumber;
156   fPrevRCUId = fRCUId;
157   fPrevHWAddress = fHWAddress;
158   fPrevTime = fTime;
159
160   while (fCount == 0) {  // next trailer
161     if (fPosition <= 0) {  // next payload
162       do {
163         if (!fRawReader->ReadNextData(fData)) return kFALSE;
164       } while (fRawReader->GetDataSize() == 0);
165
166       fDDLNumber = fRawReader->GetDDLID();
167
168       fPosition = GetPosition();
169     }
170
171     ReadTrailer();
172
173     fBunchLength = 0;
174   }
175
176   if (fBunchLength == 0) ReadBunch();
177   else fTime--;
178
179   ReadAmplitude();
180
181   return kTRUE;
182 }
183
184 //_____________________________________________________________________________
185 void AliAltroRawStream::SelectRawData(Int_t detId)
186 {
187   // Select the raw data for specific
188   // detector id
189   AliDebug(1,Form("Selecting raw data for detector %d",detId));
190   fRawReader->Select(detId);
191 }
192
193 //_____________________________________________________________________________
194 void AliAltroRawStream::SelectRawData(const char *detName)
195 {
196   // Select the raw data for specific
197   // detector name
198   AliDebug(1,Form("Selecting raw data for detector %s",detName));
199   fRawReader->Select(detName);
200 }
201
202 //_____________________________________________________________________________
203 UShort_t AliAltroRawStream::GetNextWord()
204 {
205   // Read the next 10 bit word in backward direction
206   // The input stream access is given by fData and fPosition
207
208   fPosition--;
209
210   Int_t iBit = fPosition * 10;
211   Int_t iByte = iBit / 8;
212   Int_t shift = iBit % 8;
213
214   // the raw data is written as integers where the low bits are filled first
215   // -> little endian is assumed here !
216   Int_t iByteLow = iByte;
217   iByte++;
218   Int_t iByteHigh  = iByte;
219   return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
220 }
221
222 //_____________________________________________________________________________
223 Bool_t AliAltroRawStream::ReadTrailer()
224 {
225   //Read a trailer of 40 bits in the backward reading mode
226   //In case of no mapping is provided, read a dummy trailer
227   if (fNoAltroMapping) {
228     AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
229     return ReadDummyTrailer();
230   }
231
232   //First reading filling words
233   UShort_t temp;
234   Int_t nFillWords = 0;
235   while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
236   if (nFillWords == 0) {
237     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
238     //    PrintDebug();
239     AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
240     // trying to recover and find the next bunch
241     while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
242     if (temp != 0x2AA) {
243       fCount = fPosition = 0;
244       return kFALSE;
245     }
246     temp = GetNextWord();
247   }
248
249   //Then read the trailer
250   if (fPosition < 5) {
251     fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
252                                                     fPosition));
253     //    PrintDebug();
254     AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
255     fCount = fPosition = 0;
256     return kFALSE;
257   }
258
259   fCount = (temp << 4) & 0x3FF;
260   if ((temp >> 6) != 0xA) {
261     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
262     //    PrintDebug();
263     AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
264     fCount = 0;
265     return kFALSE;
266   }
267
268   temp = GetNextWord();
269   fHWAddress = (temp & 0x3) << 10;
270   if (((temp >> 2) & 0xF) != 0xA) {
271     fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
272     //    PrintDebug();
273     AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
274     fCount = 0;
275     return kFALSE;
276   }
277   fCount |= ((temp & 0x3FF) >> 6);
278   if (fCount == 0) return kFALSE;
279
280   temp = GetNextWord();
281   fHWAddress |= temp;
282
283   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
284
285   return kTRUE;
286 }
287
288 //_____________________________________________________________________________
289 Bool_t AliAltroRawStream::ReadDummyTrailer()
290 {
291   //Read a trailer of 40 bits in the backward reading mode
292   //In case of no mapping is provided, read a dummy trailer
293   UShort_t temp;
294   while ((temp = GetNextWord()) == 0x2AA);
295
296   fSegmentation[0] = temp;
297   fSegmentation[1] = GetNextWord();
298   fSegmentation[2] = GetNextWord();
299   fCount = GetNextWord();
300   if (fCount == 0) return kFALSE;
301   fHWAddress = -1;
302
303   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
304
305   return kTRUE;
306 }
307
308 //_____________________________________________________________________________
309 void AliAltroRawStream::ReadBunch()
310 {
311   // Read altro payload in 
312   // backward direction
313   if (fPosition <= 0) {
314     fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
315     //    PrintDebug();
316     AliWarning("Could not read bunch length !");
317   }
318
319   fBunchLength = GetNextWord() - 2;
320   fTimeBunch = fBunchLength;
321   fCount--;
322
323   if (fPosition <= 0) {
324     fRawReader->AddMinorErrorLog(kTimeBinReadErr,"");
325     //    PrintDebug();
326     AliWarning("Could not read time bin !");
327   }
328
329   fTime = GetNextWord();
330   fCount--;
331
332   return;
333 }
334
335 //_____________________________________________________________________________
336 void AliAltroRawStream::ReadAmplitude()
337 {
338   // Read next time bin amplitude
339   if (fPosition <= 0) {
340     fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
341     //    PrintDebug();
342     AliWarning("Could not read sample amplitude !");
343   }
344
345   fSignal = GetNextWord();
346   fCount--;
347   fBunchLength--;
348
349   return;
350 }
351
352 //_____________________________________________________________________________
353 Int_t AliAltroRawStream::GetPosition()
354 {
355   // Sets the position in the
356   // input stream
357   // Read the RCU trailer
358   // This includes the trailer size,
359   // RCU identifier and raw data payload.
360   // The RCU trailer format is described
361   // in details in the RCU manual.
362
363   if (!fIsOldRCUFormat) {
364     // First read 32-bit word with the
365     // trailer size (22 bits) and RCU ID (the rest)
366     Int_t index = fRawReader->GetDataSize();
367     UInt_t word = Get32bitWord(index);
368     fRCUId = (Int_t)(word >> 22);
369     Int_t trailerSize = (word & 0x3FFFFF);
370
371     // Now read the beginning of the trailer
372     // where the payload size is written
373     if (trailerSize < 2) {
374       PrintDebug();
375       AliFatal(Form("Invalid trailer size found (%d bytes) !",trailerSize*4));
376     }
377     fRCUTrailerSize = (trailerSize-2)*4;
378     index -= fRCUTrailerSize;
379     if (index < 4) {
380       PrintDebug();
381       AliFatal(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
382                     trailerSize*4,
383                     fRawReader->GetDataSize()));
384     }
385     fRCUTrailerData = fData + index;
386     Int_t position = Get32bitWord(index);
387     // The size is specified in a number of 40bits
388     // Therefore we need to transform it to number of bytes
389     position *= 5;
390
391     // Check the consistency of the header and trailer
392     if ((fRawReader->GetDataSize() - trailerSize*4) != position) {
393       PrintDebug();
394       AliFatal(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
395                     fRawReader->GetDataSize(),
396                     trailerSize*4,
397                     position));
398     }
399
400     return position * 8 / 10;
401   }
402   else {
403     // In case of the Old RCU trailer format
404     // we have to read just the size of altro payload
405     // in units of 40-bit words
406     Int_t index = fRawReader->GetDataSize();
407     Int_t position = Get32bitWord(index);
408
409     fRCUId = -1;
410     fRCUTrailerSize = 0;
411     fRCUTrailerData = NULL;
412
413     // The size is specified in a number of 40bits
414     // Therefore we need to transform it to number of bytes
415     position *= 5;
416
417     if (!fIsShortDataHeader) {
418
419       // Check the consistency of the header and trailer
420       if ((fRawReader->GetDataSize() - 4) != position) {
421         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
422                                                              fRawReader->GetDataSize()-4,
423                                                              position));
424         //      PrintDebug();
425         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
426                         fRawReader->GetDataSize()-4,
427                         position));
428         position = fRawReader->GetDataSize()-4;
429       }
430     }
431     else {
432       // Check the consistency of the header and trailer
433       // In this case the header is shorter by 4 bytes
434       if (fRawReader->GetDataSize() != position) {
435         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
436                                                              fRawReader->GetDataSize(),
437                                                              position));
438         //      PrintDebug();
439         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
440                         fRawReader->GetDataSize(),
441                         position));
442         position = fRawReader->GetDataSize();
443       }
444
445       // 7 32-bit words Common Data Header
446       // therefore we have to shift back by 4 bytes
447       // the pointer to the raw data payload
448       fData -= 4;
449     }
450      
451     // Return the position in units of 10-bit words
452     return position*8/10;
453   }
454 }
455
456 //_____________________________________________________________________________
457 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
458 {
459   // This method returns the 32 bit word at a given
460   // position inside the raw data payload.
461   // The 'index' points to the beginning of the next word.
462   // The method is supposed to be endian (platform)
463   // independent.
464   if (!fData) {
465     PrintDebug();
466     AliFatal("Raw data paylod buffer is not yet initialized !");
467   }
468
469   if (index < 4) {
470     fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
471     //    PrintDebug();
472     AliWarning(Form("Invalid raw data payload position (%d) !",index));
473   }
474
475   UInt_t word = 0;
476   word  = fData[--index] << 24;
477   word |= fData[--index] << 16;
478   word |= fData[--index] << 8;
479   word |= fData[--index];
480
481   return word;
482 }
483
484 //_____________________________________________________________________________
485 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
486 {
487   // Return a pointer to the RCU trailer
488   // data. Should be called always after
489   // the RCU trailer was already processed
490   // in the GetPosition() method
491   if (!fRCUTrailerSize || !fRCUTrailerData) {
492     AliError("No valid RCU trailer data is found !");
493     data = NULL;
494     return kFALSE;
495   }
496
497   data = fRCUTrailerData;
498
499   return kTRUE;
500 }
501
502 //_____________________________________________________________________________
503 void AliAltroRawStream::PrintDebug() const
504 {
505   // The method prints all the available
506   // debug information.
507   // Its is used in case of decoding errors.
508
509   AliError("Start of debug printout\n--------------------");
510
511   Dump();
512   if (fRawReader) fRawReader->Dump();
513
514   AliError("End of debug printout\n--------------------");
515 }
516
517 //_____________________________________________________________________________
518 Int_t AliAltroRawStream::GetBranch() const
519 {
520   // The method provides the RCU branch index (0 or 1)
521   // for the current hardware address.
522   // In case the hardware address has not been yet
523   // initialized, the method returns -1
524   if (fHWAddress == -1) return -1;
525
526   return ((fHWAddress >> 11) & 0x1);
527 }
528
529 //_____________________________________________________________________________
530 Int_t AliAltroRawStream::GetFEC() const
531 {
532   // The method provides the front-end card index
533   // for the current hardware address.
534   // In case the hardware address has not been yet
535   // initialized, the method returns -1
536   if (fHWAddress == -1) return -1;
537
538   return ((fHWAddress >> 7) & 0xF);
539 }
540
541 //_____________________________________________________________________________
542 Int_t AliAltroRawStream::GetAltro() const
543 {
544   // The method provides the altro chip index
545   // for the current hardware address.
546   // In case the hardware address has not been yet
547   // initialized, the method returns -1
548   if (fHWAddress == -1) return -1;
549
550   return ((fHWAddress >> 4) & 0x7);
551 }
552
553 //_____________________________________________________________________________
554 Int_t AliAltroRawStream::GetChannel() const
555 {
556   // The method provides the channel index
557   // for the current hardware address.
558   // In case the hardware address has not been yet
559   // initialized, the method returns -1
560   if (fHWAddress == -1) return -1;
561
562   return (fHWAddress & 0xF);
563 }
564
565 //_____________________________________________________________________________
566 void AliAltroRawStream::AddMappingErrorLog(const char *message)
567 {
568   // Signal a mapping error
569   // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
570   // classes in order to log an error related to bad altro mapping
571
572   if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
573 }