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;
280 temp = GetNextWord();
283 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
288 //_____________________________________________________________________________
289 Bool_t AliAltroRawStream::ReadDummyTrailer()
291 //Read a trailer of 40 bits in the backward reading mode
292 //In case of no mapping is provided, read a dummy trailer
294 while ((temp = GetNextWord()) == 0x2AA);
296 fSegmentation[0] = temp;
297 fSegmentation[1] = GetNextWord();
298 fSegmentation[2] = GetNextWord();
299 fCount = GetNextWord();
300 if (fCount == 0) return kFALSE;
303 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
308 //_____________________________________________________________________________
309 void AliAltroRawStream::ReadBunch()
311 // Read altro payload in
312 // backward direction
313 if (fPosition <= 0) {
314 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
316 AliWarning("Could not read bunch length !");
319 fBunchLength = GetNextWord() - 2;
320 fTimeBunch = fBunchLength;
323 if (fPosition <= 0) {
324 fRawReader->AddMinorErrorLog(kTimeBinReadErr,"");
326 AliWarning("Could not read time bin !");
329 fTime = GetNextWord();
335 //_____________________________________________________________________________
336 void AliAltroRawStream::ReadAmplitude()
338 // Read next time bin amplitude
339 if (fPosition <= 0) {
340 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
342 AliWarning("Could not read sample amplitude !");
345 fSignal = GetNextWord();
352 //_____________________________________________________________________________
353 Int_t AliAltroRawStream::GetPosition()
355 // Sets the position in the
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.
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);
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",
376 AliWarning(Form("Invalid trailer size found (%d bytes) !",
379 fRCUTrailerSize = (trailerSize-2)*4;
380 index -= fRCUTrailerSize;
382 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
384 fRawReader->GetDataSize()));
385 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
387 fRawReader->GetDataSize()));
389 fRCUTrailerData = fData + index;
390 Int_t position = Get32bitWord(index);
391 // The size is specified in a number of 40bits
392 // Therefore we need to transform it to number of bytes
395 // Check the consistency of the header and trailer
396 if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
397 ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
398 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
399 fRawReader->GetDataSize(),
402 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
403 fRawReader->GetDataSize(),
406 position = fRawReader->GetDataSize() - trailerSize*4;
409 return position * 8 / 10;
412 // In case of the Old RCU trailer format
413 // we have to read just the size of altro payload
414 // in units of 40-bit words
415 Int_t index = fRawReader->GetDataSize();
416 Int_t position = Get32bitWord(index);
420 fRCUTrailerData = NULL;
422 // The size is specified in a number of 40bits
423 // Therefore we need to transform it to number of bytes
426 if (!fIsShortDataHeader) {
428 // Check the consistency of the header and trailer
429 if (((fRawReader->GetDataSize() - 4) < position) ||
430 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
431 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
432 fRawReader->GetDataSize()-4,
435 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
436 fRawReader->GetDataSize()-4,
438 position = fRawReader->GetDataSize()-4;
442 // Check the consistency of the header and trailer
443 // In this case the header is shorter by 4 bytes
444 if ((fRawReader->GetDataSize() < position) ||
445 (fRawReader->GetDataSize() >= (position + 4))) {
446 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
447 fRawReader->GetDataSize(),
450 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
451 fRawReader->GetDataSize(),
453 position = fRawReader->GetDataSize();
456 // 7 32-bit words Common Data Header
457 // therefore we have to shift back by 4 bytes
458 // the pointer to the raw data payload
462 // Return the position in units of 10-bit words
463 return position*8/10;
467 //_____________________________________________________________________________
468 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
470 // This method returns the 32 bit word at a given
471 // position inside the raw data payload.
472 // The 'index' points to the beginning of the next word.
473 // The method is supposed to be endian (platform)
477 AliFatal("Raw data paylod buffer is not yet initialized !");
481 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
483 AliWarning(Form("Invalid raw data payload position (%d) !",index));
487 word = fData[--index] << 24;
488 word |= fData[--index] << 16;
489 word |= fData[--index] << 8;
490 word |= fData[--index];
495 //_____________________________________________________________________________
496 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
498 // Return a pointer to the RCU trailer
499 // data. Should be called always after
500 // the RCU trailer was already processed
501 // in the GetPosition() method
502 if (!fRCUTrailerSize || !fRCUTrailerData) {
503 AliError("No valid RCU trailer data is found !");
508 data = fRCUTrailerData;
513 //_____________________________________________________________________________
514 void AliAltroRawStream::PrintDebug() const
516 // The method prints all the available
517 // debug information.
518 // Its is used in case of decoding errors.
520 AliError("Start of debug printout\n--------------------");
523 if (fRawReader) fRawReader->Dump();
525 AliError("End of debug printout\n--------------------");
528 //_____________________________________________________________________________
529 Int_t AliAltroRawStream::GetBranch() const
531 // The method provides the RCU branch index (0 or 1)
532 // for the current hardware address.
533 // In case the hardware address has not been yet
534 // initialized, the method returns -1
535 if (fHWAddress == -1) return -1;
537 return ((fHWAddress >> 11) & 0x1);
540 //_____________________________________________________________________________
541 Int_t AliAltroRawStream::GetFEC() const
543 // The method provides the front-end card index
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 >> 7) & 0xF);
552 //_____________________________________________________________________________
553 Int_t AliAltroRawStream::GetAltro() const
555 // The method provides the altro chip 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 >> 4) & 0x7);
564 //_____________________________________________________________________________
565 Int_t AliAltroRawStream::GetChannel() const
567 // The method provides the channel 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 & 0xF);
576 //_____________________________________________________________________________
577 void AliAltroRawStream::AddMappingErrorLog(const char *message)
579 // Signal a mapping error
580 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
581 // classes in order to log an error related to bad altro mapping
583 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);