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