]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliAltroRawStreamV3.cxx
Update the RCU trailer reading accordingto the RCU frimware V2 user's manual. Thanks...
[u/mrichter/AliRoot.git] / RAW / AliAltroRawStreamV3.cxx
CommitLineData
f8e5b5a0 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///////////////////////////////////////////////////////////////////////////////
17///
18/// This is a base class for reading raw data digits in Altro format.
19/// The class is able to read the RCU v3 and above formats.
20/// The main difference between the format V3 and older ones is in
21/// the coding of the 10-bit Altro payload words. In V3 3 10-bit words
22/// are coded in one 32-bit word. The bits 30 and 31 are used to identify
23/// the payload, altro header and RCU trailer contents.
24///
25///
26/// cvetan.cheshkov@cern.ch 1/04/2009
27///////////////////////////////////////////////////////////////////////////////
28
29#include "AliAltroRawStreamV3.h"
30#include "AliRawReader.h"
31#include "AliLog.h"
32
33ClassImp(AliAltroRawStreamV3)
34
35
36//_____________________________________________________________________________
37AliAltroRawStreamV3::AliAltroRawStreamV3(AliRawReader* rawReader) :
38 fIsShortDataHeader(kFALSE),
39 fDDLNumber(-1),
40 fRCUId(-1),
41 fHWAddress(-1),
42 fRawReader(rawReader),
43 fData(NULL),
44 fPosition(-1),
45 fCount(-1),
46 fStartTimeBin(-1),
47 fBunchLength(-1),
48 fBadChannel(kFALSE),
49 fPayloadSize(-1),
6d4dd848 50 fBunchDataPointer(NULL),
51 fBunchDataIndex(-1),
f8e5b5a0 52 fRCUTrailerData(NULL),
53 fRCUTrailerSize(0),
54 fFECERRA(0),
55 fFECERRB(0),
56 fERRREG2(0),
57 fERRREG3(0),
f8e5b5a0 58 fActiveFECsA(0),
59 fActiveFECsB(0),
60 fAltroCFG1(0),
61 fAltroCFG2(0)
62{
63 // Constructor
64 // Create an object to read Altro raw digits in
65 // RCU version 3 and beyond format
66 for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = 0;
67}
68
69//_____________________________________________________________________________
70AliAltroRawStreamV3::~AliAltroRawStreamV3()
71{
72// destructor
73// nothing to do
74}
75
76//_____________________________________________________________________________
77AliAltroRawStreamV3::AliAltroRawStreamV3(const AliAltroRawStreamV3& stream) :
78 TObject(stream),
79 fIsShortDataHeader(stream.fIsShortDataHeader),
80 fDDLNumber(stream.fDDLNumber),
81 fRCUId(stream.fRCUId),
82 fHWAddress(stream.fHWAddress),
83 fRawReader(stream.fRawReader),
84 fData(stream.fData),
85 fPosition(stream.fPosition),
86 fCount(stream.fCount),
87 fStartTimeBin(stream.fStartTimeBin),
88 fBunchLength(stream.fBunchLength),
89 fBadChannel(stream.fBadChannel),
90 fPayloadSize(stream.fPayloadSize),
6d4dd848 91 fBunchDataPointer(stream.fBunchDataPointer),
92 fBunchDataIndex(stream.fBunchDataIndex),
f8e5b5a0 93 fRCUTrailerData(stream.fRCUTrailerData),
94 fRCUTrailerSize(stream.fRCUTrailerSize),
95 fFECERRA(stream.fFECERRA),
96 fFECERRB(stream.fFECERRB),
97 fERRREG2(stream.fERRREG2),
98 fERRREG3(stream.fERRREG3),
f8e5b5a0 99 fActiveFECsA(stream.fActiveFECsA),
100 fActiveFECsB(stream.fActiveFECsB),
101 fAltroCFG1(stream.fAltroCFG1),
102 fAltroCFG2(stream.fAltroCFG2)
103{
104 // Copy constructor
105 // Copy the bunch data array
106 for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i];
107}
108
109//_____________________________________________________________________________
110AliAltroRawStreamV3& AliAltroRawStreamV3::operator = (const AliAltroRawStreamV3& stream)
111{
112 // assignment operator
113 // ...
114 if(&stream == this) return *this;
115
116 fIsShortDataHeader = stream.fIsShortDataHeader;
117 fDDLNumber = stream.fDDLNumber;
118 fRCUId = stream.fRCUId;
119 fHWAddress = stream.fHWAddress;
120 fRawReader = stream.fRawReader;
121 fData = stream.fData;
122 fPosition = stream.fPosition;
123 fCount = stream.fCount;
124 fStartTimeBin = stream.fStartTimeBin;
125 fBunchLength = stream.fBunchLength;
126 fBadChannel = stream.fBadChannel;
127 fPayloadSize = stream.fPayloadSize;
6d4dd848 128 fBunchDataPointer = stream.fBunchDataPointer;
129 fBunchDataIndex = stream.fBunchDataIndex;
f8e5b5a0 130 fRCUTrailerData = stream.fRCUTrailerData;
131 fRCUTrailerSize = stream.fRCUTrailerSize;
132 fFECERRA = stream.fFECERRA;
133 fFECERRB = stream.fFECERRB;
134 fERRREG2 = stream.fERRREG2;
135 fERRREG3 = stream.fERRREG3;
f8e5b5a0 136 fActiveFECsA = stream.fActiveFECsA;
137 fActiveFECsB = stream.fActiveFECsB;
138 fAltroCFG1 = stream.fAltroCFG1;
139 fAltroCFG2 = stream.fAltroCFG2;
140
141 for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i];
142
143 return *this;
144}
145
146//_____________________________________________________________________________
147void AliAltroRawStreamV3::Reset()
148{
149// Complete reset of raw stream params
150// Reset of the raw-reader as well
151
152 fDDLNumber = fRCUId = fHWAddress = -1;
153 fPosition = fCount = -1;
154 fBunchLength = fStartTimeBin = -1;
155 fBadChannel = kFALSE;
156 fPayloadSize = -1;
6d4dd848 157 fBunchDataPointer = NULL;
158 fBunchDataIndex = -1;
f8e5b5a0 159
160 fRCUTrailerData = NULL;
161 fRCUTrailerSize = 0;
162
9283f3a5 163 fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
f8e5b5a0 164
165 if (fRawReader) fRawReader->Reset();
166
167}
168
169//_____________________________________________________________________________
170Bool_t AliAltroRawStreamV3::NextDDL()
171{
172// Read the next DDL payload (CDH + RCU trailer)
173// Updates the information which is coming from these
174// two sources
175
176 fPosition = 0;
177 // Get next DDL payload
178 // return wtih false in case no more data payloads
179 // are found
180 do {
181 if (!fRawReader->ReadNextData(fData)) return kFALSE;
182 } while (fRawReader->GetDataSize() == 0);
183
184 fDDLNumber = fRawReader->GetDDLID();
185
186 UChar_t rcuVer = fRawReader->GetBlockAttributes();
187
188 if (!ReadRCUTrailer(rcuVer)) return kFALSE;
189
190 return kTRUE;
191}
192
193//_____________________________________________________________________________
194Bool_t AliAltroRawStreamV3::NextChannel()
195{
196 // Read the next Altro channel from the
197 // raw-data stream
198 // Updates the channel hardware address member and
199 // channel data size. Sets the error flag in case
200 // RCU signals readout error in this channel
201 fCount = -1;
202 fBadChannel = kFALSE;
6d4dd848 203 fBunchDataIndex = 0;
f8e5b5a0 204
205 UInt_t word = 0;
206 do {
207 word = Get32bitWord(fPosition++);
6d4dd848 208 if (fPosition > fPayloadSize) return kFALSE;
f8e5b5a0 209 }
6d4dd848 210 while ((word >> 30) != 1);
f8e5b5a0 211
212 // check for readout errors
6d4dd848 213 fBadChannel = (word >> 29) & 0x1;
f8e5b5a0 214
215 // extract channel payload and hw address
6d4dd848 216 fCount = (word >> 16) & 0x3FF;
f8e5b5a0 217 fHWAddress = word & 0xFFF;
218
6d4dd848 219 // Now unpack the altro data
220 // Revert the order of the samples
221 // inside the bunch so that the
222 // first time is first in the samples
223 // array
224 Int_t isample = 0;
225 Int_t nwords = (fCount+2)/3;
226 for (Int_t iword = 0; iword < nwords; iword++) {
227 word = Get32bitWord(fPosition++);
228 if ((word >> 30) != 0) {
229 // Unexpected end of altro channel payload
230 AliWarning(Form("Unexpected end of payload in altro channel payload! Address=0x%x, word=0x%x",
231 fHWAddress,word));
232 fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress));
233 fCount = -1;
234 fPosition--;
235 return kFALSE;
236 }
237 fBunchData[isample++] = (word >> 20) & 0x3FF;
238 fBunchData[isample++] = (word >> 10) & 0x3FF;
239 fBunchData[isample++] = word & 0x3FF;
240 }
241
f8e5b5a0 242 return kTRUE;
243}
244
245//_____________________________________________________________________________
246Bool_t AliAltroRawStreamV3::NextBunch()
247{
248 // Read next altro bunch from the
249 // raw-data stream.
250 // Updates the start/end time-bins
251 // and the array with altro samples
252 fBunchLength = fStartTimeBin = -1;
6d4dd848 253 fBunchDataPointer = NULL;
f8e5b5a0 254
6d4dd848 255 if ((fBunchDataIndex >= fCount) || fBadChannel) return kFALSE;
f8e5b5a0 256
6d4dd848 257 fBunchLength = fBunchData[fBunchDataIndex];
258 if ((fBunchDataIndex + fBunchLength) > fCount) {
f8e5b5a0 259 // Too long bunch detected
6d4dd848 260 AliWarning(Form("Too long bunch detected in Address=0x%x ! Expected <= %d 10-bit words, found %d !",
261 fHWAddress,fCount-fBunchDataIndex,fBunchLength));
f8e5b5a0 262 fRawReader->AddMinorErrorLog(kAltroBunchHeadErr,Form("hw=0x%x",fHWAddress));
263 fCount = fBunchLength = -1;
264 return kFALSE;
265 }
6d4dd848 266 fBunchDataIndex++;
f8e5b5a0 267 fBunchLength -= 2;
268
6d4dd848 269 fStartTimeBin = fBunchData[fBunchDataIndex++];
f8e5b5a0 270
6d4dd848 271 fBunchDataPointer = &fBunchData[fBunchDataIndex];
f8e5b5a0 272
6d4dd848 273 fBunchDataIndex += fBunchLength;
f8e5b5a0 274
275 return kTRUE;
276}
277
278//_____________________________________________________________________________
279UInt_t AliAltroRawStreamV3::Get32bitWord(Int_t index) const
280{
281 // This method returns the 32 bit word at a given
282 // position inside the raw data payload.
283 // The 'index' points to the beginning of the word.
284 // The method is supposed to be endian (platform)
285 // independent.
286
287 index = (index << 2);
288 UInt_t word = 0;
289 word |= fData[index++];
290 word |= fData[index++] << 8;
291 word |= fData[index++] << 16;
292 word |= fData[index++] << 24;
293
294 return word;
295}
296
297///_____________________________________________________________________________
298Bool_t AliAltroRawStreamV3::ReadRCUTrailer(UChar_t rcuVer)
299{
300 // Read the RCU trailer according
301 // to the RCU formware version
302 // specified in CDH
303 // Cross-check with version found in the
304 // trailer
305
306 fRCUTrailerData = NULL;
307 fRCUTrailerSize = 0;
308 fPayloadSize = -1;
309
310 Int_t index = fRawReader->GetDataSize()/4;
311
312 // First read 32-bit word with the
313 // trailer size (7 bits), RCU ID (9 bits) and
314 // RCU firmware version (8 bits?)
315 // The two major bit should be 11 (identifies
316 // the end of the trailer)
317 UInt_t word = Get32bitWord(--index);
318
319 if ((word >> 30) != 3) {
320 fRawReader->AddFatalErrorLog(kRCUTrailerErr,"");
321 AliError("Last RCU trailer word not found!");
322 return kFALSE;
323 }
324
325 UChar_t ver = (word >> 16) & 0xFF;
326 if (ver != rcuVer) {
327 // Wrong RCU firmware version detected
328 fRawReader->AddMajorErrorLog(kRCUVerErr,Form("%d!=%d",
329 ver,rcuVer));
330 AliDebug(1,Form("Wrong RCU firmware version detected: %d != %d",
331 ver,rcuVer));
332 }
333
334 fRCUId = (Int_t)((word >> 7) & 0x1FF);
335 Int_t trailerSize = (word & 0x7F);
336
337 // Now read the beginning of the trailer
338 // where the payload size is written
339 if (trailerSize < 2) {
340 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
341 trailerSize*4));
342 AliWarning(Form("Invalid trailer size found (%d bytes) !",
343 trailerSize*4));
344 return kFALSE;
345 }
346
347 trailerSize -= 2;
348 fRCUTrailerSize = trailerSize*4;
349
350 for (; trailerSize > 0; trailerSize--) {
351 word = Get32bitWord(--index);
352 if ((word >> 30) != 2) {
353 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"missing 10");
354 AliWarning("Missing RCU trailer identifier pattern!");
355 continue;
356 }
357 Int_t parCode = (word >> 26) & 0xF;
358 Int_t parData = word & 0x3FFFFFF;
359 switch (parCode) {
360 case 1:
361 // ERR_REG1
362 fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
363 fFECERRB = ((parData & 0x1FFF)) << 7;
364 break;
365 case 2:
366 // ERR_REG2
367 fERRREG2 = parData & 0x1FF;
368 break;
369 case 3:
370 // ERR_REG3
9283f3a5 371 fERRREG3 = parData & 0x1FFFFFF;
f8e5b5a0 372 break;
373 case 4:
f8e5b5a0 374 // FEC_RO_A
375 fActiveFECsA = parData & 0xFFFF;
376 break;
9283f3a5 377 case 5:
f8e5b5a0 378 // FEC_RO_B
379 fActiveFECsB = parData & 0xFFFF;
380 break;
9283f3a5 381 case 6:
f8e5b5a0 382 // RDO_CFG1
383 fAltroCFG1 = parData & 0xFFFFF;
384 break;
9283f3a5 385 case 7:
f8e5b5a0 386 // RDO_CFG2
387 fAltroCFG2 = parData & 0x1FFFFFF;
388 break;
389 default:
390 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
391 AliWarning(Form("Undefined parameter code %d, ignore it !",
392 parCode));
393 break;
394 }
395 }
396
397 if (index < 1) {
398 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
399 fRCUTrailerSize+8,
400 fRawReader->GetDataSize()));
401 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
402 fRCUTrailerSize,
403 fRawReader->GetDataSize()));
404 }
405
406 fRCUTrailerData = fData + index*4;
407
408 // Now read the payload size
409 // (First word in the RCU trailer)
410 fPayloadSize = Get32bitWord(--index) & 0x3FFFFFF;
411
412 if ((fRawReader->GetDataSize() - fRCUTrailerSize - 8) != (fPayloadSize*4)) {
413 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
414 fRawReader->GetDataSize(),
415 fRCUTrailerSize+8,
416 fPayloadSize*4));
417 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from CDH), RCU trailer - %d bytes, raw data size (from RCU trailer) - %d bytes !",
418 fRawReader->GetDataSize(),
419 fRCUTrailerSize+8,
420 fPayloadSize*4));
421 }
422
423 return kTRUE;
424}
425
426//_____________________________________________________________________________
427Int_t AliAltroRawStreamV3::GetBranch() const
428{
429 // The method provides the RCU branch index (0 or 1)
430 // for the current hardware address.
431 // In case the hardware address has not been yet
432 // initialized, the method returns -1
433 if (fHWAddress == -1) return -1;
434
435 return ((fHWAddress >> 11) & 0x1);
436}
437
438//_____________________________________________________________________________
439Int_t AliAltroRawStreamV3::GetFEC() const
440{
441 // The method provides the front-end card index
442 // for the current hardware address.
443 // In case the hardware address has not been yet
444 // initialized, the method returns -1
445 if (fHWAddress == -1) return -1;
446
447 return ((fHWAddress >> 7) & 0xF);
448}
449
450//_____________________________________________________________________________
451Int_t AliAltroRawStreamV3::GetAltro() const
452{
453 // The method provides the altro chip index
454 // for the current hardware address.
455 // In case the hardware address has not been yet
456 // initialized, the method returns -1
457 if (fHWAddress == -1) return -1;
458
459 return ((fHWAddress >> 4) & 0x7);
460}
461
462//_____________________________________________________________________________
463Int_t AliAltroRawStreamV3::GetChannel() const
464{
465 // The method provides the channel index
466 // for the current hardware address.
467 // In case the hardware address has not been yet
468 // initialized, the method returns -1
469 if (fHWAddress == -1) return -1;
470
471 return (fHWAddress & 0xF);
472}
473
474//_____________________________________________________________________________
475Bool_t AliAltroRawStreamV3::GetRCUTrailerData(UChar_t*& data) const
476{
477 // Return a pointer to the RCU trailer
478 // data. Should be called always after
479 // the RCU trailer was already processed
480 // in the GetPosition() method
481 if (!fRCUTrailerSize || !fRCUTrailerData) {
482 AliError("No valid RCU trailer data is found !");
483 data = NULL;
484 return kFALSE;
485 }
486
487 data = fRCUTrailerData;
488
489 return kTRUE;
490}
491
492//_____________________________________________________________________________
493void AliAltroRawStreamV3::PrintRCUTrailer() const
494{
495 // Prints the contents of
496 // the RCU trailer data
497 printf("RCU trailer:\n===========\n");
498 printf("FECERRA: 0x%x\nFECERRB: 0x%x\n",fFECERRA,fFECERRB);
499 printf("ERRREG2: 0x%x\n",fERRREG2);
500 printf("#channels skipped due to address mismatch: %d\n",GetNChAddrMismatch());
501 printf("#channels skipped due to bad block length: %d\n",GetNChLengthMismatch());
502 printf("Active FECs (branch A): 0x%x\nActive FECs (branch B): 0x%x\n",fActiveFECsA,fActiveFECsB);
503 printf("Baseline corr: 0x%x\n",GetBaselineCorr());
504 printf("Number of presamples: %d\nNumber of postsamples: %d\n",GetNPresamples(),GetNPostsamples());
505 printf("Second baseline corr: %d\n",GetSecondBaselineCorr());
506 printf("GlitchFilter: %d\n",GetGlitchFilter());
507 printf("Number of non-ZS postsamples: %d\nNumber of non-ZS presamples: %d\n",GetNNonZSPostsamples(),GetNNonZSPresamples());
508 printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers());
509 printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples());
510 printf("Number of samples per channel: %d\n",GetNSamplesPerCh());
511 printf("Sparse readout: %d\n",GetSparseRO());
512 printf("Sampling time: %e s\n",GetTSample());
513 printf("L1 Phase: %e s\n",GetL1Phase());
514 printf("AltroCFG1: 0x%x\nAltroCFG2: 0x%x\n",GetAltroCFG1(),GetAltroCFG2());
515 printf("===========\n");
516}
517
518//_____________________________________________________________________________
519void AliAltroRawStreamV3::SelectRawData(Int_t detId)
520{
521 // Select the raw data for specific
522 // detector id
523 AliDebug(1,Form("Selecting raw data for detector %d",detId));
524 fRawReader->Select(detId);
525}
526
527//_____________________________________________________________________________
528void AliAltroRawStreamV3::SelectRawData(const char *detName)
529{
530 // Select the raw data for specific
531 // detector name
532 AliDebug(1,Form("Selecting raw data for detector %s",detName));
533 fRawReader->Select(detName);
534}
535
536//_____________________________________________________________________________
537Double_t AliAltroRawStreamV3::GetTSample() const
538{
539 // Returns the sampling time
540 // in seconds. In case the rcu trailer
541 // was note read, return an invalid number (0)
542
543 if (!fRCUTrailerData) return 0.;
544
545 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
546 UChar_t fq = (fAltroCFG2 >> 5) & 0xF;
547 Double_t tSample;
548 switch (fq) {
549 case 0:
550 // 20 MHz
551 tSample = 2.0*kLHCTimeSample;
552 break;
553 case 1:
554 // 10 Mhz
555 tSample = 4.0*kLHCTimeSample;
556 break;
557 case 2:
558 // 5 MHz
559 tSample = 8.0*kLHCTimeSample;
560 break;
561 default:
562 AliWarning(Form("Invalid sampling frequency value %d !",
563 fq));
564 tSample = 0.;
565 break;
566 }
567
568 return tSample;
569}
570
571//_____________________________________________________________________________
572Double_t AliAltroRawStreamV3::GetL1Phase() const
573{
574 // Returns the L1 phase w.r.t to the
575 // LHC clock
576 if (!fRCUTrailerData) return 0.;
577
578 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
579 Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample;
580
581 Double_t tSample = GetTSample();
582 if (phase >= tSample) {
583 AliWarning(Form("Invalid L1 trigger phase (%f >= %d) !",
584 phase,tSample));
585 phase = 0.;
586 }
587
588 return phase;
589}
590
591//_____________________________________________________________________________
592void AliAltroRawStreamV3::AddMappingErrorLog(const char *message)
593{
594 // Signal a mapping error
595 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
596 // classes in order to log an error related to bad altro mapping
597
598 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);
599}