]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCZeroSuppressionComponent.cxx
Remove compilser warnings
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCZeroSuppressionComponent.cxx
1 // $Id$
2
3 /**************************************************************************
4  * This file is property of and copyright by the ALICE HLT Project        * 
5  * ALICE Experiment at CERN, All rights reserved.                         *
6  *                                                                        *
7  * Primary Authors: Kenneth Aamodt <Kenneth.Aamodt@student.uib.no>        *
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   AliHLTTPCZeroSuppressionComponent.cxx
20     @author Kenneth Aamodt
21     @date   
22     @brief  The TPC ZeroSuppression component
23 */
24
25 // see header file for class documentation                                   //
26 // or                                                                        //
27 // refer to README to build package                                          //
28 // or                                                                        //
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt                          //
30
31 #if __GNUC__>= 3
32 using namespace std;
33 #endif
34 #include "AliHLTTPCZeroSuppressionComponent.h"
35 #include "AliHLTTPCDigitReaderDecoder.h"
36 #include "AliHLTTPCTransform.h"
37 #include "AliHLTTPCDefinitions.h"
38 #include "AliHLTTPCDigitData.h"
39 #include "AliHLTTPCMapping.h"
40 #include <cstdlib>
41 #include <cerrno>
42 #include <cassert>
43 #include "TString.h"
44 #include <sys/time.h>
45 #include "AliHLTAltroEncoder.h"
46 #include "AliRawDataHeader.h"
47
48 /** ROOT macro for the implementation of ROOT specific class methods */
49 ClassImp(AliHLTTPCZeroSuppressionComponent)
50
51 AliHLTTPCZeroSuppressionComponent::AliHLTTPCZeroSuppressionComponent()
52     :
53     fDigitReader(NULL),
54     fRowPadVector(),
55     fNumberOfPadsInRow(NULL),
56     fNumberOfRows(0),
57     fCurrentPatch(0),
58     fFirstRow(0),
59     fLastRow(0),
60     fStartTimeBin(0),
61     fEndTimeBin(AliHLTTPCTransform::GetNTimeBins()),
62     fNTimeBins(0),
63     fNRMSThreshold(0),
64     fSignalThreshold(0),
65     fMinimumNumberOfSignals(AliHLTTPCTransform::GetNTimeBins()/2),
66     fOldRCUFormat(0),
67     fSortPads(0),
68     fVectorInitialized(kFALSE),
69     fValueBelowAverage(5),
70     fLeftTimeBin(5),
71     fRightTimeBin(5),
72     fGetActivePads(kFALSE),
73     fSkipSendingZSData(kFALSE),
74     fSendHWList(kFALSE),
75     fHwAddressList()
76 {
77   // see header file for class documentation
78   // or
79   // refer to README to build package
80   // or
81   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
82 }
83
84 AliHLTTPCZeroSuppressionComponent::~AliHLTTPCZeroSuppressionComponent()
85 {
86   // see header file for class documentation
87   if(fVectorInitialized){
88     DeInitializePadArray();
89   }
90   if(fNumberOfPadsInRow){
91     delete [] fNumberOfPadsInRow;
92     fNumberOfPadsInRow=NULL;
93   }
94   if(fDigitReader){
95     delete fDigitReader;
96     fDigitReader=NULL;
97   }
98 }
99
100 // Public functions to implement AliHLTComponent's interface.
101 // These functions are required for the registration process
102
103 const char* AliHLTTPCZeroSuppressionComponent::GetComponentID()
104 {
105   // see header file for class documentation
106   return "TPCZeroSuppression";
107 }
108
109 void AliHLTTPCZeroSuppressionComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
110 {
111   // see header file for class documentation
112   list.clear(); 
113   list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
114 }
115
116 AliHLTComponentDataType AliHLTTPCZeroSuppressionComponent::GetOutputDataType()
117 {
118   // see header file for class documentation
119   return kAliHLTMultipleDataType;
120   //return kAliHLTDataTypeDDLRaw;
121   //  return AliHLTTPCDefinitions::fgkUnpackedRawDataType;
122 }
123
124 int AliHLTTPCZeroSuppressionComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
125 {
126   // see header file for class documentation
127   tgtList.clear();
128   tgtList.push_back(kAliHLTDataTypeDDLRaw);
129   tgtList.push_back(kAliHLTDataTypeHwAddr16);
130   return tgtList.size();
131 }
132
133 void AliHLTTPCZeroSuppressionComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
134 {
135   // see header file for class documentation
136   constBase=0;
137   inputMultiplier=2.0;
138 }
139
140 AliHLTComponent* AliHLTTPCZeroSuppressionComponent::Spawn()
141 {
142   // see header file for class documentation
143   return new AliHLTTPCZeroSuppressionComponent();
144 }
145         
146 int AliHLTTPCZeroSuppressionComponent::DoInit( int argc, const char** argv )
147 {
148   // see header file for class documentation
149
150   Int_t i = 0;
151   Char_t* cpErr;
152
153   while ( i < argc ) {      
154
155     // -- zero suppression threshold
156     if ( !strcmp( argv[i], "-signal-threshold" ) || !strcmp( argv[i], "signal-threshold" ) ) {
157       fSignalThreshold = strtoul( argv[i+1], &cpErr ,0);
158       if ( *cpErr ) {
159         HLTError("Cannot convert signal-threshold specifier '%s'.", argv[i+1]);
160         return EINVAL;
161       }
162       i+=2;
163       continue;
164     }
165
166     // -- checking for nsigma-threshold, used in 2007 December run in ZeroSuppression
167     if ( !strcmp( argv[i], "-rms-threshold" ) ||  !strcmp( argv[i], "rms-threshold" ) ) {
168       fNRMSThreshold = strtoul( argv[i+1], &cpErr ,0);
169       if ( *cpErr ){
170         HLTError("Cannot convert rms-threshold specifier '%s'. Must be integer", argv[i+1]);
171         return EINVAL;
172       }
173       i+=2;
174       continue;
175     }
176
177     // -- number of timebins
178     if ( !strcmp( argv[i], "-timebins" ) || !strcmp( argv[i], "ntimebins" ) || !strcmp( argv[i], "-ntimebins" )) {
179       fNTimeBins = strtoul( argv[i+1], &cpErr ,0);
180       AliHLTTPCTransform::SetNTimeBins(fNTimeBins);
181       if(fEndTimeBin>AliHLTTPCTransform::GetNTimeBins()){
182         fEndTimeBin = AliHLTTPCTransform::GetNTimeBins();
183       }
184       if ( *cpErr ) {
185         HLTError("Cannot convert ntimebins specifier '%s'.", argv[i+1]);
186         return EINVAL;
187       }
188       i+=2;
189       continue;
190     }
191
192     // -- first timebin
193     if ( !strcmp( argv[i], "-start-timebin" ) || !strcmp( argv[i], "start-timebin" ) ) {
194       fStartTimeBin = strtoul( argv[i+1], &cpErr ,0);
195       if ( *cpErr ) {
196         HLTError("Cannot convert start-timebin specifier '%s'.", argv[i+1]);
197         return EINVAL;
198       }
199       i+=2;
200       continue;
201     }
202
203     // -- last timebin
204     if ( !strcmp( argv[i], "-end-timebin" ) || !strcmp( argv[i], "end-timebin" ) ) {
205       if(strtoul( argv[i+1], &cpErr ,0)<=(UInt_t)AliHLTTPCTransform::GetNTimeBins()){
206         fEndTimeBin = strtoul( argv[i+1], &cpErr ,0);
207       }
208       if ( *cpErr ) {
209         HLTError("Cannot convert end-timebin specifier '%s'.", argv[i+1]);
210         return EINVAL;
211       }
212       i+=2;
213       continue;
214     }
215
216     // -- timebins to keep left of signal
217     if ( !strcmp( argv[i], "-timebin-left" ) || !strcmp( argv[i], "timebin-left" ) ) {
218       fLeftTimeBin = strtoul( argv[i+1], &cpErr ,0);
219       if ( *cpErr ) {
220         HLTError("Cannot convert timebin-left specifier '%s'.", argv[i+1]);
221         return EINVAL;
222       }
223       i+=2;
224       continue;
225     }
226
227     // -- timebin to keep right of signal
228     if ( !strcmp( argv[i], "-timebin-right" ) || !strcmp( argv[i], "timebin-right" ) ) {
229       fRightTimeBin = strtoul( argv[i+1], &cpErr ,0);
230       if ( *cpErr ) {
231         HLTError("Cannot convert timebin-right specifier '%s'.", argv[i+1]);
232         return EINVAL;
233       }
234       i+=2;
235       continue;
236     }
237
238     // -- value below average to subtract
239     if ( !strcmp( argv[i], "-value-below-average" ) || !strcmp( argv[i], "value-below-average" ) ) {
240       fValueBelowAverage = strtoul( argv[i+1], &cpErr ,0);
241       if ( *cpErr ) {
242         HLTError("Cannot convert value-below-average specifier '%s'.", argv[i+1]);
243         return EINVAL;
244       }
245       i+=2;
246       continue;
247     }
248
249     // -- pad occupancy limit
250     if ( !strcmp( argv[i], "-occupancy-limit" ) || !strcmp( argv[i], "occupancy-limit" ) ) {
251       fMinimumNumberOfSignals = strtoul( argv[i+1], &cpErr ,0);
252       if ( *cpErr ) {
253         HLTError("Cannot convert occupancy-limit specifier '%s'.", argv[i+1]);
254         return EINVAL;
255       }
256       i+=2;
257       continue;
258     }
259
260     // -- checking for rcu format
261     if ( !strcmp( argv[i], "oldrcuformat" ) ) {
262       fOldRCUFormat = strtoul( argv[i+1], &cpErr ,0);
263       if ( *cpErr ){
264         HLTError("Cannot convert oldrcuformat specifier '%s'. Should  be 0(off) or 1(on), must be integer", argv[i+1]);
265         return EINVAL;
266       }
267       i+=2;
268       continue;
269     }
270
271     // -- checking for pad sorting
272     if ( !strcmp( argv[i], "-sort-pads" ) || !strcmp( argv[i], "sort-pads" ) ) {
273       fSortPads = strtoul( argv[i+1], &cpErr ,0);
274       if ( *cpErr ){
275         HLTError("Cannot convert sort-pads specifier '%s'. Should  be 0(off) or 1(on), must be integer", argv[i+1]);
276         return EINVAL;
277       }
278       i+=2;
279       continue;
280     }
281
282     // -- checking for skipZSdatashipping
283     if ( !strcmp( argv[i], "-skip-sending-data" ) ) {
284       fSkipSendingZSData = kTRUE;
285       i++;
286       continue;
287     }
288
289     // -- checking for hw address shipping
290     if ( !strcmp( argv[i], "-send-hw-list" ) ) {
291       fSendHWList = kTRUE;
292       i++;
293       continue;
294     }
295       
296     Logging(kHLTLogError, "HLT::TPCClusterFinder::DoInit", "Unknown Option", "Unknown option '%s'", argv[i] );
297     return EINVAL;
298
299   }
300
301   if(fSkipSendingZSData == kTRUE && fSendHWList == kFALSE){
302     HLTError("Component will have no output, check your configuration.");
303   }
304   
305
306   HLTDebug("using AliHLTTPCDigitReaderDecoder");
307   fDigitReader = new AliHLTTPCDigitReaderDecoder();
308
309   fHwAddressList.clear();
310
311   return 0;
312 }
313
314 int AliHLTTPCZeroSuppressionComponent::DoDeinit()
315 {
316   // see header file for class documentation
317   return 0;
318 }
319
320 Int_t AliHLTTPCZeroSuppressionComponent::DeInitializePadArray()
321 {
322   // see header file for class documentation
323   if(fVectorInitialized){
324     for(Int_t i=0;i<fNumberOfRows;i++){
325       for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
326         delete fRowPadVector[i][j];
327         fRowPadVector[i][j]=NULL;
328       }
329       fRowPadVector[i].clear();
330     }
331     fRowPadVector.clear();
332   }
333   return 1;
334
335
336 void AliHLTTPCZeroSuppressionComponent::InitializePadArray(){
337   // see header file for class documentation
338   if(fCurrentPatch>5){
339     HLTFatal("Patch is not set");
340     return;
341   }
342
343   fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
344   fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
345
346   fNumberOfRows=fLastRow-fFirstRow+1;
347   fNumberOfPadsInRow= new Int_t[fNumberOfRows];
348
349   memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
350
351   for(Int_t i=0;i<fNumberOfRows;i++){
352     fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
353     AliHLTTPCPadVector tmpRow;
354     for(Int_t j=0;j<fNumberOfPadsInRow[i];j++){
355       AliHLTTPCPad *tmpPad = new AliHLTTPCPad();
356       tmpPad->SetID(i,j);
357       tmpRow.push_back(tmpPad);
358     }
359     fRowPadVector.push_back(tmpRow);
360   }
361   fVectorInitialized=kTRUE;
362 }
363
364
365 int AliHLTTPCZeroSuppressionComponent::DoEvent( const AliHLTComponentEventData& evtData, 
366                                                 const AliHLTComponentBlockData* blocks, 
367                                                 AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* outputPtr, 
368                                                 AliHLTUInt32_t& size, 
369                                                 vector<AliHLTComponentBlockData>& outputBlocks )
370 {
371   // see header file for class documentation
372   int iResult=0;
373   if (!fDigitReader) return -ENODEV;
374
375   AliHLTUInt32_t capacity=size;
376   size=0;
377   if (!IsDataEvent()) return 0;
378
379   //  HLTInfo("Entered DoEvent in AliHLTTPCZeroSuppressionComponent");
380
381   //  == init iter (pointer to datablock)
382   const AliHLTComponentBlockData* iter = NULL;
383   unsigned long ndx;
384   //  HLTInfo("Number of blocks: ",evtData.fBlockCnt);
385
386   fHwAddressList.clear();
387   //reading the data
388   for ( ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
389     {
390       iter = blocks+ndx;
391       
392       HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",
393                evtData.fEventID, evtData.fEventID, 
394                DataType2Text( iter->fDataType).c_str(), 
395                DataType2Text(kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC).c_str());
396
397       if ( iter->fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC)){
398         continue;
399       }
400
401       if (iter->fSize<=sizeof(AliRawDataHeader)) {
402         // forward empty DDLs and create empty HW list
403         outputBlocks.push_back(*iter);
404         if(fSendHWList == kTRUE){
405           AliHLTComponentBlockData bd;
406           FillBlockData( bd );
407           bd.fOffset = 0;
408           bd.fSize = 0;
409           bd.fDataType = kAliHLTDataTypeHwAddr16|kAliHLTDataOriginTPC;
410           bd.fSpecification = iter->fSpecification;
411           outputBlocks.push_back( bd );
412         }
413         continue;
414       }
415
416       UInt_t slice = AliHLTTPCDefinitions::GetMinSliceNr( *iter );
417       UInt_t patch = AliHLTTPCDefinitions::GetMinPatchNr( *iter );
418
419       if(!fVectorInitialized && !fSkipSendingZSData){
420         fCurrentPatch=patch;
421         InitializePadArray();
422       }
423       
424       if(fDigitReader->InitBlock(iter->fPtr,iter->fSize,patch,slice)<0){
425         HLTWarning("Decoder failed to initialize, event aborted.");
426         continue;
427       }
428       AliHLTTPCMapping mapping(patch);
429
430       int nTotalChannels=0;
431       int nSkippedChannels=0;
432       short lowestOccupancy=-1;
433       float sumOccupancy=0;
434
435       //Here the reading of the data and the zerosuppression takes place
436       while(fDigitReader->NextChannel()){//Pad
437         int sumSignals=0;
438         int maxSignal=0;
439         int nofSignals=0;
440         Int_t row=fDigitReader->GetRow();
441         Int_t pad=fDigitReader->GetPad();
442         if(row==1000 || pad==1000){
443           continue;
444         }
445         if(!fSkipSendingZSData && (row>=fNumberOfRows||row<0)){
446           continue;
447         }
448         else if(!fSkipSendingZSData && (pad>=fNumberOfPadsInRow[row]||pad<0)){
449           continue;
450         }  
451         
452         AliHLTTPCPad *tmpPad = NULL;
453         if (!fSkipSendingZSData) tmpPad=fRowPadVector[row][pad];
454         if (tmpPad) tmpPad->SetDataToDefault();
455
456         //reading data to pad
457         while(fDigitReader->NextBunch()){
458           const UInt_t *bunchData= fDigitReader->GetSignals();
459           Int_t time=fDigitReader->GetTime();
460           for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
461             if(bunchData[i]>0){// disregarding 0 data.
462               if(time+i>=fStartTimeBin && time+i<=fEndTimeBin){
463                 if (tmpPad) tmpPad->SetDataSignal(time+i,bunchData[i]);
464                 sumSignals+=bunchData[i];
465                 if (maxSignal<(int)bunchData[i]) maxSignal=bunchData[i];
466                 nofSignals++;
467               }
468             }
469           }
470         }
471
472         nTotalChannels++;
473         if (lowestOccupancy<0 || lowestOccupancy>nofSignals)
474           lowestOccupancy=nofSignals;
475         sumOccupancy+=nofSignals;
476
477         if(nofSignals>=fMinimumNumberOfSignals){
478           if (tmpPad) {
479           tmpPad->ZeroSuppress(fNRMSThreshold, fSignalThreshold, fMinimumNumberOfSignals, fStartTimeBin, fEndTimeBin, fLeftTimeBin, fRightTimeBin, fValueBelowAverage, fSkipSendingZSData);
480           if(tmpPad->GetNAddedSignals()>0){
481             assert((int)mapping.GetRow(fDigitReader->GetAltroBlockHWaddr())==row);
482             assert((int)mapping.GetPad(fDigitReader->GetAltroBlockHWaddr())==pad);
483             fHwAddressList.push_back((AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr());
484           }
485           } else {
486             assert(fSkipSendingZSData);
487             if (nofSignals>0 && maxSignal>(sumSignals/nofSignals)+fSignalThreshold) {
488               fHwAddressList.push_back((AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr());
489             }
490           }
491         } else {
492           nSkippedChannels++;
493         }
494       }
495       if (nSkippedChannels>0) {
496         HLTWarning("skipped %d of %d channels because of low occupancy: average %.2f, lowest %d, threshold %d",
497                    nSkippedChannels, nTotalChannels, sumOccupancy/nTotalChannels, lowestOccupancy, fMinimumNumberOfSignals);
498       }
499
500       AliHLTUInt32_t dataOffsetBeforeHW=0;
501
502       if(fSkipSendingZSData == kFALSE && iter->fSize>sizeof(AliRawDataHeader)) {
503   
504         AliHLTAltroEncoder *altroEncoder = new AliHLTAltroEncoder;
505         altroEncoder->SetBuffer(outputPtr,capacity); //tests if one overwrite the buffer is done in the encoder
506
507         // set CDH from the beginning of buffer
508         altroEncoder->SetCDH((AliHLTUInt8_t*)iter->fPtr,sizeof(AliRawDataHeader));
509
510         UChar_t *RCUTrailer=NULL;
511         Int_t RCUTrailerSize=fDigitReader->GetRCUTrailerSize();
512         if (RCUTrailerSize<=0 || !fDigitReader->GetRCUTrailerData( RCUTrailer )) {
513           if(RCUTrailer==NULL){
514             HLTWarning("can not find RCU trailer for data block %s 0x%08x: skipping data block",
515                        DataType2Text(iter->fDataType).c_str(), iter->fSpecification);
516             continue;
517           }
518         }
519         altroEncoder->SetRCUTrailer(RCUTrailer, RCUTrailerSize);
520
521         for(unsigned int channel=0; channel<fHwAddressList.size(); channel++){
522           int row=mapping.GetRow(fHwAddressList[channel]);
523           int pad=mapping.GetPad(fHwAddressList[channel]);
524           if (true) {
525             AliHLTTPCPad * zeroSuppressedPad= fRowPadVector[row][pad];
526             Int_t currentTime=0;
527             Int_t bunchSize=0;
528             if(zeroSuppressedPad->GetNAddedSignals()>0){
529               while(zeroSuppressedPad->GetNextGoodSignal(currentTime, bunchSize)){
530                 for(Int_t i=0;i<bunchSize;i++){
531                   if (altroEncoder->AddSignal((AliHLTUInt16_t)(zeroSuppressedPad->GetDataSignal(currentTime+i)),(AliHLTUInt16_t)(currentTime+i))<0) {
532                     // Matthias 01.10.2008: there is a problem with certain real data which produces the same
533                     // bunch multiple times, needs investigation. I found an examplary case in run 53465
534                     // (08000053465011.450.root) equipment 981.
535                     // needs to be followed up.
536                     // addon 02.10.2008 I just corrected a bug concerning the loop over the active channels.
537                     // A double loop over all rows and pads also considered pads which had not even been
538                     // filled, and thus not properly cleaned. Maybe the bug above is related to that.
539                     HLTWarning("can not add channel: slice %d, partition %d, hw address %d, row %d, pad %d, time %d, bunch size %d",
540                                slice, patch, fHwAddressList[channel], row, pad, currentTime+i, bunchSize);
541                     break;
542                   }
543                 }
544               }
545               altroEncoder->SetChannel(fHwAddressList[channel]);
546             }
547           }
548         }
549
550         int sizeOfData=altroEncoder->SetLength();
551
552         if (sizeOfData<0) {
553           HLTError("data encoding failed");
554           iResult=sizeOfData;
555           break;
556         }
557         if(sizeOfData>(int)capacity){
558           HLTWarning("Buffer too small too add the altrodata: %d of %d byte(s) already used", sizeOfData, capacity);
559           iResult=-ENOSPC;
560           break;
561         }
562
563         //Push back the zerosuppressed altro data to the output
564         if(true/* condition was deprecated but keep for the sake of formatting*/){
565           AliHLTComponentBlockData bd;
566           FillBlockData( bd );
567           bd.fOffset = 0;
568           bd.fSize = sizeOfData;
569           bd.fDataType = kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
570           bd.fSpecification = iter->fSpecification;
571           outputBlocks.push_back( bd );
572     
573           //Push back the list of hardware addresses to the output
574           dataOffsetBeforeHW=sizeOfData;
575         }
576       }
577
578       AliHLTUInt32_t sizeOfHWArray = 0;
579       if(fSendHWList == kTRUE){
580
581         if(true/* condition was deprecated but keep for the sake of formatting*/){
582           sizeOfHWArray = fHwAddressList.size()*sizeof(AliHLTUInt16_t);
583       
584           if(dataOffsetBeforeHW+sizeOfHWArray>capacity){
585             HLTWarning("Buffer too small too add the active channels: %d of %d byte(s) already used", dataOffsetBeforeHW + sizeOfHWArray, capacity);
586             iResult=-ENOSPC;
587             break;
588           }
589       
590           AliHLTUInt16_t*outputHWPtr=(AliHLTUInt16_t*)(outputPtr+dataOffsetBeforeHW);
591           memcpy(outputHWPtr,&fHwAddressList[0],sizeOfHWArray);
592           AliHLTComponentBlockData bdHW;
593           FillBlockData( bdHW );
594           bdHW.fOffset = dataOffsetBeforeHW;
595           bdHW.fSize = sizeOfHWArray;
596           bdHW.fDataType = kAliHLTDataTypeHwAddr16|kAliHLTDataOriginTPC;
597           bdHW.fSpecification = iter->fSpecification;
598           outputBlocks.push_back( bdHW );
599         }
600       }
601       size = dataOffsetBeforeHW+sizeOfHWArray;
602       fDigitReader->Reset();
603     }
604
605   if (iResult<0) {
606     fDigitReader->Reset();
607     size=0;
608   }
609
610   return iResult;
611 }