]>
Commit | Line | Data |
---|---|---|
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 | 47 | ClassImp(AliAltroDecoder) |
48 | ||
49 | AliAltroDecoder::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), | |
44443c72 | 64 | fIsFatalCorruptedTrailer(kTRUE) |
65 | // fIsFirstChannelOfPayload(kTRUE) | |
31a920d3 | 66 | { |
ac672c4c | 67 | // Default constructor |
da42bffc | 68 | memset(fOutBuffer, 0, sizeof(fOutBuffer)); |
69 | memset(fDDLBlockDummy, 0, sizeof(fDDLBlockDummy)); | |
31a920d3 | 70 | } |
71 | ||
72 | ||
73 | AliAltroDecoder::~AliAltroDecoder() | |
74 | { | |
ac672c4c | 75 | // Default destructor |
31a920d3 | 76 | } |
77 | ||
78 | ||
ac672c4c | 79 | Bool_t AliAltroDecoder::CheckPayloadTrailer() const |
31a920d3 | 80 | { |
86525f0f | 81 | //Check consistency between the number of 40 bit altro words given by |
ac672c4c | 82 | //the RCU payload and the number of 40 bit words calculated from the size of the RCU payload. |
83 | ||
31a920d3 | 84 | if(fN40AltroWords != fN40RcuAltroWords) |
85 | { | |
86 | return kFALSE; | |
87 | } | |
88 | else | |
89 | { | |
90 | return kTRUE; | |
91 | } | |
92 | } | |
93 | ||
94 | ||
95 | Bool_t AliAltroDecoder::Decode() | |
ebf7cafe | 96 | { |
be9a8bd4 | 97 | // Decodes the RCU payload (all altro channels in one go) from the DDL/Altro |
98 | // format to PC readable format. | |
99 | // The 10 bit words of the 40/10 bit Altro format are transformed to separated | |
100 | // integers. | |
101 | ||
ebf7cafe | 102 | if( fIsFatalCorruptedTrailer == kTRUE) |
31a920d3 | 103 | { |
987d6d62 | 104 | // printf("\n AliAltroDecoder::Decode(), WARNING, attempt to decode badly corrupted data\n"); |
105 | // printf("\n AliAltroDecoder::Decode(). Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n"); | |
ebf7cafe | 106 | return kFALSE; |
107 | } | |
817c796a | 108 | else if (!f8DtaPtr || !f32DtaPtr || |
109 | (UChar_t*)f32DtaPtr < f8DtaPtr-fSize || | |
110 | (UChar_t*)f32DtaPtr > f8DtaPtr) | |
111 | { | |
112 | return kFALSE; | |
113 | } | |
ebf7cafe | 114 | else |
31a920d3 | 115 | { |
ebf7cafe | 116 | // see header file for class documentation |
117 | fComplete = 0; | |
118 | fInComplete = 0; | |
119 | ||
ac672c4c | 120 | Int_t tmpcnt = CountAAApaddings(); |
31a920d3 | 121 | |
ebf7cafe | 122 | if(tmpcnt == 3) |
123 | { | |
124 | fN40AltroWords = fN40AltroWords -1; | |
125 | } | |
126 | else if(tmpcnt == 5) | |
127 | { | |
128 | fN40AltroWords = fN40AltroWords -2; | |
129 | } | |
130 | else if(tmpcnt == 8) | |
131 | { | |
132 | fN40AltroWords = fN40AltroWords -3; | |
133 | } | |
31a920d3 | 134 | |
ebf7cafe | 135 | if( ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE ) && (fSize > 32) ) |
31a920d3 | 136 | { |
ebf7cafe | 137 | fOutBufferIndex = 0; |
138 | ||
139 | for(Int_t i = 0; i < fNDDLBlocks; i++) | |
140 | { | |
141 | DecodeDDLBlock(); | |
142 | } | |
31a920d3 | 143 | |
ebf7cafe | 144 | DecodeLastDDLBlock(); |
145 | fOutBufferIndex = fN40AltroWords*4 - 1; | |
ebf7cafe | 146 | fIsDecoded = kTRUE; |
147 | return kTRUE; | |
148 | } | |
149 | ||
150 | else | |
151 | { | |
987d6d62 | 152 | // cout <<" ERROR: data integrity check failed, discarding data" << endl; |
153 | // cout << "Size of datablock is " << fSize << endl; | |
154 | // cout << "fN40AltroWords = " << fN40AltroWords << endl; | |
155 | // cout << "fN40RcuAltroWords = " << fN40RcuAltroWords << endl; | |
ebf7cafe | 156 | return kFALSE; |
157 | } | |
49f90cc3 | 158 | |
31a920d3 | 159 | } |
160 | } | |
161 | ||
162 | ||
44443c72 | 163 | |
164 | ||
31a920d3 | 165 | Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr) |
166 | { | |
be9a8bd4 | 167 | // Reads the next altro channel in the RCU payload after the RCU payload |
168 | // has been decoded. The channels are read starting from the end (backlinked list) | |
169 | // Returns kTRUE as long as ther are unread channels in the payload | |
170 | // Returns kFALSE when all the channels have been read. | |
171 | ||
ebf7cafe | 172 | if(fIsFatalCorruptedTrailer == kTRUE) |
31a920d3 | 173 | { |
ebf7cafe | 174 | return kFALSE; |
175 | } | |
176 | ||
177 | else | |
31a920d3 | 178 | { |
31a920d3 | 179 | |
ebf7cafe | 180 | if(fIsDecoded != kTRUE) |
181 | { | |
ebf7cafe | 182 | Decode(); |
183 | } | |
31a920d3 | 184 | |
be9a8bd4 | 185 | // an altro block must constist of at least 2 40bit words: |
186 | // - 40bit Altro trailer | |
187 | // - at least 3 10bit words (bunch length, time bin, signal) padded to 40 bit | |
188 | // we are reading backwards, so the index is already 1 inside the block | |
86525f0f | 189 | if(fOutBufferIndex >= 7) |
31a920d3 | 190 | { |
d3f2a99e | 191 | if(((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6)) == 0x2aaa) |
ebf7cafe | 192 | { |
193 | altroDataPtr->SetIsComplete(kTRUE); | |
194 | fComplete ++; | |
195 | } | |
196 | else | |
197 | { | |
198 | altroDataPtr->SetIsComplete(kFALSE); | |
199 | fInComplete ++; | |
200 | } | |
201 | ||
202 | fOutBufferIndex --; | |
203 | fNAltro10bitWords = ( (fOutBuffer[fOutBufferIndex] & 0x3f) << 4 ) | ((fOutBuffer[fOutBufferIndex -1] & (0xF << 6)) >> 6) ; | |
204 | fOutBufferIndex --; | |
44443c72 | 205 | altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ), fOutBufferIndex); |
ebf7cafe | 206 | |
207 | fOutBufferIndex --; | |
208 | ||
209 | if(fNAltro10bitWords%4 == 0) | |
210 | { | |
211 | fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords; | |
212 | } | |
213 | else | |
214 | { | |
215 | fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords -(4 - fNAltro10bitWords%4); | |
216 | } | |
84111923 | 217 | |
49f90cc3 | 218 | if(fOutBufferIndex >= 0) |
84111923 | 219 | { |
84111923 | 220 | altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] ); |
be9a8bd4 | 221 | fOutBufferIndex --; |
84111923 | 222 | altroDataPtr->SetDataSize( fNAltro10bitWords ); |
223 | return kTRUE; | |
224 | } | |
225 | else | |
226 | { | |
227 | //TODO write a fatal log message when this happends | |
228 | return kFALSE; | |
229 | } | |
86525f0f | 230 | |
31a920d3 | 231 | } |
232 | else | |
233 | { | |
ebf7cafe | 234 | return kFALSE; |
31a920d3 | 235 | } |
236 | ||
31a920d3 | 237 | } |
238 | } | |
239 | ||
31a920d3 | 240 | |
ac672c4c | 241 | Int_t AliAltroDecoder::CountAAApaddings() const |
31a920d3 | 242 | { |
ac672c4c | 243 | // Use for simulated data only. |
244 | // Patch for incorrectly simulated data. Counts the number of | |
245 | // 2aaa word in the trailer of the payload and tries to figure out | |
246 | // the correct number of 40 bit altro words in the RCU pauload | |
86525f0f | 247 | // |
248 | // The simulated raw data differs from the real data by a number | |
249 | // of additional 0x2aa words between the Altro payload and the | |
250 | // RCU trailer. This is most likely to bring the total number of | |
251 | // bytes to a common multiple of 4 and 5. | |
ac672c4c | 252 | |
86525f0f | 253 | UShort_t *tailPtr= (UShort_t *)((UChar_t*)f32DtaPtr + f8PayloadSize); |
31a920d3 | 254 | Int_t cnt = 0; |
255 | ||
256 | tailPtr --; | |
257 | ||
258 | while(*tailPtr == 0xaaaa) | |
259 | { | |
260 | cnt ++; | |
261 | tailPtr --; | |
262 | } | |
263 | ||
264 | tailPtr = tailPtr + cnt +1; | |
265 | ||
266 | return cnt; | |
267 | } | |
268 | ||
269 | ||
270 | Float_t AliAltroDecoder::GetFailureRate() | |
271 | { | |
ac672c4c | 272 | // Prints to stdout the percent of altroblocks that |
273 | // is missing the 2aaa trailer. | |
274 | ||
31a920d3 | 275 | Float_t tmp = 0; |
987d6d62 | 276 | // cout << "Number of Complete channles = " << fComplete <<endl; |
277 | // cout << "Number of InComplete channles = " << fInComplete <<endl; | |
31a920d3 | 278 | tmp = (100*(Float_t)fInComplete)/((Float_t)fComplete + (Float_t)fInComplete); |
987d6d62 | 279 | // cout <<"There are "<< tmp <<"% incomplete channels"<<endl; |
31a920d3 | 280 | return tmp; |
281 | } | |
282 | ||
283 | ||
44443c72 | 284 | |
31a920d3 | 285 | void AliAltroDecoder::PrintInfo(AliAltroData &altrodata, Int_t n, Int_t nPerLine) |
286 | { | |
ac672c4c | 287 | // prints data and address information contained in altrodata |
288 | // to the standard output | |
289 | ||
987d6d62 | 290 | // cout << "altrodata.fDataSize = " << altrodata.GetDataSize() << endl; |
291 | // cout << "altrodata.fHadd = " << altrodata.GetHadd() <<endl; | |
31a920d3 | 292 | const UInt_t* data = altrodata.GetData(); |
293 | for(Int_t i= 0; i< n; i++) | |
294 | { | |
295 | if( (i%nPerLine == 0) && (i != 0) ) | |
296 | { | |
297 | printf("\n"); | |
298 | } | |
299 | printf("%d\t", data[i]); | |
300 | } | |
301 | printf("\n"); | |
302 | } | |
303 | ||
304 | ||
ebf7cafe | 305 | int AliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size) |
31a920d3 | 306 | { |
ac672c4c | 307 | // Sets the pointer to the memory block that should be decoded |
308 | // Returns a negative value if an inconsistency in the data is detected | |
309 | ||
44443c72 | 310 | // fIsFirstChannelOfPayload = kTRUE; |
be9a8bd4 | 311 | int iRet = 0; |
312 | fIsDecoded = kFALSE; | |
44443c72 | 313 | |
84111923 | 314 | if(dtaPtr == 0) |
315 | { | |
44443c72 | 316 | // printf("\nAliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size) FATAL ERROR, dtaPtr = ZERO !!!!!!!!!!!!\n"); |
317 | // printf("Please check your code that you don't give a zero pointer to the decoder \n"); | |
84111923 | 318 | return -99; |
319 | } | |
320 | ||
d3f2a99e | 321 | if ((Int_t)size<(fkN32HeaderWords+1)*4) |
49f90cc3 | 322 | { |
44443c72 | 323 | // printf("\nAliAltroDecoder::SetMemory(UChar_t *dtaPtr, UInt_t size) FATAL ERROR, too little data (%d)\n", size); |
324 | // printf("Data buffer must contain the CDH and at least one 32bit RCU trailer word\n"); | |
49f90cc3 | 325 | return -99; |
326 | } | |
327 | ||
49f90cc3 | 328 | UInt_t tmpTrailerSize; |
31a920d3 | 329 | f8DtaPtr =dtaPtr; |
330 | fSize = size; | |
331 | f8DtaPtr =f8DtaPtr + fSize; | |
332 | f32DtaPtr = (UInt_t *)f8DtaPtr; | |
49f90cc3 | 333 | tmpTrailerSize = *(f32DtaPtr - 1); |
334 | ||
335 | // format of the trailer has been fixed in the RCU FW2 | |
336 | // Bit 31 to 16: 0xaaaa (16 bit) | |
337 | // Bit 15 to 7: RCU address ( 9 bit) | |
338 | // Bit 6 to 0: Trailer length ( 7 bit) | |
339 | // | |
340 | // RCU FW1 has one trailer word containing the number of | |
341 | // 10bit Altro words. According to some early documents, | |
342 | // it should have at least 2 32bit words: trailer length and | |
343 | // the number of 10bit Altro words. This is the format of | |
344 | // the simulation at time of writing (June 2008) | |
345 | bool haveFw2=false; | |
346 | if ((tmpTrailerSize>>16)==0xaaaa) { | |
347 | haveFw2=true; | |
348 | tmpTrailerSize = tmpTrailerSize&0x7f; // 7 LSBs of the last word | |
349 | } else | |
31a920d3 | 350 | if(tmpTrailerSize <= MAX_TRAILER_WORDS) |
351 | { | |
352 | tmpTrailerSize = tmpTrailerSize; //assume that the last word of the buffer gives the number of trailer words | |
353 | } | |
49f90cc3 | 354 | // nof 10bit AltroWords * 5/4 + bytes in the CDH + 4 bytes RCU trailer |
355 | else if (((*(f32DtaPtr-1)*5)/4 + fkN32HeaderWords*4 + 4)<=fSize) | |
31a920d3 | 356 | { |
357 | tmpTrailerSize = 1; //assume that last word is ONE, and that the this word gives the number of 40 bit altro words | |
358 | } | |
49f90cc3 | 359 | else |
360 | { | |
361 | tmpTrailerSize=0; | |
362 | fIsFatalCorruptedTrailer = kTRUE; | |
363 | iRet = -1; | |
364 | } | |
31a920d3 | 365 | |
49f90cc3 | 366 | if(tmpTrailerSize > 0 && (fkN32HeaderWords + tmpTrailerSize)*4<=fSize) |
ebf7cafe | 367 | { |
49f90cc3 | 368 | f8PayloadSize = fSize - (fkN32HeaderWords + tmpTrailerSize)*4; |
369 | fN40AltroWords = f8PayloadSize/5; | |
370 | fNDDLBlocks = fN40AltroWords/4; | |
371 | f32LastDDLBlockSize = ((f8PayloadSize%(4*DDL_32BLOCK_SIZE))+3)/4; | |
372 | ||
ebf7cafe | 373 | f32DtaPtr = f32DtaPtr - tmpTrailerSize; |
374 | fN40RcuAltroWords = *f32DtaPtr; | |
ac672c4c | 375 | f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords; |
ebf7cafe | 376 | fIsFatalCorruptedTrailer = kFALSE; |
ebf7cafe | 377 | } |
817c796a | 378 | |
379 | // all subsequent consistency checks depend on the correct initialization | |
380 | // of the pointer and size variables | |
381 | assert(f8DtaPtr == dtaPtr + fSize); | |
ebf7cafe | 382 | return iRet; |
383 | ||
31a920d3 | 384 | } |
385 | ||
386 | ||
387 | void AliAltroDecoder::DecodeDDLBlock() | |
388 | { | |
ac672c4c | 389 | //Decode one 160 bit DDL block into 16 x 16 bit integers (only least significant 10 bits are filled) |
390 | ||
31a920d3 | 391 | fOutBuffer[fOutBufferIndex] = *f32DtaPtr & 0x3ff; //s0 |
392 | fOutBufferIndex ++; | |
393 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00) >> 10; //s1 | |
394 | fOutBufferIndex ++; | |
395 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00000) >> 20; //s2 | |
396 | fOutBufferIndex ++; | |
397 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xc0000000) >> 30; //s3_1 | |
398 | f32DtaPtr ++; | |
399 | fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xff) << 2); //s3_2 | |
400 | fOutBufferIndex ++; | |
401 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff00) >> 8; //s4 | |
402 | fOutBufferIndex ++; | |
403 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0000) >> 18; //s5 | |
404 | fOutBufferIndex ++; | |
405 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xf0000000) >> 28; //s6_1 | |
406 | f32DtaPtr ++; | |
407 | fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3f) << 4); //s6_2 | |
408 | fOutBufferIndex ++; | |
409 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc0) >> 6; //s7 | |
410 | fOutBufferIndex ++; | |
411 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0000) >> 16; //s8 | |
412 | fOutBufferIndex ++; | |
413 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xFC000000) >> 26; //s9_1 | |
414 | f32DtaPtr ++; | |
415 | fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0xf) << 6); //s9_2 | |
416 | fOutBufferIndex ++; | |
417 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff0) >> 4; //s10 | |
418 | fOutBufferIndex ++; | |
419 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc000) >> 14; //s11 | |
420 | fOutBufferIndex ++; | |
421 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xff000000) >> 24; //s12_1 | |
422 | f32DtaPtr ++; | |
423 | fOutBuffer[fOutBufferIndex] = fOutBuffer[fOutBufferIndex] | ((*f32DtaPtr & 0x3) << 8); //s12_2 | |
424 | fOutBufferIndex ++; | |
425 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc) >> 2; //s13 | |
426 | fOutBufferIndex ++; | |
427 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0x3ff000) >> 12; //s14 | |
428 | fOutBufferIndex ++; | |
429 | fOutBuffer[fOutBufferIndex] = (*f32DtaPtr & 0xffc00000) >> 22; //s15 | |
430 | f32DtaPtr ++; | |
431 | fOutBufferIndex ++; | |
432 | } | |
433 | ||
434 | ||
44443c72 | 435 | |
436 | ||
437 | ||
438 | ||
439 | ||
440 | ||
31a920d3 | 441 | void AliAltroDecoder::DecodeLastDDLBlock() |
442 | { | |
ac672c4c | 443 | // Decode one 160 bit DDL block into 16 integers. |
444 | // In order to use the same decoding function (DecodeDDLBlock()) | |
445 | // a copy of the the last DDL block is made and | |
44443c72 | 446 | // if the last block does not align with 160 bits then it is padded with zeroes |
ac672c4c | 447 | |
31a920d3 | 448 | for(Int_t i=0; i < f32LastDDLBlockSize; i++) |
449 | { | |
450 | fDDLBlockDummy[i] = *f32DtaPtr; | |
451 | f32DtaPtr ++; | |
452 | } | |
453 | ||
454 | f32DtaPtr = fDDLBlockDummy; | |
31a920d3 | 455 | DecodeDDLBlock(); |
86525f0f | 456 | f32DtaPtr=(UInt_t*)(f8DtaPtr-fSize+f8PayloadSize+fkN32HeaderWords*4); |
457 | } | |
458 | ||
44443c72 | 459 | |
460 | ||
461 | ||
462 | ||
463 | ||
464 | ||
465 | ||
466 | ||
467 | ||
468 | ||
469 | ||
470 | ||
471 | ||
472 | ||
473 | ||
474 | ||
475 | ||
476 | ||
477 | ||
478 | ||
479 | ||
480 | ||
481 | ||
482 | ||
483 | ||
484 | ||
485 | ||
486 | ||
86525f0f | 487 | Int_t AliAltroDecoder::CopyBackward(Byte_t* pBuffer, Int_t bufferSize) |
488 | { | |
489 | // Copy the original 10/40 bit encecoded data of the current channel. | |
490 | // The funtions copies the data to the end of the provided buffer. | |
491 | // @param pBuffer target buffer | |
492 | // @param bufferSize size of target buffer | |
493 | // @return number of copied bytes, neg. error code if failed | |
494 | Int_t iCopy=0; | |
495 | ||
496 | if(fIsDecoded != kTRUE) { | |
497 | AliWarning("buffer has not been decoded, no channel data available"); | |
498 | return 0; | |
499 | } | |
500 | ||
501 | // This method does not need to be the fastest possible implementation | |
502 | // For the sake of stability, there are a lot of consistency checks. | |
503 | ||
504 | // the fOutBufferIndex always points to the next channel, since we are | |
505 | // reading backwards, this is one byte before the start of the current | |
506 | // channel. | |
507 | Int_t currentIndex=fOutBufferIndex+1; | |
508 | if (fNAltro10bitWords>0 && currentIndex < fN40AltroWords*4 ) { | |
509 | ||
510 | // calculate the position in the encoded data, beginning right | |
511 | // after the CDH. 10 -> 8 bit: needs 5/4 times the index | |
512 | Int_t position=(currentIndex*5)/4; | |
513 | if (position*4==currentIndex*5) { | |
514 | // no of 10 bit words is without the fill words to fill complete 40 bit words | |
515 | // in addition, align to complete 40 bit words (the '+3') | |
516 | iCopy=((fNAltro10bitWords+3)/4)*5; | |
517 | ||
518 | // calculate the source pointer in the encoded data | |
519 | // f8DtaPtr was set to the end of the whole data buffer | |
520 | // f32DtaPtr is behind the payload after decoding | |
521 | Byte_t* pSrc=f8DtaPtr-fSize+(fkN32HeaderWords*4)+position; | |
522 | if (pSrc+5<(Byte_t*)f32DtaPtr) { | |
523 | ||
524 | // check the first byte of the source buffer, has to be consistent | |
525 | // with the 8 LSBs of the decoded 10 bit word at the beginning of | |
526 | // the current channel | |
527 | //assert(*pSrc==fOutBuffer[currentIndex]&0xff); | |
be9a8bd4 | 528 | if (*pSrc==(fOutBuffer[currentIndex]&0xff)) { |
86525f0f | 529 | |
530 | // try to verfify the length of the channel | |
ecc0795d | 531 | UInt_t lenCheck=*(pSrc+iCopy+2)|(*(pSrc+iCopy+3)&0x3)<<8; |
86525f0f | 532 | if (lenCheck==fNAltro10bitWords) { |
533 | ||
534 | // copy including the 40 bit altro trailer | |
535 | iCopy+=5; | |
536 | if (iCopy<=bufferSize) { | |
537 | ||
538 | // copy to the end of the buffer | |
539 | Byte_t* pTgt=pBuffer+bufferSize-iCopy; | |
540 | memcpy(pTgt, pSrc, iCopy); | |
541 | } else { | |
542 | AliError(Form("target buffer too small: available %d, required %d", bufferSize, iCopy)); | |
543 | iCopy=-1; | |
544 | } | |
545 | } else { | |
ecc0795d | 546 | AliWarning(Form("format error: can not reproduce channel length: expected %d, read %d", fNAltro10bitWords, lenCheck)); |
86525f0f | 547 | iCopy=-1; |
548 | } | |
549 | } else { | |
550 | AliError(Form("first byte of encoded data (%#x at %d) does not match decoded word (%#x at %d)", *pSrc, position, fOutBuffer[currentIndex]&0xff, currentIndex)); | |
551 | iCopy=-1; | |
552 | } | |
553 | } else { | |
554 | AliError(Form("buffer size missmatch: payload ends at %p, but current channel pretends to end at %p", f32DtaPtr, pSrc+5)); | |
555 | iCopy=-1; | |
556 | } | |
557 | } else { | |
558 | AliError(Form("current position does not match a byte: currentIndex=%d", currentIndex)); | |
559 | iCopy=-1; | |
560 | } | |
561 | } | |
562 | return iCopy; | |
563 | } | |
564 | ||
565 | Bool_t AliAltroDecoder::GetRCUTrailerData(UChar_t*& data) const | |
566 | { | |
567 | // Provide a pointer to RCU trailer. | |
568 | // The type of the parameter might not be optimal, but the function has | |
569 | // been chosen that way to be similar to the counterpart in | |
570 | // AliAltroRawStream. | |
571 | // @return kTRUE if trailer available; | |
572 | if (!f8DtaPtr) return kFALSE; | |
573 | data=f8DtaPtr-(fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t))); | |
574 | assert((UChar_t*)f32DtaPtr == data); | |
575 | return kTRUE; | |
576 | } | |
577 | ||
578 | Int_t AliAltroDecoder::GetRCUTrailerSize() const | |
579 | { | |
580 | // Provide size of RCU trailer. | |
be9a8bd4 | 581 | if (!f8DtaPtr || !fIsDecoded || fSize==0) return 0; |
86525f0f | 582 | assert(fSize>(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t))); |
583 | return fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t)); | |
31a920d3 | 584 | } |