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 "AliRawDataHeader.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"
72 ClassImp(AliHLTMUONDigitPublisherComponent)
75 AliHLTMUONDigitPublisherComponent::AliHLTMUONDigitPublisherComponent() :
76 AliHLTOfflineDataSource(),
78 fCurrentEventIndex(0),
80 fMCDataInterface(NULL),
82 fChamberExclusionList(0),
83 fDetElemExclusionList(0)
85 /// Default constructor.
89 AliHLTMUONDigitPublisherComponent::~AliHLTMUONDigitPublisherComponent()
91 /// Default destructor.
93 if (fMCDataInterface != NULL) delete fMCDataInterface;
94 if (fDataInterface != NULL) delete fDataInterface;
97 const char* AliHLTMUONDigitPublisherComponent::GetComponentID()
99 /// Inherited from AliHLTComponent. Returns the component ID.
101 return AliHLTMUONConstants::DigitPublisherId();
105 AliHLTComponentDataType AliHLTMUONDigitPublisherComponent::GetOutputDataType()
107 /// Inherited from AliHLTComponent. Returns the raw DDL data type.
109 return AliHLTMUONConstants::DDLRawDataType();
113 void AliHLTMUONDigitPublisherComponent::GetOutputDataSize(
114 unsigned long& constBase, double& inputMultiplier
117 /// Inherited from AliHLTComponent.
118 /// Returns an estimate of the expected output data size.
120 // estimated as max number of channels * raw data word size + max headers size.
121 constBase = sizeof(AliRawDataHeader) + 65536*sizeof(UInt_t)
122 + sizeof(AliMUONBlockHeaderStruct)*2 + sizeof(AliMUONDSPHeaderStruct)*10
123 + sizeof(AliMUONBusPatchHeaderStruct) * 50;
128 AliHLTComponent* AliHLTMUONDigitPublisherComponent::Spawn()
130 /// Inherited from AliHLTComponent. Creates a new object instance.
132 return new AliHLTMUONDigitPublisherComponent;
136 int AliHLTMUONDigitPublisherComponent::ParseChamberString(const char* str)
138 /// Parses a string with the following format:
139 /// <number>|<number>-<number>[,<number>|<number>-<number>]...
140 /// For example: 1 1,2,3 1-2 1,2-4,5 etc...
141 /// Chamber numbers must be in the range [1..10] for tracking chambers.
142 /// All valid tracking chamber numbers will added to fChamberExclusionList.
143 /// @param str The string to parse.
144 /// @return Zero on success and EINVAL if there is a parse error.
146 char* end = const_cast<char*>(str);
147 long lastChamber = -1;
150 // Parse the next number.
152 long chamber = strtol(current, &end, 0);
154 // Check for parse errors of the number.
157 HLTError("Expected a number in the range [1..%d] but got '%s'.",
158 AliMUONConstants::NTrackingCh(), current
162 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
164 HLTError("Received the chamber number %d, which is outside the valid range of [1..%d].",
165 chamber, AliMUONConstants::NTrackingCh()
170 // Skip any whitespace after the number
171 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
173 // Check if we are dealing with a list or range, or if we are at
174 // the end of the string.
177 lastChamber = chamber;
181 else if (*end == ',')
183 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
184 Int_t size = fChamberExclusionList.GetSize();
185 fChamberExclusionList.Set(size+1);
186 fChamberExclusionList[size] = chamber-1;
189 else if (*end == '\0')
191 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
192 Int_t size = fChamberExclusionList.GetSize();
193 fChamberExclusionList.Set(size+1);
194 fChamberExclusionList[size] = chamber-1;
198 HLTError("Could not understand parameter list '%s'. Expected '-', ','"
199 " or end of line, but received '%c' at character %d.",
200 str, *end, (int)(end - str) +1
205 // Set the range of chambers to publish for.
209 if (lastChamber < chamber)
220 assert( max <= AliMUONConstants::NTrackingCh() );
221 for (Int_t i = min; i <= max; i++)
223 Int_t size = fChamberExclusionList.GetSize();
224 fChamberExclusionList.Set(size+1);
225 fChamberExclusionList[size] = i-1;
230 while (*end != '\0');
235 int AliHLTMUONDigitPublisherComponent::ParseDetElemString(const char* str)
237 /// Parses a string with the following format:
238 /// <number>|<number>-<number>[,<number>|<number>-<number>]...
239 /// For example: 100 100,201,208 100-104 105,202-204,503 etc...
240 /// Detector element numbers must be in the range [100..1099] for tracking stations.
241 /// All valid detector element numbers will added to fDetElemExclusionList.
242 /// @param str The string to parse.
243 /// @return Zero on success and EINVAL if there is a parse error.
245 char* end = const_cast<char*>(str);
246 long lastDetElem = -1;
249 // Parse the next number.
251 long detElem = strtol(current, &end, 0);
253 // Check for parse errors of the number.
256 HLTError("Expected a number in the range [100..1099] but got '%s'.",
261 if (detElem < 100 or 1099 < detElem)
263 HLTError("Received the detector element ID number of %d,"
264 " which is outside the valid range of [100..1099].",
270 // Skip any whitespace after the number
271 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
273 // Check if we are dealing with a list or range, or if we are at
274 // the end of the string.
277 lastDetElem = detElem;
281 else if (*end == ',')
283 assert( 100 <= detElem and detElem <= 1099 );
284 Int_t size = fDetElemExclusionList.GetSize();
285 fDetElemExclusionList.Set(size+1);
286 fDetElemExclusionList[size] = detElem-1;
289 else if (*end == '\0')
291 assert( 100 <= detElem and detElem <= 1099 );
292 Int_t size = fDetElemExclusionList.GetSize();
293 fDetElemExclusionList.Set(size+1);
294 fDetElemExclusionList[size] = detElem-1;
298 HLTError("Could not understand parameter list '%s'. Expected '-', ','"
299 " or end of line, but received '%c' at character %d.",
300 str, *end, (int)(end - str) +1
305 // Set the range of detector elements to publish for.
309 if (lastDetElem < detElem)
319 assert( min >= 100 );
320 assert( max <= 1099 );
321 for (Int_t i = min; i <= max; i++)
323 Int_t size = fDetElemExclusionList.GetSize();
324 fDetElemExclusionList.Set(size+1);
325 fDetElemExclusionList[size] = i-1;
330 while (*end != '\0');
335 int AliHLTMUONDigitPublisherComponent::DoInit(int argc, const char** argv)
337 /// Inherited from AliHLTComponent.
338 /// Parses the command line parameters and initialises the component.
340 HLTInfo("Initialising dHLT digit publisher component.");
342 if (fMCDataInterface != NULL)
344 delete fMCDataInterface;
345 fMCDataInterface = NULL;
347 if (fDataInterface != NULL)
349 delete fDataInterface;
350 fDataInterface = NULL;
353 // Initialise with default values.
355 fCurrentEventIndex = 0;
356 fMakeScalars = false;
357 fChamberExclusionList.Set(0);
358 fDetElemExclusionList.Set(0);
359 bool simdata = false;
360 bool recdata = false;
361 bool firstEventSet = false;
362 bool eventNumLitSet = false;
364 for (int i = 0; i < argc; i++)
366 if (strcmp(argv[i], "-makescalars") == 0)
371 if (strcmp(argv[i], "-simdata") == 0)
376 if (strcmp(argv[i], "-recdata") == 0)
381 if (strcmp(argv[i], "-ddl") == 0)
385 HLTError("DDL number not specified. It must be in the range [1..22]" );
390 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
391 if (cpErr == NULL or *cpErr != '\0')
393 HLTError("Cannot convert '%s' to a DDL number.", argv[i+1]);
396 if (num < 1 or 22 < num)
398 HLTError("The DDL number must be in the range [1..22].");
401 fDDL = num - 1; // Convert to DDL number in the range 0..21
406 if (strcmp(argv[i], "-ddlid") == 0)
410 HLTError("DDL equipment ID number not specified."
411 " It must be in the range [2560..2579] or [2816..2817]."
417 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
418 if (cpErr == NULL or *cpErr != '\0')
420 HLTError("Cannot convert '%s' to a DDL equipment ID number.", argv[i+1]);
423 fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
424 if (fDDL < 0 or 21 < fDDL)
426 HLTError("The DDL equipment ID number must be in the range"
427 " [2560..2579] or [2816..2817]."
435 if (strcmp(argv[i], "-firstevent") == 0)
439 HLTWarning("The -firstevent flag is overridden by a"
440 " previous use of -event_number_literal."
445 HLTError("Expected a positive number after -firstevent.");
449 long num = strtol(argv[i], &end, 0);
450 if (*end != '\0' or num < 0) // Check if the conversion is OK.
452 HLTError("Expected a positive number after -firstevent"
453 " but got: %s", argv[i]
457 fCurrentEventIndex = Int_t(num);
458 firstEventSet = true;
461 if (strcmp(argv[i], "-event_number_literal") == 0)
465 HLTWarning("The -event_number_literal option will"
466 " override -firstevent."
469 fCurrentEventIndex = -1;
470 eventNumLitSet = true;
473 if (strcmp(argv[i], "-exclude_chamber") == 0)
477 HLTError("Expected a chamber number, a range eg. '1-10', or a list eg."
478 " '1,2,3' after '-exclude_chamber'."
483 int result = ParseChamberString(argv[i+1]);
484 if (result != 0) return result;
488 if (strcmp(argv[i], "-exclude_detelem") == 0)
492 HLTError("Expected a detector element ID number, a range eg. '100-108',"
493 " or a list eg. '100,102,301' after '-exclude_detelem'."
498 int result = ParseDetElemString(argv[i+1]);
499 if (result != 0) return result;
504 HLTError("Unknown option '%s'.", argv[i]);
510 HLTError("DDL number must be set with the -ddl option, but it was not.");
514 // Must load the mapping data if it is not already loaded.
515 if (AliMpDDLStore::Instance(false) == NULL)
517 AliMpCDB::LoadDDLStore();
518 if (AliMpDDLStore::Instance(false) == NULL)
520 HLTError("Could not load the DDL mapping store from CDB.");
525 // Now we can initialise the data interface objects and loaders.
528 HLTDebug("Loading simulated digits with AliMUONMCDataInterface.");
532 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
534 catch (const std::bad_alloc&)
536 HLTError("Not enough memory to allocate AliMUONMCDataInterface.");
542 HLTDebug("Loading reconstructed digits with AliMUONDataInterface.");
546 fDataInterface = new AliMUONDataInterface("galice.root");
548 catch (const std::bad_alloc&)
550 HLTError("Not enough memory to allocate AliMUONDataInterface.");
555 // Check that the fCurrentEventIndex number falls within the correct range.
557 if (fMCDataInterface != NULL)
558 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
559 else if (fDataInterface != NULL)
560 maxevent = UInt_t(fDataInterface->NumberOfEvents());
561 if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
563 fCurrentEventIndex = 0;
564 HLTWarning("The selected first event number (%d) was larger than"
565 " the available number of events (%d). Resetting the event"
566 " counter to zero.", fCurrentEventIndex, maxevent
574 int AliHLTMUONDigitPublisherComponent::DoDeinit()
576 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
578 HLTInfo("Deinitialising dHLT digit publisher component.");
580 if (fMCDataInterface != NULL)
582 delete fMCDataInterface;
583 fMCDataInterface = NULL;
585 if (fDataInterface != NULL)
587 delete fDataInterface;
588 fDataInterface = NULL;
594 int AliHLTMUONDigitPublisherComponent::GetEvent(
595 const AliHLTComponentEventData& evtData,
596 AliHLTComponentTriggerData& /*trigData*/,
597 AliHLTUInt8_t* outputPtr,
598 AliHLTUInt32_t& size,
599 vector<AliHLTComponentBlockData>& outputBlocks
602 /// Inherited from AliHLTOfflineDataSource.
604 assert( fMCDataInterface != NULL or fDataInterface != NULL );
606 // Check the size of the event descriptor structure.
607 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
609 HLTError(kHLTLogError,
610 "The event descriptor (AliHLTComponentEventData) size is"
611 " smaller than expected. It claims to be %d bytes, but"
612 " we expect it to be %d bytes.",
614 sizeof(AliHLTComponentEventData)
616 size = 0; // Important to tell framework that nothing was generated.
620 // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
621 // check it and load that event with the runloader.
622 // If fCurrentEventIndex is a positive number then use it instead and
624 UInt_t eventnumber = UInt_t(evtData.fEventID);
626 if (fMCDataInterface != NULL)
627 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
628 else if (fDataInterface != NULL)
629 maxevent = UInt_t(fDataInterface->NumberOfEvents());
630 if (fCurrentEventIndex != -1)
632 eventnumber = UInt_t(fCurrentEventIndex);
633 fCurrentEventIndex++;
634 if (UInt_t(fCurrentEventIndex) >= maxevent)
635 fCurrentEventIndex = 0;
637 if ( eventnumber >= maxevent )
639 HLTError("The event number (%d) is larger than the available number"
640 " of events on file (%d).",
641 eventnumber, maxevent
643 size = 0; // Important to tell framework that nothing was generated.
647 const AliMUONVDigitStore* digitStore = NULL;
648 const AliMUONVTriggerStore* triggerStore = NULL;
650 if (fMCDataInterface != NULL)
652 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
656 digitStore = fMCDataInterface->DigitStore(eventnumber);
660 triggerStore = fMCDataInterface->TriggerStore(eventnumber);
663 else if (fDataInterface != NULL)
665 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
669 digitStore = fDataInterface->DigitStore(eventnumber);
673 triggerStore = fDataInterface->TriggerStore(eventnumber);
678 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
679 size = 0; // Important to tell framework that nothing was generated.
683 // Make sure we have the correct CTP trigger loaded.
684 AliRunLoader* runloader = AliRunLoader::GetRunLoader();
685 if (runloader != NULL)
687 if (runloader->GetTrigger() == NULL)
688 runloader->LoadTrigger();
689 runloader->GetEvent(eventnumber);
692 if (fDDL < 20 and digitStore != NULL)
694 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
697 size = 0; // Important to tell framework that nothing was generated.
701 else if (triggerStore != NULL)
703 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
706 size = 0; // Important to tell framework that nothing was generated.
712 size = 0; // Important to tell framework that nothing was generated.
716 AliHLTComponentBlockData bd;
721 bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
722 bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
723 outputBlocks.push_back(bd);
729 /////////////////////////////////////////////////////////////////////////////////////////
730 // Methods copied from AliMUONRawWriter.
731 //TODO: This is not ideal. We should have AliMUONRawWriter re-factored so that
732 // we can have raw data generated into a memory resident buffer, rather than
733 // always written to a file on disk, as it is now. But this will take some time
734 // since people need to be convinced of this fact.
736 //____________________________________________________________________
737 void AliHLTMUONDigitPublisherComponent::LocalWordPacking(UInt_t& word, UInt_t locId, UInt_t locDec,
738 UInt_t trigY, UInt_t posY, UInt_t posX,
739 UInt_t sdevX, UInt_t devX)
741 /// pack local trigger word
743 AliBitPacking::PackWord(locId,word,19,22); //card id number in crate
744 AliBitPacking::PackWord(locDec,word,15,18);
745 AliBitPacking::PackWord(trigY,word,14,14);
746 AliBitPacking::PackWord(posY,word,10,13);
747 AliBitPacking::PackWord(sdevX,word,9,9);
748 AliBitPacking::PackWord(devX,word,5,8);
749 AliBitPacking::PackWord(posX,word,0,4);
752 //______________________________________________________________________________
754 AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
755 const AliMUONVDigitStore& digitStore,
756 AliMpExMap& busPatchMap, Int_t iDDL
759 /// Create bus patch structures corresponding to digits in the store
761 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
762 assert(ddlStore != NULL);
764 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
765 busPatchMap.SetSize(ddl->GetNofBusPatches());
767 if (ddl->GetNofDEs() <= 0) return;
768 Int_t minDetElem = ddl->GetDEId(0);
769 Int_t maxDetElem = ddl->GetDEId(0);
770 for (Int_t i = 1; i < ddl->GetNofDEs(); i++)
772 if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
773 if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
776 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
778 // DDL event one per half chamber
783 UChar_t channelId = 0;
785 Int_t busPatchId = 0;
786 Int_t currentBusPatchId = -1;
789 AliMUONBusStruct* busStruct(0x0);
791 TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
792 AliMUONVDigit* digit;
794 while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
796 // Check if we should exclude digits from a particular chamber or detector element.
797 bool excludeDigit = false;
798 for (Int_t i = 0; i < fDetElemExclusionList.GetSize(); i++)
800 if (digit->DetElemId() == fDetElemExclusionList[i])
806 for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
808 if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
814 if (excludeDigit) continue;
816 charge = digit->ADC();
817 if ( charge > kMAXADC )
819 // This is most probably an error in the digitizer (which should insure
820 // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
821 HLTError("ADC value %d above 0x%x for DE %d . Setting to 0x%x. Digit is:",
822 charge,kMAXADC,digit->DetElemId(),kMAXADC);
827 busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
829 if (busPatchId<0) continue;
831 if ( digit->ManuId() > 0x7FF ||
832 digit->ManuChannel() > 0x3F )
834 HLTFatal("<%s>: ID %12u DE %4d Cath %d (Ix,Iy)=(%3d,%3d) (Manu,Channel)=(%4d,%2d)"
835 ", Charge=%7.2f\nManuId,ManuChannel are invalid for this digit.",
836 digit->ClassName(), digit->GetUniqueID(),
837 digit->DetElemId(), digit->Cathode(), digit->PadX(), digit->PadY(),
838 digit->ManuId(), digit->ManuChannel(), digit->Charge()
842 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
843 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
847 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
848 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
849 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
853 for (Int_t i = 1; i <= 30; ++i)
855 parity ^= ((word >> i) & 0x1);
857 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
859 if ( currentBusPatchId != busPatchId )
862 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
863 currentBusPatchId = busPatchId;
868 busStruct = new AliMUONBusStruct;
869 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
870 busStruct->SetBusPatchId(busPatchId);
871 busStruct->SetLength(0);
872 busPatchMap.Add(busPatchId,busStruct);
876 busStruct->AddData(word);
880 //______________________________________________________________________________
881 int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
882 const AliMUONVDigitStore* digitStore, Int_t iDDL,
883 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
886 /// Write DDL file for one tracker DDL
888 assert(0 <= iDDL and iDDL <= 19);
890 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
891 assert(ddlStore != NULL);
893 if (ddlStore->GetDDL(iDDL) == NULL)
895 HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
899 AliMpExMap busPatchMap;
900 Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
902 AliMUONBlockHeader blockHeader;
903 AliMUONDspHeader dspHeader;
904 blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
905 dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
907 if (outBufferSize < sizeof(AliRawDataHeader))
909 HLTError("The output buffer size is too small to write output."
910 " It is only %d bytes, but we need at least %d bytes.",
911 outBufferSize, sizeof(AliRawDataHeader)
915 AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
916 // Fill header with default values.
917 *header = AliRawDataHeader();
918 AliRunLoader* runloader = AliRunLoader::GetRunLoader();
919 if (runloader != NULL)
921 if (runloader->GetTrigger() != NULL)
923 AliCentralTrigger *aCTP = runloader->GetTrigger();
924 ULong64_t mask = aCTP->GetClassMask();
925 header->SetTriggerClass(mask);
929 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
930 Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeader)) / sizeof(Int_t);
932 // buffer size (max'ed out)
933 // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch
934 // + 10 dsp words)*5 dsps + 8 block words)*2 blocks
936 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
937 Int_t iDspMax = ddl->GetMaxDsp();
938 Int_t iBusPerDSP[5]; //number of bus patches per DSP
939 ddl->GetBusPerDsp(iBusPerDSP);
942 Int_t totalDDLLength = 0;
946 // two blocks A and B per DDL
947 for (Int_t iBlock = 0; iBlock < 2; ++iBlock)
949 Int_t length = blockHeader.GetHeaderLength();
950 if (index + length >= endOfBuffer)
952 HLTError("The output buffer size is too small to write output."
953 " It is only %d bytes, but we need at least %d bytes.",
955 sizeof(AliRawDataHeader) + (index+length)*sizeof(UInt_t)
961 memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
962 Int_t indexBlk = index;
965 // 5 DSP's max per block
966 for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp)
968 Int_t dspHeaderLength = dspHeader.GetHeaderLength();
969 if (index + dspHeaderLength >= endOfBuffer)
971 HLTError("The output buffer size is too small to write output."
972 " It is only %d bytes, but we need at least %d bytes.",
974 sizeof(AliRawDataHeader) + (index+dspHeaderLength)*sizeof(UInt_t)
980 memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
981 Int_t indexDsp = index;
982 index += dspHeaderLength;
984 // 5 buspatches max per DSP
985 for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i)
987 Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
989 // iteration over bus patch in DDL
992 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
996 AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
998 Int_t busHeaderLength = busStructPtr->GetHeaderLength();
999 if (index + busHeaderLength >= endOfBuffer)
1001 HLTError("The output buffer size is too small to write output."
1002 " It is only %d bytes, but we need at least %d bytes.",
1004 sizeof(AliRawDataHeader) + (index+busHeaderLength)*sizeof(UInt_t)
1009 // check if buspatchid has digit
1012 // add bus patch structure header
1013 memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1014 index += busHeaderLength;
1016 Int_t busLength = busStructPtr->GetLength();
1017 if (index + busLength >= endOfBuffer)
1019 HLTError("The output buffer size is too small to write output."
1020 " It is only %d bytes, but we need at least %d bytes.",
1022 sizeof(AliRawDataHeader) + (index+busLength)*sizeof(UInt_t)
1027 // add bus patch data
1028 memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1033 // writting anyhow buspatch structure (empty ones)
1034 buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
1035 buffer[index++] = busStructPtr->GetHeaderLength(); // header length
1036 buffer[index++] = 0; // raw data length
1037 buffer[index++] = iBusPatch; // bus patch
1041 if (index + 1 >= endOfBuffer)
1043 HLTError("The output buffer size is too small to write output."
1044 " It is only %d bytes, but we need at least %d bytes.",
1046 sizeof(AliRawDataHeader) + (index+1)*sizeof(UInt_t)
1051 // check if totalLength even
1052 // set padding word in case
1053 // Add one word 0xBEEFFACE at the end of DSP structure
1054 Int_t totalDspLength = index - indexDsp;
1055 if ((totalDspLength % 2) == 1)
1057 buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1058 buffer[index++] = dspHeader.GetDefaultPaddingWord();
1062 Int_t dspLength = totalDspLength - dspHeader.GetHeaderLength();
1064 buffer[indexDsp+1] = totalDspLength; // dsp total length
1065 buffer[indexDsp+2] = dspLength; // data length
1069 Int_t totalBlkLength = index - indexBlk;
1070 Int_t blkLength = totalBlkLength - blockHeader.GetHeaderLength();
1071 totalDDLLength += totalBlkLength;
1073 buffer[indexBlk+1] = totalBlkLength; // total block length
1074 buffer[indexBlk+2] = blkLength;
1078 if (index + 2 >= endOfBuffer)
1080 HLTError("The output buffer size is too small to write output."
1081 " It is only %d bytes, but we need at least %d bytes.",
1083 sizeof(AliRawDataHeader) + (index+2)*sizeof(UInt_t)
1088 // add twice the end of CRT structure data key
1089 // hope it's good placed (ChF)
1090 buffer[index++] = blockHeader.GetDdlDataKey();
1091 buffer[index++] = blockHeader.GetDdlDataKey();
1092 totalDDLLength += 2;
1094 header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeader);
1095 outBufferSize = header->fSize;
1100 //______________________________________________________________________________
1101 int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1102 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1103 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1107 /// Write trigger DDL
1109 assert(0 <= iDDL and iDDL <= 19);
1111 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1112 assert(ddlStore != NULL);
1114 if (outBufferSize < sizeof(AliRawDataHeader))
1116 HLTError("The output buffer size is too small to write output."
1117 " It is only %d bytes, but we need at least %d bytes.",
1118 outBufferSize, sizeof(AliRawDataHeader)
1122 AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(outBuffer);
1123 // Fill header with default values.
1124 *header = AliRawDataHeader();
1125 AliRunLoader* runloader = AliRunLoader::GetRunLoader();
1126 if (runloader != NULL)
1128 if (runloader->GetTrigger() != NULL)
1130 AliCentralTrigger *aCTP = runloader->GetTrigger();
1131 ULong64_t mask = aCTP->GetClassMask();
1132 header->SetTriggerClass(mask);
1136 // global trigger for trigger pattern
1137 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1143 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1146 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1149 UChar_t locDec, trigY, posY, posX, regOut;
1155 UInt_t version = 1; // software version
1156 UInt_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
1157 UInt_t serialNb = 0xF; // serial nb of card: all bits on for the moment
1158 Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
1160 AliMUONDarcHeader darcHeader;
1161 AliMUONRegHeader regHeader;
1162 AliMUONLocalStruct localStruct;
1165 static const Int_t kDarcHeaderLength = darcHeader.GetDarcHeaderLength();
1166 static const Int_t kGlobalHeaderLength = darcHeader.GetGlobalHeaderLength();
1167 static const Int_t kDarcScalerLength = darcHeader.GetDarcScalerLength();
1168 static const Int_t kGlobalScalerLength = darcHeader.GetGlobalScalerLength();
1169 static const Int_t kRegHeaderLength = regHeader.GetHeaderLength();
1170 static const Int_t kRegScalerLength = regHeader.GetScalerLength();
1171 static const Int_t kLocHeaderLength = localStruct.GetLength();
1172 static const Int_t kLocScalerLength = localStruct.GetScalerLength();
1174 // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824
1175 static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) + (kRegHeaderLength+1))* 8
1176 + kDarcHeaderLength + kGlobalHeaderLength + 2;
1178 // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
1179 static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength + kLocScalerLength +1) +
1180 (kRegHeaderLength + kRegScalerLength +1))* 8 +
1181 (kDarcHeaderLength + kDarcScalerLength +
1182 kGlobalHeaderLength + kGlobalScalerLength + 2);
1184 eventPhys = 0; //set to generate scaler events
1185 header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1189 if (outBufferSize < sizeof(AliRawDataHeader) + kScalerBufferSize)
1191 HLTError("The output buffer size is too small to write output."
1192 " It is only %d bytes, but we need at least %d bytes.",
1193 outBufferSize, sizeof(AliRawDataHeader) + kScalerBufferSize
1200 if (outBufferSize < sizeof(AliRawDataHeader) + kBufferSize)
1202 HLTError("The output buffer size is too small to write output."
1203 " It is only %d bytes, but we need at least %d bytes.",
1204 outBufferSize, sizeof(AliRawDataHeader) + kBufferSize
1212 if (iDDL == 0) // suppose global info in DDL one
1218 // set darc status word
1219 // see AliMUONDarcHeader.h for details
1220 AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
1221 AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
1222 AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
1223 AliBitPacking::PackWord((UInt_t)version,word,12,19);
1224 darcHeader.SetWord(word);
1226 memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4);
1227 index += kDarcHeaderLength;
1229 // no global input for the moment....
1231 darcHeader.SetGlobalOutput(gloTrigResp);
1233 darcHeader.SetGlobalOutput(0);
1236 // 6 DARC scaler words
1237 memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1238 index += kDarcScalerLength;
1241 buffer[index++] = darcHeader.GetEndOfDarc();
1243 // 4 words of global board input + Global board output
1244 memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4);
1245 index += kGlobalHeaderLength;
1248 // 10 Global scaler words
1249 memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1250 index += kGlobalScalerLength;
1253 // end of global word
1254 buffer[index++] = darcHeader.GetEndOfGlobal();
1255 const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger();
1257 Int_t nCrate = reg->GetNofTriggerCrates()/2;
1258 // 8 regional cards per DDL
1259 for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1262 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1265 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1267 // regional info tree, make sure that no reg card missing
1268 AliMUONRegionalTrigger* regTrg = triggerStore->FindRegional(crate->GetId());
1270 AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1272 // Regional card header
1275 // set darc status word
1276 regHeader.SetDarcWord(word);
1278 regOut = regTrg->GetOutput();
1279 regInpHpt = regTrg->GetLocalOutput(0);
1280 regInpLpt = regTrg->GetLocalOutput(1);
1282 // fill darc word, not darc status for the moment (empty)
1283 //see AliMUONRegHeader.h for details
1284 AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31);
1285 AliBitPacking::PackWord((UInt_t)serialNb,word,20,25);
1286 AliBitPacking::PackWord((UInt_t)version,word,8,15);
1287 AliBitPacking::PackWord((UInt_t)crate->GetId(),word,16,19);
1288 AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
1289 regHeader.SetWord(word);
1292 // fill header later, need local response
1293 Int_t indexReg = index;
1294 index += kRegHeaderLength;
1296 // 11 regional scaler word
1298 memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1299 index += kRegScalerLength;
1302 // end of regional word
1303 buffer[index++] = regHeader.GetEndOfReg();
1305 // 16 local card per regional board
1306 // UShort_t localMask = 0x0;
1308 Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1310 for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1312 // slot zero for Regional card
1313 Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1315 if (localBoardId) { // if not empty slot
1316 AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1318 if (localBoard->IsNotified()) {// if notified board
1319 AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1321 locCard = locTrg->LoCircuit();
1322 locDec = locTrg->GetLoDecision();
1323 trigY = locTrg->LoTrigY();
1324 posY = locTrg->LoStripY();
1325 posX = locTrg->LoStripX();
1326 devX = locTrg->LoDev();
1327 sdevX = locTrg->LoSdev();
1329 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
1330 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
1333 LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY,
1334 (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1336 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
1337 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
1338 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
1339 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
1340 buffer[index++] = (Int_t)word; // data word
1344 // fill copy card X-Y inputs from the notified cards
1345 if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom())
1348 locDec = 0; trigY = 1; posY = 15;
1349 posX = 0; devX = 0; sdevX = 1;
1350 LocalWordPacking(word, (UInt_t)iLoc, (UInt_t)locDec, (UInt_t)trigY, (UInt_t)posY,
1351 (UInt_t)posX, (UInt_t)sdevX, (UInt_t)devX);
1353 Int_t localFromId = localBoard->GetInputXfrom();
1354 AliMUONLocalTrigger* locTrgfrom = triggerStore->FindLocal(localFromId);
1356 buffer[index++] = 0; // copy only X3-4 & Y1-4
1357 buffer[index++] = (locTrgfrom->GetX3Pattern() | (locTrgfrom->GetX4Pattern() << 16));
1358 buffer[index++] = (locTrgfrom->GetY1Pattern() | (locTrgfrom->GetY2Pattern() << 16));
1359 buffer[index++] = (locTrgfrom->GetY3Pattern() | (locTrgfrom->GetY4Pattern() << 16));
1360 buffer[index++] = word;
1364 // fill with 10CDEAD word for empty slots
1365 for (Int_t i = 0; i < localStruct.GetLength(); i++)
1366 buffer[index++] = localStruct.GetDisableWord();
1367 }// condition localBoard
1369 // 45 regional scaler word
1371 memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1372 index += kLocScalerLength;
1375 // end of local structure words
1376 buffer[index++] = localStruct.GetEndOfLocal();
1379 // fill regional header with local output
1380 regHeader.SetInput(regInpHpt, 0);
1381 regHeader.SetInput(regInpHpt, 1);
1382 memcpy(&buffer[indexReg],regHeader.GetHeader(),kRegHeaderLength*4);
1386 header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeader);
1387 outBufferSize = header->fSize;
1393 /////////////////////////////////////////////////////////////////////////////////////////