]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCHWCFDataReverterComponent.cxx
bugfix: correct calculation of remaining payload to detect decoding errors
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCHWCFDataReverterComponent.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: Kenneth Aamodt <Kenneth.Aamodt@student.uib.no>        *
7 //*                  for The ALICE HLT Project.                            *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 /// @file   AliHLTTPCHWCFDataReverterComponent.cxx
19 /// @author Kenneth Aamodt
20 /// @date   
21 /// @brief  Component for reverting data for the HW clusterfinder
22 ///
23
24 // see header file for class documentation                                   //
25 // or                                                                        //
26 // refer to README to build package                                          //
27 // or                                                                        //
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt                          //
29
30 #if __GNUC__>= 3
31 using namespace std;
32 #endif
33 #include "AliHLTTPCHWCFDataReverterComponent.h"
34 #include "AliHLTTPCDigitReader32Bit.h"
35 #include "AliHLTTPCTransform.h"
36 #include "AliHLTTPCDefinitions.h"
37 #include "AliHLTTPCDigitData.h"
38 #include "AliHLTTPCMapping.h"
39 #include <cstdlib>
40 #include <cerrno>
41 #include <cassert>
42 #include "TString.h"
43 #include <sys/time.h>
44 #include "AliHLTAltroEncoder.h"
45 #include "AliRawDataHeader.h"
46
47 /** ROOT macro for the implementation of ROOT specific class methods */
48 ClassImp(AliHLTTPCHWCFDataReverterComponent)
49
50   AliHLTTPCHWCFDataReverterComponent::AliHLTTPCHWCFDataReverterComponent()
51     :
52     fDigitReader(NULL),
53     fRowPadVector(),
54     fNumberOfPadsInRow(NULL),
55     fFirstPadHigh(NULL),
56     fNumberOfRows(0),
57     fCurrentPatch(0),
58     fFirstRow(0),
59     fLastRow(0),
60     fNTimeBins(0),
61     fVectorInitialized(kFALSE),
62     fMapping(NULL),
63     fInterleave(kTRUE)
64 {
65   // see header file for class documentation
66   // or
67   // refer to README to build package
68   // or
69   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
70 }
71
72 AliHLTTPCHWCFDataReverterComponent::~AliHLTTPCHWCFDataReverterComponent()
73 {
74   // see header file for class documentation
75   if(fVectorInitialized){
76     DeInitializePadArray();
77   }
78   if(fNumberOfPadsInRow){
79     delete [] fNumberOfPadsInRow;
80     fNumberOfPadsInRow=NULL;
81   }
82   if(fFirstPadHigh){
83     delete [] fFirstPadHigh;
84     fFirstPadHigh=NULL;
85   }
86   if(fDigitReader){
87     delete fDigitReader;
88     fDigitReader=NULL;
89   }
90   if(fMapping){
91     delete fMapping;
92     fMapping = NULL;
93   }
94 }
95
96 // Public functions to implement AliHLTComponent's interface.
97 // These functions are required for the registration process
98
99 const char* AliHLTTPCHWCFDataReverterComponent::GetComponentID()
100 {
101   // see header file for class documentation
102   return "TPCHWCFDataReverter";
103 }
104
105 void AliHLTTPCHWCFDataReverterComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
106 {
107   // see header file for class documentation
108   list.clear(); 
109   list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
110 }
111
112 AliHLTComponentDataType AliHLTTPCHWCFDataReverterComponent::GetOutputDataType()
113 {
114   // see header file for class documentation
115   return kAliHLTDataTypeDDLRaw;
116 }
117
118 int AliHLTTPCHWCFDataReverterComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
119 {
120   // see header file for class documentation
121   tgtList.clear();
122   tgtList.push_back(kAliHLTDataTypeDDLRaw);
123   return tgtList.size();
124 }
125
126 void AliHLTTPCHWCFDataReverterComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
127 {
128   // see header file for class documentation
129   constBase=0;
130   inputMultiplier=1.0;
131 }
132
133 AliHLTComponent* AliHLTTPCHWCFDataReverterComponent::Spawn()
134 {
135   // see header file for class documentation
136   return new AliHLTTPCHWCFDataReverterComponent();
137 }
138         
139 int AliHLTTPCHWCFDataReverterComponent::DoInit( int argc, const char** argv )
140 {
141   // see header file for class documentation
142
143   Int_t i = 0;
144   Char_t* cpErr;
145
146   while ( i < argc ) {      
147
148     // -- number of timebins
149     if ( !strcmp( argv[i], "-timebins" )) {
150       fNTimeBins = strtoul( argv[i+1], &cpErr ,0);
151       AliHLTTPCTransform::SetNTimeBins(fNTimeBins);
152       if ( *cpErr ) {
153         HLTError("Cannot convert ntimebins specifier '%s'.", argv[i+1]);
154         return EINVAL;
155       }
156       i+=2;
157       continue;
158     }
159     // -- number of timebins
160     if ( !strcmp( argv[i], "-interleave-off" )) {
161       fInterleave = kFALSE;
162       i++;
163       continue;
164     }
165      
166     HLTError("HLT::TPCClusterFinder::DoInit", "Unknown Option", "Unknown option '%s'", argv[i] );
167
168     return EINVAL;
169   }
170
171   fDigitReader = new AliHLTTPCDigitReader32Bit();
172
173   return 0;
174 }
175
176 int AliHLTTPCHWCFDataReverterComponent::DoDeinit()
177 {
178   // see header file for class documentation
179   return 0;
180 }
181
182 Int_t AliHLTTPCHWCFDataReverterComponent::DeInitializePadArray()
183 {
184   // see header file for class documentation
185   if(fVectorInitialized){
186     for(Int_t i=0;i<fNumberOfRows;i++){
187       for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
188         delete fRowPadVector[i][j];
189         fRowPadVector[i][j]=NULL;
190       }
191       fRowPadVector[i].clear();
192     }
193     fRowPadVector.clear();
194   }
195   return 1;
196
197
198 void AliHLTTPCHWCFDataReverterComponent::InitializePadArray(){
199   // see header file for class documentation
200   if(fCurrentPatch>5){
201     HLTFatal("Patch is not set");
202     return;
203   }
204
205   fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
206   fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
207
208   fNumberOfRows=fLastRow-fFirstRow+1;
209   fNumberOfPadsInRow= new Int_t[fNumberOfRows];
210   fFirstPadHigh= new Int_t[fNumberOfRows];
211
212   memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
213   memset( fFirstPadHigh, 0, sizeof(Int_t)*(fNumberOfRows));
214
215   for(Int_t i=0;i<fNumberOfRows;i++){
216     fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
217     AliHLTTPCPadVector tmpRow;
218     for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
219       AliHLTTPCPad *tmpPad = new AliHLTTPCPad();
220       if(fFirstPadHigh[i] == 0){
221         if(fMapping->GetHwAddress(i,j) > 2047){
222           fFirstPadHigh[i]=j;
223         }
224       }
225       tmpPad->SetID(i,j);
226       tmpPad->SetDataToDefault();
227       tmpRow.push_back(tmpPad);
228     }
229     fRowPadVector.push_back(tmpRow);
230   }
231   fVectorInitialized=kTRUE;
232 }
233
234
235 int AliHLTTPCHWCFDataReverterComponent::DoEvent( const AliHLTComponentEventData& evtData, 
236                                                  const AliHLTComponentBlockData* blocks, 
237                                                  AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* outputPtr, 
238                                                  AliHLTUInt32_t& size, 
239                                                  vector<AliHLTComponentBlockData>& outputBlocks )
240 {
241   // see header file for class documentation
242   int iResult=0;
243   if (!fDigitReader) return -ENODEV;
244
245   AliHLTUInt32_t capacity=size;
246   size=0;
247   if (!IsDataEvent()) return 0;
248
249   //  == init iter (pointer to datablock)
250   const AliHLTComponentBlockData* iter = NULL;
251   unsigned long ndx;
252
253   //reading the data
254   for ( ndx = 0; ndx < evtData.fBlockCnt; ndx++ ){
255
256     iter = blocks+ndx;
257       
258     HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",
259              evtData.fEventID, evtData.fEventID, 
260              DataType2Text( iter->fDataType).c_str(), 
261              DataType2Text(kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC).c_str());
262
263     if ( iter->fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC)){
264       continue;
265     }
266
267     if (iter->fSize<=sizeof(AliRawDataHeader)) {
268       // forward empty DDLs
269       outputBlocks.push_back(*iter);
270       continue;
271     }
272
273     UInt_t slice = AliHLTTPCDefinitions::GetMinSliceNr( *iter );
274     UInt_t patch = AliHLTTPCDefinitions::GetMinPatchNr( *iter );
275
276     if(fDigitReader->InitBlock(iter->fPtr,iter->fSize,patch,slice)<0){
277       HLTWarning("Decoder failed to initialize, event aborted.");
278       continue;
279     }
280       
281     fMapping = new AliHLTTPCMapping(patch);
282
283     if(!fVectorInitialized){
284       fCurrentPatch=patch;
285       InitializePadArray();
286     }
287
288     //Here the reading of the data and the zerosuppression takes place
289     while(fDigitReader->NextChannel()){//Pad
290
291       Int_t row=fDigitReader->GetRow();
292       Int_t pad=fDigitReader->GetPad();
293
294       if(row >= fNumberOfRows || row < 0){
295         continue;
296       }
297       else if(pad >= fNumberOfPadsInRow[row] || pad < 0){
298         continue;
299       }  
300         
301       AliHLTTPCPad *tmpPad = fRowPadVector[row][pad];
302       if (tmpPad){
303         tmpPad->SetDataToDefault();
304       }
305         
306       //reading data to pad
307       while(fDigitReader->NextBunch()){
308         const UInt_t *bunchData= fDigitReader->GetSignals();
309         Int_t time=fDigitReader->GetTime();
310         for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
311           if(bunchData[i]>0){// disregarding 0 data.
312             if(time+i >= 0 && time+i < AliHLTTPCTransform::GetNTimeBins()){
313               if (tmpPad){
314                 tmpPad->SetDataSignal(time+i,bunchData[i]);
315               }
316             }
317           }
318         }
319       }
320     }
321
322     if( iter->fSize > sizeof(AliRawDataHeader )){
323   
324       AliHLTAltroEncoder *altroEncoder = new AliHLTAltroEncoder;
325       altroEncoder->SetUse32BitFormat(kTRUE);
326       Int_t ddlno=768;
327       if (patch>1) ddlno+=72+4*slice+(patch-2);
328       else ddlno+=2*slice+patch;
329       altroEncoder->SetDDLid(ddlno);
330       altroEncoder->SetSlice(slice);
331       altroEncoder->SetPartition(patch);
332       
333       altroEncoder->SetBuffer(outputPtr,capacity); //tests if one overwrite the buffer is done in the encoder
334
335       // set CDH from the beginning of buffer
336       altroEncoder->SetCDH((AliHLTUInt8_t*)iter->fPtr,sizeof(AliRawDataHeader));
337
338       UChar_t *RCUTrailer=NULL;
339       Int_t RCUTrailerSize=fDigitReader->GetRCUTrailerSize();
340       if (RCUTrailerSize<=0 || !fDigitReader->GetRCUTrailerData( RCUTrailer )) {
341         if(RCUTrailer==NULL){
342           HLTWarning("can not find RCU trailer for data block %s 0x%08x: skipping data block",
343                      DataType2Text(iter->fDataType).c_str(), iter->fSpecification);
344           continue;
345         }
346       }
347       altroEncoder->SetRCUTrailer(RCUTrailer, RCUTrailerSize);
348
349       for(Int_t row = 0; row< fNumberOfRows;row++){
350
351         if(fInterleave == kFALSE){
352           Int_t currentTime = 0;
353           Int_t bunchSize = 0;
354           for(Int_t ipad=0;ipad<fNumberOfPadsInRow[row];ipad++){
355             AliHLTTPCPad * pad = fRowPadVector[row][ipad];
356             if(pad->GetNAddedSignals() > 0){
357               while(pad->GetNextGoodSignal(currentTime, bunchSize)){
358                 for(Int_t i=bunchSize-1;i>=0;i--){
359                   if (altroEncoder->AddSignal((AliHLTUInt16_t)(pad->GetDataSignal(currentTime+i)),(AliHLTUInt16_t)(currentTime+i))<0) {
360                     HLTWarning("can not add channel: slice %d, partition %d, hw address %d, row %d, pad %d, time %d, bunch size %d Charge %d",
361                                slice, patch, fMapping->GetHwAddress(row,ipad), row, ipad, currentTime+i, bunchSize,pad->GetDataSignal(currentTime+i));
362                     break;
363                   }
364                 }
365               }
366               altroEncoder->SetChannel(fMapping->GetHwAddress(row,ipad));
367               currentTime = 0;
368               bunchSize = 0;
369             }
370           }
371         }
372         else{
373           Int_t padHigh=fFirstPadHigh[row];
374           
375           Int_t padLowIndex=0;
376           Int_t padHighIndex= padHigh;
377           
378           while(padLowIndex < padHigh || padHighIndex < fNumberOfPadsInRow[row]){
379             Int_t currentTime = 0;
380             Int_t bunchSize = 0;
381             //add the data from low side
382             if(padLowIndex < padHigh){
383               AliHLTTPCPad * lowPad= fRowPadVector[row][padLowIndex];
384               if(lowPad->GetNAddedSignals()>0){
385                 while(lowPad->GetNextGoodSignal(currentTime, bunchSize)){
386                   for(Int_t i=bunchSize-1;i>=0;i--){
387                     if (altroEncoder->AddSignal((AliHLTUInt16_t)(lowPad->GetDataSignal(currentTime+i)),(AliHLTUInt16_t)(currentTime+i))<0) {
388                       HLTWarning("can not add channel: slice %d, partition %d, hw address %d, row %d, pad %d, time %d, bunch size %d",
389                                  slice, patch, fMapping->GetHwAddress(row,padLowIndex), row, padLowIndex, currentTime+i, bunchSize);
390                       break;
391                     }
392                   }
393                 }
394                 altroEncoder->SetChannel(fMapping->GetHwAddress(row,padLowIndex));
395               }
396             }
397             currentTime = 0;
398             bunchSize = 0;
399             //add the data from the high side
400             if(padHighIndex < fNumberOfPadsInRow[row]){
401               AliHLTTPCPad * highPad= fRowPadVector[row][padHighIndex];
402               if(highPad->GetNAddedSignals()>0){
403                 while(highPad->GetNextGoodSignal(currentTime, bunchSize)){
404                   for(Int_t i=bunchSize-1;i>=0;i--){
405                     if (altroEncoder->AddSignal((AliHLTUInt16_t)(highPad->GetDataSignal(currentTime+i)),(AliHLTUInt16_t)(currentTime+i))<0) {
406                       HLTWarning("can not add channel: slice %d, partition %d, hw address %d, row %d, pad %d, time %d, bunch size %d",
407                                  slice, patch, fMapping->GetHwAddress(row,padHighIndex), row, padHighIndex, currentTime+i, bunchSize);
408                       break;
409                     }
410                   }
411                 }
412                 altroEncoder->SetChannel(fMapping->GetHwAddress(row,padHighIndex));
413               }
414             }
415             padLowIndex++;
416             padHighIndex++;
417           }
418         }
419       } 
420       
421       int sizeOfData=altroEncoder->SetLength();
422       
423
424       if (sizeOfData<0) {
425         HLTError("data encoding failed");
426         iResult=sizeOfData;
427         break;
428       }
429       if(sizeOfData>(int)capacity){
430         HLTWarning("Buffer too small too add the altrodata: %d of %d byte(s) already used", sizeOfData, capacity);
431         iResult=-ENOSPC;
432         break;
433       }
434
435       AliHLTComponentBlockData bd;
436       FillBlockData( bd );
437       bd.fOffset = 0;
438       bd.fSize = sizeOfData;
439       bd.fDataType = kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
440       bd.fSpecification = iter->fSpecification;
441       outputBlocks.push_back( bd );
442
443       size+=sizeOfData;
444     }
445     fDigitReader->Reset();
446   }
447   
448   if(iResult < 0) {
449     fDigitReader->Reset();
450     size=0;
451   }
452   HLTDebug("Total size of output is: %d ",size);
453   return iResult;
454 }