]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/AliAltroDecoder.cxx
added library definition for libHLTshuttle
[u/mrichter/AliRoot.git] / RAW / AliAltroDecoder.cxx
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>                 *
6  *                  Ã\98ystein Djuvsland <oystein.djuvsland@gmail.com>       *
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
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
36 ClassImp(AliAltroDecoder)
37
38 AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0),
39                                      f8DtaPtr(0),
40                                      fkN32HeaderWords(8), 
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) 
54 {
55  // Default constructor
56 }
57
58
59 AliAltroDecoder::~AliAltroDecoder()
60 {
61   // Default destructor
62 }
63
64
65 Bool_t AliAltroDecoder::CheckPayloadTrailer() const
66 {
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
70   if(fN40AltroWords != fN40RcuAltroWords)
71     {
72       return  kFALSE;
73     } 
74   else
75     {
76       return kTRUE;
77     }
78 }
79
80
81 Bool_t AliAltroDecoder::Decode()
82
83   // Decodes the RCU payload (all altro channels in one go) from the DDL format to
84   // PC readable form
85
86   if( fIsFatalCorruptedTrailer == kTRUE)
87     {
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
94     {
95       // see header file for class documentation
96       fComplete = 0;
97       fInComplete = 0;
98
99       Int_t tmpcnt = CountAAApaddings();
100   
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         } 
113
114       if(  ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE  )  &&  (fSize > 32) )
115         {
116           //      fDDLBlockCnt = 0;
117           fOutBufferIndex = 0;
118
119           for(Int_t i = 0; i < fNDDLBlocks; i++)
120             {
121               DecodeDDLBlock();
122             }
123
124           DecodeLastDDLBlock(); 
125           fOutBufferIndex =  fN40AltroWords*4  -  1;
126   
127           //      DumpData(fOutBuffer, 400,4);
128     
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         }
141
142     }
143 }
144
145
146 Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr)
147 {
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
153   if(fIsFatalCorruptedTrailer == kTRUE)
154     {
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
161     {
162
163       if(fIsDecoded != kTRUE)
164         {
165           cout <<"AliAltroDecoder::NextChanne, WARNING, buffer was not decoded, decoding now.. "<< endl;
166           Decode();
167         }
168
169       if(fOutBufferIndex >  fkN32HeaderWords)
170         {
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
204         }
205       else
206         {
207           return kFALSE;
208         }
209
210     }
211 }
212
213
214 Int_t AliAltroDecoder::CountAAApaddings() const
215 {
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  
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
238 Float_t AliAltroDecoder::GetFailureRate()
239 {
240   // Prints to stdout the percent of altroblocks that
241   // is missing the 2aaa trailer.
242  
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
252 void AliAltroDecoder::PrintInfo(AliAltroData &altrodata, Int_t n, Int_t nPerLine)
253 {
254   // prints data and address information contained in altrodata 
255   // to the standard output
256
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
272 int AliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size)
273 {
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
277   int iRet = 0;
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
295   f32PayloadSize = fSize/4 -  (fkN32HeaderWords +  tmpTrailerSize);
296   fN40AltroWords = (32*f32PayloadSize)/40; 
297   fNDDLBlocks =  f32PayloadSize/5;
298   f32LastDDLBlockSize =  f32PayloadSize%DDL_32BLOCK_SIZE;
299
300   if(tmpTrailerSize > 0 && tmpTrailerSize < 5)
301     {
302       f32DtaPtr =  f32DtaPtr -  tmpTrailerSize;
303       fN40RcuAltroWords =  *f32DtaPtr;
304       f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords;
305       fIsFatalCorruptedTrailer = kFALSE; 
306     }
307   else
308     {
309       printf("\n AliAltroDecoder::SetMemory, ERROR\n, trailer is corrupted");
310       fIsFatalCorruptedTrailer = kTRUE;
311       iRet = -1;
312     }
313   
314   return iRet;
315
316 }
317
318
319 void AliAltroDecoder::DecodeDDLBlock()
320 {
321   //Decode one 160 bit DDL block into 16 x 16 bit integers (only least significant 10 bits are filled)
322
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
367 void AliAltroDecoder::DecodeLastDDLBlock()
368 {
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
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 }