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) {
375 AliFatal(Form("Invalid trailer size found (%d bytes) !",trailerSize*4));
377 fRCUTrailerSize = (trailerSize-2)*4;
378 index -= fRCUTrailerSize;
381 AliFatal(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
383 fRawReader->GetDataSize()));
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
391 // Check the consistency of the header and trailer
392 if ((fRawReader->GetDataSize() - trailerSize*4) != position) {
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(),
400 return position * 8 / 10;
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);
411 fRCUTrailerData = NULL;
413 // The size is specified in a number of 40bits
414 // Therefore we need to transform it to number of bytes
417 if (!fIsShortDataHeader) {
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,
425 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
426 fRawReader->GetDataSize()-4,
428 position = fRawReader->GetDataSize()-4;
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(),
439 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
440 fRawReader->GetDataSize(),
442 position = fRawReader->GetDataSize();
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
451 // Return the position in units of 10-bit words
452 return position*8/10;
456 //_____________________________________________________________________________
457 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
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)
466 AliFatal("Raw data paylod buffer is not yet initialized !");
470 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
472 AliWarning(Form("Invalid raw data payload position (%d) !",index));
476 word = fData[--index] << 24;
477 word |= fData[--index] << 16;
478 word |= fData[--index] << 8;
479 word |= fData[--index];
484 //_____________________________________________________________________________
485 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
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 !");
497 data = fRCUTrailerData;
502 //_____________________________________________________________________________
503 void AliAltroRawStream::PrintDebug() const
505 // The method prints all the available
506 // debug information.
507 // Its is used in case of decoding errors.
509 AliError("Start of debug printout\n--------------------");
512 if (fRawReader) fRawReader->Dump();
514 AliError("End of debug printout\n--------------------");
517 //_____________________________________________________________________________
518 Int_t AliAltroRawStream::GetBranch() const
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;
526 return ((fHWAddress >> 11) & 0x1);
529 //_____________________________________________________________________________
530 Int_t AliAltroRawStream::GetFEC() const
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;
538 return ((fHWAddress >> 7) & 0xF);
541 //_____________________________________________________________________________
542 Int_t AliAltroRawStream::GetAltro() const
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;
550 return ((fHWAddress >> 4) & 0x7);
553 //_____________________________________________________________________________
554 Int_t AliAltroRawStream::GetChannel() const
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;
562 return (fHWAddress & 0xF);
565 //_____________________________________________________________________________
566 void AliAltroRawStream::AddMappingErrorLog(const char *message)
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
572 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);