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