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