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