]>
Commit | Line | Data |
---|---|---|
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" | |
0148e633 | 32 | #include "AliAltroRawStream.h" |
eae29211 | 33 | #include "AliRawEventHeaderBase.h" |
f8e5b5a0 | 34 | |
35 | ClassImp(AliAltroRawStreamV3) | |
36 | ||
37 | ||
38 | //_____________________________________________________________________________ | |
39 | AliAltroRawStreamV3::AliAltroRawStreamV3(AliRawReader* rawReader) : | |
40 | fIsShortDataHeader(kFALSE), | |
41 | fDDLNumber(-1), | |
42 | fRCUId(-1), | |
43 | fHWAddress(-1), | |
44 | fRawReader(rawReader), | |
45 | fData(NULL), | |
8e9fa05e | 46 | fChannelStartPos(-1), |
f8e5b5a0 | 47 | fPosition(-1), |
48 | fCount(-1), | |
49 | fStartTimeBin(-1), | |
50 | fBunchLength(-1), | |
51 | fBadChannel(kFALSE), | |
52 | fPayloadSize(-1), | |
e76a0935 | 53 | fChannelPayloadSize(-1), |
6d4dd848 | 54 | fBunchDataPointer(NULL), |
55 | fBunchDataIndex(-1), | |
f8e5b5a0 | 56 | fRCUTrailerData(NULL), |
57 | fRCUTrailerSize(0), | |
58 | fFECERRA(0), | |
59 | fFECERRB(0), | |
60 | fERRREG2(0), | |
61 | fERRREG3(0), | |
f8e5b5a0 | 62 | fActiveFECsA(0), |
63 | fActiveFECsB(0), | |
64 | fAltroCFG1(0), | |
0148e633 | 65 | fAltroCFG2(0), |
3ce326c0 | 66 | fOldStream(NULL), |
38f5da76 | 67 | fCheckAltroPayload(kTRUE), |
68 | fFormatVersion(0) | |
f8e5b5a0 | 69 | { |
70 | // Constructor | |
71 | // Create an object to read Altro raw digits in | |
72 | // RCU version 3 and beyond format | |
73 | for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = 0; | |
74 | } | |
75 | ||
76 | //_____________________________________________________________________________ | |
77 | AliAltroRawStreamV3::~AliAltroRawStreamV3() | |
78 | { | |
79 | // destructor | |
0148e633 | 80 | // delete old stream object if one exists |
81 | if (fOldStream) delete fOldStream; | |
f8e5b5a0 | 82 | } |
83 | ||
84 | //_____________________________________________________________________________ | |
85 | AliAltroRawStreamV3::AliAltroRawStreamV3(const AliAltroRawStreamV3& stream) : | |
86 | TObject(stream), | |
87 | fIsShortDataHeader(stream.fIsShortDataHeader), | |
88 | fDDLNumber(stream.fDDLNumber), | |
89 | fRCUId(stream.fRCUId), | |
90 | fHWAddress(stream.fHWAddress), | |
91 | fRawReader(stream.fRawReader), | |
92 | fData(stream.fData), | |
8e9fa05e | 93 | fChannelStartPos(stream.fChannelStartPos), |
f8e5b5a0 | 94 | fPosition(stream.fPosition), |
95 | fCount(stream.fCount), | |
96 | fStartTimeBin(stream.fStartTimeBin), | |
97 | fBunchLength(stream.fBunchLength), | |
98 | fBadChannel(stream.fBadChannel), | |
99 | fPayloadSize(stream.fPayloadSize), | |
e76a0935 | 100 | fChannelPayloadSize(stream.fChannelPayloadSize), |
6d4dd848 | 101 | fBunchDataPointer(stream.fBunchDataPointer), |
102 | fBunchDataIndex(stream.fBunchDataIndex), | |
f8e5b5a0 | 103 | fRCUTrailerData(stream.fRCUTrailerData), |
104 | fRCUTrailerSize(stream.fRCUTrailerSize), | |
105 | fFECERRA(stream.fFECERRA), | |
106 | fFECERRB(stream.fFECERRB), | |
107 | fERRREG2(stream.fERRREG2), | |
108 | fERRREG3(stream.fERRREG3), | |
f8e5b5a0 | 109 | fActiveFECsA(stream.fActiveFECsA), |
110 | fActiveFECsB(stream.fActiveFECsB), | |
111 | fAltroCFG1(stream.fAltroCFG1), | |
0148e633 | 112 | fAltroCFG2(stream.fAltroCFG2), |
3ce326c0 | 113 | fOldStream(NULL), |
38f5da76 | 114 | fCheckAltroPayload(stream.fCheckAltroPayload), |
115 | fFormatVersion(0) | |
f8e5b5a0 | 116 | { |
117 | // Copy constructor | |
118 | // Copy the bunch data array | |
119 | for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i]; | |
0148e633 | 120 | |
121 | if (stream.fOldStream) | |
122 | fOldStream = new AliAltroRawStream(*stream.fOldStream); | |
f8e5b5a0 | 123 | } |
124 | ||
125 | //_____________________________________________________________________________ | |
126 | AliAltroRawStreamV3& AliAltroRawStreamV3::operator = (const AliAltroRawStreamV3& stream) | |
127 | { | |
128 | // assignment operator | |
129 | // ... | |
130 | if(&stream == this) return *this; | |
131 | ||
132 | fIsShortDataHeader = stream.fIsShortDataHeader; | |
133 | fDDLNumber = stream.fDDLNumber; | |
134 | fRCUId = stream.fRCUId; | |
135 | fHWAddress = stream.fHWAddress; | |
136 | fRawReader = stream.fRawReader; | |
137 | fData = stream.fData; | |
8e9fa05e | 138 | fChannelStartPos = stream.fChannelStartPos; |
f8e5b5a0 | 139 | fPosition = stream.fPosition; |
140 | fCount = stream.fCount; | |
141 | fStartTimeBin = stream.fStartTimeBin; | |
142 | fBunchLength = stream.fBunchLength; | |
143 | fBadChannel = stream.fBadChannel; | |
144 | fPayloadSize = stream.fPayloadSize; | |
e76a0935 | 145 | fChannelPayloadSize= stream.fChannelPayloadSize; |
6d4dd848 | 146 | fBunchDataPointer = stream.fBunchDataPointer; |
147 | fBunchDataIndex = stream.fBunchDataIndex; | |
f8e5b5a0 | 148 | fRCUTrailerData = stream.fRCUTrailerData; |
149 | fRCUTrailerSize = stream.fRCUTrailerSize; | |
150 | fFECERRA = stream.fFECERRA; | |
151 | fFECERRB = stream.fFECERRB; | |
152 | fERRREG2 = stream.fERRREG2; | |
153 | fERRREG3 = stream.fERRREG3; | |
f8e5b5a0 | 154 | fActiveFECsA = stream.fActiveFECsA; |
155 | fActiveFECsB = stream.fActiveFECsB; | |
156 | fAltroCFG1 = stream.fAltroCFG1; | |
157 | fAltroCFG2 = stream.fAltroCFG2; | |
38f5da76 | 158 | fFormatVersion = stream.fFormatVersion; |
f8e5b5a0 | 159 | |
160 | for(Int_t i = 0; i < kMaxNTimeBins; i++) fBunchData[i] = stream.fBunchData[i]; | |
161 | ||
0148e633 | 162 | if (stream.fOldStream) { |
163 | if (fOldStream) delete fOldStream; | |
164 | fOldStream = new AliAltroRawStream(stream.fRawReader); | |
165 | *fOldStream = *stream.fOldStream; | |
166 | } | |
167 | ||
3ce326c0 | 168 | fCheckAltroPayload = stream.fCheckAltroPayload; |
169 | ||
f8e5b5a0 | 170 | return *this; |
171 | } | |
172 | ||
173 | //_____________________________________________________________________________ | |
174 | void AliAltroRawStreamV3::Reset() | |
175 | { | |
176 | // Complete reset of raw stream params | |
177 | // Reset of the raw-reader as well | |
178 | ||
179 | fDDLNumber = fRCUId = fHWAddress = -1; | |
8e9fa05e | 180 | fChannelStartPos = -1; |
f8e5b5a0 | 181 | fPosition = fCount = -1; |
182 | fBunchLength = fStartTimeBin = -1; | |
183 | fBadChannel = kFALSE; | |
184 | fPayloadSize = -1; | |
e76a0935 | 185 | fChannelPayloadSize = -1; |
6d4dd848 | 186 | fBunchDataPointer = NULL; |
187 | fBunchDataIndex = -1; | |
f8e5b5a0 | 188 | |
189 | fRCUTrailerData = NULL; | |
190 | fRCUTrailerSize = 0; | |
191 | ||
9283f3a5 | 192 | fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0; |
f8e5b5a0 | 193 | |
194 | if (fRawReader) fRawReader->Reset(); | |
195 | ||
0148e633 | 196 | if (fOldStream) fOldStream->Reset(); |
f8e5b5a0 | 197 | } |
198 | ||
199 | //_____________________________________________________________________________ | |
200 | Bool_t AliAltroRawStreamV3::NextDDL() | |
201 | { | |
202 | // Read the next DDL payload (CDH + RCU trailer) | |
203 | // Updates the information which is coming from these | |
204 | // two sources | |
38f5da76 | 205 | fFormatVersion = 0; |
f8e5b5a0 | 206 | fPosition = 0; |
207 | // Get next DDL payload | |
208 | // return wtih false in case no more data payloads | |
209 | // are found | |
210 | do { | |
211 | if (!fRawReader->ReadNextData(fData)) return kFALSE; | |
212 | } while (fRawReader->GetDataSize() == 0); | |
213 | ||
214 | fDDLNumber = fRawReader->GetDDLID(); | |
e76a0935 | 215 | fChannelPayloadSize = -1; |
8e9fa05e | 216 | fChannelStartPos = -1; |
f8e5b5a0 | 217 | |
3bc742e5 | 218 | fFormatVersion = (fRawReader->GetBlockAttributes() & 0xF); |
f8e5b5a0 | 219 | |
38f5da76 | 220 | if (fFormatVersion < 2) { |
0148e633 | 221 | // old altro format data |
222 | if (!fOldStream) { | |
223 | fOldStream = new AliAltroRawStream(fRawReader); | |
224 | AliInfo(Form("RCU firmware verion %d detected. Using AliAltroRawStream to decode the data.", | |
38f5da76 | 225 | fFormatVersion)); |
0148e633 | 226 | } |
227 | Bool_t status = fOldStream->NextDDL(fData); | |
228 | if (status) { | |
229 | fRCUId = fOldStream->GetRCUId(); | |
230 | fRCUTrailerSize = fOldStream->GetRCUTrailerSize(); | |
231 | fOldStream->GetRCUTrailerData(fRCUTrailerData); | |
232 | fFECERRA = fOldStream->GetFECERRA(); | |
233 | fFECERRB = fOldStream->GetFECERRB(); | |
234 | fERRREG2 = fOldStream->GetERRREG2(); | |
235 | fERRREG3 = ((UInt_t)fOldStream->GetNChAddrMismatch()) | | |
236 | (((UInt_t)fOldStream->GetNChLengthMismatch()) << 12); | |
237 | fActiveFECsA = fOldStream->GetActiveFECsA(); | |
238 | fActiveFECsB = fOldStream->GetActiveFECsB(); | |
239 | fAltroCFG1 = fOldStream->GetAltroCFG1(); | |
240 | fAltroCFG2 = fOldStream->GetAltroCFG2(); | |
eae29211 | 241 | if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) |
242 | fPayloadSize = fOldStream->GetRCUPayloadSizeInSOD(); | |
0148e633 | 243 | } |
244 | return status; | |
245 | } | |
f8e5b5a0 | 246 | |
38f5da76 | 247 | return ReadRCUTrailer(fFormatVersion); |
f8e5b5a0 | 248 | } |
249 | ||
250 | //_____________________________________________________________________________ | |
251 | Bool_t AliAltroRawStreamV3::NextChannel() | |
252 | { | |
253 | // Read the next Altro channel from the | |
254 | // raw-data stream | |
255 | // Updates the channel hardware address member and | |
256 | // channel data size. Sets the error flag in case | |
257 | // RCU signals readout error in this channel | |
0148e633 | 258 | if (fOldStream) { |
259 | Bool_t status = fOldStream->NextChannel(); | |
e76a0935 | 260 | if (status) { |
261 | fHWAddress = fOldStream->GetHWAddress(); | |
262 | fChannelPayloadSize = fOldStream->GetChannelPayloadSize(); | |
263 | } | |
0148e633 | 264 | return status; |
265 | } | |
266 | ||
8e9fa05e | 267 | Int_t channelStartPos=fPosition; |
268 | fChannelStartPos = -1; | |
f8e5b5a0 | 269 | fCount = -1; |
270 | fBadChannel = kFALSE; | |
6d4dd848 | 271 | fBunchDataIndex = 0; |
3ce326c0 | 272 | fBunchLength = -1; |
f8e5b5a0 | 273 | |
274 | UInt_t word = 0; | |
275 | do { | |
276 | word = Get32bitWord(fPosition++); | |
6d4dd848 | 277 | if (fPosition > fPayloadSize) return kFALSE; |
f8e5b5a0 | 278 | } |
6d4dd848 | 279 | while ((word >> 30) != 1); |
f8e5b5a0 | 280 | |
281 | // check for readout errors | |
6d4dd848 | 282 | fBadChannel = (word >> 29) & 0x1; |
f8e5b5a0 | 283 | |
284 | // extract channel payload and hw address | |
6d4dd848 | 285 | fCount = (word >> 16) & 0x3FF; |
e76a0935 | 286 | fChannelPayloadSize = fCount; |
f8e5b5a0 | 287 | fHWAddress = word & 0xFFF; |
288 | ||
6d4dd848 | 289 | // Now unpack the altro data |
290 | // Revert the order of the samples | |
291 | // inside the bunch so that the | |
292 | // first time is first in the samples | |
293 | // array | |
294 | Int_t isample = 0; | |
295 | Int_t nwords = (fCount+2)/3; | |
296 | for (Int_t iword = 0; iword < nwords; iword++) { | |
297 | word = Get32bitWord(fPosition++); | |
298 | if ((word >> 30) != 0) { | |
299 | // Unexpected end of altro channel payload | |
499187ca | 300 | AliWarning(Form("Unexpected end of payload in altro channel payload! DDL=%03d, Address=0x%x, word=0x%x", |
301 | fDDLNumber,fHWAddress,word)); | |
6d4dd848 | 302 | fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress)); |
499187ca | 303 | if (AliDebugLevel() > 0) HexDumpChannel(); |
6d4dd848 | 304 | fCount = -1; |
305 | fPosition--; | |
306 | return kFALSE; | |
307 | } | |
308 | fBunchData[isample++] = (word >> 20) & 0x3FF; | |
309 | fBunchData[isample++] = (word >> 10) & 0x3FF; | |
310 | fBunchData[isample++] = word & 0x3FF; | |
311 | } | |
312 | ||
8e9fa05e | 313 | fChannelStartPos=channelStartPos; |
f8e5b5a0 | 314 | return kTRUE; |
315 | } | |
316 | ||
317 | //_____________________________________________________________________________ | |
318 | Bool_t AliAltroRawStreamV3::NextBunch() | |
319 | { | |
320 | // Read next altro bunch from the | |
321 | // raw-data stream. | |
322 | // Updates the start/end time-bins | |
323 | // and the array with altro samples | |
0148e633 | 324 | if (fOldStream) { |
325 | Bool_t status = fOldStream->NextBunch(fBunchData,fBunchLength,fStartTimeBin); | |
326 | if (status) fBunchDataPointer = &fBunchData[0]; | |
327 | else fBunchDataPointer = NULL; | |
328 | return status; | |
329 | } | |
330 | ||
3ce326c0 | 331 | Int_t prevTimeBin = (fBunchLength > 0) ? fStartTimeBin-fBunchLength+1 : 1024; |
f8e5b5a0 | 332 | fBunchLength = fStartTimeBin = -1; |
6d4dd848 | 333 | fBunchDataPointer = NULL; |
f8e5b5a0 | 334 | |
6d4dd848 | 335 | if ((fBunchDataIndex >= fCount) || fBadChannel) return kFALSE; |
f8e5b5a0 | 336 | |
6d4dd848 | 337 | fBunchLength = fBunchData[fBunchDataIndex]; |
3ce326c0 | 338 | if (fBunchLength <= 2) { |
339 | // Invalid bunch size | |
f3aadf33 | 340 | AliWarning(Form("Too short bunch length (%d) @ %d in Address=0x%x (DDL=%03d)!", |
341 | fBunchLength,fBunchDataIndex,fHWAddress,fDDLNumber)); | |
3ce326c0 | 342 | fRawReader->AddMinorErrorLog(kAltroBunchHeadErr,Form("hw=0x%x",fHWAddress)); |
499187ca | 343 | if (AliDebugLevel() > 0) HexDumpChannel(); |
3ce326c0 | 344 | fCount = fBunchLength = -1; |
345 | return kFALSE; | |
346 | } | |
6d4dd848 | 347 | if ((fBunchDataIndex + fBunchLength) > fCount) { |
f8e5b5a0 | 348 | // Too long bunch detected |
f3aadf33 | 349 | AliWarning(Form("Too long bunch detected @ %d in Address=0x%x (DDL=%03d) ! Expected <= %d 10-bit words, found %d !", fBunchDataIndex, |
499187ca | 350 | fHWAddress,fDDLNumber,fCount-fBunchDataIndex,fBunchLength)); |
f8e5b5a0 | 351 | fRawReader->AddMinorErrorLog(kAltroBunchHeadErr,Form("hw=0x%x",fHWAddress)); |
499187ca | 352 | if (AliDebugLevel() > 0) HexDumpChannel(); |
f8e5b5a0 | 353 | fCount = fBunchLength = -1; |
354 | return kFALSE; | |
355 | } | |
6d4dd848 | 356 | fBunchDataIndex++; |
f8e5b5a0 | 357 | fBunchLength -= 2; |
358 | ||
6d4dd848 | 359 | fStartTimeBin = fBunchData[fBunchDataIndex++]; |
3ce326c0 | 360 | if (fCheckAltroPayload) { |
361 | if ((fStartTimeBin-fBunchLength+1) < 0) { | |
f3aadf33 | 362 | AliWarning(Form("Invalid start time-bin @ %d in Address=0x%x (DDL=%03d)! (%d-%d+1) < 0", fBunchDataIndex-1, |
499187ca | 363 | fHWAddress,fDDLNumber,fStartTimeBin,fBunchLength)); |
3ce326c0 | 364 | fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress)); |
499187ca | 365 | if (AliDebugLevel() > 0) HexDumpChannel(); |
3ce326c0 | 366 | fCount = fBunchLength = -1; |
367 | return kFALSE; | |
368 | } | |
369 | if (fStartTimeBin >= prevTimeBin) { | |
f3aadf33 | 370 | AliWarning(Form("Invalid start time-bin @ %d in Address=0x%x (DDL=%03d)! (%d>=%d)", fBunchDataIndex-1, |
499187ca | 371 | fHWAddress,fDDLNumber,fStartTimeBin,prevTimeBin)); |
3ce326c0 | 372 | fRawReader->AddMinorErrorLog(kAltroPayloadErr,Form("hw=0x%x",fHWAddress)); |
499187ca | 373 | if (AliDebugLevel() > 0) HexDumpChannel(); |
3ce326c0 | 374 | fCount = fBunchLength = -1; |
375 | return kFALSE; | |
376 | } | |
377 | } | |
f8e5b5a0 | 378 | |
6d4dd848 | 379 | fBunchDataPointer = &fBunchData[fBunchDataIndex]; |
f8e5b5a0 | 380 | |
6d4dd848 | 381 | fBunchDataIndex += fBunchLength; |
f8e5b5a0 | 382 | |
383 | return kTRUE; | |
384 | } | |
385 | ||
8e9fa05e | 386 | //_____________________________________________________________________________ |
387 | const UChar_t *AliAltroRawStreamV3::GetChannelPayload() const | |
388 | { | |
389 | //returns raw channel data, length 4+(fChannelPayloadSize+2)/3*4 | |
390 | if (fChannelStartPos<0 || fChannelPayloadSize<0) return NULL; | |
391 | Int_t channelSize=1+(fChannelPayloadSize+2)/3; // nof 32bit words | |
392 | if (fPosition<fChannelStartPos+channelSize) return NULL; | |
393 | return fData+(fChannelStartPos<<2); | |
394 | } | |
395 | ||
f8e5b5a0 | 396 | //_____________________________________________________________________________ |
397 | UInt_t AliAltroRawStreamV3::Get32bitWord(Int_t index) const | |
398 | { | |
399 | // This method returns the 32 bit word at a given | |
400 | // position inside the raw data payload. | |
401 | // The 'index' points to the beginning of the word. | |
402 | // The method is supposed to be endian (platform) | |
403 | // independent. | |
404 | ||
405 | index = (index << 2); | |
406 | UInt_t word = 0; | |
407 | word |= fData[index++]; | |
408 | word |= fData[index++] << 8; | |
409 | word |= fData[index++] << 16; | |
410 | word |= fData[index++] << 24; | |
411 | ||
412 | return word; | |
413 | } | |
414 | ||
415 | ///_____________________________________________________________________________ | |
416 | Bool_t AliAltroRawStreamV3::ReadRCUTrailer(UChar_t rcuVer) | |
417 | { | |
418 | // Read the RCU trailer according | |
419 | // to the RCU formware version | |
420 | // specified in CDH | |
421 | // Cross-check with version found in the | |
422 | // trailer | |
423 | ||
424 | fRCUTrailerData = NULL; | |
425 | fRCUTrailerSize = 0; | |
426 | fPayloadSize = -1; | |
427 | ||
428 | Int_t index = fRawReader->GetDataSize()/4; | |
429 | ||
430 | // First read 32-bit word with the | |
431 | // trailer size (7 bits), RCU ID (9 bits) and | |
432 | // RCU firmware version (8 bits?) | |
433 | // The two major bit should be 11 (identifies | |
434 | // the end of the trailer) | |
435 | UInt_t word = Get32bitWord(--index); | |
436 | ||
437 | if ((word >> 30) != 3) { | |
438 | fRawReader->AddFatalErrorLog(kRCUTrailerErr,""); | |
439 | AliError("Last RCU trailer word not found!"); | |
440 | return kFALSE; | |
441 | } | |
442 | ||
443 | UChar_t ver = (word >> 16) & 0xFF; | |
444 | if (ver != rcuVer) { | |
445 | // Wrong RCU firmware version detected | |
446 | fRawReader->AddMajorErrorLog(kRCUVerErr,Form("%d!=%d", | |
447 | ver,rcuVer)); | |
448 | AliDebug(1,Form("Wrong RCU firmware version detected: %d != %d", | |
449 | ver,rcuVer)); | |
450 | } | |
451 | ||
452 | fRCUId = (Int_t)((word >> 7) & 0x1FF); | |
453 | Int_t trailerSize = (word & 0x7F); | |
454 | ||
455 | // Now read the beginning of the trailer | |
456 | // where the payload size is written | |
457 | if (trailerSize < 2) { | |
458 | fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes", | |
459 | trailerSize*4)); | |
460 | AliWarning(Form("Invalid trailer size found (%d bytes) !", | |
461 | trailerSize*4)); | |
462 | return kFALSE; | |
463 | } | |
464 | ||
465 | trailerSize -= 2; | |
466 | fRCUTrailerSize = trailerSize*4; | |
467 | ||
468 | for (; trailerSize > 0; trailerSize--) { | |
469 | word = Get32bitWord(--index); | |
470 | if ((word >> 30) != 2) { | |
471 | fRawReader->AddMinorErrorLog(kRCUTrailerErr,"missing 10"); | |
472 | AliWarning("Missing RCU trailer identifier pattern!"); | |
473 | continue; | |
474 | } | |
475 | Int_t parCode = (word >> 26) & 0xF; | |
476 | Int_t parData = word & 0x3FFFFFF; | |
477 | switch (parCode) { | |
478 | case 1: | |
479 | // ERR_REG1 | |
480 | fFECERRA = ((parData >> 13) & 0x1FFF) << 7; | |
481 | fFECERRB = ((parData & 0x1FFF)) << 7; | |
482 | break; | |
483 | case 2: | |
484 | // ERR_REG2 | |
485 | fERRREG2 = parData & 0x1FF; | |
486 | break; | |
487 | case 3: | |
488 | // ERR_REG3 | |
9283f3a5 | 489 | fERRREG3 = parData & 0x1FFFFFF; |
f8e5b5a0 | 490 | break; |
491 | case 4: | |
f8e5b5a0 | 492 | // FEC_RO_A |
493 | fActiveFECsA = parData & 0xFFFF; | |
494 | break; | |
9283f3a5 | 495 | case 5: |
f8e5b5a0 | 496 | // FEC_RO_B |
497 | fActiveFECsB = parData & 0xFFFF; | |
498 | break; | |
9283f3a5 | 499 | case 6: |
f8e5b5a0 | 500 | // RDO_CFG1 |
501 | fAltroCFG1 = parData & 0xFFFFF; | |
502 | break; | |
9283f3a5 | 503 | case 7: |
f8e5b5a0 | 504 | // RDO_CFG2 |
505 | fAltroCFG2 = parData & 0x1FFFFFF; | |
506 | break; | |
507 | default: | |
508 | fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word"); | |
509 | AliWarning(Form("Undefined parameter code %d, ignore it !", | |
510 | parCode)); | |
511 | break; | |
512 | } | |
513 | } | |
514 | ||
515 | if (index < 1) { | |
516 | fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes", | |
517 | fRCUTrailerSize+8, | |
518 | fRawReader->GetDataSize())); | |
519 | AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!", | |
520 | fRCUTrailerSize, | |
521 | fRawReader->GetDataSize())); | |
522 | } | |
523 | ||
524 | fRCUTrailerData = fData + index*4; | |
525 | ||
526 | // Now read the payload size | |
527 | // (First word in the RCU trailer) | |
528 | fPayloadSize = Get32bitWord(--index) & 0x3FFFFFF; | |
529 | ||
530 | if ((fRawReader->GetDataSize() - fRCUTrailerSize - 8) != (fPayloadSize*4)) { | |
531 | fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes", | |
532 | fRawReader->GetDataSize(), | |
533 | fRCUTrailerSize+8, | |
534 | fPayloadSize*4)); | |
535 | 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 !", | |
536 | fRawReader->GetDataSize(), | |
537 | fRCUTrailerSize+8, | |
538 | fPayloadSize*4)); | |
539 | } | |
540 | ||
541 | return kTRUE; | |
542 | } | |
543 | ||
544 | //_____________________________________________________________________________ | |
545 | Int_t AliAltroRawStreamV3::GetBranch() const | |
546 | { | |
547 | // The method provides the RCU branch index (0 or 1) | |
548 | // for the current hardware address. | |
549 | // In case the hardware address has not been yet | |
550 | // initialized, the method returns -1 | |
551 | if (fHWAddress == -1) return -1; | |
552 | ||
553 | return ((fHWAddress >> 11) & 0x1); | |
554 | } | |
555 | ||
556 | //_____________________________________________________________________________ | |
557 | Int_t AliAltroRawStreamV3::GetFEC() const | |
558 | { | |
559 | // The method provides the front-end card index | |
560 | // for the current hardware address. | |
561 | // In case the hardware address has not been yet | |
562 | // initialized, the method returns -1 | |
563 | if (fHWAddress == -1) return -1; | |
564 | ||
565 | return ((fHWAddress >> 7) & 0xF); | |
566 | } | |
567 | ||
568 | //_____________________________________________________________________________ | |
569 | Int_t AliAltroRawStreamV3::GetAltro() const | |
570 | { | |
571 | // The method provides the altro chip index | |
572 | // for the current hardware address. | |
573 | // In case the hardware address has not been yet | |
574 | // initialized, the method returns -1 | |
575 | if (fHWAddress == -1) return -1; | |
576 | ||
577 | return ((fHWAddress >> 4) & 0x7); | |
578 | } | |
579 | ||
580 | //_____________________________________________________________________________ | |
581 | Int_t AliAltroRawStreamV3::GetChannel() const | |
582 | { | |
583 | // The method provides the channel index | |
584 | // for the current hardware address. | |
585 | // In case the hardware address has not been yet | |
586 | // initialized, the method returns -1 | |
587 | if (fHWAddress == -1) return -1; | |
588 | ||
589 | return (fHWAddress & 0xF); | |
590 | } | |
591 | ||
592 | //_____________________________________________________________________________ | |
593 | Bool_t AliAltroRawStreamV3::GetRCUTrailerData(UChar_t*& data) const | |
594 | { | |
595 | // Return a pointer to the RCU trailer | |
596 | // data. Should be called always after | |
597 | // the RCU trailer was already processed | |
598 | // in the GetPosition() method | |
599 | if (!fRCUTrailerSize || !fRCUTrailerData) { | |
600 | AliError("No valid RCU trailer data is found !"); | |
601 | data = NULL; | |
602 | return kFALSE; | |
603 | } | |
604 | ||
605 | data = fRCUTrailerData; | |
606 | ||
607 | return kTRUE; | |
608 | } | |
609 | ||
610 | //_____________________________________________________________________________ | |
611 | void AliAltroRawStreamV3::PrintRCUTrailer() const | |
612 | { | |
613 | // Prints the contents of | |
614 | // the RCU trailer data | |
38f5da76 | 615 | printf("RCU trailer (Format version %d):\n" |
616 | "==================================================\n", GetFormatVersion()); | |
617 | printf("FECERRA: 0x%x\n", fFECERRA); | |
618 | printf("FECERRB: 0x%x\n", fFECERRB); | |
619 | printf("ERRREG2: 0x%x\n", fERRREG2); | |
f8e5b5a0 | 620 | printf("#channels skipped due to address mismatch: %d\n",GetNChAddrMismatch()); |
621 | printf("#channels skipped due to bad block length: %d\n",GetNChLengthMismatch()); | |
38f5da76 | 622 | printf("Active FECs (branch A): 0x%x\n", fActiveFECsA); |
623 | printf("Active FECs (branch B): 0x%x\n", fActiveFECsB); | |
624 | printf("Baseline corr: 0x%x\n",GetBaselineCorr()); | |
625 | printf("Number of presamples: %d\n", GetNPresamples()); | |
626 | printf("Number of postsamples: %d\n",GetNPostsamples()); | |
627 | printf("Second baseline corr: %d\n",GetSecondBaselineCorr()); | |
628 | printf("GlitchFilter: %d\n",GetGlitchFilter()); | |
629 | printf("Number of non-ZS postsamples: %d\n",GetNNonZSPostsamples()); | |
630 | printf("Number of non-ZS presamples: %d\n",GetNNonZSPresamples()); | |
631 | printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers()); | |
632 | printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples()); | |
633 | printf("Number of samples per channel: %d\n",GetNSamplesPerCh()); | |
634 | printf("Sparse readout: %d\n",GetSparseRO()); | |
635 | printf("Sampling time: %e s\n",GetTSample()); | |
636 | printf("L1 Phase: %e s\n",GetL1Phase()); | |
637 | printf("AltroCFG1: 0x%x\n",GetAltroCFG1()); | |
638 | printf("AltroCFG2: 0x%x\n",GetAltroCFG2()); | |
639 | printf("==================================================\n"); | |
f8e5b5a0 | 640 | } |
641 | ||
642 | //_____________________________________________________________________________ | |
643 | void AliAltroRawStreamV3::SelectRawData(Int_t detId) | |
644 | { | |
645 | // Select the raw data for specific | |
646 | // detector id | |
647 | AliDebug(1,Form("Selecting raw data for detector %d",detId)); | |
648 | fRawReader->Select(detId); | |
649 | } | |
650 | ||
651 | //_____________________________________________________________________________ | |
652 | void AliAltroRawStreamV3::SelectRawData(const char *detName) | |
653 | { | |
654 | // Select the raw data for specific | |
655 | // detector name | |
656 | AliDebug(1,Form("Selecting raw data for detector %s",detName)); | |
657 | fRawReader->Select(detName); | |
658 | } | |
659 | ||
660 | //_____________________________________________________________________________ | |
661 | Double_t AliAltroRawStreamV3::GetTSample() const | |
662 | { | |
663 | // Returns the sampling time | |
664 | // in seconds. In case the rcu trailer | |
665 | // was note read, return an invalid number (0) | |
666 | ||
667 | if (!fRCUTrailerData) return 0.; | |
668 | ||
669 | const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz | |
670 | UChar_t fq = (fAltroCFG2 >> 5) & 0xF; | |
671 | Double_t tSample; | |
672 | switch (fq) { | |
673 | case 0: | |
674 | // 20 MHz | |
675 | tSample = 2.0*kLHCTimeSample; | |
676 | break; | |
677 | case 1: | |
678 | // 10 Mhz | |
679 | tSample = 4.0*kLHCTimeSample; | |
680 | break; | |
681 | case 2: | |
682 | // 5 MHz | |
683 | tSample = 8.0*kLHCTimeSample; | |
684 | break; | |
685 | default: | |
686 | AliWarning(Form("Invalid sampling frequency value %d !", | |
687 | fq)); | |
688 | tSample = 0.; | |
689 | break; | |
690 | } | |
691 | ||
692 | return tSample; | |
693 | } | |
694 | ||
695 | //_____________________________________________________________________________ | |
696 | Double_t AliAltroRawStreamV3::GetL1Phase() const | |
697 | { | |
698 | // Returns the L1 phase w.r.t to the | |
699 | // LHC clock | |
700 | if (!fRCUTrailerData) return 0.; | |
701 | ||
702 | const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz | |
703 | Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample; | |
704 | ||
705 | Double_t tSample = GetTSample(); | |
706 | if (phase >= tSample) { | |
6c12d59f | 707 | AliWarning(Form("Invalid L1 trigger phase (%f >= %f) !", |
f8e5b5a0 | 708 | phase,tSample)); |
709 | phase = 0.; | |
710 | } | |
711 | ||
712 | return phase; | |
713 | } | |
714 | ||
715 | //_____________________________________________________________________________ | |
716 | void AliAltroRawStreamV3::AddMappingErrorLog(const char *message) | |
717 | { | |
718 | // Signal a mapping error | |
719 | // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream | |
720 | // classes in order to log an error related to bad altro mapping | |
721 | ||
722 | if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message); | |
723 | } | |
eae29211 | 724 | |
725 | //_____________________________________________________________________________ | |
726 | UChar_t *AliAltroRawStreamV3::GetRCUPayloadInSOD() const | |
727 | { | |
728 | // Get a pointer to the data in case | |
729 | // of SOD events | |
730 | if (fRawReader) { | |
731 | if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) { | |
732 | return fData; | |
733 | } | |
734 | } | |
735 | return NULL; | |
736 | } | |
737 | ||
738 | //_____________________________________________________________________________ | |
739 | Int_t AliAltroRawStreamV3::GetRCUPayloadSizeInSOD() const | |
740 | { | |
741 | // Get the size of the RCU data in case | |
742 | // of SOD events | |
743 | if (fRawReader) { | |
744 | if (fRawReader->GetType() == AliRawEventHeaderBase::kStartOfData) { | |
745 | return fPayloadSize; | |
746 | } | |
747 | } | |
748 | return -1; | |
749 | } | |
499187ca | 750 | |
751 | //_____________________________________________________________________________ | |
752 | ||
753 | void AliAltroRawStreamV3::HexDumpChannel() const | |
754 | { | |
755 | // Print of the Hex Data of the current channel | |
756 | // to decipher read-out warnings and errors | |
757 | if (fCount>0 && fPosition>0) { | |
758 | printf("Hex-Dump of DDL: %3d, RCU ID: %d, HWADDR: 0x%03x\n", | |
759 | fDDLNumber,fRCUId,fHWAddress); | |
f3aadf33 | 760 | printf("32-bit - 2bit 10bit 10bit 10bit - "); |
761 | printf("Index 10bit 10bit 10bit\n"); | |
762 | printf("********** **** ***** ***** ***** - "); | |
763 | printf("***** ****** ****** ******\n"); | |
499187ca | 764 | Int_t nwords = (fCount+2)/3+1; |
765 | for (Int_t iword = 0; iword < nwords; iword++) { | |
766 | UInt_t word32 = Get32bitWord(fPosition-nwords+iword); | |
767 | UInt_t marker = word32 >> 30 & 0x3; | |
768 | UInt_t word101 = word32 >> 20 & 0x3FF; | |
769 | UInt_t word102 = word32 >> 10 & 0x3FF; | |
770 | UInt_t word103 = word32 >> 00 & 0x3FF; // nice octal number | |
f3aadf33 | 771 | printf("0x%08x - 0b%1d%1d 0x%03x 0x%03x 0x%03x", |
499187ca | 772 | word32,marker>>1,marker&0x1,word101,word102,word103); |
f3aadf33 | 773 | if (iword == 0) { printf(" - Channel Header\n"); continue; } |
774 | Int_t base = 3*(iword-1); | |
775 | printf(" - %5d 0x%03x%c 0x%03x%c 0x%03x%c\n", base, | |
776 | fBunchData[base], (fBunchDataIndex == base ? '*' : ' '), | |
777 | fBunchData[base+1], (fBunchDataIndex == base+1 ? '*' : ' '), | |
778 | fBunchData[base+2], (fBunchDataIndex == base+2 ? '*' : ' ')); | |
499187ca | 779 | } |
780 | } | |
781 | } |