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