]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliAltroDecoder.cxx
Just something left from v2...now clean
[u/mrichter/AliRoot.git] / RAW / AliAltroDecoder.cxx
CommitLineData
86525f0f 1// $Id$
2
31a920d3 3/**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * All rights reserved. *
6 * *
7 * Primary Authors: Per Thomas Hille <perthi@fys.uio.no> *
86525f0f 8 * Oystein Djuvsland <oystein.djuvsland@gmail.com> *
31a920d3 9 * *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
18
86525f0f 19/**
20 @file AliAltroDocoder.cxx
21 @author Per Thomas Hille, Oystein Djuvsland
22 @date
23 @brief High performance decoder class for the RCU/Altro data format
24*/
25
26#include <cassert>
31a920d3 27#include <Riostream.h>
28#include "AliAltroDecoder.h"
29#include "AliAltroData.h"
86525f0f 30#include "AliLog.h"
31a920d3 31
ac672c4c 32// Class for fast decoding of RCU/Altro raw data format (DDL format)
33// to PC readable form. The decoding is done in 3 steps.
86525f0f 34// 1) The RCU payload consist of a variable number of 160 bit words
35// denoted a DDL block. All the DDL blocks of an RCU payload are transformed
36// into 16 bit integers and stored into a buffer of integers big enought to contain the
ac672c4c 37// biggest number of samples possible
38// 2) The decoded buffer is then accesible for the NextChannel functions wich reads
39// the altro channel data (samples) contained in the payload. The first call to NextChannel gives the
86525f0f 40// last altro channel of the back linked list, the next call the second last channel ..etc until
41// all channels are read.
ac672c4c 42// 3) (optional) For each Altro channel one chan invoke the member function NextBunch which gives on first call
43// The last bunch (the bunch with the highest timestamp), on next call the second last bunch..etc
44// untill all bunches are read
45
46
31a920d3 47ClassImp(AliAltroDecoder)
48
49AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0),
ebf7cafe 50 f8DtaPtr(0),
ac672c4c 51 fkN32HeaderWords(8),
ebf7cafe 52 fN40AltroWords(0),
53 fN40RcuAltroWords(0),
54 fNDDLBlocks(0),
55 f32LastDDLBlockSize(5),
86525f0f 56 f8PayloadSize(0),
ebf7cafe 57 fOutBufferIndex(0),
58 fSize(0),
59 fNAltro10bitWords(0),
60 fComplete(0),
61 fInComplete(0),
62 fDecodeIfCorruptedTrailer(kTRUE),
63 fIsDecoded(kFALSE),
64 fIsFatalCorruptedTrailer(kTRUE)
31a920d3 65{
ac672c4c 66 // Default constructor
31a920d3 67}
68
69
70AliAltroDecoder::~AliAltroDecoder()
71{
ac672c4c 72 // Default destructor
31a920d3 73}
74
75
ac672c4c 76Bool_t AliAltroDecoder::CheckPayloadTrailer() const
31a920d3 77{
86525f0f 78 //Check consistency between the number of 40 bit altro words given by
ac672c4c 79 //the RCU payload and the number of 40 bit words calculated from the size of the RCU payload.
80
31a920d3 81 if(fN40AltroWords != fN40RcuAltroWords)
82 {
83 return kFALSE;
84 }
85 else
86 {
87 return kTRUE;
88 }
89}
90
91
92Bool_t AliAltroDecoder::Decode()
ebf7cafe 93{
86525f0f 94 // Decodes the RCU payload (all altro channels in one go) from the DDL/Altro
95 // format to PC readable format.
96 // The 10 bit words of the 40/10 bit Altro format are transformed to separated
97 // integers.
ac672c4c 98
ebf7cafe 99 if( fIsFatalCorruptedTrailer == kTRUE)
31a920d3 100 {
987d6d62 101 // printf("\n AliAltroDecoder::Decode(), WARNING, attempt to decode badly corrupted data\n");
102 // printf("\n AliAltroDecoder::Decode(). Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n");
ebf7cafe 103 return kFALSE;
104 }
105
106 else
31a920d3 107 {
ebf7cafe 108 // see header file for class documentation
109 fComplete = 0;
110 fInComplete = 0;
111
ac672c4c 112 Int_t tmpcnt = CountAAApaddings();
31a920d3 113
ebf7cafe 114 if(tmpcnt == 3)
115 {
116 fN40AltroWords = fN40AltroWords -1;
117 }
118 else if(tmpcnt == 5)
119 {
120 fN40AltroWords = fN40AltroWords -2;
121 }
122 else if(tmpcnt == 8)
123 {
124 fN40AltroWords = fN40AltroWords -3;
125 }
31a920d3 126
ebf7cafe 127 if( ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE ) && (fSize > 32) )
31a920d3 128 {
ebf7cafe 129 // fDDLBlockCnt = 0;
130 fOutBufferIndex = 0;
131
132 for(Int_t i = 0; i < fNDDLBlocks; i++)
133 {
134 DecodeDDLBlock();
135 }
31a920d3 136
ebf7cafe 137 DecodeLastDDLBlock();
138 fOutBufferIndex = fN40AltroWords*4 - 1;
31a920d3 139
ebf7cafe 140 // DumpData(fOutBuffer, 400,4);
31a920d3 141
ebf7cafe 142 fIsDecoded = kTRUE;
143 return kTRUE;
144 }
145
146 else
147 {
987d6d62 148// cout <<" ERROR: data integrity check failed, discarding data" << endl;
149// cout << "Size of datablock is " << fSize << endl;
150// cout << "fN40AltroWords = " << fN40AltroWords << endl;
151// cout << "fN40RcuAltroWords = " << fN40RcuAltroWords << endl;
ebf7cafe 152 return kFALSE;
153 }
31a920d3 154
31a920d3 155 }
156}
157
158
159Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr)
160{
ac672c4c 161 // Reads the next altro channel in the RCU payload after the RCU payload
86525f0f 162 // has been decoded. The channels are read starting from the end (backlinked list)
163 // Returns kTRUE as long as ther are unread channels in the payload
164 // Returns kFALSE when all the channels have been read.
ac672c4c 165
ebf7cafe 166 if(fIsFatalCorruptedTrailer == kTRUE)
31a920d3 167 {
987d6d62 168 // printf("\n AliAltroDecoder::NextChannel(), WARNING, attempt to decode badly corrupted data\n");
169 // printf("\n AliAltroDecoder::NextChannel(), Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n");
ebf7cafe 170 return kFALSE;
171 }
172
173 else
31a920d3 174 {
31a920d3 175
ebf7cafe 176 if(fIsDecoded != kTRUE)
177 {
987d6d62 178 // cout <<"AliAltroDecoder::NextChanne, WARNING, buffer was not decoded, decoding now.. "<< endl;
ebf7cafe 179 Decode();
180 }
31a920d3 181
86525f0f 182 // an altro block must constist of at least 2 40bit words:
183 // - 40bit Altro trailer
184 // - at least 3 10bit words (bunch length, time bin, signal) padded to 40 bit
185 // we are reading backwards, so the index is already 1 inside the block
186 if(fOutBufferIndex >= 7)
31a920d3 187 {
ebf7cafe 188 if((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6) == 0x2aaa)
189 {
190 altroDataPtr->SetIsComplete(kTRUE);
191 fComplete ++;
192 }
193 else
194 {
195 altroDataPtr->SetIsComplete(kFALSE);
196 fInComplete ++;
197 }
198
199 fOutBufferIndex --;
200 fNAltro10bitWords = ( (fOutBuffer[fOutBufferIndex] & 0x3f) << 4 ) | ((fOutBuffer[fOutBufferIndex -1] & (0xF << 6)) >> 6) ;
201 fOutBufferIndex --;
202 altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ) );
203
204 fOutBufferIndex --;
205
206 if(fNAltro10bitWords%4 == 0)
207 {
208 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords;
209 }
210 else
211 {
212 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords -(4 - fNAltro10bitWords%4);
213 }
214
84111923 215
216 if(fOutBufferIndex > 0)
217 {
218
219 //cout << " AliAltroDecoder::NextChannel fOutBufferIndex =" << fOutBufferIndex << endl;
220 // printf( "AliAltroDecoder::NextChannel fOutBufferIndex = %d", fOutBufferIndex);
221 altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] );
222 fOutBufferIndex --;
223 altroDataPtr->SetDataSize( fNAltro10bitWords );
224 return kTRUE;
225 }
226 else
227 {
228 //TODO write a fatal log message when this happends
229 return kFALSE;
230 }
86525f0f 231
ebf7cafe 232
31a920d3 233 }
234 else
235 {
ebf7cafe 236 return kFALSE;
31a920d3 237 }
238
31a920d3 239 }
240}
241
31a920d3 242
ac672c4c 243Int_t AliAltroDecoder::CountAAApaddings() const
31a920d3 244{
ac672c4c 245 // Use for simulated data only.
246 // Patch for incorrectly simulated data. Counts the number of
247 // 2aaa word in the trailer of the payload and tries to figure out
248 // the correct number of 40 bit altro words in the RCU pauload
86525f0f 249 //
250 // The simulated raw data differs from the real data by a number
251 // of additional 0x2aa words between the Altro payload and the
252 // RCU trailer. This is most likely to bring the total number of
253 // bytes to a common multiple of 4 and 5.
ac672c4c 254
86525f0f 255 UShort_t *tailPtr= (UShort_t *)((UChar_t*)f32DtaPtr + f8PayloadSize);
31a920d3 256 Int_t cnt = 0;
257
258 tailPtr --;
259
260 while(*tailPtr == 0xaaaa)
261 {
262 cnt ++;
263 tailPtr --;
264 }
265
266 tailPtr = tailPtr + cnt +1;
267
268 return cnt;
269}
270
271
272Float_t AliAltroDecoder::GetFailureRate()
273{
ac672c4c 274 // Prints to stdout the percent of altroblocks that
275 // is missing the 2aaa trailer.
276
31a920d3 277 Float_t tmp = 0;
987d6d62 278 // cout << "Number of Complete channles = " << fComplete <<endl;
279 // cout << "Number of InComplete channles = " << fInComplete <<endl;
31a920d3 280 tmp = (100*(Float_t)fInComplete)/((Float_t)fComplete + (Float_t)fInComplete);
987d6d62 281 // cout <<"There are "<< tmp <<"% incomplete channels"<<endl;
31a920d3 282 return tmp;
283}
284
285
286void AliAltroDecoder::PrintInfo(AliAltroData &altrodata, Int_t n, Int_t nPerLine)
287{
ac672c4c 288 // prints data and address information contained in altrodata
289 // to the standard output
290
987d6d62 291 // cout << "altrodata.fDataSize = " << altrodata.GetDataSize() << endl;
292 // cout << "altrodata.fHadd = " << altrodata.GetHadd() <<endl;
31a920d3 293 const UInt_t* data = altrodata.GetData();
294 for(Int_t i= 0; i< n; i++)
295 {
296 if( (i%nPerLine == 0) && (i != 0) )
297 {
298 printf("\n");
299 }
300 printf("%d\t", data[i]);
301 }
302 printf("\n");
303}
304
305
ebf7cafe 306int AliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size)
31a920d3 307{
ac672c4c 308 // Sets the pointer to the memory block that should be decoded
309 // Returns a negative value if an inconsistency in the data is detected
310
84111923 311 if(dtaPtr == 0)
312 {
313 printf("\nAliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size) FATAL ERROR, dtaPtr = ZERO !!!!!!!!!!!!\n");
314 printf("\nThis is an user error, please check in your code that you don give a zero pointer to the decoder \n");
315 return -99;
316 }
317
318
ebf7cafe 319 int iRet = 0;
31a920d3 320 Int_t tmpTrailerSize;
321 fIsDecoded = kFALSE;
322 f8DtaPtr =dtaPtr;
323 fSize = size;
324 f8DtaPtr =f8DtaPtr + fSize;
325 f32DtaPtr = (UInt_t *)f8DtaPtr;
326 tmpTrailerSize = *(f32DtaPtr - 1);
327
328 if(tmpTrailerSize <= MAX_TRAILER_WORDS)
329 {
330 tmpTrailerSize = tmpTrailerSize; //assume that the last word of the buffer gives the number of trailer words
331 }
332 else
333 {
334 tmpTrailerSize = 1; //assume that last word is ONE, and that the this word gives the number of 40 bit altro words
335 }
336
86525f0f 337 f8PayloadSize = fSize - (fkN32HeaderWords + tmpTrailerSize)*4;
338 fN40AltroWords = f8PayloadSize/5;
339 fNDDLBlocks = fN40AltroWords/4;
340 f32LastDDLBlockSize = ((f8PayloadSize%(4*DDL_32BLOCK_SIZE))+3)/4;
ebf7cafe 341
342 if(tmpTrailerSize > 0 && tmpTrailerSize < 5)
343 {
344 f32DtaPtr = f32DtaPtr - tmpTrailerSize;
345 fN40RcuAltroWords = *f32DtaPtr;
ac672c4c 346 f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords;
ebf7cafe 347 fIsFatalCorruptedTrailer = kFALSE;
348 }
349 else
350 {
987d6d62 351 // printf("\n AliAltroDecoder::SetMemory, ERROR\n, trailer is corrupted");
ebf7cafe 352 fIsFatalCorruptedTrailer = kTRUE;
353 iRet = -1;
354 }
ebf7cafe 355
356 return iRet;
357
31a920d3 358}
359
360
361void AliAltroDecoder::DecodeDDLBlock()
362{
ac672c4c 363 //Decode one 160 bit DDL block into 16 x 16 bit integers (only least significant 10 bits are filled)
364
31a920d3 365 fOutBuffer[fOutBufferIndex] = *f32DtaPtr & 0x3ff; //s0
366 fOutBufferIndex ++;
367 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00) >> 10; //s1
368 fOutBufferIndex ++;
369 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00000) >> 20; //s2
370 fOutBufferIndex ++;
371 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xc0000000) >> 30; //s3_1
372 f32DtaPtr ++;
373 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xff) << 2); //s3_2
374 fOutBufferIndex ++;
375 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00) >> 8; //s4
376 fOutBufferIndex ++;
377 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0000) >> 18; //s5
378 fOutBufferIndex ++;
379 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xf0000000) >> 28; //s6_1
380 f32DtaPtr ++;
381 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3f) << 4); //s6_2
382 fOutBufferIndex ++;
383 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0) >> 6; //s7
384 fOutBufferIndex ++;
385 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0000) >> 16; //s8
386 fOutBufferIndex ++;
387 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xFC000000) >> 26; //s9_1
388 f32DtaPtr ++;
389 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xf) << 6); //s9_2
390 fOutBufferIndex ++;
391 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0) >> 4; //s10
392 fOutBufferIndex ++;
393 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc000) >> 14; //s11
394 fOutBufferIndex ++;
395 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xff000000) >> 24; //s12_1
396 f32DtaPtr ++;
397 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3) << 8); //s12_2
398 fOutBufferIndex ++;
399 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc) >> 2; //s13
400 fOutBufferIndex ++;
401 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff000) >> 12; //s14
402 fOutBufferIndex ++;
403 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00000) >> 22; //s15
404 f32DtaPtr ++;
405 fOutBufferIndex ++;
406}
407
408
409void AliAltroDecoder::DecodeLastDDLBlock()
410{
ac672c4c 411 // Decode one 160 bit DDL block into 16 integers.
412 // In order to use the same decoding function (DecodeDDLBlock())
413 // a copy of the the last DDL block is made and
414 // if the las block does not align with 160 bits then it is padded with zeroes
415
31a920d3 416 for(Int_t i=0; i < f32LastDDLBlockSize; i++)
417 {
418 fDDLBlockDummy[i] = *f32DtaPtr;
419 f32DtaPtr ++;
420 }
421
422 f32DtaPtr = fDDLBlockDummy;
31a920d3 423 DecodeDDLBlock();
86525f0f 424 f32DtaPtr=(UInt_t*)(f8DtaPtr-fSize+f8PayloadSize+fkN32HeaderWords*4);
425}
426
427Int_t AliAltroDecoder::CopyBackward(Byte_t* pBuffer, Int_t bufferSize)
428{
429 // Copy the original 10/40 bit encecoded data of the current channel.
430 // The funtions copies the data to the end of the provided buffer.
431 // @param pBuffer target buffer
432 // @param bufferSize size of target buffer
433 // @return number of copied bytes, neg. error code if failed
434 Int_t iCopy=0;
435
436 if(fIsDecoded != kTRUE) {
437 AliWarning("buffer has not been decoded, no channel data available");
438 return 0;
439 }
440
441 // This method does not need to be the fastest possible implementation
442 // For the sake of stability, there are a lot of consistency checks.
443
444 // the fOutBufferIndex always points to the next channel, since we are
445 // reading backwards, this is one byte before the start of the current
446 // channel.
447 Int_t currentIndex=fOutBufferIndex+1;
448 if (fNAltro10bitWords>0 && currentIndex < fN40AltroWords*4 ) {
449
450 // calculate the position in the encoded data, beginning right
451 // after the CDH. 10 -> 8 bit: needs 5/4 times the index
452 Int_t position=(currentIndex*5)/4;
453 if (position*4==currentIndex*5) {
454 // no of 10 bit words is without the fill words to fill complete 40 bit words
455 // in addition, align to complete 40 bit words (the '+3')
456 iCopy=((fNAltro10bitWords+3)/4)*5;
457
458 // calculate the source pointer in the encoded data
459 // f8DtaPtr was set to the end of the whole data buffer
460 // f32DtaPtr is behind the payload after decoding
461 Byte_t* pSrc=f8DtaPtr-fSize+(fkN32HeaderWords*4)+position;
462 if (pSrc+5<(Byte_t*)f32DtaPtr) {
463
464 // check the first byte of the source buffer, has to be consistent
465 // with the 8 LSBs of the decoded 10 bit word at the beginning of
466 // the current channel
467 //assert(*pSrc==fOutBuffer[currentIndex]&0xff);
468 if (*pSrc==fOutBuffer[currentIndex]&0xff) {
469
470 // try to verfify the length of the channel
ecc0795d 471 UInt_t lenCheck=*(pSrc+iCopy+2)|(*(pSrc+iCopy+3)&0x3)<<8;
86525f0f 472 if (lenCheck==fNAltro10bitWords) {
473
474 // copy including the 40 bit altro trailer
475 iCopy+=5;
476 if (iCopy<=bufferSize) {
477
478 // copy to the end of the buffer
479 Byte_t* pTgt=pBuffer+bufferSize-iCopy;
480 memcpy(pTgt, pSrc, iCopy);
481 } else {
482 AliError(Form("target buffer too small: available %d, required %d", bufferSize, iCopy));
483 iCopy=-1;
484 }
485 } else {
ecc0795d 486 AliWarning(Form("format error: can not reproduce channel length: expected %d, read %d", fNAltro10bitWords, lenCheck));
86525f0f 487 iCopy=-1;
488 }
489 } else {
490 AliError(Form("first byte of encoded data (%#x at %d) does not match decoded word (%#x at %d)", *pSrc, position, fOutBuffer[currentIndex]&0xff, currentIndex));
491 iCopy=-1;
492 }
493 } else {
494 AliError(Form("buffer size missmatch: payload ends at %p, but current channel pretends to end at %p", f32DtaPtr, pSrc+5));
495 iCopy=-1;
496 }
497 } else {
498 AliError(Form("current position does not match a byte: currentIndex=%d", currentIndex));
499 iCopy=-1;
500 }
501 }
502 return iCopy;
503}
504
505Bool_t AliAltroDecoder::GetRCUTrailerData(UChar_t*& data) const
506{
507 // Provide a pointer to RCU trailer.
508 // The type of the parameter might not be optimal, but the function has
509 // been chosen that way to be similar to the counterpart in
510 // AliAltroRawStream.
511 // @return kTRUE if trailer available;
512 if (!f8DtaPtr) return kFALSE;
513 data=f8DtaPtr-(fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t)));
514 assert((UChar_t*)f32DtaPtr == data);
515 return kTRUE;
516}
517
518Int_t AliAltroDecoder::GetRCUTrailerSize() const
519{
520 // Provide size of RCU trailer.
521 if (!f8DtaPtr) return 0;
522 assert(fSize>(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t)));
523 return fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t));
31a920d3 524}