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