]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliAltroDecoder.cxx
TPC data is now split into 18 branches in order to avoid big memory consumption on...
[u/mrichter/AliRoot.git] / RAW / AliAltroDecoder.cxx
CommitLineData
31a920d3 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
4 * *
5 * Primary Authors: Per Thomas Hille <perthi@fys.uio.no> *
ebf7cafe 6 * Ã\98ystein Djuvsland <oystein.djuvsland@gmail.com> *
31a920d3 7 * *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17#include <Riostream.h>
18#include "AliAltroDecoder.h"
19#include "AliAltroData.h"
20
ac672c4c 21// Class for fast decoding of RCU/Altro raw data format (DDL format)
22// to PC readable form. The decoding is done in 3 steps.
23// 1) The RCU payload consistist of a variable number of 160 bit words
24// denoted a DDL block. All the DDL blocks of an RCU payload is transformed
25// to 16 integers wich is then put into a buffer of integers big enought to contain the
26// biggest number of samples possible
27// 2) The decoded buffer is then accesible for the NextChannel functions wich reads
28// the altro channel data (samples) contained in the payload. The first call to NextChannel gives the
29// last altro channel of the back linked list, the next call the second last channel ..etc untill
30// all channles are read.
31// 3) (optional) For each Altro channel one chan invoke the member function NextBunch which gives on first call
32// The last bunch (the bunch with the highest timestamp), on next call the second last bunch..etc
33// untill all bunches are read
34
35
31a920d3 36ClassImp(AliAltroDecoder)
37
38AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0),
ebf7cafe 39 f8DtaPtr(0),
ac672c4c 40 fkN32HeaderWords(8),
ebf7cafe 41 fN40AltroWords(0),
42 fN40RcuAltroWords(0),
43 fNDDLBlocks(0),
44 f32LastDDLBlockSize(5),
45 f32PayloadSize(0),
46 fOutBufferIndex(0),
47 fSize(0),
48 fNAltro10bitWords(0),
49 fComplete(0),
50 fInComplete(0),
51 fDecodeIfCorruptedTrailer(kTRUE),
52 fIsDecoded(kFALSE),
53 fIsFatalCorruptedTrailer(kTRUE)
31a920d3 54{
ac672c4c 55 // Default constructor
31a920d3 56}
57
58
59AliAltroDecoder::~AliAltroDecoder()
60{
ac672c4c 61 // Default destructor
31a920d3 62}
63
64
ac672c4c 65Bool_t AliAltroDecoder::CheckPayloadTrailer() const
31a920d3 66{
ac672c4c 67 //Check wether or not there is consistency between the number of 40 bit altro words given by
68 //the RCU payload and the number of 40 bit words calculated from the size of the RCU payload.
69
31a920d3 70 if(fN40AltroWords != fN40RcuAltroWords)
71 {
72 return kFALSE;
73 }
74 else
75 {
76 return kTRUE;
77 }
78}
79
80
81Bool_t AliAltroDecoder::Decode()
ebf7cafe 82{
ac672c4c 83 // Decodes the RCU payload (all altro channels in one go) from the DDL format to
84 // PC readable form
85
ebf7cafe 86 if( fIsFatalCorruptedTrailer == kTRUE)
31a920d3 87 {
ebf7cafe 88 printf("\n AliAltroDecoder::Decode(), WARNING, attempt to decode badly corrupted data\n");
89 printf("\n AliAltroDecoder::Decode(). Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n");
90 return kFALSE;
91 }
92
93 else
31a920d3 94 {
ebf7cafe 95 // see header file for class documentation
96 fComplete = 0;
97 fInComplete = 0;
98
ac672c4c 99 Int_t tmpcnt = CountAAApaddings();
31a920d3 100
ebf7cafe 101 if(tmpcnt == 3)
102 {
103 fN40AltroWords = fN40AltroWords -1;
104 }
105 else if(tmpcnt == 5)
106 {
107 fN40AltroWords = fN40AltroWords -2;
108 }
109 else if(tmpcnt == 8)
110 {
111 fN40AltroWords = fN40AltroWords -3;
112 }
31a920d3 113
ebf7cafe 114 if( ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE ) && (fSize > 32) )
31a920d3 115 {
ebf7cafe 116 // fDDLBlockCnt = 0;
117 fOutBufferIndex = 0;
118
119 for(Int_t i = 0; i < fNDDLBlocks; i++)
120 {
121 DecodeDDLBlock();
122 }
31a920d3 123
ebf7cafe 124 DecodeLastDDLBlock();
125 fOutBufferIndex = fN40AltroWords*4 - 1;
31a920d3 126
ebf7cafe 127 // DumpData(fOutBuffer, 400,4);
31a920d3 128
ebf7cafe 129 fIsDecoded = kTRUE;
130 return kTRUE;
131 }
132
133 else
134 {
135 cout <<" ERROR: data integrity check failed, discarding data" << endl;
136 cout << "Size of datablock is " << fSize << endl;
137 cout << "fN40AltroWords = " << fN40AltroWords << endl;
138 cout << "fN40RcuAltroWords = " << fN40RcuAltroWords << endl;
139 return kFALSE;
140 }
31a920d3 141
31a920d3 142 }
143}
144
145
146Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr)
147{
ac672c4c 148 // Reads the next altro channel in the RCU payload after the RCU payload
149 // has been decoded. The channles are read strarting from the end (backlinked list)
150 // Returns kTRUE as long as ther are unread channles in the payload
151 // Returns kFALSE when all the channels has been read.
152
ebf7cafe 153 if(fIsFatalCorruptedTrailer == kTRUE)
31a920d3 154 {
ebf7cafe 155 printf("\n AliAltroDecoder::NextChannel(), WARNING, attempt to decode badly corrupted data\n");
156 printf("\n AliAltroDecoder::NextChannel(), Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n");
157 return kFALSE;
158 }
159
160 else
31a920d3 161 {
31a920d3 162
ebf7cafe 163 if(fIsDecoded != kTRUE)
164 {
165 cout <<"AliAltroDecoder::NextChanne, WARNING, buffer was not decoded, decoding now.. "<< endl;
166 Decode();
167 }
31a920d3 168
ac672c4c 169 if(fOutBufferIndex > fkN32HeaderWords)
31a920d3 170 {
ebf7cafe 171 if((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6) == 0x2aaa)
172 {
173 altroDataPtr->SetIsComplete(kTRUE);
174 fComplete ++;
175 }
176 else
177 {
178 altroDataPtr->SetIsComplete(kFALSE);
179 fInComplete ++;
180 }
181
182 fOutBufferIndex --;
183 fNAltro10bitWords = ( (fOutBuffer[fOutBufferIndex] & 0x3f) << 4 ) | ((fOutBuffer[fOutBufferIndex -1] & (0xF << 6)) >> 6) ;
184 fOutBufferIndex --;
185 altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ) );
186
187 fOutBufferIndex --;
188
189 if(fNAltro10bitWords%4 == 0)
190 {
191 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords;
192 }
193 else
194 {
195 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords -(4 - fNAltro10bitWords%4);
196 }
197
198
199 altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] );
200 fOutBufferIndex --;
201 altroDataPtr->SetDataSize( fNAltro10bitWords );
202 return kTRUE;
203
31a920d3 204 }
205 else
206 {
ebf7cafe 207 return kFALSE;
31a920d3 208 }
209
31a920d3 210 }
211}
212
31a920d3 213
ac672c4c 214Int_t AliAltroDecoder::CountAAApaddings() const
31a920d3 215{
ac672c4c 216 // Use for simulated data only.
217 // Patch for incorrectly simulated data. Counts the number of
218 // 2aaa word in the trailer of the payload and tries to figure out
219 // the correct number of 40 bit altro words in the RCU pauload
220
31a920d3 221 UShort_t *tailPtr= (UShort_t *)(f32DtaPtr +f32PayloadSize);
222 Int_t cnt = 0;
223
224 tailPtr --;
225
226 while(*tailPtr == 0xaaaa)
227 {
228 cnt ++;
229 tailPtr --;
230 }
231
232 tailPtr = tailPtr + cnt +1;
233
234 return cnt;
235}
236
237
238Float_t AliAltroDecoder::GetFailureRate()
239{
ac672c4c 240 // Prints to stdout the percent of altroblocks that
241 // is missing the 2aaa trailer.
242
31a920d3 243 Float_t tmp = 0;
244 cout << "Number of Complete channles = " << fComplete <<endl;
245 cout << "Number of InComplete channles = " << fInComplete <<endl;
246 tmp = (100*(Float_t)fInComplete)/((Float_t)fComplete + (Float_t)fInComplete);
247 cout <<"There are "<< tmp <<"% incomplete channels"<<endl;
248 return tmp;
249}
250
251
252void AliAltroDecoder::PrintInfo(AliAltroData &altrodata, Int_t n, Int_t nPerLine)
253{
ac672c4c 254 // prints data and address information contained in altrodata
255 // to the standard output
256
31a920d3 257 cout << "altrodata.fDataSize = " << altrodata.GetDataSize() << endl;
258 cout << "altrodata.fHadd = " << altrodata.GetHadd() <<endl;
259 const UInt_t* data = altrodata.GetData();
260 for(Int_t i= 0; i< n; i++)
261 {
262 if( (i%nPerLine == 0) && (i != 0) )
263 {
264 printf("\n");
265 }
266 printf("%d\t", data[i]);
267 }
268 printf("\n");
269}
270
271
ebf7cafe 272int AliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size)
31a920d3 273{
ac672c4c 274 // Sets the pointer to the memory block that should be decoded
275 // Returns a negative value if an inconsistency in the data is detected
276
ebf7cafe 277 int iRet = 0;
31a920d3 278 Int_t tmpTrailerSize;
279 fIsDecoded = kFALSE;
280 f8DtaPtr =dtaPtr;
281 fSize = size;
282 f8DtaPtr =f8DtaPtr + fSize;
283 f32DtaPtr = (UInt_t *)f8DtaPtr;
284 tmpTrailerSize = *(f32DtaPtr - 1);
285
286 if(tmpTrailerSize <= MAX_TRAILER_WORDS)
287 {
288 tmpTrailerSize = tmpTrailerSize; //assume that the last word of the buffer gives the number of trailer words
289 }
290 else
291 {
292 tmpTrailerSize = 1; //assume that last word is ONE, and that the this word gives the number of 40 bit altro words
293 }
294
ac672c4c 295 f32PayloadSize = fSize/4 - (fkN32HeaderWords + tmpTrailerSize);
31a920d3 296 fN40AltroWords = (32*f32PayloadSize)/40;
297 fNDDLBlocks = f32PayloadSize/5;
298 f32LastDDLBlockSize = f32PayloadSize%DDL_32BLOCK_SIZE;
ebf7cafe 299
300 if(tmpTrailerSize > 0 && tmpTrailerSize < 5)
301 {
302 f32DtaPtr = f32DtaPtr - tmpTrailerSize;
303 fN40RcuAltroWords = *f32DtaPtr;
ac672c4c 304 f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords;
ebf7cafe 305 fIsFatalCorruptedTrailer = kFALSE;
306 }
307 else
308 {
309 printf("\n AliAltroDecoder::SetMemory, ERROR\n, trailer is corrupted");
310 fIsFatalCorruptedTrailer = kTRUE;
311 iRet = -1;
312 }
ebf7cafe 313
314 return iRet;
315
31a920d3 316}
317
318
319void AliAltroDecoder::DecodeDDLBlock()
320{
ac672c4c 321 //Decode one 160 bit DDL block into 16 x 16 bit integers (only least significant 10 bits are filled)
322
31a920d3 323 fOutBuffer[fOutBufferIndex] = *f32DtaPtr & 0x3ff; //s0
324 fOutBufferIndex ++;
325 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00) >> 10; //s1
326 fOutBufferIndex ++;
327 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00000) >> 20; //s2
328 fOutBufferIndex ++;
329 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xc0000000) >> 30; //s3_1
330 f32DtaPtr ++;
331 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xff) << 2); //s3_2
332 fOutBufferIndex ++;
333 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00) >> 8; //s4
334 fOutBufferIndex ++;
335 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0000) >> 18; //s5
336 fOutBufferIndex ++;
337 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xf0000000) >> 28; //s6_1
338 f32DtaPtr ++;
339 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3f) << 4); //s6_2
340 fOutBufferIndex ++;
341 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0) >> 6; //s7
342 fOutBufferIndex ++;
343 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0000) >> 16; //s8
344 fOutBufferIndex ++;
345 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xFC000000) >> 26; //s9_1
346 f32DtaPtr ++;
347 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xf) << 6); //s9_2
348 fOutBufferIndex ++;
349 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0) >> 4; //s10
350 fOutBufferIndex ++;
351 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc000) >> 14; //s11
352 fOutBufferIndex ++;
353 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xff000000) >> 24; //s12_1
354 f32DtaPtr ++;
355 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3) << 8); //s12_2
356 fOutBufferIndex ++;
357 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc) >> 2; //s13
358 fOutBufferIndex ++;
359 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff000) >> 12; //s14
360 fOutBufferIndex ++;
361 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00000) >> 22; //s15
362 f32DtaPtr ++;
363 fOutBufferIndex ++;
364}
365
366
367void AliAltroDecoder::DecodeLastDDLBlock()
368{
ac672c4c 369 // Decode one 160 bit DDL block into 16 integers.
370 // In order to use the same decoding function (DecodeDDLBlock())
371 // a copy of the the last DDL block is made and
372 // if the las block does not align with 160 bits then it is padded with zeroes
373
31a920d3 374 for(Int_t i=0; i < f32LastDDLBlockSize; i++)
375 {
376 fDDLBlockDummy[i] = *f32DtaPtr;
377 f32DtaPtr ++;
378 }
379
380 f32DtaPtr = fDDLBlockDummy;
381 f32DtaPtr ++;
382 DecodeDDLBlock();
383}