ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONDigitPublisherComponent.cxx
CommitLineData
887a669c 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
4 * *
5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
7 * *
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 **************************************************************************/
16
1d8ae082 17// $Id: AliHLTMUONDigitPublisherComponent.cxx 26179 2008-05-29 22:27:27Z aszostak $
887a669c 18
19///
20/// @file AliHLTMUONDigitPublisherComponent.cxx
21/// @author Artur Szostak <artursz@iafrica.com>
22/// @date 29 May 2008
23/// @brief Implementation of the dHLT digit publisher component.
24///
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
27/// on the fly.
28///
29
30#include "AliHLTMUONDigitPublisherComponent.h"
31#include "AliHLTMUONConstants.h"
2ee47a65 32#include "AliHLTMUONUtils.h"
887a669c 33#include "AliHLTLogging.h"
34#include "AliHLTSystem.h"
35#include "AliHLTDefinitions.h"
16e6f752 36#include "AliRawDataHeaderV3.h"
887a669c 37#include "AliMUONTrackerDDLDecoderEventHandler.h"
2ee47a65 38#include "AliMUONConstants.h"
39#include "AliMUONMCDataInterface.h"
40#include "AliMUONDataInterface.h"
41#include "AliMUONVDigitStore.h"
42#include "AliMUONVTriggerStore.h"
43#include "AliMpExMap.h"
44#include "AliMpCDB.h"
45#include "AliMpDDL.h"
46#include "AliMpDDLStore.h"
649ab027 47#include "AliMpDEManager.h"
2ee47a65 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"
c93255fe 65#include "AliLog.h"
887a669c 66#include <cstring>
67#include <cstdlib>
68#include <cmath>
69#include <cerrno>
70#include <cassert>
71
72
73ClassImp(AliHLTMUONDigitPublisherComponent)
74
75
76AliHLTMUONDigitPublisherComponent::AliHLTMUONDigitPublisherComponent() :
77 AliHLTOfflineDataSource(),
78 fDDL(-1),
2ee47a65 79 fCurrentEventIndex(0),
80 fMakeScalars(false),
81 fMCDataInterface(NULL),
649ab027 82 fDataInterface(NULL),
83 fChamberExclusionList(0),
84 fDetElemExclusionList(0)
887a669c 85{
86 /// Default constructor.
87}
88
89
90AliHLTMUONDigitPublisherComponent::~AliHLTMUONDigitPublisherComponent()
91{
92 /// Default destructor.
2ee47a65 93
94 if (fMCDataInterface != NULL) delete fMCDataInterface;
95 if (fDataInterface != NULL) delete fDataInterface;
887a669c 96}
97
98const char* AliHLTMUONDigitPublisherComponent::GetComponentID()
99{
100 /// Inherited from AliHLTComponent. Returns the component ID.
101
102 return AliHLTMUONConstants::DigitPublisherId();
103}
104
105
106AliHLTComponentDataType AliHLTMUONDigitPublisherComponent::GetOutputDataType()
107{
108 /// Inherited from AliHLTComponent. Returns the raw DDL data type.
109
110 return AliHLTMUONConstants::DDLRawDataType();
111}
112
113
114void AliHLTMUONDigitPublisherComponent::GetOutputDataSize(
115 unsigned long& constBase, double& inputMultiplier
116 )
117{
118 /// Inherited from AliHLTComponent.
119 /// Returns an estimate of the expected output data size.
120
121 // estimated as max number of channels * raw data word size + max headers size.
16e6f752 122 constBase = sizeof(AliRawDataHeaderV3) + 65536*sizeof(UInt_t)
887a669c 123 + sizeof(AliMUONBlockHeaderStruct)*2 + sizeof(AliMUONDSPHeaderStruct)*10
124 + sizeof(AliMUONBusPatchHeaderStruct) * 50;
125 inputMultiplier = 0;
126}
127
128
129AliHLTComponent* AliHLTMUONDigitPublisherComponent::Spawn()
130{
131 /// Inherited from AliHLTComponent. Creates a new object instance.
132
133 return new AliHLTMUONDigitPublisherComponent;
134}
135
136
649ab027 137int AliHLTMUONDigitPublisherComponent::ParseChamberString(const char* str)
138{
139 /// Parses a string with the following format:
a47233fb 140 /// <number>|<number>-<number>[,<number>|<number>-<number>,...]
649ab027 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.
146
147 char* end = const_cast<char*>(str);
148 long lastChamber = -1;
149 do
150 {
151 // Parse the next number.
152 char* current = end;
153 long chamber = strtol(current, &end, 0);
154
155 // Check for parse errors of the number.
156 if (current == end)
157 {
158 HLTError("Expected a number in the range [1..%d] but got '%s'.",
159 AliMUONConstants::NTrackingCh(), current
160 );
161 return -EINVAL;
162 }
163 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
164 {
165 HLTError("Received the chamber number %d, which is outside the valid range of [1..%d].",
166 chamber, AliMUONConstants::NTrackingCh()
167 );
168 return -EINVAL;
169 }
170
171 // Skip any whitespace after the number
172 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
173
174 // Check if we are dealing with a list or range, or if we are at
175 // the end of the string.
176 if (*end == '-')
177 {
178 lastChamber = chamber;
179 end++;
180 continue;
181 }
182 else if (*end == ',')
183 {
184 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
185 Int_t size = fChamberExclusionList.GetSize();
186 fChamberExclusionList.Set(size+1);
187 fChamberExclusionList[size] = chamber-1;
188 end++;
189 }
190 else if (*end == '\0')
191 {
192 assert( 1 <= chamber and chamber <= AliMUONConstants::NTrackingCh() );
193 Int_t size = fChamberExclusionList.GetSize();
194 fChamberExclusionList.Set(size+1);
195 fChamberExclusionList[size] = chamber-1;
196 }
197 else
198 {
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
202 );
203 return -EINVAL;
204 }
205
206 // Set the range of chambers to publish for.
207 if (lastChamber > 0)
208 {
209 Int_t min, max;
210 if (lastChamber < chamber)
211 {
212 min = lastChamber;
213 max = chamber;
214 }
215 else
216 {
217 min = chamber;
218 max = lastChamber;
219 }
220 assert( min >= 1 );
221 assert( max <= AliMUONConstants::NTrackingCh() );
222 for (Int_t i = min; i <= max; i++)
223 {
224 Int_t size = fChamberExclusionList.GetSize();
225 fChamberExclusionList.Set(size+1);
226 fChamberExclusionList[size] = i-1;
227 }
228 }
229 lastChamber = -1;
230 }
231 while (*end != '\0');
232 return 0;
233}
234
235
236int AliHLTMUONDigitPublisherComponent::ParseDetElemString(const char* str)
237{
238 /// Parses a string with the following format:
a47233fb 239 /// <number>|<number>-<number>[,<number>|<number>-<number>,...]
649ab027 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.
245
246 char* end = const_cast<char*>(str);
247 long lastDetElem = -1;
248 do
249 {
250 // Parse the next number.
251 char* current = end;
252 long detElem = strtol(current, &end, 0);
253
254 // Check for parse errors of the number.
255 if (current == end)
256 {
257 HLTError("Expected a number in the range [100..1099] but got '%s'.",
258 current
259 );
260 return -EINVAL;
261 }
262 if (detElem < 100 or 1099 < detElem)
263 {
264 HLTError("Received the detector element ID number of %d,"
265 " which is outside the valid range of [100..1099].",
266 detElem
267 );
268 return -EINVAL;
269 }
270
271 // Skip any whitespace after the number
272 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
273
274 // Check if we are dealing with a list or range, or if we are at
275 // the end of the string.
276 if (*end == '-')
277 {
278 lastDetElem = detElem;
279 end++;
280 continue;
281 }
282 else if (*end == ',')
283 {
284 assert( 100 <= detElem and detElem <= 1099 );
285 Int_t size = fDetElemExclusionList.GetSize();
286 fDetElemExclusionList.Set(size+1);
287 fDetElemExclusionList[size] = detElem-1;
288 end++;
289 }
290 else if (*end == '\0')
291 {
292 assert( 100 <= detElem and detElem <= 1099 );
293 Int_t size = fDetElemExclusionList.GetSize();
294 fDetElemExclusionList.Set(size+1);
295 fDetElemExclusionList[size] = detElem-1;
296 }
297 else
298 {
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
302 );
303 return -EINVAL;
304 }
305
306 // Set the range of detector elements to publish for.
307 if (lastDetElem > 0)
308 {
309 Int_t min, max;
310 if (lastDetElem < detElem)
311 {
312 min = lastDetElem;
313 max = detElem;
314 }
315 else
316 {
317 min = detElem;
318 max = lastDetElem;
319 }
320 assert( min >= 100 );
321 assert( max <= 1099 );
322 for (Int_t i = min; i <= max; i++)
323 {
324 Int_t size = fDetElemExclusionList.GetSize();
325 fDetElemExclusionList.Set(size+1);
326 fDetElemExclusionList[size] = i-1;
327 }
328 }
329 lastDetElem = -1;
330 }
331 while (*end != '\0');
332 return 0;
333}
334
335
887a669c 336int AliHLTMUONDigitPublisherComponent::DoInit(int argc, const char** argv)
337{
338 /// Inherited from AliHLTComponent.
339 /// Parses the command line parameters and initialises the component.
340
341 HLTInfo("Initialising dHLT digit publisher component.");
342
2ee47a65 343 if (fMCDataInterface != NULL)
344 {
345 delete fMCDataInterface;
346 fMCDataInterface = NULL;
347 }
348 if (fDataInterface != NULL)
349 {
350 delete fDataInterface;
351 fDataInterface = NULL;
352 }
353
887a669c 354 // Initialise with default values.
355 fDDL = -1;
356 fCurrentEventIndex = 0;
2ee47a65 357 fMakeScalars = false;
649ab027 358 fChamberExclusionList.Set(0);
359 fDetElemExclusionList.Set(0);
887a669c 360 bool simdata = false;
361 bool recdata = false;
362 bool firstEventSet = false;
363 bool eventNumLitSet = false;
364
365 for (int i = 0; i < argc; i++)
366 {
2ee47a65 367 if (strcmp(argv[i], "-makescalars") == 0)
368 {
369 fMakeScalars = true;
370 continue;
371 }
887a669c 372 if (strcmp(argv[i], "-simdata") == 0)
373 {
374 simdata = true;
375 continue;
376 }
377 if (strcmp(argv[i], "-recdata") == 0)
378 {
379 recdata = true;
380 continue;
381 }
382 if (strcmp(argv[i], "-ddl") == 0)
383 {
384 if (argc <= i+1)
385 {
649ab027 386 HLTError("DDL number not specified. It must be in the range [1..22]" );
887a669c 387 return -EINVAL;
388 }
389
390 char* cpErr = NULL;
391 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
392 if (cpErr == NULL or *cpErr != '\0')
393 {
649ab027 394 HLTError("Cannot convert '%s' to a DDL number.", argv[i+1]);
887a669c 395 return -EINVAL;
396 }
397 if (num < 1 or 22 < num)
398 {
649ab027 399 HLTError("The DDL number must be in the range [1..22].");
887a669c 400 return -EINVAL;
401 }
402 fDDL = num - 1; // Convert to DDL number in the range 0..21
403
404 i++;
405 continue;
406 }
649ab027 407 if (strcmp(argv[i], "-ddlid") == 0)
408 {
409 if (argc <= i+1)
410 {
411 HLTError("DDL equipment ID number not specified."
412 " It must be in the range [2560..2579] or [2816..2817]."
413 );
414 return -EINVAL;
415 }
416
417 char* cpErr = NULL;
418 unsigned long num = strtoul(argv[i+1], &cpErr, 0);
419 if (cpErr == NULL or *cpErr != '\0')
420 {
421 HLTError("Cannot convert '%s' to a DDL equipment ID number.", argv[i+1]);
422 return -EINVAL;
423 }
424 fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
425 if (fDDL < 0 or 21 < fDDL)
426 {
427 HLTError("The DDL equipment ID number must be in the range"
428 " [2560..2579] or [2816..2817]."
429 );
430 return -EINVAL;
431 }
432
433 i++;
434 continue;
435 }
887a669c 436 if (strcmp(argv[i], "-firstevent") == 0)
437 {
438 if (eventNumLitSet)
439 {
440 HLTWarning("The -firstevent flag is overridden by a"
441 " previous use of -event_number_literal."
442 );
443 }
444 if (++i >= argc)
445 {
446 HLTError("Expected a positive number after -firstevent.");
447 return -EINVAL;
448 }
4e22efc4 449 char* end = NULL;
887a669c 450 long num = strtol(argv[i], &end, 0);
4e22efc4 451 if ((end != NULL and *end != '\0') or num < 0) // Check if the conversion is OK.
887a669c 452 {
453 HLTError("Expected a positive number after -firstevent"
454 " but got: %s", argv[i]
455 );
456 return -EINVAL;
457 }
458 fCurrentEventIndex = Int_t(num);
459 firstEventSet = true;
460 continue;
461 }
462 if (strcmp(argv[i], "-event_number_literal") == 0)
463 {
464 if (firstEventSet)
465 {
466 HLTWarning("The -event_number_literal option will"
467 " override -firstevent."
468 );
469 }
470 fCurrentEventIndex = -1;
471 eventNumLitSet = true;
472 continue;
473 }
649ab027 474 if (strcmp(argv[i], "-exclude_chamber") == 0)
475 {
476 if (argc <= i+1)
477 {
478 HLTError("Expected a chamber number, a range eg. '1-10', or a list eg."
479 " '1,2,3' after '-exclude_chamber'."
480 );
481 return -EINVAL;
482 }
483
484 int result = ParseChamberString(argv[i+1]);
485 if (result != 0) return result;
486 i++;
487 continue;
488 }
489 if (strcmp(argv[i], "-exclude_detelem") == 0)
490 {
491 if (argc <= i+1)
492 {
493 HLTError("Expected a detector element ID number, a range eg. '100-108',"
494 " or a list eg. '100,102,301' after '-exclude_detelem'."
495 );
496 return -EINVAL;
497 }
498
499 int result = ParseDetElemString(argv[i+1]);
500 if (result != 0) return result;
501 i++;
502 continue;
503 }
887a669c 504
505 HLTError("Unknown option '%s'.", argv[i]);
506 return -EINVAL;
507 }
508
509 if (fDDL == -1)
510 {
511 HLTError("DDL number must be set with the -ddl option, but it was not.");
512 return -EINVAL;
513 }
514
2ee47a65 515 // Must load the mapping data if it is not already loaded.
516 if (AliMpDDLStore::Instance(false) == NULL)
517 {
518 AliMpCDB::LoadDDLStore();
519 if (AliMpDDLStore::Instance(false) == NULL)
520 {
521 HLTError("Could not load the DDL mapping store from CDB.");
522 return -EFAULT;
523 }
524 }
525
526 // Now we can initialise the data interface objects and loaders.
527 if (simdata)
528 {
529 HLTDebug("Loading simulated digits with AliMUONMCDataInterface.");
530
531 try
532 {
533 fMCDataInterface = new AliMUONMCDataInterface("galice.root");
534 }
535 catch (const std::bad_alloc&)
536 {
537 HLTError("Not enough memory to allocate AliMUONMCDataInterface.");
538 return -ENOMEM;
539 }
540 }
541 else if (recdata)
542 {
543 HLTDebug("Loading reconstructed digits with AliMUONDataInterface.");
544
545 try
546 {
547 fDataInterface = new AliMUONDataInterface("galice.root");
548 }
549 catch (const std::bad_alloc&)
550 {
551 HLTError("Not enough memory to allocate AliMUONDataInterface.");
552 return -ENOMEM;
553 }
554 }
555
556 // Check that the fCurrentEventIndex number falls within the correct range.
557 UInt_t maxevent = 0;
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)
563 {
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
568 );
569 }
887a669c 570
571 return 0;
572}
573
574
575int AliHLTMUONDigitPublisherComponent::DoDeinit()
576{
577 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
578
579 HLTInfo("Deinitialising dHLT digit publisher component.");
2ee47a65 580
581 if (fMCDataInterface != NULL)
582 {
583 delete fMCDataInterface;
584 fMCDataInterface = NULL;
585 }
586 if (fDataInterface != NULL)
587 {
588 delete fDataInterface;
589 fDataInterface = NULL;
590 }
887a669c 591 return 0;
592}
593
594
595int AliHLTMUONDigitPublisherComponent::GetEvent(
2ee47a65 596 const AliHLTComponentEventData& evtData,
887a669c 597 AliHLTComponentTriggerData& /*trigData*/,
2ee47a65 598 AliHLTUInt8_t* outputPtr,
887a669c 599 AliHLTUInt32_t& size,
ffb64d3e 600 AliHLTComponentBlockDataList& outputBlocks
887a669c 601 )
602{
603 /// Inherited from AliHLTOfflineDataSource.
604
2ee47a65 605 assert( fMCDataInterface != NULL or fDataInterface != NULL );
594c94c2 606
607 if (not IsDataEvent()) return 0; // ignore non data events.
2ee47a65 608
609 // Check the size of the event descriptor structure.
610 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
611 {
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.",
616 evtData.fStructSize,
617 sizeof(AliHLTComponentEventData)
618 );
619 size = 0; // Important to tell framework that nothing was generated.
620 return -EINVAL;
621 }
622
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
626 // increment it.
627 UInt_t eventnumber = UInt_t(evtData.fEventID);
628 UInt_t maxevent = 0;
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)
634 {
635 eventnumber = UInt_t(fCurrentEventIndex);
636 fCurrentEventIndex++;
637 if (UInt_t(fCurrentEventIndex) >= maxevent)
638 fCurrentEventIndex = 0;
639 }
640 if ( eventnumber >= maxevent )
641 {
642 HLTError("The event number (%d) is larger than the available number"
643 " of events on file (%d).",
644 eventnumber, maxevent
645 );
646 size = 0; // Important to tell framework that nothing was generated.
647 return -EINVAL;
648 }
649
650 const AliMUONVDigitStore* digitStore = NULL;
651 const AliMUONVTriggerStore* triggerStore = NULL;
652
653 if (fMCDataInterface != NULL)
654 {
655 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
656
657 if (fDDL < 20)
658 {
659 digitStore = fMCDataInterface->DigitStore(eventnumber);
660 }
661 else
662 {
663 triggerStore = fMCDataInterface->TriggerStore(eventnumber);
664 }
665 }
666 else if (fDataInterface != NULL)
667 {
668 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
669
670 if (fDDL < 20)
671 {
672 digitStore = fDataInterface->DigitStore(eventnumber);
673 }
674 else
675 {
676 triggerStore = fDataInterface->TriggerStore(eventnumber);
677 }
678 }
679 else
680 {
681 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
682 size = 0; // Important to tell framework that nothing was generated.
683 return -EFAULT;
684 }
685
686 // Make sure we have the correct CTP trigger loaded.
33c3c91a 687 AliRunLoader* runloader = AliRunLoader::Instance();
2ee47a65 688 if (runloader != NULL)
689 {
690 if (runloader->GetTrigger() == NULL)
691 runloader->LoadTrigger();
692 runloader->GetEvent(eventnumber);
693 }
694
695 if (fDDL < 20 and digitStore != NULL)
696 {
697 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
698 if (result != 0)
699 {
700 size = 0; // Important to tell framework that nothing was generated.
701 return result;
702 }
703 }
704 else if (triggerStore != NULL)
705 {
706 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
707 if (result != 0)
708 {
709 size = 0; // Important to tell framework that nothing was generated.
710 return result;
711 }
712 }
713 else
714 {
715 size = 0; // Important to tell framework that nothing was generated.
716 return 0;
717 }
718
719 AliHLTComponentBlockData bd;
720 FillBlockData(bd);
721 bd.fPtr = outputPtr;
722 bd.fOffset = 0;
723 bd.fSize = size;
724 bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
725 bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
726 outputBlocks.push_back(bd);
887a669c 727
887a669c 728 return 0;
729}
730
2ee47a65 731
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.
738
739//____________________________________________________________________
740void 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)
743{
744/// pack local trigger word
745
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);
753}
754
755//______________________________________________________________________________
756void
757AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
758 const AliMUONVDigitStore& digitStore,
759 AliMpExMap& busPatchMap, Int_t iDDL
760 )
761{
762 /// Create bus patch structures corresponding to digits in the store
763
764 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
765 assert(ddlStore != NULL);
766
767 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
768 busPatchMap.SetSize(ddl->GetNofBusPatches());
769
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++)
774 {
775 if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
776 if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
777 }
778
779 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
780
781 // DDL event one per half chamber
782
783 // raw data
784 Char_t parity = 0x4;
785 UShort_t manuId = 0;
786 UChar_t channelId = 0;
787 UShort_t charge = 0;
788 Int_t busPatchId = 0;
789 Int_t currentBusPatchId = -1;
790 UInt_t word;
791
792 AliMUONBusStruct* busStruct(0x0);
793
794 TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
795 AliMUONVDigit* digit;
796
797 while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
798 {
649ab027 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++)
802 {
803 if (digit->DetElemId() == fDetElemExclusionList[i])
804 {
805 excludeDigit = true;
806 break;
807 }
808 }
809 for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
810 {
811 if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
812 {
813 excludeDigit = true;
814 break;
815 }
816 }
817 if (excludeDigit) continue;
818
2ee47a65 819 charge = digit->ADC();
820 if ( charge > kMAXADC )
821 {
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);
826 charge = kMAXADC;
827 }
828
829 // inverse mapping
830 busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
831
832 if (busPatchId<0) continue;
833
834 if ( digit->ManuId() > 0x7FF ||
835 digit->ManuChannel() > 0x3F )
836 {
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()
842 );
843 }
844
845 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
846 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
847
848 //packing word
849 word = 0;
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);
853
854 // parity word
855 parity = word & 0x1;
856 for (Int_t i = 1; i <= 30; ++i)
857 {
858 parity ^= ((word >> i) & 0x1);
859 }
860 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
861
862 if ( currentBusPatchId != busPatchId )
863 {
864 busStruct =
865 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
866 currentBusPatchId = busPatchId;
867 }
868
869 if (!busStruct)
870 {
871 busStruct = new AliMUONBusStruct;
872 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
873 busStruct->SetBusPatchId(busPatchId);
874 busStruct->SetLength(0);
875 busPatchMap.Add(busPatchId,busStruct);
876 }
877
878 // set sub Event
879 busStruct->AddData(word);
880 }
881}
882
883//______________________________________________________________________________
884int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
885 const AliMUONVDigitStore* digitStore, Int_t iDDL,
886 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
887 )
888{
889 /// Write DDL file for one tracker DDL
890
891 assert(0 <= iDDL and iDDL <= 19);
892
893 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
894 assert(ddlStore != NULL);
895
896 if (ddlStore->GetDDL(iDDL) == NULL)
897 {
898 HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
899 return -EFAULT;
900 }
901
902 AliMpExMap busPatchMap;
903 Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
904
905 AliMUONBlockHeader blockHeader;
906 AliMUONDspHeader dspHeader;
907 blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
908 dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
909
16e6f752 910 if (outBufferSize < sizeof(AliRawDataHeaderV3))
2ee47a65 911 {
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.",
16e6f752 914 outBufferSize, sizeof(AliRawDataHeaderV3)
2ee47a65 915 );
916 return -ENOBUFS;
917 }
16e6f752 918 AliRawDataHeaderV3* header = reinterpret_cast<AliRawDataHeaderV3*>(outBuffer);
2ee47a65 919 // Fill header with default values.
16e6f752 920 *header = AliRawDataHeaderV3();
33c3c91a 921 AliRunLoader* runloader = AliRunLoader::Instance();
2ee47a65 922 if (runloader != NULL)
923 {
924 if (runloader->GetTrigger() != NULL)
925 {
926 AliCentralTrigger *aCTP = runloader->GetTrigger();
927 ULong64_t mask = aCTP->GetClassMask();
928 header->SetTriggerClass(mask);
16e6f752 929 mask = aCTP->GetClassMaskNext50();
930 header->SetTriggerClassNext50(mask);
2ee47a65 931 }
932 }
933
934 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
16e6f752 935 Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeaderV3)) / sizeof(Int_t);
2ee47a65 936
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
940
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);
945 Int_t busIter = 0;
946
947 Int_t totalDDLLength = 0;
948
949 Int_t index = 0;
950
951 // two blocks A and B per DDL
952 for (Int_t iBlock = 0; iBlock < 2; ++iBlock)
953 {
954 Int_t length = blockHeader.GetHeaderLength();
955 if (index + length >= endOfBuffer)
956 {
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.",
959 outBufferSize,
16e6f752 960 sizeof(AliRawDataHeaderV3) + (index+length)*sizeof(UInt_t)
2ee47a65 961 );
962 return -ENOBUFS;
963 }
964
965 // block header
966 memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
967 Int_t indexBlk = index;
968 index += length;
969
970 // 5 DSP's max per block
971 for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp)
972 {
973 Int_t dspHeaderLength = dspHeader.GetHeaderLength();
974 if (index + dspHeaderLength >= endOfBuffer)
975 {
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.",
978 outBufferSize,
16e6f752 979 sizeof(AliRawDataHeaderV3) + (index+dspHeaderLength)*sizeof(UInt_t)
2ee47a65 980 );
981 return -ENOBUFS;
982 }
983
984 // DSP header
985 memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
986 Int_t indexDsp = index;
987 index += dspHeaderLength;
988
989 // 5 buspatches max per DSP
990 for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i)
991 {
992 Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
993
994 // iteration over bus patch in DDL
995 if (iBusPatch == -1)
996 {
997 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
998 continue;
999 }
1000
1001 AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
1002
1003 Int_t busHeaderLength = busStructPtr->GetHeaderLength();
1004 if (index + busHeaderLength >= endOfBuffer)
1005 {
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.",
1008 outBufferSize,
16e6f752 1009 sizeof(AliRawDataHeaderV3) + (index+busHeaderLength)*sizeof(UInt_t)
2ee47a65 1010 );
1011 return -ENOBUFS;
1012 }
1013
1014 // check if buspatchid has digit
1015 if (busStructPtr)
1016 {
1017 // add bus patch structure header
1018 memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1019 index += busHeaderLength;
1020
1021 Int_t busLength = busStructPtr->GetLength();
1022 if (index + busLength >= endOfBuffer)
1023 {
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.",
1026 outBufferSize,
16e6f752 1027 sizeof(AliRawDataHeaderV3) + (index+busLength)*sizeof(UInt_t)
2ee47a65 1028 );
1029 return -ENOBUFS;
1030 }
1031
1032 // add bus patch data
1033 memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1034 index += busLength;
1035 }
1036 else
1037 {
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
1043 }
1044 } // bus patch
1045
1046 if (index + 1 >= endOfBuffer)
1047 {
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.",
1050 outBufferSize,
16e6f752 1051 sizeof(AliRawDataHeaderV3) + (index+1)*sizeof(UInt_t)
2ee47a65 1052 );
1053 return -ENOBUFS;
1054 }
1055
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)
1061 {
1062 buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1063 buffer[index++] = dspHeader.GetDefaultPaddingWord();
1064 totalDspLength++;
1065 }
1066
1067 Int_t dspLength = totalDspLength - dspHeader.GetHeaderLength();
1068
1069 buffer[indexDsp+1] = totalDspLength; // dsp total length
1070 buffer[indexDsp+2] = dspLength; // data length
1071
1072 } // dsp
1073
1074 Int_t totalBlkLength = index - indexBlk;
1075 Int_t blkLength = totalBlkLength - blockHeader.GetHeaderLength();
1076 totalDDLLength += totalBlkLength;
1077
1078 buffer[indexBlk+1] = totalBlkLength; // total block length
1079 buffer[indexBlk+2] = blkLength;
1080
1081 } // block
1082
1083 if (index + 2 >= endOfBuffer)
1084 {
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.",
1087 outBufferSize,
16e6f752 1088 sizeof(AliRawDataHeaderV3) + (index+2)*sizeof(UInt_t)
2ee47a65 1089 );
1090 return -ENOBUFS;
1091 }
1092
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;
1098
16e6f752 1099 header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeaderV3);
2ee47a65 1100 outBufferSize = header->fSize;
1101
1102 return 0;
1103}
1104
1105//______________________________________________________________________________
1106int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1107 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1108 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1109 bool scalarEvent
1110 )
1111{
1112 /// Write trigger DDL
1113
1114 assert(0 <= iDDL and iDDL <= 19);
1115
1116 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1117 assert(ddlStore != NULL);
1118
16e6f752 1119 if (outBufferSize < sizeof(AliRawDataHeaderV3))
2ee47a65 1120 {
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.",
16e6f752 1123 outBufferSize, sizeof(AliRawDataHeaderV3)
2ee47a65 1124 );
1125 return -ENOBUFS;
1126 }
16e6f752 1127 AliRawDataHeaderV3* header = reinterpret_cast<AliRawDataHeaderV3*>(outBuffer);
2ee47a65 1128 // Fill header with default values.
16e6f752 1129 *header = AliRawDataHeaderV3();
33c3c91a 1130 AliRunLoader* runloader = AliRunLoader::Instance();
2ee47a65 1131 if (runloader != NULL)
1132 {
1133 if (runloader->GetTrigger() != NULL)
1134 {
1135 AliCentralTrigger *aCTP = runloader->GetTrigger();
1136 ULong64_t mask = aCTP->GetClassMask();
1137 header->SetTriggerClass(mask);
1138 }
1139 }
1140
1141 // global trigger for trigger pattern
1142 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1143 if (!gloTrg)
1144 {
1145 return 0;
1146 }
1147
1148 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1149
1150 UInt_t word;
1151 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1152 Int_t index;
766ec4b3 1153 //Int_t locCard;
2ee47a65 1154 UChar_t locDec, trigY, posY, posX, regOut;
1155 UInt_t regInpLpt;
1156 UInt_t regInpHpt;
1157
1158 UInt_t devX;
1159 UChar_t sdevX;
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
1164
1165 AliMUONDarcHeader darcHeader;
1166 AliMUONRegHeader regHeader;
1167 AliMUONLocalStruct localStruct;
1168
1169 // size of headers
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();
1178
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;
1182
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);
1188 if(scalarEvent) {
1189 eventPhys = 0; //set to generate scaler events
1190 header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1191 }
1192 if(scalarEvent)
1193 {
16e6f752 1194 if (outBufferSize < sizeof(AliRawDataHeaderV3) + kScalerBufferSize)
2ee47a65 1195 {
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.",
16e6f752 1198 outBufferSize, sizeof(AliRawDataHeaderV3) + kScalerBufferSize
2ee47a65 1199 );
1200 return -ENOBUFS;
1201 }
1202 }
1203 else
1204 {
16e6f752 1205 if (outBufferSize < sizeof(AliRawDataHeaderV3) + kBufferSize)
2ee47a65 1206 {
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.",
16e6f752 1209 outBufferSize, sizeof(AliRawDataHeaderV3) + kBufferSize
2ee47a65 1210 );
1211 return -ENOBUFS;
1212 }
1213 }
1214
1215 index = 0;
1216
1217 if (iDDL == 0) // suppose global info in DDL one
1218 globalFlag = 1;
1219 else
1220 globalFlag = 0;
1221
1222 word = 0;
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);
1230
1231 memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4);
1232 index += kDarcHeaderLength;
1233
1234 // no global input for the moment....
1235 if (iDDL == 0)
1236 darcHeader.SetGlobalOutput(gloTrigResp);
1237 else
1238 darcHeader.SetGlobalOutput(0);
1239
1240 if (scalarEvent) {
1241 // 6 DARC scaler words
1242 memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1243 index += kDarcScalerLength;
1244 }
1245 // end of darc word
1246 buffer[index++] = darcHeader.GetEndOfDarc();
1247
1248 // 4 words of global board input + Global board output
1249 memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4);
1250 index += kGlobalHeaderLength;
1251
1252 if (scalarEvent) {
1253 // 10 Global scaler words
1254 memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1255 index += kGlobalScalerLength;
1256 }
1257
1258 // end of global word
1259 buffer[index++] = darcHeader.GetEndOfGlobal();
1260 const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger();
1261
1262 Int_t nCrate = reg->GetNofTriggerCrates()/2;
1263 // 8 regional cards per DDL
1264 for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1265
1266 // crate info
1267 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1268
1f8c7c31 1269 if (!crate)
1270 {
2ee47a65 1271 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1f8c7c31 1272 continue;
1273 }
1274
2ee47a65 1275 // regional info tree, make sure that no reg card missing
1276 AliMUONRegionalTrigger* regTrg = triggerStore->FindRegional(crate->GetId());
1f8c7c31 1277 if (!regTrg)
1278 {
2ee47a65 1279 AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1f8c7c31 1280 continue;
1281 }
1282
2ee47a65 1283 // Regional card header
1284 word = 0;
1285
1286 // set darc status word
1287 regHeader.SetDarcWord(word);
1288
1289 regOut = regTrg->GetOutput();
1290 regInpHpt = regTrg->GetLocalOutput(0);
1291 regInpLpt = regTrg->GetLocalOutput(1);
1292
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);
dbd465f6 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);
2ee47a65 1300 regHeader.SetWord(word);
1301
1302
1303 // fill header later, need local response
1304 Int_t indexReg = index;
1305 index += kRegHeaderLength;
1306
1307 // 11 regional scaler word
1308 if (scalarEvent) {
1309 memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1310 index += kRegScalerLength;
1311 }
1312
1313 // end of regional word
1314 buffer[index++] = regHeader.GetEndOfReg();
1315
1316 // 16 local card per regional board
1317 // UShort_t localMask = 0x0;
1318
1319 Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1320
1321 for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1322
1323 // slot zero for Regional card
1324 Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1325
1326 if (localBoardId) { // if not empty slot
1327 AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1328
1329 if (localBoard->IsNotified()) {// if notified board
1330 AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1331
766ec4b3 1332 //locCard = locTrg->LoCircuit();
2ee47a65 1333 locDec = locTrg->GetLoDecision();
1334 trigY = locTrg->LoTrigY();
1335 posY = locTrg->LoStripY();
1336 posX = locTrg->LoStripX();
1337 devX = locTrg->LoDev();
1338 sdevX = locTrg->LoSdev();
1339
1340 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
1341 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
1342 //packing word
1343 word = 0;
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);
1346
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
1352
1353
1354 }
1355 // fill copy card X-Y inputs from the notified cards
1356 if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom())
1357 {
1358 // not triggered
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);
1363
1364 Int_t localFromId = localBoard->GetInputXfrom();
1365 AliMUONLocalTrigger* locTrgfrom = triggerStore->FindLocal(localFromId);
1366
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;
1372 }
1373
1374 } else {
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
1379
1380 // 45 regional scaler word
1381 if (scalarEvent) {
1382 memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1383 index += kLocScalerLength;
1384 }
1385
1386 // end of local structure words
1387 buffer[index++] = localStruct.GetEndOfLocal();
1388
1389 } // local card
1390 // fill regional header with local output
1391 regHeader.SetInput(regInpHpt, 0);
766ec4b3 1392 regHeader.SetInput(regInpLpt, 1);
2ee47a65 1393 memcpy(&buffer[indexReg],regHeader.GetHeader(),kRegHeaderLength*4);
1394
1395 } // Regional card
1396
16e6f752 1397 header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeaderV3);
2ee47a65 1398 outBufferSize = header->fSize;
1399
1400 return 0;
1401}
1402
1403
1404/////////////////////////////////////////////////////////////////////////////////////////