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