]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/MUON/OfflineInterface/AliHLTMUONDigitPublisherComponent.cxx
Possibility to use time zero signal in drift speed fit for SDD injectors (F. Prino)
[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 }
448 char* end = "";
449 long num = strtol(argv[i], &end, 0);
450 if (*end != '\0' or num < 0) // Check if the conversion is OK.
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 );
605
606 // Check the size of the event descriptor structure.
607 if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
608 {
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.",
613 evtData.fStructSize,
614 sizeof(AliHLTComponentEventData)
615 );
616 size = 0; // Important to tell framework that nothing was generated.
617 return -EINVAL;
618 }
619
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
623 // increment it.
624 UInt_t eventnumber = UInt_t(evtData.fEventID);
625 UInt_t maxevent = 0;
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)
631 {
632 eventnumber = UInt_t(fCurrentEventIndex);
633 fCurrentEventIndex++;
634 if (UInt_t(fCurrentEventIndex) >= maxevent)
635 fCurrentEventIndex = 0;
636 }
637 if ( eventnumber >= maxevent )
638 {
639 HLTError("The event number (%d) is larger than the available number"
640 " of events on file (%d).",
641 eventnumber, maxevent
642 );
643 size = 0; // Important to tell framework that nothing was generated.
644 return -EINVAL;
645 }
646
647 const AliMUONVDigitStore* digitStore = NULL;
648 const AliMUONVTriggerStore* triggerStore = NULL;
649
650 if (fMCDataInterface != NULL)
651 {
652 HLTDebug("Filling data block with simulated digits for event %d.", eventnumber);
653
654 if (fDDL < 20)
655 {
656 digitStore = fMCDataInterface->DigitStore(eventnumber);
657 }
658 else
659 {
660 triggerStore = fMCDataInterface->TriggerStore(eventnumber);
661 }
662 }
663 else if (fDataInterface != NULL)
664 {
665 HLTDebug("Filling data block with reconstructed digits for event %d.", eventnumber);
666
667 if (fDDL < 20)
668 {
669 digitStore = fDataInterface->DigitStore(eventnumber);
670 }
671 else
672 {
673 triggerStore = fDataInterface->TriggerStore(eventnumber);
674 }
675 }
676 else
677 {
678 HLTError("Neither AliMUONDataInterface nor AliMUONMCDataInterface were created.");
679 size = 0; // Important to tell framework that nothing was generated.
680 return -EFAULT;
681 }
682
683 // Make sure we have the correct CTP trigger loaded.
684 AliRunLoader* runloader = AliRunLoader::GetRunLoader();
685 if (runloader != NULL)
686 {
687 if (runloader->GetTrigger() == NULL)
688 runloader->LoadTrigger();
689 runloader->GetEvent(eventnumber);
690 }
691
692 if (fDDL < 20 and digitStore != NULL)
693 {
694 int result = WriteTrackerDDL(digitStore, fDDL, outputPtr, size);
695 if (result != 0)
696 {
697 size = 0; // Important to tell framework that nothing was generated.
698 return result;
699 }
700 }
701 else if (triggerStore != NULL)
702 {
703 int result = WriteTriggerDDL(triggerStore, fDDL-20, outputPtr, size, fMakeScalars);
704 if (result != 0)
705 {
706 size = 0; // Important to tell framework that nothing was generated.
707 return result;
708 }
709 }
710 else
711 {
712 size = 0; // Important to tell framework that nothing was generated.
713 return 0;
714 }
715
716 AliHLTComponentBlockData bd;
717 FillBlockData(bd);
718 bd.fPtr = outputPtr;
719 bd.fOffset = 0;
720 bd.fSize = size;
721 bd.fDataType = AliHLTMUONConstants::DDLRawDataType();
722 bd.fSpecification = AliHLTMUONUtils::DDLNumberToSpec(fDDL);
723 outputBlocks.push_back(bd);
887a669c 724
887a669c 725 return 0;
726}
727
2ee47a65 728
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.
735
736//____________________________________________________________________
737void 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)
740{
741/// pack local trigger word
742
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);
750}
751
752//______________________________________________________________________________
753void
754AliHLTMUONDigitPublisherComponent::Digits2BusPatchMap(
755 const AliMUONVDigitStore& digitStore,
756 AliMpExMap& busPatchMap, Int_t iDDL
757 )
758{
759 /// Create bus patch structures corresponding to digits in the store
760
761 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
762 assert(ddlStore != NULL);
763
764 AliMpDDL* ddl = ddlStore->GetDDL(iDDL);
765 busPatchMap.SetSize(ddl->GetNofBusPatches());
766
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++)
771 {
772 if (ddl->GetDEId(i) < minDetElem) minDetElem = ddl->GetDEId(i);
773 if (ddl->GetDEId(i) > maxDetElem) maxDetElem = ddl->GetDEId(i);
774 }
775
776 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
777
778 // DDL event one per half chamber
779
780 // raw data
781 Char_t parity = 0x4;
782 UShort_t manuId = 0;
783 UChar_t channelId = 0;
784 UShort_t charge = 0;
785 Int_t busPatchId = 0;
786 Int_t currentBusPatchId = -1;
787 UInt_t word;
788
789 AliMUONBusStruct* busStruct(0x0);
790
791 TIter next(digitStore.CreateIterator(minDetElem, maxDetElem));
792 AliMUONVDigit* digit;
793
794 while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
795 {
649ab027 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++)
799 {
800 if (digit->DetElemId() == fDetElemExclusionList[i])
801 {
802 excludeDigit = true;
803 break;
804 }
805 }
806 for (Int_t i = 0; i < fChamberExclusionList.GetSize(); i++)
807 {
808 if (AliMpDEManager::GetChamberId(digit->DetElemId()) == fChamberExclusionList[i])
809 {
810 excludeDigit = true;
811 break;
812 }
813 }
814 if (excludeDigit) continue;
815
2ee47a65 816 charge = digit->ADC();
817 if ( charge > kMAXADC )
818 {
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);
823 charge = kMAXADC;
824 }
825
826 // inverse mapping
827 busPatchId = ddlStore->GetBusPatchId(digit->DetElemId(), digit->ManuId());
828
829 if (busPatchId<0) continue;
830
831 if ( digit->ManuId() > 0x7FF ||
832 digit->ManuChannel() > 0x3F )
833 {
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()
839 );
840 }
841
842 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
843 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
844
845 //packing word
846 word = 0;
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);
850
851 // parity word
852 parity = word & 0x1;
853 for (Int_t i = 1; i <= 30; ++i)
854 {
855 parity ^= ((word >> i) & 0x1);
856 }
857 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
858
859 if ( currentBusPatchId != busPatchId )
860 {
861 busStruct =
862 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
863 currentBusPatchId = busPatchId;
864 }
865
866 if (!busStruct)
867 {
868 busStruct = new AliMUONBusStruct;
869 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
870 busStruct->SetBusPatchId(busPatchId);
871 busStruct->SetLength(0);
872 busPatchMap.Add(busPatchId,busStruct);
873 }
874
875 // set sub Event
876 busStruct->AddData(word);
877 }
878}
879
880//______________________________________________________________________________
881int AliHLTMUONDigitPublisherComponent::WriteTrackerDDL(
882 const AliMUONVDigitStore* digitStore, Int_t iDDL,
883 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize
884 )
885{
886 /// Write DDL file for one tracker DDL
887
888 assert(0 <= iDDL and iDDL <= 19);
889
890 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
891 assert(ddlStore != NULL);
892
893 if (ddlStore->GetDDL(iDDL) == NULL)
894 {
895 HLTError("Could not find DDL mapping for DDL %d.", iDDL+1);
896 return -EFAULT;
897 }
898
899 AliMpExMap busPatchMap;
900 Digits2BusPatchMap(*digitStore,busPatchMap,iDDL);
901
902 AliMUONBlockHeader blockHeader;
903 AliMUONDspHeader dspHeader;
904 blockHeader.SetDataKey(blockHeader.GetDefaultDataKey());
905 dspHeader.SetDataKey(dspHeader.GetDefaultDataKey());
906
907 if (outBufferSize < sizeof(AliRawDataHeader))
908 {
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)
912 );
913 return -ENOBUFS;
914 }
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)
920 {
921 if (runloader->GetTrigger() != NULL)
922 {
923 AliCentralTrigger *aCTP = runloader->GetTrigger();
924 ULong64_t mask = aCTP->GetClassMask();
925 header->SetTriggerClass(mask);
926 }
927 }
928
929 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
930 Int_t endOfBuffer = (outBufferSize - sizeof(AliRawDataHeader)) / sizeof(Int_t);
931
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
935
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);
940 Int_t busIter = 0;
941
942 Int_t totalDDLLength = 0;
943
944 Int_t index = 0;
945
946 // two blocks A and B per DDL
947 for (Int_t iBlock = 0; iBlock < 2; ++iBlock)
948 {
949 Int_t length = blockHeader.GetHeaderLength();
950 if (index + length >= endOfBuffer)
951 {
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.",
954 outBufferSize,
955 sizeof(AliRawDataHeader) + (index+length)*sizeof(UInt_t)
956 );
957 return -ENOBUFS;
958 }
959
960 // block header
961 memcpy(&buffer[index],blockHeader.GetHeader(),length*4);
962 Int_t indexBlk = index;
963 index += length;
964
965 // 5 DSP's max per block
966 for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp)
967 {
968 Int_t dspHeaderLength = dspHeader.GetHeaderLength();
969 if (index + dspHeaderLength >= endOfBuffer)
970 {
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.",
973 outBufferSize,
974 sizeof(AliRawDataHeader) + (index+dspHeaderLength)*sizeof(UInt_t)
975 );
976 return -ENOBUFS;
977 }
978
979 // DSP header
980 memcpy(&buffer[index],dspHeader.GetHeader(),dspHeaderLength*4);
981 Int_t indexDsp = index;
982 index += dspHeaderLength;
983
984 // 5 buspatches max per DSP
985 for (Int_t i = 0; i < iBusPerDSP[iDsp]; ++i)
986 {
987 Int_t iBusPatch = ddl->GetBusPatchId(busIter++);
988
989 // iteration over bus patch in DDL
990 if (iBusPatch == -1)
991 {
992 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
993 continue;
994 }
995
996 AliMUONBusStruct* busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
997
998 Int_t busHeaderLength = busStructPtr->GetHeaderLength();
999 if (index + busHeaderLength >= endOfBuffer)
1000 {
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.",
1003 outBufferSize,
1004 sizeof(AliRawDataHeader) + (index+busHeaderLength)*sizeof(UInt_t)
1005 );
1006 return -ENOBUFS;
1007 }
1008
1009 // check if buspatchid has digit
1010 if (busStructPtr)
1011 {
1012 // add bus patch structure header
1013 memcpy(&buffer[index],busStructPtr->GetHeader(),busHeaderLength*4);
1014 index += busHeaderLength;
1015
1016 Int_t busLength = busStructPtr->GetLength();
1017 if (index + busLength >= endOfBuffer)
1018 {
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.",
1021 outBufferSize,
1022 sizeof(AliRawDataHeader) + (index+busLength)*sizeof(UInt_t)
1023 );
1024 return -ENOBUFS;
1025 }
1026
1027 // add bus patch data
1028 memcpy(&buffer[index],busStructPtr->GetData(),busLength*4);
1029 index += busLength;
1030 }
1031 else
1032 {
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
1038 }
1039 } // bus patch
1040
1041 if (index + 1 >= endOfBuffer)
1042 {
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.",
1045 outBufferSize,
1046 sizeof(AliRawDataHeader) + (index+1)*sizeof(UInt_t)
1047 );
1048 return -ENOBUFS;
1049 }
1050
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)
1056 {
1057 buffer[indexDsp + dspHeader.GetHeaderLength() - 2] = 1;
1058 buffer[index++] = dspHeader.GetDefaultPaddingWord();
1059 totalDspLength++;
1060 }
1061
1062 Int_t dspLength = totalDspLength - dspHeader.GetHeaderLength();
1063
1064 buffer[indexDsp+1] = totalDspLength; // dsp total length
1065 buffer[indexDsp+2] = dspLength; // data length
1066
1067 } // dsp
1068
1069 Int_t totalBlkLength = index - indexBlk;
1070 Int_t blkLength = totalBlkLength - blockHeader.GetHeaderLength();
1071 totalDDLLength += totalBlkLength;
1072
1073 buffer[indexBlk+1] = totalBlkLength; // total block length
1074 buffer[indexBlk+2] = blkLength;
1075
1076 } // block
1077
1078 if (index + 2 >= endOfBuffer)
1079 {
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.",
1082 outBufferSize,
1083 sizeof(AliRawDataHeader) + (index+2)*sizeof(UInt_t)
1084 );
1085 return -ENOBUFS;
1086 }
1087
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;
1093
1094 header->fSize = (totalDDLLength) * sizeof(Int_t) + sizeof(AliRawDataHeader);
1095 outBufferSize = header->fSize;
1096
1097 return 0;
1098}
1099
1100//______________________________________________________________________________
1101int AliHLTMUONDigitPublisherComponent::WriteTriggerDDL(
1102 const AliMUONVTriggerStore* triggerStore, Int_t iDDL,
1103 AliHLTUInt8_t* outBuffer, AliHLTUInt32_t& outBufferSize,
1104 bool scalarEvent
1105 )
1106{
1107 /// Write trigger DDL
1108
1109 assert(0 <= iDDL and iDDL <= 19);
1110
1111 AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1112 assert(ddlStore != NULL);
1113
1114 if (outBufferSize < sizeof(AliRawDataHeader))
1115 {
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)
1119 );
1120 return -ENOBUFS;
1121 }
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)
1127 {
1128 if (runloader->GetTrigger() != NULL)
1129 {
1130 AliCentralTrigger *aCTP = runloader->GetTrigger();
1131 ULong64_t mask = aCTP->GetClassMask();
1132 header->SetTriggerClass(mask);
1133 }
1134 }
1135
1136 // global trigger for trigger pattern
1137 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
1138 if (!gloTrg)
1139 {
1140 return 0;
1141 }
1142
1143 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
1144
1145 UInt_t word;
1146 Int_t* buffer = reinterpret_cast<Int_t*>(header+1);
1147 Int_t index;
1148 Int_t locCard;
1149 UChar_t locDec, trigY, posY, posX, regOut;
1150 UInt_t regInpLpt;
1151 UInt_t regInpHpt;
1152
1153 UInt_t devX;
1154 UChar_t sdevX;
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
1159
1160 AliMUONDarcHeader darcHeader;
1161 AliMUONRegHeader regHeader;
1162 AliMUONLocalStruct localStruct;
1163
1164 // size of headers
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();
1173
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;
1177
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);
1183 if(scalarEvent) {
1184 eventPhys = 0; //set to generate scaler events
1185 header->fWord2 |= (0x1 << 14); // set L1SwC bit on
1186 }
1187 if(scalarEvent)
1188 {
1189 if (outBufferSize < sizeof(AliRawDataHeader) + kScalerBufferSize)
1190 {
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
1194 );
1195 return -ENOBUFS;
1196 }
1197 }
1198 else
1199 {
1200 if (outBufferSize < sizeof(AliRawDataHeader) + kBufferSize)
1201 {
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
1205 );
1206 return -ENOBUFS;
1207 }
1208 }
1209
1210 index = 0;
1211
1212 if (iDDL == 0) // suppose global info in DDL one
1213 globalFlag = 1;
1214 else
1215 globalFlag = 0;
1216
1217 word = 0;
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);
1225
1226 memcpy(&buffer[index], darcHeader.GetHeader(), (kDarcHeaderLength)*4);
1227 index += kDarcHeaderLength;
1228
1229 // no global input for the moment....
1230 if (iDDL == 0)
1231 darcHeader.SetGlobalOutput(gloTrigResp);
1232 else
1233 darcHeader.SetGlobalOutput(0);
1234
1235 if (scalarEvent) {
1236 // 6 DARC scaler words
1237 memcpy(&buffer[index], darcHeader.GetDarcScalers(),kDarcScalerLength*4);
1238 index += kDarcScalerLength;
1239 }
1240 // end of darc word
1241 buffer[index++] = darcHeader.GetEndOfDarc();
1242
1243 // 4 words of global board input + Global board output
1244 memcpy(&buffer[index], darcHeader.GetGlobalInput(), (kGlobalHeaderLength)*4);
1245 index += kGlobalHeaderLength;
1246
1247 if (scalarEvent) {
1248 // 10 Global scaler words
1249 memcpy(darcHeader.GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
1250 index += kGlobalScalerLength;
1251 }
1252
1253 // end of global word
1254 buffer[index++] = darcHeader.GetEndOfGlobal();
1255 const AliMpRegionalTrigger* reg = ddlStore->GetRegionalTrigger();
1256
1257 Int_t nCrate = reg->GetNofTriggerCrates()/2;
1258 // 8 regional cards per DDL
1259 for (Int_t iReg = 0; iReg < nCrate; ++iReg) {
1260
1261 // crate info
1262 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(iDDL, iReg);
1263
1264 if (!crate)
1265 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
1266
1267 // regional info tree, make sure that no reg card missing
1268 AliMUONRegionalTrigger* regTrg = triggerStore->FindRegional(crate->GetId());
1269 if (!regTrg)
1270 AliError(Form("Missing regional board %d in trigger Store\n", crate->GetId()));
1271
1272 // Regional card header
1273 word = 0;
1274
1275 // set darc status word
1276 regHeader.SetDarcWord(word);
1277
1278 regOut = regTrg->GetOutput();
1279 regInpHpt = regTrg->GetLocalOutput(0);
1280 regInpLpt = regTrg->GetLocalOutput(1);
1281
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);
dbd465f6 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);
2ee47a65 1289 regHeader.SetWord(word);
1290
1291
1292 // fill header later, need local response
1293 Int_t indexReg = index;
1294 index += kRegHeaderLength;
1295
1296 // 11 regional scaler word
1297 if (scalarEvent) {
1298 memcpy(&buffer[index], regHeader.GetScalers(), kRegScalerLength*4);
1299 index += kRegScalerLength;
1300 }
1301
1302 // end of regional word
1303 buffer[index++] = regHeader.GetEndOfReg();
1304
1305 // 16 local card per regional board
1306 // UShort_t localMask = 0x0;
1307
1308 Int_t nLocalBoard = AliMpConstants::LocalBoardNofChannels();
1309
1310 for (Int_t iLoc = 0; iLoc < nLocalBoard; iLoc++) {
1311
1312 // slot zero for Regional card
1313 Int_t localBoardId = crate->GetLocalBoardId(iLoc);
1314
1315 if (localBoardId) { // if not empty slot
1316 AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(localBoardId);
1317
1318 if (localBoard->IsNotified()) {// if notified board
1319 AliMUONLocalTrigger* locTrg = triggerStore->FindLocal(localBoardId);
1320
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();
1328
1329 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
1330 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
1331 //packing word
1332 word = 0;
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);
1335
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
1341
1342
1343 }
1344 // fill copy card X-Y inputs from the notified cards
1345 if (localBoard->GetInputXfrom() && localBoard->GetInputYfrom())
1346 {
1347 // not triggered
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);
1352
1353 Int_t localFromId = localBoard->GetInputXfrom();
1354 AliMUONLocalTrigger* locTrgfrom = triggerStore->FindLocal(localFromId);
1355
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;
1361 }
1362
1363 } else {
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
1368
1369 // 45 regional scaler word
1370 if (scalarEvent) {
1371 memcpy(&buffer[index], localStruct.GetScalers(), kLocScalerLength*4);
1372 index += kLocScalerLength;
1373 }
1374
1375 // end of local structure words
1376 buffer[index++] = localStruct.GetEndOfLocal();
1377
1378 } // local card
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);
1383
1384 } // Regional card
1385
1386 header->fSize = index * sizeof(Int_t) + sizeof(AliRawDataHeader);
1387 outBufferSize = header->fSize;
1388
1389 return 0;
1390}
1391
1392
1393/////////////////////////////////////////////////////////////////////////////////////////