]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliAltroRawStream.cxx
RCU data block is always aligned to 32bit, but the altro payload inside is not! So...
[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       fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
375                                                        trailerSize*4));
376       AliWarning(Form("Invalid trailer size found (%d bytes) !",
377                       trailerSize*4));
378     }
379     fRCUTrailerSize = (trailerSize-2)*4;
380     index -= fRCUTrailerSize;
381     if (index < 4) {
382       PrintDebug();
383       AliFatal(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
384                     trailerSize*4,
385                     fRawReader->GetDataSize()));
386     }
387     fRCUTrailerData = fData + index;
388     Int_t position = Get32bitWord(index);
389     // The size is specified in a number of 40bits
390     // Therefore we need to transform it to number of bytes
391     position *= 5;
392
393     // Check the consistency of the header and trailer
394     if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
395         ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
396       fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
397                                                            fRawReader->GetDataSize(),
398                                                            trailerSize*4,
399                                                            position));
400       AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
401                     fRawReader->GetDataSize(),
402                     trailerSize*4,
403                     position));
404       position = fRawReader->GetDataSize() - trailerSize*4;
405     }
406
407     return position * 8 / 10;
408   }
409   else {
410     // In case of the Old RCU trailer format
411     // we have to read just the size of altro payload
412     // in units of 40-bit words
413     Int_t index = fRawReader->GetDataSize();
414     Int_t position = Get32bitWord(index);
415
416     fRCUId = -1;
417     fRCUTrailerSize = 0;
418     fRCUTrailerData = NULL;
419
420     // The size is specified in a number of 40bits
421     // Therefore we need to transform it to number of bytes
422     position *= 5;
423
424     if (!fIsShortDataHeader) {
425
426       // Check the consistency of the header and trailer
427       if (((fRawReader->GetDataSize() - 4) < position) ||
428           ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
429         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
430                                                              fRawReader->GetDataSize()-4,
431                                                              position));
432         //      PrintDebug();
433         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
434                         fRawReader->GetDataSize()-4,
435                         position));
436         position = fRawReader->GetDataSize()-4;
437       }
438     }
439     else {
440       // Check the consistency of the header and trailer
441       // In this case the header is shorter by 4 bytes
442       if ((fRawReader->GetDataSize() < position) ||
443           (fRawReader->GetDataSize() >= (position + 4))) {
444         fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
445                                                              fRawReader->GetDataSize(),
446                                                              position));
447         //      PrintDebug();
448         AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
449                         fRawReader->GetDataSize(),
450                         position));
451         position = fRawReader->GetDataSize();
452       }
453
454       // 7 32-bit words Common Data Header
455       // therefore we have to shift back by 4 bytes
456       // the pointer to the raw data payload
457       fData -= 4;
458     }
459      
460     // Return the position in units of 10-bit words
461     return position*8/10;
462   }
463 }
464
465 //_____________________________________________________________________________
466 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
467 {
468   // This method returns the 32 bit word at a given
469   // position inside the raw data payload.
470   // The 'index' points to the beginning of the next word.
471   // The method is supposed to be endian (platform)
472   // independent.
473   if (!fData) {
474     PrintDebug();
475     AliFatal("Raw data paylod buffer is not yet initialized !");
476   }
477
478   if (index < 4) {
479     fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
480     //    PrintDebug();
481     AliWarning(Form("Invalid raw data payload position (%d) !",index));
482   }
483
484   UInt_t word = 0;
485   word  = fData[--index] << 24;
486   word |= fData[--index] << 16;
487   word |= fData[--index] << 8;
488   word |= fData[--index];
489
490   return word;
491 }
492
493 //_____________________________________________________________________________
494 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
495 {
496   // Return a pointer to the RCU trailer
497   // data. Should be called always after
498   // the RCU trailer was already processed
499   // in the GetPosition() method
500   if (!fRCUTrailerSize || !fRCUTrailerData) {
501     AliError("No valid RCU trailer data is found !");
502     data = NULL;
503     return kFALSE;
504   }
505
506   data = fRCUTrailerData;
507
508   return kTRUE;
509 }
510
511 //_____________________________________________________________________________
512 void AliAltroRawStream::PrintDebug() const
513 {
514   // The method prints all the available
515   // debug information.
516   // Its is used in case of decoding errors.
517
518   AliError("Start of debug printout\n--------------------");
519
520   Dump();
521   if (fRawReader) fRawReader->Dump();
522
523   AliError("End of debug printout\n--------------------");
524 }
525
526 //_____________________________________________________________________________
527 Int_t AliAltroRawStream::GetBranch() const
528 {
529   // The method provides the RCU branch index (0 or 1)
530   // for the current hardware address.
531   // In case the hardware address has not been yet
532   // initialized, the method returns -1
533   if (fHWAddress == -1) return -1;
534
535   return ((fHWAddress >> 11) & 0x1);
536 }
537
538 //_____________________________________________________________________________
539 Int_t AliAltroRawStream::GetFEC() const
540 {
541   // The method provides the front-end card index
542   // for the current hardware address.
543   // In case the hardware address has not been yet
544   // initialized, the method returns -1
545   if (fHWAddress == -1) return -1;
546
547   return ((fHWAddress >> 7) & 0xF);
548 }
549
550 //_____________________________________________________________________________
551 Int_t AliAltroRawStream::GetAltro() const
552 {
553   // The method provides the altro chip index
554   // for the current hardware address.
555   // In case the hardware address has not been yet
556   // initialized, the method returns -1
557   if (fHWAddress == -1) return -1;
558
559   return ((fHWAddress >> 4) & 0x7);
560 }
561
562 //_____________________________________________________________________________
563 Int_t AliAltroRawStream::GetChannel() const
564 {
565   // The method provides the channel index
566   // for the current hardware address.
567   // In case the hardware address has not been yet
568   // initialized, the method returns -1
569   if (fHWAddress == -1) return -1;
570
571   return (fHWAddress & 0xF);
572 }
573
574 //_____________________________________________________________________________
575 void AliAltroRawStream::AddMappingErrorLog(const char *message)
576 {
577   // Signal a mapping error
578   // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
579   // classes in order to log an error related to bad altro mapping
580
581   if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
582 }