]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/RCU/AliHLTAltroChannelSelectorComponent.cxx
(Matthias) Fixed bug, rcuTrailerLength is already in bytes.
[u/mrichter/AliRoot.git] / HLT / RCU / AliHLTAltroChannelSelectorComponent.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: Matthias Richter <Matthias.Richter@ift.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   AliHLTAltroChannelSelectorComponent.cxx
20     @author Matthias Richter
21     @date   
22     @brief  A filter/selective readout component for Altro data.
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 #include <cassert>
32 #include "AliHLTAltroChannelSelectorComponent.h"
33 #include "AliAltroDecoder.h"
34 #include "AliAltroData.h"
35
36 /** ROOT macro for the implementation of ROOT specific class methods */
37 ClassImp(AliHLTAltroChannelSelectorComponent)
38
39 AliHLTAltroChannelSelectorComponent::AliHLTAltroChannelSelectorComponent()
40   :
41   AliHLTProcessor(),
42   fSkipCorrupted(false),
43   fTalkative(false)
44 {
45   // see header file for class documentation
46   // or
47   // refer to README to build package
48   // or
49   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
50 }
51
52 AliHLTAltroChannelSelectorComponent::~AliHLTAltroChannelSelectorComponent()
53 {
54   // see header file for class documentation
55 }
56
57 const char* AliHLTAltroChannelSelectorComponent::GetComponentID()
58 {
59   // see header file for class documentation
60   return "AltroChannelSelector";
61 }
62
63 void AliHLTAltroChannelSelectorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
64 {
65   // see header file for class documentation
66   list.clear();
67   list.push_back(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC);
68   list.push_back(kAliHLTDataTypeHwAddr16);
69 }
70
71 AliHLTComponentDataType AliHLTAltroChannelSelectorComponent::GetOutputDataType()
72 {
73   // see header file for class documentation
74   return kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
75 }
76
77 void AliHLTAltroChannelSelectorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
78 {
79   // see header file for class documentation
80   constBase=0;
81   inputMultiplier=1.0;
82 }
83
84 AliHLTComponent* AliHLTAltroChannelSelectorComponent::Spawn()
85 {
86   // see header file for class documentation
87   return new AliHLTAltroChannelSelectorComponent;
88 }
89
90 int AliHLTAltroChannelSelectorComponent::DoInit(int argc, const char** argv)
91 {
92   // see header file for class documentation
93   int iResult=0;
94   TString argument="";
95   bool bMissingParam=0;
96   for (int i=0; i<argc && iResult>=0; i++) {
97     argument=argv[i];
98     if (argument.IsNull()) continue;
99
100     // -skip-corrupted
101     if (argument.CompareTo("-skip-corrupted")==0) {
102       fSkipCorrupted=true;
103
104     // -talkative
105     } else if (argument.CompareTo("-talkative")==0) {
106       fTalkative=true;
107     } else {
108       HLTError("unknown argument %s", argument.Data());
109       iResult=-EINVAL;
110     }
111   }
112
113   if (bMissingParam) {
114     HLTError("missing parameter for argument %s", argument.Data());
115     iResult=-EINVAL;
116   }
117
118   return iResult;
119 }
120
121 int AliHLTAltroChannelSelectorComponent::DoDeinit()
122 {
123   // see header file for class documentation
124   return 0;
125 }
126
127 int AliHLTAltroChannelSelectorComponent::DoEvent(const AliHLTComponentEventData& evtData,
128                                                  const AliHLTComponentBlockData* blocks, 
129                                                  AliHLTComponentTriggerData& /*trigData*/,
130                                                  AliHLTUInt8_t* outputPtr, 
131                                                  AliHLTUInt32_t& size,
132                                                  AliHLTComponentBlockDataList& outputBlocks )
133 {
134   // see header file for class documentation
135   int iResult=0;
136   const int cdhSize=32;
137
138   // process the DLL input
139   int blockno=0;
140   const AliHLTComponentBlockData* pDesc=NULL;
141
142   AliAltroDecoder* decoder=NULL;
143   for (pDesc=GetFirstInputBlock(kAliHLTDataTypeDDLRaw); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
144     iResult=0;
145     if (pDesc->fSize<=32) continue;
146
147     // search for the active pad information
148     AliHLTUInt16_t* pActiveHwAddressArray=NULL;
149     int iArraySize=0;
150     for (int i=0; i<(int)evtData.fBlockCnt; i++ ) {
151       // search for selection data of hw address type
152       // which matches the data specification of the block
153       if (blocks[i].fDataType==kAliHLTDataTypeHwAddr16 && blocks[i].fSpecification==pDesc->fSpecification) {
154         pActiveHwAddressArray=reinterpret_cast<AliHLTUInt16_t*>(blocks[i].fPtr);
155         iArraySize=blocks[i].fSize/sizeof(AliHLTUInt16_t);
156         break;
157       }
158     }
159     if (pActiveHwAddressArray==NULL) {
160       HLTWarning("no block of type %s for specification 0x%08x available, data block unchanged", 
161                  DataType2Text(kAliHLTDataTypeHwAddr16).c_str(), 
162                  pDesc->fSpecification);
163       iResult=-EFAULT;
164     }
165
166     if (decoder) delete decoder;
167     decoder=new AliAltroDecoder;
168     if (decoder->SetMemory(reinterpret_cast<UChar_t*>(pDesc->fPtr), pDesc->fSize)<0) {
169       HLTWarning("corrupted data block: initialization of decoder failed for block: %s specification %#x size %d",
170                  DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, pDesc->fSize);
171       iResult=-EFAULT;
172     } else {
173       if (decoder->Decode()) {
174         HLTDebug("init decoder %p size %d", pDesc->fPtr,pDesc->fSize);
175       } else {
176         HLTWarning("corrupted data block: decoding failed for raw data block: %s specification %#x size %d",
177                    DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, pDesc->fSize);
178         iResult=-EFAULT;
179       }
180     }
181
182     int rcuTrailerLength=decoder->GetRCUTrailerSize();
183     if (rcuTrailerLength>pDesc->fSize-cdhSize) {
184       HLTWarning("corrupted data block: RCU trailer length exceeds buffer size");
185       iResult=-EFAULT;
186     }
187
188     if (iResult<0) {
189       // forward the whole block
190       outputBlocks.push_back(*pDesc);
191       iResult=0;
192       continue;
193     }
194
195     int iSelected=0;
196     int iTotal=0;
197     int iCorrupted=0;
198     AliHLTUInt32_t iOutputSize=0;
199     AliHLTUInt32_t iNofAltro40=0;
200     AliHLTUInt32_t iCapacity=size;
201     AliAltroData channel;
202     while (decoder->NextChannel(&channel) && iResult>=0) {
203       iTotal++;
204
205       int hwAddress=channel.GetHadd();
206       int active=0;
207       for (active=0; active<iArraySize; active++) {
208         if (pActiveHwAddressArray[active]==(AliHLTUInt16_t)hwAddress) {
209           break;
210         }
211       }
212       if (active>=iArraySize) {
213         HLTDebug("ALTRO block %#x (%d) discarded (inactive)", hwAddress, hwAddress);
214         continue;
215       }
216
217       // no of 10 bit words is without the fill words to fill complete 40 bit words
218       // in addition, align to complete 40 bit words (the '+3')
219       // also, the 5 bytes of the Altro trailer must be added to get the full size
220       int channelSize=((channel.GetDataSize()+3)/4)*5;
221       channelSize+=5;
222       HLTDebug("ALTRO block hwAddress 0x%08x (%d) selected (active), size %d", hwAddress, hwAddress, channelSize);
223       if (iOutputSize==0) {
224         // first add the RCU trailer
225         AliHLTUInt8_t* pSrc=reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr);
226         pSrc+=pDesc->fSize-rcuTrailerLength;
227         if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pSrc, rcuTrailerLength))>=0) {
228           assert(iResult==rcuTrailerLength);
229           iOutputSize+=rcuTrailerLength;
230         } else {
231           HLTError("failed to write RCU trailer of length %d for block %d, too little space in output buffer?", rcuTrailerLength, blockno);
232           iResult=-ENOSPC;
233           break;
234         }
235       }
236
237       if ((iResult=decoder->CopyBackward(outputPtr, iCapacity-iOutputSize))>=0) {
238         if (channelSize == iResult) {
239           if (channelSize%5 == 0) {
240             iNofAltro40+=channelSize/5;
241             iOutputSize+=channelSize;
242           } else {
243             if (fTalkative) HLTWarning("corrupted ALTRO channel: incomplete 40 bit word");
244             iCorrupted++;
245             continue;
246           }
247         } else {
248           if (fTalkative) HLTWarning("internal error: failed to copy full channel: %d out of %d bytes", iResult, channelSize);
249           iCorrupted++;
250           continue;
251         }
252       } else {
253         if (fTalkative) HLTError("failed to write ALTRO channel of length %d for block %d", channelSize, blockno);
254         // corrupted channel, but keep going
255         iCorrupted++;
256         iResult=0;
257         continue;
258       }
259       iSelected++;
260     }
261     if (iResult>=0) {
262       // write the common data header
263       if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pDesc->fPtr, cdhSize))>=0) {
264         assert(iResult==cdhSize);
265         iOutputSize+=cdhSize;
266
267         // set new length of the data block
268         AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-iOutputSize);
269         *pCdhSize=iOutputSize;
270
271         // set number of Altro words
272         AliHLTUInt32_t* pNofAltro40=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-rcuTrailerLength);
273         *pNofAltro40=iNofAltro40;
274
275         // insert block descriptor
276         AliHLTComponentBlockData bd;
277         FillBlockData(bd);
278         bd.fOffset=iCapacity-iOutputSize;
279         bd.fSize=iOutputSize;
280         bd.fDataType=pDesc->fDataType;
281         bd.fSpecification=pDesc->fSpecification;
282         outputBlocks.push_back(bd);
283         iCapacity-=iOutputSize;
284       } else {
285         HLTError("failed to write CDH of length %d for block %d", cdhSize, blockno);
286         break;
287       }
288     }
289     HLTInfo("data block %d (0x%08x): selected %d out of %d ALTRO channel(s), %d corrupted channels skipped", blockno, pDesc->fSpecification, iSelected, iTotal, iCorrupted);
290   }
291   if (decoder) delete decoder;
292
293   if (iResult<0) {
294     outputBlocks.clear();
295   }
296
297   // !!! do not change the size since the output buffer is filled from the end !!!
298
299   return iResult;
300 }
301
302 int AliHLTAltroChannelSelectorComponent::CopyBlockToEnd(AliHLTUInt8_t* pTgt, unsigned capacity, unsigned position, void* pSrc, unsigned size)
303 {
304   int iResult=0;
305   if (pTgt==NULL || pSrc==NULL) return -EINVAL;
306   if (capacity-position<size) return -ENOSPC;
307   
308   memcpy(pTgt+(capacity-position-size), pSrc, size);
309   iResult=size;
310   
311   return iResult;
312 }