]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx
HWCFEmulator update
[u/mrichter/AliRoot.git] / HLT / TPCLib / HWCFemulator / AliHLTTPCHWCFSupport.cxx
1 // $Id$
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"
36 #include "AliTPCcalibDB.h"
37 #include "AliTPCCalPad.h"
38 #include "AliTPCCalROC.h"
39 #include "TMath.h"
40
41 #if __GNUC__>= 3
42 using namespace std;
43 #endif
44
45 #include <cstdlib>
46 #include <algorithm>
47 #include <cerrno>
48 #include <sys/time.h>
49
50
51 AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport()
52   : 
53   AliHLTLogging(),
54   fEventMemory(0),
55   fEventMCMemory(0)
56 {
57   // see header file for class documentation
58   for( int i=0; i<fgkNSlices; i++ )
59     for( int j=0; j<fgkNPatches; j++ ) fMapping[i][j] = 0;
60 }
61
62
63 AliHLTTPCHWCFSupport::~AliHLTTPCHWCFSupport()
64 {
65   // see header file for class documentation
66   for( int i=0; i<fgkNSlices; i++ )
67     for( int j=0; j<fgkNPatches; j++ ) delete[] fMapping[i][j];
68   delete[] fEventMemory;
69   delete[] fEventMCMemory;
70 }
71
72 AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&)
73   : 
74   AliHLTLogging(),
75   fEventMemory(0),
76   fEventMCMemory(0)
77 {
78   // dummy
79 }
80
81 AliHLTTPCHWCFSupport& AliHLTTPCHWCFSupport::operator=(const AliHLTTPCHWCFSupport&){
82   // dummy
83   return *this;
84 }
85
86
87 const AliHLTUInt32_t *AliHLTTPCHWCFSupport::GetMapping( int slice, int patch )
88
89   // see header file for class documentation
90   if( slice<0 || slice>=fgkNSlices ){
91     HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
92     return 0;
93   }
94   if( patch<0 || patch>= fgkNPatches ){
95     HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
96     return 0;
97   }
98   if( !fMapping[slice][patch] ) fMapping[slice][patch] = ReadMapping(slice,patch);
99 return fMapping[slice][patch];
100 }
101
102
103 AliHLTUInt32_t *AliHLTTPCHWCFSupport::ReadMapping( int slice, int patch, const char *mappingFileName ) const
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   
124   if( slice<0 || slice>=fgkNSlices ){
125      HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
126      return 0;
127   }
128
129   if( patch<0 || patch>5 ){
130      HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
131      return 0;
132   }
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
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
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   
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
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;
263
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
304 int 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
428         AliHLTUInt32_t hwAddr = mapping.GetHwAddress(row, pad);
429
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()){
441
442           if( hwAddr > 0xFFF ) continue;
443
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
467           if( nWords10 + 2 + nSignals > 0x3FF ){
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 ){                      
492                 fEventMCMemory[mcIndex].fClusterID[i].fWeight  = ((float)bunchData[is])/nmc;
493               }
494             }     
495             mcIndex++;
496           }       
497
498         } // bunches
499         
500       *header = (1<<30) | ((nWords10&0x3FF)<<16) | (hwAddr & 0xFFF);
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
520 void 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
546 int 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