Bug fix for https://savannah.cern.ch/bugs/?86055, crashing global trigger component.
[u/mrichter/AliRoot.git] / HLT / TPCLib / HWCFemulator / AliHLTTPCHWCFSupport.cxx
CommitLineData
33861fe0 1// $Id$
c012881c 2//****************************************************************************
3//* This file is property of and copyright by the ALICE HLT Project *
4//* ALICE Experiment at CERN, All rights reserved. *
5//* *
6//* Primary Authors: Sergey Gorbunov, Torsten Alt *
7//* Developers: Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
8//* Torsten Alt <talt@cern.ch> *
9//* for The ALICE HLT Project. *
10//* *
11//* Permission to use, copy, modify and distribute this software and its *
12//* documentation strictly for non-commercial purposes is hereby granted *
13//* without fee, provided that the above copyright notice appears in all *
14//* copies and that both the copyright notice and this permission notice *
15//* appear in the supporting documentation. The authors make no claims *
16//* about the suitability of this software for any purpose. It is *
17//* provided "as is" without express or implied warranty. *
18//****************************************************************************
19
20// @file AliHLTTPCHWCFSupport.cxx
21// @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
22// @author Torsten Alt <talt@cern.ch>
23// @brief Input interfaces for FPGA ClusterFinder Emulator for TPC
24// @brief ( see AliHLTTPCHWCFEmulator class )
25// @note
26
27
28#include "AliHLTTPCHWCFSupport.h"
29#include "AliHLTDataTypes.h"
30#include "AliHLTTPCMapping.h"
31#include "AliHLTTPCDigitReaderUnpacked.h"
32#include "AliHLTTPCTransform.h"
33#include "AliHLTTPCDefinitions.h"
34#include "AliRawDataHeader.h"
35#include "AliHLTTPCHWCFEmulator.h"
230b2bef 36#include "AliTPCcalibDB.h"
37#include "AliTPCCalPad.h"
38#include "AliTPCCalROC.h"
39#include "TMath.h"
c012881c 40
41#if __GNUC__>= 3
42using namespace std;
43#endif
44
45#include <cstdlib>
46#include <algorithm>
47#include <cerrno>
48#include <sys/time.h>
49
50
51AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport()
52 :
53 AliHLTLogging(),
54 fEventMemory(0),
55 fEventMCMemory(0)
56{
57 // see header file for class documentation
230b2bef 58 for( int i=0; i<fgkNSlices; i++ )
59 for( int j=0; j<fgkNPatches; j++ ) fMapping[i][j] = 0;
c012881c 60}
61
62
63AliHLTTPCHWCFSupport::~AliHLTTPCHWCFSupport()
64{
65 // see header file for class documentation
230b2bef 66 for( int i=0; i<fgkNSlices; i++ )
67 for( int j=0; j<fgkNPatches; j++ ) delete[] fMapping[i][j];
c012881c 68 delete[] fEventMemory;
69 delete[] fEventMCMemory;
70}
71
72AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&)
73 :
74 AliHLTLogging(),
75 fEventMemory(0),
76 fEventMCMemory(0)
77{
78 // dummy
79}
80
81AliHLTTPCHWCFSupport& AliHLTTPCHWCFSupport::operator=(const AliHLTTPCHWCFSupport&){
82 // dummy
83 return *this;
84}
85
86
230b2bef 87const AliHLTUInt32_t *AliHLTTPCHWCFSupport::GetMapping( int slice, int patch )
c012881c 88{
89 // see header file for class documentation
230b2bef 90 if( slice<0 || slice>=fgkNSlices ){
91 HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
92 return 0;
93 }
c012881c 94 if( patch<0 || patch>= fgkNPatches ){
95 HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
96 return 0;
97 }
230b2bef 98 if( !fMapping[slice][patch] ) fMapping[slice][patch] = ReadMapping(slice,patch);
99return fMapping[slice][patch];
c012881c 100}
101
102
230b2bef 103AliHLTUInt32_t *AliHLTTPCHWCFSupport::ReadMapping( int slice, int patch, const char *mappingFileName ) const
c012881c 104{
105 // Create mapping array for one patch
106 // If no mapping file provided, reads from default file
107 // Output: mapping [] array of type AliHLTUInt32_t, where :
108 //
109 // mapping[0] == N hardware adresses in the array (mapping size is maping[0] + 1 )
110 // mapping[hwAddress] == configWord
111 //
112 // configWord consist of:
113 //
114 // bits 0-7: pad number
115 // bits 8-13: row number
116 // bit 14 : flag for border pad
117 // bit 15 : is the pad active
118 // bits 16->28 : gain calibration as 13 bit fixed point,
119 // with 1 bit position before decimal point
120
121 const AliHLTUInt32_t kBorderFlag = (1 << 14);
122 const AliHLTUInt32_t kActiveFlag = (1 << 15);
123
230b2bef 124 if( slice<0 || slice>=fgkNSlices ){
125 HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
126 return 0;
127 }
128
c012881c 129 if( patch<0 || patch>5 ){
130 HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
131 return 0;
132 }
230b2bef 133
134 // AliHLTTPCTransform::GetFirstRow returns first row in scheme A.
135 // We have to transform to scheme B by AliHLTTPCTransform::Slice2Sector.
136
137 UInt_t offsetSchemeB=0;
138 Int_t sector = 0;
139 {
140 Int_t tmp=0;
141 AliHLTTPCTransform::Slice2Sector(slice, AliHLTTPCTransform::GetFirstRow(patch),
142 sector, tmp);
143 offsetSchemeB = (UInt_t) tmp;
144 }
145
146
147 AliTPCcalibDB *calib = AliTPCcalibDB::Instance();
148 AliTPCCalPad * gainTPC = 0;
149 AliTPCCalROC * gainROC = 0;
150 if( calib ) gainTPC = calib->GetPadGainFactor();
151 if( gainTPC ) gainROC = gainTPC->GetCalROC(sector); // pad gains per given sector
152 else{
153 HLTWarning("No TPC gain calibration found");
154 }
155
c012881c 156 TString filename;
157
158 if( mappingFileName ){
159 filename = mappingFileName;
160 } else {
161 const char* basePath=getenv("ALICE_ROOT");
162 if (basePath) filename.Form("%s/TPC/mapping/Patch%d.data", basePath,patch);
163 }
164
165 ifstream inFile;
166 inFile.open(filename.Data());
167 if (!inFile) {
168 HLTFatal("Unable to open mapping file: %s This means no mapping is provided.", filename.Data());
169 return 0;
170 }
171
c012881c 172
173 AliHLTUInt32_t *mapping = 0;
174 AliHLTUInt32_t *rowBranchPadHw = 0;
175 bool err = 1;
176 do{
177
178 UInt_t nHWAdd=0;
179 UInt_t maxHWAdd=0;
180
181 if( !(inFile >> nHWAdd ) || !(inFile >> maxHWAdd) ){
182 HLTError("Mapping file for patch %d corrupted &s", patch,filename.Data());
183 break;
184 }
185
186 if( maxHWAdd > 0xFFF ){
187 HLTError("Max hardware address exceeded for patch %d, max number is %d, number from mapping file is %d.",patch, 0xFFF, maxHWAdd+1);
188 break;
189 }
190
191 if(nHWAdd > maxHWAdd ){
192 HLTError("Too large number of hardware addresses for patch %d: max number is %d, number from mapping file is %d.",patch, maxHWAdd, nHWAdd );
193 break;
194 }
195
196 mapping = new AliHLTUInt32_t[maxHWAdd+2];
197 rowBranchPadHw = new AliHLTUInt32_t[nHWAdd];
198 if( !mapping || !rowBranchPadHw ){
199 HLTError("Can not allocate &d bytes of memory", (maxHWAdd+1+nHWAdd)*sizeof(AliHLTUInt32_t));
200 break;
201 }
202
203 for( unsigned int i=0; i<maxHWAdd+2; i++ ) mapping[i] = 0;
204 for( unsigned int i=0; i<nHWAdd; i++ ) rowBranchPadHw[i] = 0;
205 mapping[0] = maxHWAdd+1;
206 UInt_t nRead = 0;
207 err = 0;
208 while(!err ){
209 UInt_t hwAdd=0;
210 UInt_t row=0;
211 UInt_t pad=0;
212 if( !(inFile>>hwAdd) || !(inFile>>row) || !(inFile>>pad) ) break;
213
214 err = 1;
215
216 if ( nRead >= nHWAdd ){
217 HLTError("Too many hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead+1, nHWAdd, filename.Data());
218 break;
219 }
220 if (hwAdd>maxHWAdd) {
221 HLTError("hardware address exceeds max hwAddress %d, mapping file %s corrupted?", maxHWAdd, filename.Data());
222 break;
223 }
224
225 if( row < offsetSchemeB ){
226 HLTError("row number %d below minimum %d for patch %d, mapping file %s corrupted?", row, offsetSchemeB, patch, filename.Data());
227 break;
228 }
229
230 row -= offsetSchemeB;
231
232 if( row > 0x3F ){
233 HLTError("row number %d withing patch exceed the maximum %d for patch %d, mapping file %s corrupted?", row, 0x3F, patch, filename.Data());
234 break;
235 }
236
237 if( pad > 0xFF ){
238 HLTError("pad number %d exceed the maximum %d for patch %d, mapping file %s corrupted?", pad, 0xFF, patch, filename.Data());
239 break;
240 }
241
242 bool active = true; // Currently all channels are always active
230b2bef 243 //
244
245 AliHLTFloat64_t gain = 1.;
246 if( gainROC ){
247 gain = gainROC->GetValue(offsetSchemeB+row,pad);
248 if( gain>1.e-4 ) gain = 1./gain;
249 else gain = 0;
250 }
251 gain*= (1<<12);
252 AliHLTUInt32_t gainCalib = TMath::Nint(gain);
253 if( gainCalib > 0x1FFF ) gainCalib = 0x1FFF;
254
c012881c 255 AliHLTUInt32_t configWord = ( (row & 0x3F) << 8 ) | (pad & 0xFF);
256 if ( active ) configWord |= kActiveFlag;
257 configWord |= (gainCalib & 0x1FFF) << 16;
258
259 mapping[1+hwAdd] = configWord;
260
261 AliHLTUInt32_t branch = (hwAdd >> 11) & 0x1;
262 rowBranchPadHw[nRead] = (row<<25) | (branch<<24) | (pad<<16) | hwAdd;
4d67c3e3 263
c012881c 264 nRead++;
265 err = 0;
266 }
267
268 if( err ) break;
269
270 if ( nRead!= nHWAdd ){
271 HLTError("Too less hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead, nHWAdd, filename.Data());
272 err = 1;
273 break;
274 }
275
276 // mark pads at borders of A/B branches
277
278 std::sort(rowBranchPadHw, rowBranchPadHw + nHWAdd);
279 int rowBranchLast = -1;
280 for( unsigned int i=0; i<nHWAdd; i++ ){
281 int rowBranch = rowBranchPadHw[i]>>24;
282 if( rowBranch != rowBranchLast ){
283 mapping[1+(rowBranchPadHw[i] & 0xFFF)] |= kBorderFlag;
284 rowBranchLast = rowBranch;
285 if( i>0 ) mapping[1+(rowBranchPadHw[i-1] & 0xFFF)] |= kBorderFlag;
286 }
287 }
288 mapping[1+(rowBranchPadHw[nRead-1] & 0xFFF)] |= kBorderFlag;
289
290 } while(0);
291
292 inFile.close();
293
294 delete[] rowBranchPadHw;
295
296 if( err ){
297 delete[] mapping;
298 return 0;
299 }
300 return mapping;
301}
302
303
304int AliHLTTPCHWCFSupport::CreateRawEvent
305( const AliHLTComponentBlockData* block,
306 const AliHLTUInt32_t *&rawEvent, AliHLTUInt32_t &rawEventSize32,
307 const AliHLTTPCClusterMCLabel *&mcLabels, AliHLTUInt32_t &nMCLabels
308)
309{
310 // the method creates TPC raw data out of the input block
311 // MC labels are provided if possible
312 //
313
314 delete[] fEventMemory;
315 delete[] fEventMCMemory;
316
317 rawEvent = 0;
318 rawEventSize32 = 0;
319 mcLabels = 0;
320 nMCLabels = 0;
321
322 if( block->fPtr==NULL ){
323 HLTWarning("NULL pointer to the data block");
324 return 0;
325 }
326
327 Int_t slice = AliHLTTPCDefinitions::GetMinSliceNr( *block );
328 Int_t patch = AliHLTTPCDefinitions::GetMinPatchNr( *block );
329 AliHLTTPCMapping mapping(patch);
330
331 const char *str=Form("slice %d patch %d:", slice, patch);
332
333 if ( block->fDataType == (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) )
334 {
335 // already raw format -> only set the pointers and estimate the size
336
337 // read CDH header, estimate size of the data
338
339 AliHLTUInt64_t headerSize = sizeof(AliRawDataHeader);
340
341 AliRawDataHeader *cdhHeader = reinterpret_cast<AliRawDataHeader*>(block->fPtr);
342
343 AliHLTUInt64_t blockSize = block->fSize; // size of the raw data in bytes
344
345 if( cdhHeader->fSize!=0xFFFFFFFF ){ // use size information from the header
346 blockSize = cdhHeader->fSize;
347 if( blockSize > block->fSize ){
348 HLTWarning("%s Could not find a valid DDL header!",str);
349 return 0;
350 }
351 }
352
353 if( blockSize < headerSize ){
354 HLTWarning("%s Buffer size is smaller than CDH header size", str);
355 return 0;
356 }
357
358 rawEvent = reinterpret_cast<AliHLTUInt32_t*> (reinterpret_cast<UChar_t*>(block->fPtr)+headerSize);
359 rawEventSize32 = ( blockSize - headerSize )/sizeof(AliHLTUInt32_t);
360
361 }
362 else if ( block->fDataType == AliHLTTPCDefinitions::fgkUnpackedRawDataType )
363 {
364
365 AliHLTTPCDigitReaderUnpacked digitReader;
366 digitReader.SetUnsorted(kTRUE);
367
368 if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0 ) {
369 HLTWarning("failed setting up digit reader (InitBlock)");
370 return 0;
371 }
372
373 int nDigitsTotal = 0;
374 int nBunchesTotal = 0;
375
376 while( digitReader.NextChannel() ){
377 while(digitReader.NextBunch()){
378 nBunchesTotal++;
379 nDigitsTotal+=digitReader.GetBunchSize();
380 }
381 }
382
383 digitReader.Reset();
384
385 if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0) {
386 HLTWarning("failed setting up digit reader (InitBlock)");
387 return 0;
388 }
389
390 Int_t nPadsTotal = 0;
391 Int_t firstRow = AliHLTTPCTransform::GetFirstRow(patch);
392 Int_t nRows = AliHLTTPCTransform::GetNRows(patch);
393
394 for( int i=0; i<nRows; i++ ){
395 nPadsTotal += AliHLTTPCTransform::GetNPads(firstRow+i);
396 }
397
398 AliHLTUInt32_t totalSize32 = (nDigitsTotal + nBunchesTotal*2)/3+2*nPadsTotal + 10;
399 AliHLTUInt32_t totalNMC = nDigitsTotal + 10;
400
401 fEventMemory = new AliHLTUInt32_t[totalSize32];
402 if( !fEventMemory ){
403 HLTWarning("Not enougth memory: can not allocate %d bytes",totalSize32*8);
404 return 0;
405 }
406
407 fEventMCMemory = new AliHLTTPCClusterMCLabel[totalNMC];
408 if( !fEventMCMemory ){
409 HLTWarning("Not enougth memory: can not allocate %d bytes",totalNMC*sizeof(AliHLTTPCClusterMCLabel));
410 delete[] fEventMemory;
411 return 0;
412 }
413
414 AliHLTUInt32_t nWords32 = 0;
415 AliHLTUInt32_t mcIndex = 0;
416 int err=0;
417
418 AliHLTTPCDigitData tmpDigit;
419 tmpDigit.fTrackID[0] = -1;
420 tmpDigit.fTrackID[1] = -1;
421 tmpDigit.fTrackID[2] = -1;
422
423 while( !err && digitReader.NextChannel() ){
424
425 Int_t row=digitReader.GetRow();
426 Int_t pad=digitReader.GetPad();
427
02fcedf8 428 AliHLTUInt32_t hwAddr = mapping.GetHwAddress(row, pad);
429
c012881c 430 // create header
431
432 if( nWords32 >= totalSize32){ err = 1; break; }
433
434 AliHLTUInt32_t *header = fEventMemory + nWords32;
435 nWords32++;
436
437 int seek10 = 2;
438 int prevTime = 10000000;
439 int nWords10 = 0;
440 while(digitReader.NextBunch()){
02fcedf8 441
442 if( hwAddr > 0xFFF ) continue;
443
c012881c 444 Int_t nSignals = digitReader.GetBunchSize();
445 if( nSignals <=0 ){
446 HLTWarning("Empty bunch received");
447 continue;
448 }
449
450 Int_t time = digitReader.GetTime() + nSignals-1;
451
452 if( time-nSignals+1<0 || time>=AliHLTTPCTransform::GetNTimeBins() ){
453 HLTWarning("Wrong time bins received: %d-%d for row %d pad %d", time-nSignals+1, time, row, pad);
454 break;
455 }
456
457 if( time >= prevTime ){
458 HLTWarning("Unexpected order of TPC bunches in row %d, pad %d", row, pad);
459 break;
460 }
461
462 prevTime = time-nSignals+1;
463
464 if( nWords32+( 2+nSignals)/3+1 >= totalSize32 ){ err = 1; break; }
465 if( mcIndex + nSignals >= totalNMC ){ err = 1; break; }
466
57c09e02 467 if( nWords10 + 2 + nSignals > 0x3FF ){
c012881c 468 HLTWarning("Too much data in row %d, pad %d", row, pad);
469 break;
470 }
471
472 nWords10 += 2 + nSignals;
473
474 Add10Word( nWords32, seek10, nSignals + 2 );
475 Add10Word( nWords32, seek10, time );
476
477 const UInt_t *bunchData = digitReader.GetSignals();
478 const AliHLTTPCDigitData *mcDigits = digitReader.GetBunchDigits();
479 if( !mcDigits ){
480 HLTWarning("No MC labels found for a bunch of digits");
481 }
482
483 for(Int_t is=nSignals-1; is>=0; is--){
484 Add10Word( nWords32, seek10, bunchData[is] );
485 const AliHLTTPCDigitData &digit = mcDigits ?mcDigits[is] :tmpDigit;
486 int nmc = 0;
487 for( int i=0; i<3; i++ ) if( digit.fTrackID[i] >=0 ) nmc++;
488 for( int i=0; i<3; i++ ){
489 fEventMCMemory[mcIndex].fClusterID[i].fMCID = digit.fTrackID[i];
490 fEventMCMemory[mcIndex].fClusterID[i].fWeight = 0;
491 if( digit.fTrackID[i] >=0 ){
84f3ef29 492 fEventMCMemory[mcIndex].fClusterID[i].fWeight = ((float)bunchData[is])/nmc;
c012881c 493 }
494 }
495 mcIndex++;
496 }
497
498 } // bunches
499
02fcedf8 500 *header = (1<<30) | ((nWords10&0x3FF)<<16) | (hwAddr & 0xFFF);
c012881c 501
502 }// channels (pads)
503
504 if( err ){
505 HLTError("Internal error: too less memory allocated");
506 } else {
507 for( AliHLTUInt32_t i=0; i<nWords32; i++ ) fEventMemory[i] = AliHLTTPCHWCFEmulator::WriteBigEndian(fEventMemory[i]);
508 rawEvent = fEventMemory;
509 rawEventSize32 = nWords32;
510 mcLabels = fEventMCMemory;
511 nMCLabels = mcIndex;
512 }
513
514 } // unpacked data type
515
516 return 0;
517}
518
519
520void AliHLTTPCHWCFSupport::Add10Word( AliHLTUInt32_t &nWords32, int &seek10, UInt_t data )
521{
522 // add 10-bit data to the 32-bit word
523 // fEventMemory [nWords32] --- current 32-bit word
524 // *seek10 --- 10-bit position withing the word
525 // pointers are increased, a new word is first initialised to 0
526
527 data = data & 0x3FF; // truncate to 10 bits
528
529 if( seek10 == 2 ){
530 nWords32++;
531 fEventMemory[nWords32-1] = data<<20;
532 seek10 = 1;
533 } else if( seek10 == 1 ){
534 fEventMemory[nWords32-1] &= 0xFFF003FF;
535 fEventMemory[nWords32-1] |= (data<<10);
536 seek10 = 0;
537 } else if( seek10 == 0 ){
538 fEventMemory[nWords32-1] &= 0xFFFFFC00;
539 fEventMemory[nWords32-1] |= data;
540 seek10 = 2;
541 }
542}
543
544
545
546int AliHLTTPCHWCFSupport::CheckRawData( const AliHLTUInt32_t *buffer,
547 unsigned long bufferSize32, int patch, int slice )
548{
549 //
550 // The procedure checks consistency of the data
551 //
552
553 const unsigned int headerSize32 = 8;
554
555 if (!buffer) return 0;
556
557 const char *str=Form("slice %d patch %d:", slice, patch);
558
559 if( bufferSize32 < headerSize32 ){
560 HLTWarning("%s Buffer size is smaller than CDH header size", str);
561 return kFALSE;
562 }
563
564 // read data header
565
566 AliHLTUInt32_t blockSize32 = bufferSize32; // size of the raw data in words
567
568 if( buffer[0]!=0xFFFFFFFF ) blockSize32 = buffer[0]/4; // use size information from the header
569 if( blockSize32 > bufferSize32 ){
570 HLTWarning(Form("%s Could not find a valid DDL header!",str));
571 return 0;
572 }
573
574 UChar_t rcuVer = (UChar_t)( (buffer[1] >> 24) & 0xFF );
575
576 if (rcuVer < 2) {
577 HLTWarning("%s Old data format, RCU version %d", str,rcuVer);
578 return 0;
579 }
580
581 // is the block valid
582 //AliHLTUInt32_t blockAttributes = buffer[3]; // block attributes (bits 24-31) and participating sub detectors
583 //cout<<blockAttributes<<" "<<(blockAttributes >> 24)<<endl;
584 //if ( !( (blockAttributes >> 24) & 1) ) return 0;
585
586
587 const AliHLTUInt32_t* fData = buffer + headerSize32;
588 unsigned long dataSize32 = blockSize32 - headerSize32;
589
590 // Read the RCU trailer according to the RCU formware version specified in CDH
591 // Cross-check with version found in the trailer
592 // The two major bit should be 11 (identifies the end of the trailer)
593
594 AliHLTUInt32_t word = fData[dataSize32 - 1];
595
596 if ((word >> 30) != 3) {
597 HLTWarning("%s Last RCU trailer word not found!", str);
598 return 0;
599 }
600
601 UChar_t ver = (word >> 16) & 0xFF;
602 //AliHLTUInt32_t rcuId = (Int_t)((word >> 7) & 0x1FF);
603 AliHLTUInt32_t rcuTrailerSize32 = (word & 0x7F); // size of RCU trailer data in words
604
605 if (ver != rcuVer) {
606 HLTWarning("%s Wrong RCU firmware version detected: %d != %d",
607 str,ver,rcuVer);
608 return 0;
609 }
610
611 if (rcuTrailerSize32 < 2) {
612 HLTWarning(Form("Invalid trailer size found (%d bytes) !",
613 rcuTrailerSize32*4));
614 return 0;
615 }
616
617 if( rcuTrailerSize32 > dataSize32 ){
618 HLTWarning(Form("%s Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%ld bytes)!",
619 str, rcuTrailerSize32*4,dataSize32*4));
620 return 0;
621 }
622
623 // check the trailer
624
625 Int_t trailerIndex = dataSize32 - rcuTrailerSize32;
626
627 for( unsigned int i=trailerIndex; i<dataSize32-1; i++){
628 if ((fData[i] >> 30) != 2) {
629 HLTWarning("%s Missing RCU trailer identifier pattern!",str);
630 continue;
631 }
632 }
633
634 // Read the payload size
635
636 Int_t rcuPayloadSize32 = fData[trailerIndex] & 0x3FFFFFF;
637
638 if ( rcuPayloadSize32 + rcuTrailerSize32 != dataSize32) {
639 HLTWarning(Form("%s Inconsistent raw data size ! Raw data size - %ld bytes (from CDH), RCU trailer - %d bytes, raw data size (from RCU trailer) - %d bytes !",
640 str, dataSize32*4,
641 (rcuTrailerSize32)*4,
642 rcuPayloadSize32*4));
643 return 0;
644 }
645
646
647 //AliHLTTPCMapping *mapping = new AliHLTTPCMapping(patch);
648 const int kMaxNTimeBins = 2000;
649
650 UShort_t *channelData10 = new UShort_t[kMaxNTimeBins]; // cache for the decoded altro payload
651
652 Int_t position = 0; // current position (32-bit words) in fData
653
654 while(1){
655
656 // Search for the next Altro channel
657
658 word = 0;
659 while( position < rcuPayloadSize32 ){
660 word = fData[position++];
661 if( (word >> 30) == 1) break;
662 }
663 if (position >= rcuPayloadSize32 ) break; // no next channel found
664
665 // extract channel payload and hw address
666
667 Int_t channelPayloadSize10 = (word >> 16) & 0x3FF; // payload size in 10-bit words
668 Int_t channelPayloadSize32 = (channelPayloadSize10+2)/3;
669 Bool_t channelIOErrors = (word >> 29) & 0x1; // check for readout errors
670 Short_t channelHWAddress = word & 0xFFF;
671
672 if( position + channelPayloadSize32-1> rcuPayloadSize32 ){
673 HLTWarning(Form("%s Inconsistent channel payload data size: expected <= %d bytes from RCU trailer, found %d bytes in the channel header!",
674 str,(rcuPayloadSize32 - position)*4, channelPayloadSize32*4 ));
675 continue;
676 }
677
678 //bool channelBranchAB = ((channelHWAddress >> 11) & 0x1);
679 // int channelFEC = ((channelHWAddress >> 7) & 0xF); // front-end card index
680 //int channelAltro = ((channelHWAddress >> 4) & 0x7); // altro chip index
681 //int channelIndex = (channelHWAddress & 0xF); // channel index
682 //int channelRow = mapping->GetRow(channelHWAddress);
683 //int channelPad = mapping->GetPad(channelHWAddress);
684
685 // Now unpack the Altro data: 10-bit words to 16 bit-words
686
687 Int_t channelData10Index = 0;// current position in the payload
688
689 for (Int_t iword = 0; iword < channelPayloadSize32; iword++) {
690 word = fData[position++];
691 if ((word >> 30) != 0) {
692 HLTWarning(Form("%s Unexpected end of payload in altro channel payload! Address=0x%x, word=0x%x",
693 str, channelHWAddress,word));
694 channelIOErrors = 1;
695 position--;
696 break;
697 }
698 channelData10[channelData10Index++] = (word >> 20) & 0x3FF;
699 channelData10[channelData10Index++] = (word >> 10) & 0x3FF;
700 channelData10[channelData10Index++] = word & 0x3FF;
701 }
702
703 if ( channelIOErrors ) continue;
704
705 // read bunches
706
707 Int_t prevTimeBin = 1024;
708 channelData10Index = 0;
709
710 while(1){
711
712 // Read next Altro bunch
713
714 if ((channelData10Index+1 >= channelPayloadSize10) ) break;
715
716 Int_t bunchLength = channelData10[channelData10Index++];
717 Int_t bunchStartTimeBin = channelData10[channelData10Index++];
718
719 if (bunchLength <= 2) {
720 // Invalid bunch size
721 HLTWarning(Form("%s Too short bunch length (%d) in Address=0x%x!",
722 str, bunchLength,channelHWAddress));
723 break;
724 }
725 if( channelData10Index + bunchLength - 2 > channelPayloadSize10 ){
726 // Too long bunch detected
727 HLTWarning(Form("%s Too long bunch detected in Address=0x%x! Expected <= %d 10-bit words, found %d !",
728 str,channelHWAddress,channelPayloadSize10-channelData10Index,bunchLength));
729 break;
730 }
731
732 if( bunchStartTimeBin-bunchLength+1 < 0) {
733 HLTWarning(Form("%s Invalid start time-bin in Address=0x%x ! (%d-%d+1) < 0",
734 str,channelHWAddress,bunchStartTimeBin,bunchLength));
735 break;
736 }
737 if (bunchStartTimeBin >= prevTimeBin) {
738 HLTWarning(Form("%s Invalid start time-bin in Address=0x%x! (%d>=%d)",
739 str,channelHWAddress,bunchStartTimeBin,prevTimeBin));
740 break;
741 }
742
743 prevTimeBin = bunchStartTimeBin-bunchLength+1;
744
745 bunchLength -= 2;
746
747 //UShort_t* bunchData = &channelData10[channelData10Index]; // pointer to the current bunch samples
748 channelData10Index += bunchLength;
749 }
750 }
751
752 delete[] channelData10;
753 //delete mapping;
754
755 return 1;
756}
757