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