]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx
662366e21689f81af45e36fd32dc6cc599e59b68
[u/mrichter/AliRoot.git] / HLT / TPCLib / HWCFemulator / AliHLTTPCHWCFSupport.cxx
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
37 using namespace std;
38 #endif
39
40 #include <cstdlib>
41 #include <algorithm>
42 #include <cerrno>
43 #include <sys/time.h>
44
45
46 AliHLTTPCHWCFSupport::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
57 AliHLTTPCHWCFSupport::~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
65 AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&)
66   : 
67   AliHLTLogging(),
68   fEventMemory(0),
69   fEventMCMemory(0)
70 {
71   // dummy
72 }
73
74 AliHLTTPCHWCFSupport& AliHLTTPCHWCFSupport::operator=(const AliHLTTPCHWCFSupport&){
75   // dummy
76   return *this;
77 }
78
79
80 const 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
92 AliHLTUInt32_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
264 int 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 > 0x3FF ){
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 ){                      
448                 fEventMCMemory[mcIndex].fClusterID[i].fWeight  = ((float)bunchData[is])/nmc;
449               }
450             }     
451             mcIndex++;
452           }       
453
454         } // bunches
455         
456       *header = (1<<30) | ((nWords10&0x3FF)<<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
476 void 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
502 int 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