3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
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 //**************************************************************************
19 /// @file AliHLTAltroChannelSelectorComponent.cxx
20 /// @author Matthias Richter
22 /// @brief A filter/selective readout component for Altro data.
27 #include "AliHLTAltroChannelSelectorComponent.h"
28 #include "AliHLTErrorGuard.h"
29 #include "AliHLTDAQ.h"
30 #include "AliRawReaderMemory.h"
31 #include "AliAltroRawStreamV3.h"
34 /** ROOT macro for the implementation of ROOT specific class methods */
35 ClassImp(AliHLTAltroChannelSelectorComponent)
37 AliHLTAltroChannelSelectorComponent::AliHLTAltroChannelSelectorComponent()
47 // see header file for class documentation
49 // refer to README to build package
51 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
54 AliHLTAltroChannelSelectorComponent::~AliHLTAltroChannelSelectorComponent()
56 // see header file for class documentation
59 const char* AliHLTAltroChannelSelectorComponent::GetComponentID()
61 // see header file for class documentation
62 return "AltroChannelSelector";
65 void AliHLTAltroChannelSelectorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
67 // see header file for class documentation
69 list.push_back(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC);
70 list.push_back(kAliHLTDataTypeHwAddr16);
73 AliHLTComponentDataType AliHLTAltroChannelSelectorComponent::GetOutputDataType()
75 // see header file for class documentation
76 return kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
79 void AliHLTAltroChannelSelectorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
81 // see header file for class documentation
86 AliHLTComponent* AliHLTAltroChannelSelectorComponent::Spawn()
88 // see header file for class documentation
89 return new AliHLTAltroChannelSelectorComponent;
92 int AliHLTAltroChannelSelectorComponent::DoInit(int argc, const char** argv)
94 // see header file for class documentation
100 for (; i<argc && iResult>=0; i++) {
103 if (argument.IsNull()) continue;
105 // -skip-corrupted, just for backward compatibility, not announced
106 if (argument.CompareTo("-skip-corrupted")==0) {
110 } else if (argument.CompareTo("-keep-corrupted")==0) {
111 fSkipCorrupted=false;
114 } else if (argument.CompareTo("-talkative")==0) {
118 } else if (argument.CompareTo("-start-timebin")==0) {
119 if ((bMissingParam=(++i>=argc))) break;
120 fStartTimeBin = strtoul( argv[i], &cpErr ,0);
124 } else if (argument.CompareTo("-end-timebin")==0) {
125 if ((bMissingParam=(++i>=argc))) break;
126 fEndTimeBin = strtoul( argv[i], &cpErr ,0);
130 } else if (argument.CompareTo("-signal-threshold")==0) {
131 if ((bMissingParam=(++i>=argc))) break;
132 fSignalThreshold = strtoul( argv[i], &cpErr ,0);
136 } else if (argument.CompareTo("-rms-threshold")==0) {
137 if ((bMissingParam=(++i>=argc))) break;
138 fRMSThreshold = strtoul( argv[i], &cpErr ,0);
142 HLTError("unknown argument %s", argument.Data());
147 if (cpErr && *cpErr) {
148 HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
150 } else if (bMissingParam) {
151 HLTError("missing parameter for argument %s", argument.Data());
158 int AliHLTAltroChannelSelectorComponent::DoDeinit()
160 // see header file for class documentation
164 int AliHLTAltroChannelSelectorComponent::DoEvent(const AliHLTComponentEventData& evtData,
165 const AliHLTComponentBlockData* blocks,
166 AliHLTComponentTriggerData& /*trigData*/,
167 AliHLTUInt8_t* outputPtr,
168 AliHLTUInt32_t& size,
169 AliHLTComponentBlockDataList& outputBlocks )
171 // see header file for class documentation
173 const int cdhSize=32;
175 if (!IsDataEvent()) {
180 // process the DLL input
182 const AliHLTComponentBlockData* pDesc=NULL;
183 std::auto_ptr<AliRawReaderMemory> pRawReader(new AliRawReaderMemory);
184 if (pRawReader.get()) return -ENOMEM;
186 for (pDesc=GetFirstInputBlock(kAliHLTDataTypeDDLRaw); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
188 if (pDesc->fSize<=32) {
192 // search for the active pad information
193 AliHLTUInt16_t* pActiveHwAddressArray=NULL;
195 if (fSignalThreshold==0 && fRMSThreshold==0) {
196 for (int i=0; i<(int)evtData.fBlockCnt; i++ ) {
197 // search for selection data of hw address type
198 // which matches the data specification of the block
199 if (blocks[i].fDataType==kAliHLTDataTypeHwAddr16 && blocks[i].fSpecification==pDesc->fSpecification) {
200 pActiveHwAddressArray=reinterpret_cast<AliHLTUInt16_t*>(blocks[i].fPtr);
201 iArraySize=blocks[i].fSize/sizeof(AliHLTUInt16_t);
205 if (pActiveHwAddressArray==NULL) {
206 HLTWarning("no block of type %s for specification 0x%08x available, data block skipped",
207 DataType2Text(kAliHLTDataTypeHwAddr16).c_str(),
208 pDesc->fSpecification);
213 static AliHLTErrorGuard required("AliHLTAltroChannelSelectorComponent", "DoEvent", "component commission required after major changes");
214 (++required).Throw(1);
217 int ddlid=AliHLTDAQ::DdlIDFromHLTBlockData(pDesc->fDataType.fOrigin, pDesc->fSpecification);
219 HLTError("unable to extract DDL Id for data block %s 0x%08x", DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
223 if (!pRawReader->AddBuffer((UChar_t*)pDesc->fPtr,pDesc->fSize, ddlid)) {
224 ALIHLTERRORGUARD(1, "can not set up AltroDecoder for data block %s 0x%08x,"
225 " skipping data block and suppressing further messages",
226 DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
230 std::auto_ptr<AliAltroRawStreamV3> altroRawStream(new AliAltroRawStreamV3(pRawReader.get()));
232 if (!altroRawStream.get()) {
237 altroRawStream->Reset();
238 if (!altroRawStream->NextDDL()) {
239 ALIHLTERRORGUARD(1, "internal error, can not read data from AliRawReaderMemory");
243 unsigned int rcuTrailerLength=0;
245 ((rcuTrailerLength=altroRawStream->GetRCUTrailerSize())==0 ||
246 rcuTrailerLength>pDesc->fSize-cdhSize)) {
247 if (rcuTrailerLength>0) {
248 HLTWarning("corrupted data block: RCU trailer length exceeds buffer size");
250 HLTWarning("corrupted data block: RCU trailer of zero length");
256 // TODO: here the trigger has to come into play. It is up to
257 // policy if a corrupted data block should be kept (original
258 // DDL) or discarded. In any case, the block is not going to
260 HLTWarning("skipping corrupted data block for event %lu, data block %s 0x%08x", evtData.fEventID,
261 DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
269 AliHLTUInt32_t iOutputSize=0;
270 AliHLTUInt32_t iNofAltro40=0;
271 AliHLTUInt32_t iCapacity=size;
273 // first add the RCU trailer
274 AliHLTUInt8_t* pSrc=reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr);
275 pSrc+=pDesc->fSize-rcuTrailerLength;
276 if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pSrc, rcuTrailerLength))>=0) {
277 assert(iResult==(int)rcuTrailerLength);
278 iOutputSize+=rcuTrailerLength;
280 HLTError("failed to write RCU trailer of length %d for block %d, too little space in output buffer?", rcuTrailerLength, blockno);
285 while (altroRawStream->NextChannel() && iResult>=0) {
288 int hwAddress=altroRawStream->GetHWAddress();
289 if (fSignalThreshold!=0) {
290 // treshold by adc counts
291 unsigned int sumSignals=0;
292 unsigned int maxSignal=0;
293 unsigned int nofSignals=0;
294 while(altroRawStream->NextBunch()){
295 const UShort_t *bunchData=altroRawStream->GetSignals();
296 unsigned int time=altroRawStream->GetStartTimeBin();
297 for(Int_t i=0;i<altroRawStream->GetBunchLength();i++){
298 if(bunchData[i]>0){// disregarding 0 data.
299 if(time+i>=fStartTimeBin && time+i<=fEndTimeBin){
300 sumSignals+=bunchData[i];
301 if (maxSignal<bunchData[i]) maxSignal=bunchData[i];
307 if (nofSignals==0 || maxSignal<=(sumSignals/nofSignals)+fSignalThreshold) {
311 } else if (fRMSThreshold!=0) {
312 // treshold by adc counts
313 unsigned int sumSignals=0;
314 unsigned int maxSignal=0;
315 unsigned int nofSignals=0;
316 while(altroRawStream->NextBunch()){
317 const UShort_t *bunchData=altroRawStream->GetSignals();
318 unsigned int time=altroRawStream->GetStartTimeBin();
319 for(Int_t i=0;i<altroRawStream->GetBunchLength();i++){
320 if(bunchData[i]>0){// disregarding 0 data.
321 if(time+i>=fStartTimeBin && time+i<=fEndTimeBin){
322 sumSignals+=bunchData[i]*bunchData[i];
323 if (maxSignal<bunchData[i]) maxSignal=bunchData[i];
329 if (nofSignals==0 || maxSignal<=TMath::Sqrt(sumSignals/nofSignals)*fRMSThreshold) {
335 for (active=0; active<iArraySize; active++) {
336 if (pActiveHwAddressArray[active]==(AliHLTUInt16_t)hwAddress) {
340 if (active>=iArraySize) {
341 HLTDebug("ALTRO block %#x (%d) discarded (inactive)", hwAddress, hwAddress);
346 // no of 10 bit words is without the fill words to fill complete 40 bit words
347 // in addition, align to complete 40 bit words (the '+3')
348 // also, the 5 bytes of the Altro trailer must be added to get the full size
349 int channelSize=((altroRawStream->GetChannelPayloadSize()+2)/3)*4;
350 if (channelSize==0) {
351 if (fTalkative) HLTWarning("skipping zero length channel (hw address %d)", hwAddress);
356 HLTDebug("ALTRO block hwAddress 0x%08x (%d) selected (active), size %d", hwAddress, hwAddress, channelSize);
359 if (channelSize == iResult) {
360 if (channelSize%4 == 0) {
361 iOutputSize+=channelSize;
363 if (fTalkative) HLTWarning("corrupted ALTRO channel: incomplete 40 bit word (channel hw address %d)", hwAddress);
368 if (fTalkative) HLTWarning("internal error: failed to copy full channel: %d out of %d bytes (hw address %d)", iResult, channelSize, hwAddress);
373 if (fTalkative) HLTError("failed to write ALTRO channel of length %d for block %d (hw address %d)", channelSize, blockno, hwAddress);
374 // corrupted channel, but keep going
382 // write the common data header
383 if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pDesc->fPtr, cdhSize))>=0) {
384 assert(iResult==cdhSize);
385 iOutputSize+=cdhSize;
387 // set new length of the data block
388 AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-iOutputSize);
389 *pCdhSize=iOutputSize;
391 // set number of Altro words
392 AliHLTUInt32_t* pNofAltro40=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-rcuTrailerLength);
393 *pNofAltro40=iNofAltro40;
395 // insert block descriptor
396 AliHLTComponentBlockData bd;
398 bd.fOffset=iCapacity-iOutputSize;
399 bd.fSize=iOutputSize;
400 bd.fDataType=pDesc->fDataType;
401 bd.fSpecification=pDesc->fSpecification;
402 outputBlocks.push_back(bd);
403 iCapacity-=iOutputSize;
405 HLTError("failed to write CDH of length %d for block %d", cdhSize, blockno);
409 if (fTalkative) HLTImportant("data block %d (0x%08x): selected %d out of %d ALTRO channel(s), %d corrupted channels skipped", blockno, pDesc->fSpecification, iSelected, iTotal, iCorrupted);
413 outputBlocks.clear();
416 // all data blocks need to be moved to the beginning of the
417 // buffer because PubSub is not able to handle data blocks entirely
418 // at the end of the buffer. The problem is that the component always
419 // indicates to use the full size of the buffer
420 if (outputBlocks.size()>0) {
421 int offset=outputBlocks.back().fOffset;
423 memmove(outputPtr, outputPtr+offset, size);
424 for (AliHLTComponentBlockDataList::iterator block=outputBlocks.begin();
425 block!=outputBlocks.end();
427 block->fOffset-=offset;
434 int AliHLTAltroChannelSelectorComponent::CopyBlockToEnd(AliHLTUInt8_t* pTgt, unsigned capacity, unsigned position, void* pSrc, unsigned size)
437 if (pTgt==NULL || pSrc==NULL) return -EINVAL;
438 if (capacity-position<size) return -ENOSPC;
440 memcpy(pTgt+(capacity-position-size), pSrc, size);