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