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