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