1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 /// This class provides access to Altro digits in raw data.
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.
27 ///////////////////////////////////////////////////////////////////////////////
29 #include "AliAltroRawStream.h"
30 #include "AliRawReader.h"
33 ClassImp(AliAltroRawStream)
36 //_____________________________________________________________________________
37 AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
38 fNoAltroMapping(kTRUE),
39 fIsOldRCUFormat(kFALSE),
40 fIsShortDataHeader(kFALSE),
51 fRawReader(rawReader),
56 fRCUTrailerData(NULL),
59 // create an object to read Altro raw digits
60 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
63 //_____________________________________________________________________________
64 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& 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),
76 fPrevTime(stream.fPrevTime),
77 fSignal(stream.fSignal),
78 fTimeBunch(stream.fTimeBunch),
79 fRawReader(stream.fRawReader),
81 fPosition(stream.fPosition),
82 fCount(stream.fCount),
83 fBunchLength(stream.fBunchLength),
84 fRCUTrailerData(stream.fRCUTrailerData),
85 fRCUTrailerSize(stream.fRCUTrailerSize)
87 fSegmentation[0] = stream.fSegmentation[0];
88 fSegmentation[1] = stream.fSegmentation[1];
89 fSegmentation[2] = stream.fSegmentation[2];
92 //_____________________________________________________________________________
93 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
95 if(&stream == this) return *this;
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;
118 fSegmentation[0] = stream.fSegmentation[0];
119 fSegmentation[1] = stream.fSegmentation[1];
120 fSegmentation[2] = stream.fSegmentation[2];
125 //_____________________________________________________________________________
126 AliAltroRawStream::~AliAltroRawStream()
132 //_____________________________________________________________________________
133 void AliAltroRawStream::Reset()
135 // reset altro raw stream params
137 fPosition = fCount = fBunchLength = 0;
139 fRCUTrailerData = NULL;
142 fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
144 if (fRawReader) fRawReader->Reset();
146 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
149 //_____________________________________________________________________________
150 Bool_t AliAltroRawStream::Next()
152 // read the next raw digit
153 // returns kFALSE if there is no digit left
155 fPrevDDLNumber = fDDLNumber;
157 fPrevHWAddress = fHWAddress;
160 while (fCount == 0) { // next trailer
161 if (fPosition <= 0) { // next payload
163 if (!fRawReader->ReadNextData(fData)) return kFALSE;
164 } while (fRawReader->GetDataSize() == 0);
166 fDDLNumber = fRawReader->GetDDLID();
168 fPosition = GetPosition();
176 if (fBunchLength == 0) ReadBunch();
184 //_____________________________________________________________________________
185 void AliAltroRawStream::SelectRawData(Int_t detId)
187 // Select the raw data for specific
189 AliDebug(1,Form("Selecting raw data for detector %d",detId));
190 fRawReader->Select(detId);
193 //_____________________________________________________________________________
194 void AliAltroRawStream::SelectRawData(const char *detName)
196 // Select the raw data for specific
198 AliDebug(1,Form("Selecting raw data for detector %s",detName));
199 fRawReader->Select(detName);
202 //_____________________________________________________________________________
203 UShort_t AliAltroRawStream::GetNextWord()
205 // Read the next 10 bit word in backward direction
206 // The input stream access is given by fData and fPosition
210 Int_t iBit = fPosition * 10;
211 Int_t iByte = iBit / 8;
212 Int_t shift = iBit % 8;
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;
218 Int_t iByteHigh = iByte;
219 return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
222 //_____________________________________________________________________________
223 Bool_t AliAltroRawStream::ReadTrailer()
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();
232 //First reading filling words
234 Int_t nFillWords = 0;
235 while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
236 if (nFillWords == 0) {
237 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
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();
243 fCount = fPosition = 0;
246 temp = GetNextWord();
249 //Then read the trailer
251 fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
254 AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
255 fCount = fPosition = 0;
259 fCount = (temp << 4) & 0x3FF;
260 if ((temp >> 6) != 0xA) {
261 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
263 AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
268 temp = GetNextWord();
269 fHWAddress = (temp & 0x3) << 10;
270 if (((temp >> 2) & 0xF) != 0xA) {
271 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
273 AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
277 fCount |= ((temp & 0x3FF) >> 6);
278 if (fCount == 0) return kFALSE;
279 if (fCount >= fPosition) {
280 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
282 AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
286 temp = GetNextWord();
289 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
294 //_____________________________________________________________________________
295 Bool_t AliAltroRawStream::ReadDummyTrailer()
297 //Read a trailer of 40 bits in the backward reading mode
298 //In case of no mapping is provided, read a dummy trailer
300 while ((temp = GetNextWord()) == 0x2AA);
302 fSegmentation[0] = temp;
303 fSegmentation[1] = GetNextWord();
304 fSegmentation[2] = GetNextWord();
305 fCount = GetNextWord();
306 if (fCount == 0) return kFALSE;
309 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
314 //_____________________________________________________________________________
315 void AliAltroRawStream::ReadBunch()
317 // Read altro payload in
318 // backward direction
320 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
322 AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
323 fBunchLength = fTimeBunch = fCount = 0;
327 fBunchLength = GetNextWord() - 2;
328 if (fBunchLength > fCount) {
329 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
331 AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
332 fBunchLength = fTimeBunch = fCount = 0;
335 fTimeBunch = fBunchLength;
338 fTime = GetNextWord();
344 //_____________________________________________________________________________
345 void AliAltroRawStream::ReadAmplitude()
347 // Read next time bin amplitude
349 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
351 AliWarning("Could not read sample amplitude !");
352 fCount = fSignal = fBunchLength = 0;
356 fSignal = GetNextWord();
364 //_____________________________________________________________________________
365 Int_t AliAltroRawStream::GetPosition()
367 // Sets the position in the
369 // Read the RCU trailer
370 // This includes the trailer size,
371 // RCU identifier and raw data payload.
372 // The RCU trailer format is described
373 // in details in the RCU manual.
375 if (!fIsOldRCUFormat) {
376 // First read 32-bit word with the
377 // trailer size (22 bits) and RCU ID (the rest)
378 Int_t index = fRawReader->GetDataSize();
379 UInt_t word = Get32bitWord(index);
380 fRCUId = (Int_t)(word >> 22);
381 Int_t trailerSize = (word & 0x3FFFFF);
383 // Now read the beginning of the trailer
384 // where the payload size is written
385 if (trailerSize < 2) {
386 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
388 AliWarning(Form("Invalid trailer size found (%d bytes) !",
391 fRCUTrailerSize = (trailerSize-2)*4;
392 index -= fRCUTrailerSize;
394 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
396 fRawReader->GetDataSize()));
397 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
399 fRawReader->GetDataSize()));
401 fRCUTrailerData = fData + index;
402 Int_t position = Get32bitWord(index);
403 // The size is specified in a number of 40bits
404 // Therefore we need to transform it to number of bytes
407 // Check the consistency of the header and trailer
408 if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
409 ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
410 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
411 fRawReader->GetDataSize(),
414 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
415 fRawReader->GetDataSize(),
418 position = fRawReader->GetDataSize() - trailerSize*4;
421 return position * 8 / 10;
424 // In case of the Old RCU trailer format
425 // we have to read just the size of altro payload
426 // in units of 40-bit words
427 Int_t index = fRawReader->GetDataSize();
428 Int_t position = Get32bitWord(index);
432 fRCUTrailerData = NULL;
434 // The size is specified in a number of 40bits
435 // Therefore we need to transform it to number of bytes
438 if (!fIsShortDataHeader) {
440 // Check the consistency of the header and trailer
441 if (((fRawReader->GetDataSize() - 4) < position) ||
442 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
443 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
444 fRawReader->GetDataSize()-4,
447 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
448 fRawReader->GetDataSize()-4,
450 position = fRawReader->GetDataSize()-4;
454 // Check the consistency of the header and trailer
455 // In this case the header is shorter by 4 bytes
456 if ((fRawReader->GetDataSize() < position) ||
457 (fRawReader->GetDataSize() >= (position + 4))) {
458 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
459 fRawReader->GetDataSize(),
462 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
463 fRawReader->GetDataSize(),
465 position = fRawReader->GetDataSize();
468 // 7 32-bit words Common Data Header
469 // therefore we have to shift back by 4 bytes
470 // the pointer to the raw data payload
474 // Return the position in units of 10-bit words
475 return position*8/10;
479 //_____________________________________________________________________________
480 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
482 // This method returns the 32 bit word at a given
483 // position inside the raw data payload.
484 // The 'index' points to the beginning of the next word.
485 // The method is supposed to be endian (platform)
489 AliFatal("Raw data paylod buffer is not yet initialized !");
493 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
495 AliWarning(Form("Invalid raw data payload position (%d) !",index));
499 word = fData[--index] << 24;
500 word |= fData[--index] << 16;
501 word |= fData[--index] << 8;
502 word |= fData[--index];
507 //_____________________________________________________________________________
508 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
510 // Return a pointer to the RCU trailer
511 // data. Should be called always after
512 // the RCU trailer was already processed
513 // in the GetPosition() method
514 if (!fRCUTrailerSize || !fRCUTrailerData) {
515 AliError("No valid RCU trailer data is found !");
520 data = fRCUTrailerData;
525 //_____________________________________________________________________________
526 void AliAltroRawStream::PrintDebug() const
528 // The method prints all the available
529 // debug information.
530 // Its is used in case of decoding errors.
532 AliError("Start of debug printout\n--------------------");
535 if (fRawReader) fRawReader->Dump();
537 AliError("End of debug printout\n--------------------");
540 //_____________________________________________________________________________
541 Int_t AliAltroRawStream::GetBranch() const
543 // The method provides the RCU branch index (0 or 1)
544 // for the current hardware address.
545 // In case the hardware address has not been yet
546 // initialized, the method returns -1
547 if (fHWAddress == -1) return -1;
549 return ((fHWAddress >> 11) & 0x1);
552 //_____________________________________________________________________________
553 Int_t AliAltroRawStream::GetFEC() const
555 // The method provides the front-end card index
556 // for the current hardware address.
557 // In case the hardware address has not been yet
558 // initialized, the method returns -1
559 if (fHWAddress == -1) return -1;
561 return ((fHWAddress >> 7) & 0xF);
564 //_____________________________________________________________________________
565 Int_t AliAltroRawStream::GetAltro() const
567 // The method provides the altro chip index
568 // for the current hardware address.
569 // In case the hardware address has not been yet
570 // initialized, the method returns -1
571 if (fHWAddress == -1) return -1;
573 return ((fHWAddress >> 4) & 0x7);
576 //_____________________________________________________________________________
577 Int_t AliAltroRawStream::GetChannel() const
579 // The method provides the channel index
580 // for the current hardware address.
581 // In case the hardware address has not been yet
582 // initialized, the method returns -1
583 if (fHWAddress == -1) return -1;
585 return (fHWAddress & 0xF);
588 //_____________________________________________________________________________
589 void AliAltroRawStream::AddMappingErrorLog(const char *message)
591 // Signal a mapping error
592 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
593 // classes in order to log an error related to bad altro mapping
595 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);