]> git.uio.no Git - u/mrichter/AliRoot.git/blame - 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
CommitLineData
3ea47630 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"
3a291af4 31#include "AliLog.h"
3ea47630 32
33ClassImp(AliAltroRawStream)
34
35
36//_____________________________________________________________________________
37AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
e7fd2555 38 fNoAltroMapping(kTRUE),
7e18047e 39 fIsOldRCUFormat(kFALSE),
1e984421 40 fIsShortDataHeader(kFALSE),
e7fd2555 41 fDDLNumber(-1),
42 fPrevDDLNumber(-1),
5e6235b5 43 fRCUId(-1),
44 fPrevRCUId(-1),
3a291af4 45 fHWAddress(-1),
46 fPrevHWAddress(-1),
3ea47630 47 fTime(-1),
e7fd2555 48 fPrevTime(-1),
3ea47630 49 fSignal(-1),
e7fd2555 50 fTimeBunch(-1),
3ea47630 51 fRawReader(rawReader),
52 fData(NULL),
53 fPosition(0),
54 fCount(0),
5e6235b5 55 fBunchLength(0),
56 fRCUTrailerData(NULL),
57 fRCUTrailerSize(0)
3ea47630 58{
59// create an object to read Altro raw digits
e7fd2555 60 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
3ea47630 61}
62
63//_____________________________________________________________________________
64AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
65 TObject(stream),
e7bee78b 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)
3ea47630 86{
e7bee78b 87 fSegmentation[0] = stream.fSegmentation[0];
88 fSegmentation[1] = stream.fSegmentation[1];
89 fSegmentation[2] = stream.fSegmentation[2];
3ea47630 90}
91
92//_____________________________________________________________________________
3820a703 93AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
3ea47630 94{
3820a703 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
3ea47630 122 return *this;
123}
124
125//_____________________________________________________________________________
126AliAltroRawStream::~AliAltroRawStream()
127{
128// clean up
129
130}
131
3a291af4 132//_____________________________________________________________________________
133void AliAltroRawStream::Reset()
134{
135// reset altro raw stream params
136
137 fPosition = fCount = fBunchLength = 0;
138
5e6235b5 139 fRCUTrailerData = NULL;
140 fRCUTrailerSize = 0;
141
142 fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
3a291af4 143
144 if (fRawReader) fRawReader->Reset();
e7fd2555 145
146 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
3a291af4 147}
3ea47630 148
149//_____________________________________________________________________________
150Bool_t AliAltroRawStream::Next()
151{
152// read the next raw digit
153// returns kFALSE if there is no digit left
154
e7fd2555 155 fPrevDDLNumber = fDDLNumber;
5e6235b5 156 fPrevRCUId = fRCUId;
3a291af4 157 fPrevHWAddress = fHWAddress;
e7fd2555 158 fPrevTime = fTime;
3ea47630 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
e7fd2555 166 fDDLNumber = fRawReader->GetDDLID();
167
3a291af4 168 fPosition = GetPosition();
3ea47630 169 }
3ea47630 170
eb09ec9a 171 ReadTrailer();
3ea47630 172
3a291af4 173 fBunchLength = 0;
3ea47630 174 }
175
3a291af4 176 if (fBunchLength == 0) ReadBunch();
177 else fTime--;
178
179 ReadAmplitude();
3ea47630 180
181 return kTRUE;
182}
183
e7fd2555 184//_____________________________________________________________________________
185void 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
362c9d61 193//_____________________________________________________________________________
194void 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
3ea47630 202//_____________________________________________________________________________
3a291af4 203UShort_t AliAltroRawStream::GetNextWord()
3ea47630 204{
3a291af4 205 // Read the next 10 bit word in backward direction
206 // The input stream access is given by fData and fPosition
3ea47630 207
3a291af4 208 fPosition--;
209
210 Int_t iBit = fPosition * 10;
3ea47630 211 Int_t iByte = iBit / 8;
212 Int_t shift = iBit % 8;
3ea47630 213
5e6235b5 214 // the raw data is written as integers where the low bits are filled first
3ea47630 215 // -> little endian is assumed here !
5e6235b5 216 Int_t iByteLow = iByte;
3ea47630 217 iByte++;
5e6235b5 218 Int_t iByteHigh = iByte;
3a291af4 219 return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
220}
221
222//_____________________________________________________________________________
223Bool_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++;
776c3b9c 236 if (nFillWords == 0) {
eb09ec9a 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();
776c3b9c 247 }
3a291af4 248
249 //Then read the trailer
eb09ec9a 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;
776c3b9c 257 }
3a291af4 258
259 fCount = (temp << 4) & 0x3FF;
776c3b9c 260 if ((temp >> 6) != 0xA) {
eb09ec9a 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;
776c3b9c 266 }
3a291af4 267
268 temp = GetNextWord();
269 fHWAddress = (temp & 0x3) << 10;
776c3b9c 270 if (((temp >> 2) & 0xF) != 0xA) {
eb09ec9a 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;
776c3b9c 276 }
3a291af4 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
3a291af4 285 return kTRUE;
286}
287
288//_____________________________________________________________________________
289Bool_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
e7fd2555 296 fSegmentation[0] = temp;
297 fSegmentation[1] = GetNextWord();
298 fSegmentation[2] = GetNextWord();
3a291af4 299 fCount = GetNextWord();
300 if (fCount == 0) return kFALSE;
301 fHWAddress = -1;
302
e7fd2555 303 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
304
3a291af4 305 return kTRUE;
306}
307
308//_____________________________________________________________________________
309void AliAltroRawStream::ReadBunch()
310{
311 // Read altro payload in
312 // backward direction
776c3b9c 313 if (fPosition <= 0) {
eb09ec9a 314 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
315 // PrintDebug();
316 AliWarning("Could not read bunch length !");
776c3b9c 317 }
3a291af4 318
319 fBunchLength = GetNextWord() - 2;
320 fTimeBunch = fBunchLength;
321 fCount--;
322
776c3b9c 323 if (fPosition <= 0) {
eb09ec9a 324 fRawReader->AddMinorErrorLog(kTimeBinReadErr,"");
325 // PrintDebug();
326 AliWarning("Could not read time bin !");
776c3b9c 327 }
3a291af4 328
329 fTime = GetNextWord();
330 fCount--;
331
332 return;
333}
334
335//_____________________________________________________________________________
336void AliAltroRawStream::ReadAmplitude()
337{
338 // Read next time bin amplitude
776c3b9c 339 if (fPosition <= 0) {
eb09ec9a 340 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
341 // PrintDebug();
342 AliWarning("Could not read sample amplitude !");
776c3b9c 343 }
3a291af4 344
345 fSignal = GetNextWord();
346 fCount--;
347 fBunchLength--;
348
349 return;
350}
351
352//_____________________________________________________________________________
353Int_t AliAltroRawStream::GetPosition()
354{
355 // Sets the position in the
356 // input stream
5e6235b5 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
7e18047e 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
776c3b9c 373 if (trailerSize < 2) {
7dcdcfe4 374 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
375 trailerSize*4));
376 AliWarning(Form("Invalid trailer size found (%d bytes) !",
377 trailerSize*4));
776c3b9c 378 }
7e18047e 379 fRCUTrailerSize = (trailerSize-2)*4;
380 index -= fRCUTrailerSize;
776c3b9c 381 if (index < 4) {
382 PrintDebug();
7e18047e 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()));
776c3b9c 386 }
7e18047e 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
7dcdcfe4 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 !",
7e18047e 401 fRawReader->GetDataSize(),
402 trailerSize*4,
403 position));
7dcdcfe4 404 position = fRawReader->GetDataSize() - trailerSize*4;
776c3b9c 405 }
7e18047e 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
1e984421 424 if (!fIsShortDataHeader) {
7e18047e 425
1e984421 426 // Check the consistency of the header and trailer
7dcdcfe4 427 if (((fRawReader->GetDataSize() - 4) < position) ||
428 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
eb09ec9a 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;
776c3b9c 437 }
1e984421 438 }
439 else {
440 // Check the consistency of the header and trailer
441 // In this case the header is shorter by 4 bytes
7dcdcfe4 442 if ((fRawReader->GetDataSize() < position) ||
443 (fRawReader->GetDataSize() >= (position + 4))) {
eb09ec9a 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();
776c3b9c 452 }
1e984421 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
7e18047e 460 // Return the position in units of 10-bit words
461 return position*8/10;
462 }
5e6235b5 463}
464
465//_____________________________________________________________________________
466UInt_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.
776c3b9c 473 if (!fData) {
474 PrintDebug();
5e6235b5 475 AliFatal("Raw data paylod buffer is not yet initialized !");
776c3b9c 476 }
477
478 if (index < 4) {
eb09ec9a 479 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
480 // PrintDebug();
481 AliWarning(Form("Invalid raw data payload position (%d) !",index));
776c3b9c 482 }
5e6235b5 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//_____________________________________________________________________________
494Bool_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;
3ea47630 509}
776c3b9c 510
511//_____________________________________________________________________________
512void 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}
e68dc1cf 525
526//_____________________________________________________________________________
527Int_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//_____________________________________________________________________________
539Int_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//_____________________________________________________________________________
551Int_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//_____________________________________________________________________________
563Int_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}
eb09ec9a 573
574//_____________________________________________________________________________
575void 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}