1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
5 * Primary Authors: Per Thomas Hille <perthi@fys.uio.no> *
6 * Ã
\98ystein Djuvsland <oystein.djuvsland@gmail.com> *
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 **************************************************************************/
17 #include <Riostream.h>
18 #include "AliAltroDecoder.h"
19 #include "AliAltroData.h"
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
36 ClassImp(AliAltroDecoder)
38 AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0),
44 f32LastDDLBlockSize(5),
51 fDecodeIfCorruptedTrailer(kTRUE),
53 fIsFatalCorruptedTrailer(kTRUE)
55 // Default constructor
59 AliAltroDecoder::~AliAltroDecoder()
65 Bool_t AliAltroDecoder::CheckPayloadTrailer() const
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.
70 if(fN40AltroWords != fN40RcuAltroWords)
81 Bool_t AliAltroDecoder::Decode()
83 // Decodes the RCU payload (all altro channels in one go) from the DDL format to
86 if( fIsFatalCorruptedTrailer == kTRUE)
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");
95 // see header file for class documentation
99 Int_t tmpcnt = CountAAApaddings();
103 fN40AltroWords = fN40AltroWords -1;
107 fN40AltroWords = fN40AltroWords -2;
111 fN40AltroWords = fN40AltroWords -3;
114 if( ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE ) && (fSize > 32) )
119 for(Int_t i = 0; i < fNDDLBlocks; i++)
124 DecodeLastDDLBlock();
125 fOutBufferIndex = fN40AltroWords*4 - 1;
127 // DumpData(fOutBuffer, 400,4);
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;
146 Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr)
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.
153 if(fIsFatalCorruptedTrailer == kTRUE)
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");
163 if(fIsDecoded != kTRUE)
165 cout <<"AliAltroDecoder::NextChanne, WARNING, buffer was not decoded, decoding now.. "<< endl;
169 if(fOutBufferIndex > fkN32HeaderWords)
171 if((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6) == 0x2aaa)
173 altroDataPtr->SetIsComplete(kTRUE);
178 altroDataPtr->SetIsComplete(kFALSE);
183 fNAltro10bitWords = ( (fOutBuffer[fOutBufferIndex] & 0x3f) << 4 ) | ((fOutBuffer[fOutBufferIndex -1] & (0xF << 6)) >> 6) ;
185 altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ) );
189 if(fNAltro10bitWords%4 == 0)
191 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords;
195 fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords -(4 - fNAltro10bitWords%4);
199 altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] );
201 altroDataPtr->SetDataSize( fNAltro10bitWords );
214 Int_t AliAltroDecoder::CountAAApaddings() const
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
221 UShort_t *tailPtr= (UShort_t *)(f32DtaPtr +f32PayloadSize);
226 while(*tailPtr == 0xaaaa)
232 tailPtr = tailPtr + cnt +1;
238 Float_t AliAltroDecoder::GetFailureRate()
240 // Prints to stdout the percent of altroblocks that
241 // is missing the 2aaa trailer.
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;
252 void AliAltroDecoder::PrintInfo(AliAltroData &altrodata, Int_t n, Int_t nPerLine)
254 // prints data and address information contained in altrodata
255 // to the standard output
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++)
262 if( (i%nPerLine == 0) && (i != 0) )
266 printf("%d\t", data[i]);
272 int AliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size)
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
278 Int_t tmpTrailerSize;
282 f8DtaPtr =f8DtaPtr + fSize;
283 f32DtaPtr = (UInt_t *)f8DtaPtr;
284 tmpTrailerSize = *(f32DtaPtr - 1);
286 if(tmpTrailerSize <= MAX_TRAILER_WORDS)
288 tmpTrailerSize = tmpTrailerSize; //assume that the last word of the buffer gives the number of trailer words
292 tmpTrailerSize = 1; //assume that last word is ONE, and that the this word gives the number of 40 bit altro words
295 f32PayloadSize = fSize/4 - (fkN32HeaderWords + tmpTrailerSize);
296 fN40AltroWords = (32*f32PayloadSize)/40;
297 fNDDLBlocks = f32PayloadSize/5;
298 f32LastDDLBlockSize = f32PayloadSize%DDL_32BLOCK_SIZE;
300 if(tmpTrailerSize > 0 && tmpTrailerSize < 5)
302 f32DtaPtr = f32DtaPtr - tmpTrailerSize;
303 fN40RcuAltroWords = *f32DtaPtr;
304 f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords;
305 fIsFatalCorruptedTrailer = kFALSE;
309 printf("\n AliAltroDecoder::SetMemory, ERROR\n, trailer is corrupted");
310 fIsFatalCorruptedTrailer = kTRUE;
319 void AliAltroDecoder::DecodeDDLBlock()
321 //Decode one 160 bit DDL block into 16 x 16 bit integers (only least significant 10 bits are filled)
323 fOutBuffer[fOutBufferIndex] = *f32DtaPtr & 0x3ff; //s0
325 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00) >> 10; //s1
327 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00000) >> 20; //s2
329 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xc0000000) >> 30; //s3_1
331 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xff) << 2); //s3_2
333 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00) >> 8; //s4
335 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0000) >> 18; //s5
337 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xf0000000) >> 28; //s6_1
339 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3f) << 4); //s6_2
341 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0) >> 6; //s7
343 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0000) >> 16; //s8
345 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xFC000000) >> 26; //s9_1
347 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xf) << 6); //s9_2
349 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0) >> 4; //s10
351 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc000) >> 14; //s11
353 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xff000000) >> 24; //s12_1
355 fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3) << 8); //s12_2
357 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc) >> 2; //s13
359 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff000) >> 12; //s14
361 fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00000) >> 22; //s15
367 void AliAltroDecoder::DecodeLastDDLBlock()
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
374 for(Int_t i=0; i < f32LastDDLBlockSize; i++)
376 fDDLBlockDummy[i] = *f32DtaPtr;
380 f32DtaPtr = fDDLBlockDummy;