1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
17 // $Id: AliHLTMUONDigitPublisherComponent.cxx 26179 2008-05-29 22:27:27Z aszostak $
20 /// @file AliHLTMUONDigitPublisherComponent.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
23 /// @brief Implementation of the dHLT digit publisher component.
25 /// This component is used to publish simulated or reconstructed digits from
26 /// the digits trees as DDL raw data. The data is converted into DDL format
30 #include "AliHLTMUONDigitPublisherComponent.h"
31 #include "AliHLTMUONConstants.h"
32 #include "AliHLTMUONUtils.h"
33 #include "AliHLTLogging.h"
34 #include "AliHLTSystem.h"
35 #include "AliHLTDefinitions.h"
36 #include "AliRawDataHeaderV3.h"
37 #include "AliMUONTrackerDDLDecoderEventHandler.h"
38 #include "AliMUONConstants.h"
39 #include "AliMUONMCDataInterface.h"
40 #include "AliMUONDataInterface.h"
41 #include "AliMUONVDigitStore.h"
42 #include "AliMUONVTriggerStore.h"
43 #include "AliMpExMap.h"
46 #include "AliMpDDLStore.h"
47 #include "AliMpDEManager.h"
48 #include "AliMpTriggerCrate.h"
49 #include "AliMpConstants.h"
50 #include "AliBitPacking.h"
51 #include "AliMUONBlockHeader.h"
52 #include "AliMUONBusStruct.h"
53 #include "AliMUONConstants.h"
54 #include "AliMUONDarcHeader.h"
55 #include "AliMUONVDigit.h"
56 #include "AliMUONDspHeader.h"
57 #include "AliMUONGlobalTrigger.h"
58 #include "AliMUONLocalStruct.h"
59 #include "AliMUONLocalTrigger.h"
60 #include "AliMUONLocalTriggerBoard.h"
61 #include "AliMUONRegionalTrigger.h"
62 #include "AliMUONRegHeader.h"
63 #include "AliRunLoader.h"
64 #include "AliCentralTrigger.h"
73 ClassImp(AliHLTMUONDigitPublisherComponent)
76 AliHLTMUONDigitPublisherComponent::AliHLTMUONDigitPublisherComponent() :
77 AliHLTOfflineDataSource(),
79 fCurrentEventIndex(0),
81 fMCDataInterface(NULL),
83 fChamberExclusionList(0),
84 fDetElemExclusionList(0)
86 /// Default constructor.
90 AliHLTMUONDigitPublisherComponent::~AliHLTMUONDigitPublisherComponent()
92 /// Default destructor.
94 if (fMCDataInterface != NULL) delete fMCDataInterface;
95 if (fDataInterface != NULL) delete fDataInterface;
98 const char* AliHLTMUONDigitPublisherComponent::GetComponentID()
100 /// Inherited from AliHLTComponent. Returns the component ID.
102 return AliHLTMUONConstants::DigitPublisherId();
106 AliHLTComponentDataType AliHLTMUONDigitPublisherComponent::GetOutputDataType()
108 /// Inherited from AliHLTComponent. Returns the raw DDL data type.
110 return AliHLTMUONConstants::DDLRawDataType();
114 void AliHLTMUONDigitPublisherComponent::GetOutputDataSize(
115 unsigned long& constBase, double& inputMultiplier
118 /// Inherited from AliHLTComponent.
119 /// Returns an estimate of the expected output data size.
121 // estimated as max number of channels * raw data word size + max headers size.
122 constBase = sizeof(AliRawDataHeaderV3) + 65536*sizeof(UInt_t)
123 + sizeof(AliMUONBlockHeaderStruct)*2 + sizeof(AliMUONDSPHeaderStruct)*10
124 + sizeof(AliMUONBusPatchHeaderStruct) * 50;
129 AliHLTComponent* AliHLTMUONDigitPublisherComponent::Spawn()
131 /// Inherited from AliHLTComponent. Creates a new object instance.
133 return new AliHLTMUONDigitPublisherComponent;
137 int AliHLTMUONDigitPublisherComponent::ParseChamberString(const char* str)
139 /// Parses a string with the following format:
140 /// <number>|<number>-<number>[,<number>|<number>-<number>,...]
141 /// For example: 1 1,2,3 1-2 1,2-4,5 etc...
142 /// Chamber numbers must be in the range [1..10] for tracking chambers.
143 /// All valid tracking chamber numbers will added to fChamberExclusionList.
144 /// @param str The string to parse.
145 /// @return Zero on success and EINVAL if there is a parse error.
147 char* end = const_cast<char*>(str);
148 long lastChamber = -1;
151 // Parse the next number.
153 long chamber = strtol(current, &end, 0);
155 // Check for parse errors of the number.
158 HLTError("Expected a number in the range [1..%d] but got '%s'.",
159 AliMUONConstants::NTrackingCh(), current
163 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
165 HLTError("Received the chamber number %d, which is outside the valid range of [1..%d].",
166 chamber, AliMUONConstants::NTrackingCh()
171 // Skip any whitespace after the number
172 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
174 // Check if we are dealing with a list or range, or if we are at
175 // the end of the string.
178 lastChamber = chamber;
182 else if (*end == ',')
184 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
185 Int_t size = fChamberExclusionList.GetSize();
186 fChamberExclusionList.Set(size+1);
187 fChamberExclusionList[size] = chamber-1;
190 else if (*end == '\0')
192 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
193 Int_t size = fChamberExclusionList.GetSize();
194 fChamberExclusionList.Set(size+1);
195 fChamberExclusionList[size] = chamber-1;
199 HLTError("Could not understand parameter list '%s'. Expected '-', ','"
200 " or end of line, but received '%c' at character %d.",
201 str, *end, (int)(end - str) +1
206 // Set the range of chambers to publish for.
210 if (lastChamber < chamber)
221 assert( max <= AliMUONConstants::NTrackingCh() );
222 for (Int_t i = min; i <= max; i++)
224 Int_t size = fChamberExclusionList.GetSize();
225 fChamberExclusionList.Set(size+1);
226 fChamberExclusionList[size] = i-1;
231 while (*end != '\0');
236 int AliHLTMUONDigitPublisherComponent::ParseDetElemString(const char* str)
238 /// Parses a string with the following format:
239 /// <number>|<number>-<number>[,<number>|<number>-<number>,...]
240 /// For example: 100 100,201,208 100-104 105,202-204,503 etc...
241 /// Detector element numbers must be in the range [100..1099] for tracking stations.
242 /// All valid detector element numbers will added to fDetElemExclusionList.
243 /// @param str The string to parse.
244 /// @return Zero on success and EINVAL if there is a parse error.
246 char* end = const_cast<char*>(str);
247 long lastDetElem = -1;
250 // Parse the next number.
252 long detElem = strtol(current, &end, 0);
254 // Check for parse errors of the number.
257 HLTError("Expected a number in the range [100..1099] but got '%s'.",
262 if (detElem < 100 or 1099 < detElem)
264 HLTError("Received the detector element ID number of %d,"
265 " which is outside the valid range of [100..1099].",
271 // Skip any whitespace after the number
272 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
274 // Check if we are dealing with a list or range, or if we are at
275 // the end of the string.
278 lastDetElem = detElem;
282 else if (*end == ',')
284 assert( 100 <= detElem and detElem <= 1099 );
285 Int_t size = fDetElemExclusionList.GetSize();
286 fDetElemExclusionList.Set(size+1);
287 fDetElemExclusionList[size] = detElem-1;
290 else if (*end == '\0')
292 assert( 100 <= detElem and detElem <= 1099 );
293 Int_t size = fDetElemExclusionList.GetSize();
294 fDetElemExclusionList.Set(size+1);
295 fDetElemExclusionList[size] = detElem-1;
299 HLTError("Could not understand parameter list '%s'. Expected '-', ','"
300 " or end of line, but received '%c' at character %d.",
301 str, *end, (int)(end - str) +1
306 // Set the range of detector elements to publish for.
310 if (lastDetElem < detElem)
320 assert( min >= 100 );
321 assert( max <= 1099 );
322 for (Int_t i = min; i <= max; i++)
324 Int_t size = fDetElemExclusionList.GetSize();
325 fDetElemExclusionList.Set(size+1);
326 fDetElemExclusionList[size] = i-1;
331 while (*end != '\0');
336 int AliHLTMUONDigitPublisherComponent::DoInit(int argc, const char** argv)
338 /// Inherited from AliHLTComponent.
339 /// Parses the command line parameters and initialises the component.
341 HLTInfo("Initialising dHLT digit publisher component.");
343 if (fMCDataInterface != NULL)
345 delete fMCDataInterface;
346 fMCDataInterface = NULL;
348 if (fDataInterface != NULL)
350 delete fDataInterface;
351 fDataInterface = NULL;
354 // Initialise with default values.
356 fCurrentEventIndex = 0;
357 fMakeScalars = false;
358 fChamberExclusionList.Set(0);
359 fDetElemExclusionList.Set(0);
360 bool simdata = false;
361 bool recdata = false;
362 bool firstEventSet = false;
363 bool eventNumLitSet = false;
365 for (int i = 0; i < argc; i++)
367 if (strcmp(argv[i], "-makescalars") == 0)
372 if (strcmp(argv[i], "-simdata") == 0)
377 if (strcmp(argv[i], "-recdata") == 0)
382 if (strcmp(argv[i], "-ddl") == 0)
386 HLTError("DDL number not specified. It must be in the range [1..22]" );
391 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
392 if (cpErr == NULL or *cpErr != '\0')
394 HLTError("Cannot convert '%s' to a DDL number.", argv[i+1]);
397 if (num < 1 or 22 < num)
399 HLTError("The DDL number must be in the range [1..22].");
402 fDDL = num - 1; // Convert to DDL number in the range 0..21
407 if (strcmp(argv[i], "-ddlid") == 0)
411 HLTError("DDL equipment ID number not specified."
412 " It must be in the range [2560..2579] or [2816..2817]."
418 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
419 if (cpErr == NULL or *cpErr != '\0')
421 HLTError("Cannot convert '%s' to a DDL equipment ID number.", argv[i+1]);
424 fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
425 if (fDDL < 0 or 21 < fDDL)
427 HLTError("The DDL equipment ID number must be in the range"
428 " [2560..2579] or [2816..2817]."
436 if (strcmp(argv[i], "-firstevent") == 0)
440 HLTWarning("The -firstevent flag is overridden by a"
441 " previous use of -event_number_literal."
446 HLTError("Expected a positive number after -firstevent.");
450 long num = strtol(argv[i], &end, 0);
451 if ((end != NULL and *end != '\0') or num < 0) // Check if the conversion is OK.
453 HLTError("Expected a positive number after -firstevent"
454 " but got: %s", argv[i]
458 fCurrentEventIndex = Int_t(num);
459 firstEventSet = true;
462 if (strcmp(argv[i], "-event_number_literal") == 0)
466 HLTWarning("The -event_number_literal option will"
467 " override -firstevent."
470 fCurrentEventIndex = -1;
471 eventNumLitSet = true;
474 if (strcmp(argv[i], "-exclude_chamber") == 0)
478 HLTError("Expected a chamber number, a range eg. '1-10', or a list eg."
479 " '1,2,3' after '-exclude_chamber'."
484 int result = ParseChamberString(argv[i+1]);
485 if (result != 0) return result;
489 if (strcmp(argv[i], "-exclude_detelem") == 0)
493 HLTError("Expected a detector element ID number, a range eg. '100-108',"
494 " or a list eg. '100,102,301' after '-exclude_detelem'."
499 int result = ParseDetElemString(argv[i+1]);
500 if (result != 0) return result;
505 HLTError("Unknown option '%s'.", argv[i]);
511 HLTError("DDL number must be set with the -ddl option, but it was not.");
515 // Must load the mapping data if it is not already loaded.
516 if (AliMpDDLStore::Instance(false) == NULL)
518 AliMpCDB::LoadDDLStore();
519 if (AliMpDDLStore::Instance(false) == NULL)
521 HLTError("Could not load the DDL mapping store from CDB.");
526 // Now we can initialise the data interface objects and loaders.
529 HLTDebug("Loading simulated digits with AliMUONMCDataInterface.");
533 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
535 catch (const std::bad_alloc&)
537 HLTError("Not enough memory to allocate AliMUONMCDataInterface.");
543 HLTDebug("Loading reconstructed digits with AliMUONDataInterface.");
547 fDataInterface = new AliMUONDataInterface("galice.root");
549 catch (const std::bad_alloc&)
551 HLTError("Not enough memory to allocate AliMUONDataInterface.");
556 // Check that the fCurrentEventIndex number falls within the correct range.
558 if (fMCDataInterface != NULL)
559 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
560 else if (fDataInterface != NULL)
561 maxevent = UInt_t(fDataInterface->NumberOfEvents());
562 if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
564 fCurrentEventIndex = 0;
565 HLTWarning("The selected first event number (%d) was larger than"
566 " the available number of events (%d). Resetting the event"
567 " counter to zero.", fCurrentEventIndex, maxevent
575 int AliHLTMUONDigitPublisherComponent::DoDeinit()
577 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
579 HLTInfo("Deinitialising dHLT digit publisher component.");
581 if (fMCDataInterface != NULL)
583 delete fMCDataInterface;
584 fMCDataInterface = NULL;
586 if (fDataInterface != NULL)
588 delete fDataInterface;
589 fDataInterface = NULL;
595 int AliHLTMUONDigitPublisherComponent::GetEvent(
596 const AliHLTComponentEventData& evtData,
597 AliHLTComponentTriggerData& /*trigData*/,
598 AliHLTUInt8_t* outputPtr,
599 AliHLTUInt32_t& size,
600 AliHLTComponentBlockDataList& outputBlocks
603 /// Inherited from AliHLTOfflineDataSource.
605 assert( fMCDataInterface != NULL or fDataInterface != NULL );
607 if (not IsDataEvent()) return 0; // ignore non data events.
609 // Check the size of the event descriptor structure.
610 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
612 HLTError(kHLTLogError,
613 "The event descriptor (AliHLTComponentEventData) size is"
614 " smaller than expected. It claims to be %d bytes, but"
615 " we expect it to be %d bytes.",
617 sizeof(AliHLTComponentEventData)
619 size = 0; // Important to tell framework that nothing was generated.
623 // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
624 // check it and load that event with the runloader.
625 // If fCurrentEventIndex is a positive number then use it instead and
627 UInt_t eventnumber = UInt_t(evtData.fEventID);
629 if (fMCDataInterface != NULL)
630 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
631 else if (fDataInterface != NULL)
632 maxevent = UInt_t(fDataInterface->NumberOfEvents());
633 if (fCurrentEventIndex != -1)
635 eventnumber = UInt_t(fCurrentEventIndex);
636 fCurrentEventIndex++;
637 if (UInt_t(fCurrentEventIndex) >= maxevent)
638 fCurrentEventIndex = 0;
640 if ( eventnumber >= maxevent )
642 HLTError("The event number (%d) is larger than the available number"
643 " of events on file (%d).",
644 eventnumber, maxevent
646 size = 0; // Important to tell framework that nothing was generated.
650 const AliMUONVDigitStore* digitStore = NULL;
651 const AliMUONVTriggerStore* triggerStore = NULL;
653 if (fMCDataInterface != NULL)
655 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
659 digitStore = fMCDataInterface->DigitStore(eventnumber);
663 triggerStore = fMCDataInterface->TriggerStore(eventnumber);
666 else if (fDataInterface != NULL)
668 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
672 digitStore = fDataInterface->DigitStore(eventnumber);
676 triggerStore = fDataInterface->TriggerStore(eventnumber);
681 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
682 size = 0; // Important to tell framework that nothing was generated.
686 // Make sure we have the correct CTP trigger loaded.
687 AliRunLoader* runloader = AliRunLoader::Instance();
688 if (runloader != NULL)
690 if (runloader->GetTrigger() == NULL)
691 runloader->LoadTrigger();
692 runloader->GetEvent(eventnumber);
695 if (fDDL < 20 and digitStore != NULL)
697 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
700 size = 0; // Important to tell framework that nothing was generated.
704 else if (triggerStore != NULL)
706 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
709 size = 0; // Important to tell framework that nothing was generated.
715 size = 0; // Important to tell framework that nothing was generated.
719 AliHLTComponentBlockData bd;
724 bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
725 bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
726 outputBlocks.push_back(bd);
732 /////////////////////////////////////////////////////////////////////////////////////////
733 // Methods copied from AliMUONRawWriter.
734 //TODO: This is not ideal. We should have AliMUONRawWriter re-factored so that
735 // we can have raw data generated into a memory resident buffer, rather than
736 // always written to a file on disk, as it is now. But this will take some time
737 // since people need to be convinced of this fact.
739 //____________________________________________________________________
740 void AliHLTMUONDigitPublisherComponent::LocalWordPacking(UInt_t& word, UInt_t locId, UInt_t locDec,
741 UInt_t trigY, UInt_t posY, UInt_t posX,
742 UInt_t sdevX, UInt_t devX)
744 /// pack local trigger word
746 AliBitPacking::PackWord(locId,word,19,22); //card id number in crate
747 AliBitPacking::PackWord(locDec,word,15,18);
748 AliBitPacking::PackWord(trigY,word,14,14);
749 AliBitPacking::PackWord(posY,word,10,13);
750 AliBitPacking::PackWord(sdevX,word,9,9);
751 AliBitPacking::PackWord(devX,word,5,8);
752 AliBitPacking::PackWord(posX,word,0,4);
755 //______________________________________________________________________________
757 AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
758 const AliMUONVDigitStore& digitStore,
759 AliMpExMap& busPatchMap, Int_t iDDL
762 /// Create bus patch structures corresponding to digits in the store
764 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
765 assert(ddlStore != NULL);
767 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
768 busPatchMap.SetSize(ddl->GetNofBusPatches());
770 if (ddl->GetNofDEs() <= 0) return;
771 Int_t minDetElem = ddl->GetDEId(0);
772 Int_t maxDetElem = ddl->GetDEId(0);
773 for (Int_t i = 1; i < ddl->GetNofDEs(); i++)
775 if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
776 if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
779 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
781 // DDL event one per half chamber
786 UChar_t channelId = 0;
788 Int_t busPatchId = 0;
789 Int_t currentBusPatchId = -1;
792 AliMUONBusStruct* busStruct(0x0);
794 TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
795 AliMUONVDigit* digit;
797 while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
799 // Check if we should exclude digits from a particular chamber or detector element.
800 bool excludeDigit = false;
801 for (Int_t i = 0; i < fDetElemExclusionList.GetSize(); i++)
803 if (digit->DetElemId() == fDetElemExclusionList[i])
809 for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
811 if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
817 if (excludeDigit) continue;
819 charge = digit->ADC();
820 if ( charge > kMAXADC )
822 // This is most probably an error in the digitizer (which should insure
823 // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
824 HLTError("ADC value %d above 0x%x for DE %d . Setting to 0x%x. Digit is:",
825 charge,kMAXADC,digit->DetElemId(),kMAXADC);
830 busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
832 if (busPatchId<0) continue;
834 if ( digit->ManuId() > 0x7FF ||
835 digit->ManuChannel() > 0x3F )
837 HLTFatal("<%s>: ID %12u DE %4d Cath %d (Ix,Iy)=(%3d,%3d) (Manu,Channel)=(%4d,%2d)"
838 ", Charge=%7.2f\nManuId,ManuChannel are invalid for this digit.",
839 digit->ClassName(), digit->GetUniqueID(),
840 digit->DetElemId(), digit->Cathode(), digit->PadX(), digit->PadY(),
841 digit->ManuId(), digit->ManuChannel(), digit->Charge()
845 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
846 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
850 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
851 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
852 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
856 for (Int_t i = 1; i <= 30; ++i)
858 parity ^= ((word >> i) & 0x1);
860 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
862 if ( currentBusPatchId != busPatchId )
865 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
866 currentBusPatchId = busPatchId;
871 busStruct = new AliMUONBusStruct;
872 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
873 busStruct->SetBusPatchId(busPatchId);
874 busStruct->SetLength(0);
875 busPatchMap.Add(busPatchId,busStruct);
879 busStruct->AddData(word);
883 //______________________________________________________________________________
884 int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
885 const AliMUONVDigitStore* digitStore, Int_t iDDL,
886 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
889 /// Write DDL file for one tracker DDL
891 assert(0 <= iDDL and iDDL <= 19);
893 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
894 assert(ddlStore != NULL);
896 if (ddlStore->GetDDL(iDDL) == NULL)
898 HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
902 AliMpExMap busPatchMap;
903 Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
905 AliMUONBlockHeader blockHeader;
906 AliMUONDspHeader dspHeader;
907 blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
908 dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
910 if (outBufferSize < sizeof(AliRawDataHeaderV3))
912 HLTError("The output buffer size is too small to write output."
913 " It is only %d bytes, but we need at least %d bytes.",
914 outBufferSize, sizeof(AliRawDataHeaderV3)
918 AliRawDataHeaderV3* header = reinterpret_cast<AliRawDataHeaderV3*>(outBuffer);
919 // Fill header with default values.
920 *header = AliRawDataHeaderV3();
921 AliRunLoader* runloader = AliRunLoader::Instance();
922 if (runloader != NULL)
924 if (runloader->GetTrigger() != NULL)
926 AliCentralTrigger *aCTP = runloader->GetTrigger();
927 ULong64_t mask = aCTP->GetClassMask();
928 header->SetTriggerClass(mask);
929 mask = aCTP->GetClassMaskNext50();
930 header->SetTriggerClassNext50(mask);
934 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
935 Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeaderV3)) / sizeof(Int_t);
937 // buffer size (max'ed out)
938 // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch
939 // + 10 dsp words)*5 dsps + 8 block words)*2 blocks
941 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
942 Int_t iDspMax = ddl->GetMaxDsp();
943 Int_t iBusPerDSP[5]; //number of bus patches per DSP
944 ddl->GetBusPerDsp(iBusPerDSP);
947 Int_t totalDDLLength = 0;
951 // two blocks A and B per DDL
952 for (Int_t iBlock = 0; iBlock < 2; ++iBlock)
954 Int_t length = blockHeader.GetHeaderLength();
955 if (index + length >= endOfBuffer)
957 HLTError("The output buffer size is too small to write output."
958 " It is only %d bytes, but we need at least %d bytes.",
960 sizeof(AliRawDataHeaderV3) + (index+length)*sizeof(UInt_t)
966 memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
967 Int_t indexBlk = index;
970 // 5 DSP's max per block
971 for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp)
973 Int_t dspHeaderLength = dspHeader.GetHeaderLength();
974 if (index + dspHeaderLength >= endOfBuffer)
976 HLTError("The output buffer size is too small to write output."
977 " It is only %d bytes, but we need at least %d bytes.",
979 sizeof(AliRawDataHeaderV3) + (index+dspHeaderLength)*sizeof(UInt_t)
985 memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
986 Int_t indexDsp = index;
987 index += dspHeaderLength;
989 // 5 buspatches max per DSP
990 for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i)
992 Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
994 // iteration over bus patch in DDL
997 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
1001 AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
1003 Int_t busHeaderLength = busStructPtr->GetHeaderLength();
1004 if (index + busHeaderLength >= endOfBuffer)
1006 HLTError("The output buffer size is too small to write output."
1007 " It is only %d bytes, but we need at least %d bytes.",
1009 sizeof(AliRawDataHeaderV3) + (index+busHeaderLength)*sizeof(UInt_t)
1014 // check if buspatchid has digit
1017 // add bus patch structure header
1018 memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1019 index += busHeaderLength;
1021 Int_t busLength = busStructPtr->GetLength();
1022 if (index + busLength >= endOfBuffer)
1024 HLTError("The output buffer size is too small to write output."
1025 " It is only %d bytes, but we need at least %d bytes.",
1027 sizeof(AliRawDataHeaderV3) + (index+busLength)*sizeof(UInt_t)
1032 // add bus patch data
1033 memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1038 // writting anyhow buspatch structure (empty ones)
1039 buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
1040 buffer[index++] = busStructPtr->GetHeaderLength(); // header length
1041 buffer[index++] = 0; // raw data length
1042 buffer[index++] = iBusPatch; // bus patch
1046 if (index + 1 >= endOfBuffer)
1048 HLTError("The output buffer size is too small to write output."
1049 " It is only %d bytes, but we need at least %d bytes.",
1051 sizeof(AliRawDataHeaderV3) + (index+1)*sizeof(UInt_t)
1056 // check if totalLength even
1057 // set padding word in case
1058 // Add one word 0xBEEFFACE at the end of DSP structure
1059 Int_t totalDspLength = index - indexDsp;
1060 if ((totalDspLength % 2) == 1)
1062 buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1063 buffer[index++] = dspHeader.GetDefaultPaddingWord();
1067 Int_t dspLength = totalDspLength - dspHeader.GetHeaderLength();
1069 buffer[indexDsp+1] = totalDspLength; // dsp total length
1070 buffer[indexDsp+2] = dspLength; // data length
1074 Int_t totalBlkLength = index - indexBlk;
1075 Int_t blkLength = totalBlkLength - blockHeader.GetHeaderLength();
1076 totalDDLLength += totalBlkLength;
1078 buffer[indexBlk+1] = totalBlkLength; // total block length
1079 buffer[indexBlk+2] = blkLength;
1083 if (index + 2 >= endOfBuffer)
1085 HLTError("The output buffer size is too small to write output."
1086 " It is only %d bytes, but we need at least %d bytes.",
1088 sizeof(AliRawDataHeaderV3) + (index+2)*sizeof(UInt_t)
1093 // add twice the end of CRT structure data key
1094 // hope it's good placed (ChF)
1095 buffer[index++] = blockHeader.GetDdlDataKey();
1096 buffer[index++] = blockHeader.GetDdlDataKey();
1097 totalDDLLength += 2;
1099 header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeaderV3);
1100 outBufferSize = header->fSize;
1105 //______________________________________________________________________________
1106 int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1107 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1108 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1112 /// Write trigger DDL
1114 assert(0 <= iDDL and iDDL <= 19);
1116 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1117 assert(ddlStore != NULL);
1119 if (outBufferSize < sizeof(AliRawDataHeaderV3))
1121 HLTError("The output buffer size is too small to write output."
1122 " It is only %d bytes, but we need at least %d bytes.",
1123 outBufferSize, sizeof(AliRawDataHeaderV3)
1127 AliRawDataHeaderV3* header = reinterpret_cast<AliRawDataHeaderV3*>(outBuffer);
1128 // Fill header with default values.
1129 *header = AliRawDataHeaderV3();
1130 AliRunLoader* runloader = AliRunLoader::Instance();
1131 if (runloader != NULL)
1133 if (runloader->GetTrigger() != NULL)
1135 AliCentralTrigger *aCTP = runloader->GetTrigger();
1136 ULong64_t mask = aCTP->GetClassMask();
1137 header->SetTriggerClass(mask);
1141 // global trigger for trigger pattern
1142 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1148 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1151 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1154 UChar_t locDec, trigY, posY, posX, regOut;
1160 UInt_t version = 1; // software version
1161 UInt_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
1162 UInt_t serialNb = 0xF; // serial nb of card: all bits on for the moment
1163 Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
1165 AliMUONDarcHeader darcHeader;
1166 AliMUONRegHeader regHeader;
1167 AliMUONLocalStruct localStruct;
1170 static const Int_t kDarcHeaderLength = darcHeader.GetDarcHeaderLength();
1171 static const Int_t kGlobalHeaderLength = darcHeader.GetGlobalHeaderLength();
1172 static const Int_t kDarcScalerLength = darcHeader.GetDarcScalerLength();
1173 static const Int_t kGlobalScalerLength = darcHeader.GetGlobalScalerLength();
1174 static const Int_t kRegHeaderLength = regHeader.GetHeaderLength();
1175 static const Int_t kRegScalerLength = regHeader.GetScalerLength();
1176 static const Int_t kLocHeaderLength = localStruct.GetLength();
1177 static const Int_t kLocScalerLength = localStruct.GetScalerLength();
1179 // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824
1180 static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) + (kRegHeaderLength+1))* 8
1181 + kDarcHeaderLength + kGlobalHeaderLength + 2;
1183 // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
1184 static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength + kLocScalerLength +1) +
1185 (kRegHeaderLength + kRegScalerLength +1))* 8 +
1186 (kDarcHeaderLength + kDarcScalerLength +
1187 kGlobalHeaderLength + kGlobalScalerLength + 2);
1189 eventPhys = 0; //set to generate scaler events
1190 header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1194 if (outBufferSize < sizeof(AliRawDataHeaderV3) + kScalerBufferSize)
1196 HLTError("The output buffer size is too small to write output."
1197 " It is only %d bytes, but we need at least %d bytes.",
1198 outBufferSize, sizeof(AliRawDataHeaderV3) + kScalerBufferSize
1205 if (outBufferSize < sizeof(AliRawDataHeaderV3) + kBufferSize)
1207 HLTError("The output buffer size is too small to write output."
1208 " It is only %d bytes, but we need at least %d bytes.",
1209 outBufferSize, sizeof(AliRawDataHeaderV3) + kBufferSize
1217 if (iDDL == 0) // suppose global info in DDL one
1223 // set darc status word
1224 // see AliMUONDarcHeader.h for details
1225 AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
1226 AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
1227 AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
1228 AliBitPacking::PackWord((UInt_t)version,word,12,19);
1229 darcHeader.SetWord(word);
1231 memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4);
1232 index += kDarcHeaderLength;
1234 // no global input for the moment....
1236 darcHeader.SetGlobalOutput(gloTrigResp);
1238 darcHeader.SetGlobalOutput(0);
1241 // 6 DARC scaler words
1242 memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1243 index += kDarcScalerLength;
1246 buffer[index++] = darcHeader.GetEndOfDarc();
1248 // 4 words of global board input + Global board output
1249 memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4);
1250 index += kGlobalHeaderLength;
1253 // 10 Global scaler words
1254 memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1255 index += kGlobalScalerLength;
1258 // end of global word
1259 buffer[index++] = darcHeader.GetEndOfGlobal();
1260 const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger();
1262 Int_t nCrate = reg->GetNofTriggerCrates()/2;
1263 // 8 regional cards per DDL
1264 for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1267 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1271 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1275 // regional info tree, make sure that no reg card missing
1276 AliMUONRegionalTrigger* regTrg = triggerStore->FindRegional(crate->GetId());
1279 AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1283 // Regional card header
1286 // set darc status word
1287 regHeader.SetDarcWord(word);
1289 regOut = regTrg->GetOutput();
1290 regInpHpt = regTrg->GetLocalOutput(0);
1291 regInpLpt = regTrg->GetLocalOutput(1);
1293 // fill darc word, not darc status for the moment (empty)
1294 //see AliMUONRegHeader.h for details
1295 AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31);
1296 AliBitPacking::PackWord((UInt_t)serialNb,word,20,25);
1297 AliBitPacking::PackWord((UInt_t)version,word,8,15);
1298 AliBitPacking::PackWord((UInt_t)crate->GetId(),word,16,19);
1299 AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
1300 regHeader.SetWord(word);
1303 // fill header later, need local response
1304 Int_t indexReg = index;
1305 index += kRegHeaderLength;
1307 // 11 regional scaler word
1309 memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1310 index += kRegScalerLength;
1313 // end of regional word
1314 buffer[index++] = regHeader.GetEndOfReg();
1316 // 16 local card per regional board
1317 // UShort_t localMask = 0x0;
1319 Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1321 for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1323 // slot zero for Regional card
1324 Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1326 if (localBoardId) { // if not empty slot
1327 AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1329 if (localBoard->IsNotified()) {// if notified board
1330 AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1332 //locCard = locTrg->LoCircuit();
1333 locDec = locTrg->GetLoDecision();
1334 trigY = locTrg->LoTrigY();
1335 posY = locTrg->LoStripY();
1336 posX = locTrg->LoStripX();
1337 devX = locTrg->LoDev();
1338 sdevX = locTrg->LoSdev();
1340 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
1341 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
1344 LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY,
1345 (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1347 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
1348 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
1349 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
1350 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
1351 buffer[index++] = (Int_t)word; // data word
1355 // fill copy card X-Y inputs from the notified cards
1356 if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom())
1359 locDec = 0; trigY = 1; posY = 15;
1360 posX = 0; devX = 0; sdevX = 1;
1361 LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY,
1362 (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1364 Int_t localFromId = localBoard->GetInputXfrom();
1365 AliMUONLocalTrigger* locTrgfrom = triggerStore->FindLocal(localFromId);
1367 buffer[index++] = 0; // copy only X3-4 & Y1-4
1368 buffer[index++] = (locTrgfrom->GetX3Pattern() | (locTrgfrom->GetX4Pattern() << 16));
1369 buffer[index++] = (locTrgfrom->GetY1Pattern() | (locTrgfrom->GetY2Pattern() << 16));
1370 buffer[index++] = (locTrgfrom->GetY3Pattern() | (locTrgfrom->GetY4Pattern() << 16));
1371 buffer[index++] = word;
1375 // fill with 10CDEAD word for empty slots
1376 for (Int_t i = 0; i < localStruct.GetLength(); i++)
1377 buffer[index++] = localStruct.GetDisableWord();
1378 }// condition localBoard
1380 // 45 regional scaler word
1382 memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1383 index += kLocScalerLength;
1386 // end of local structure words
1387 buffer[index++] = localStruct.GetEndOfLocal();
1390 // fill regional header with local output
1391 regHeader.SetInput(regInpHpt, 0);
1392 regHeader.SetInput(regInpLpt, 1);
1393 memcpy(&buffer[indexReg],regHeader.GetHeader(),kRegHeaderLength*4);
1397 header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeaderV3);
1398 outBufferSize = header->fSize;
1404 /////////////////////////////////////////////////////////////////////////////////////////