96870ca580c2a93364c0c6b0e18b94e899f108eb
[u/mrichter/AliRoot.git] / MUON / AliMUONRawWriter.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ////////////////////////////////////
19 //
20 // MUON Raw Data generaton in ALICE-MUON
21 // This class version 3 (further details could be found in Alice-note)
22 //
23 // Implemented non-constant buspatch numbers for tracking
24 // with correct DDL id (first guess)
25 // (Ch. Finck, dec 2005)
26 //
27 // Digits2Raw:
28 // Generates raw data for MUON tracker and finally for trigger
29 // Using real mapping (inverse) for tracker
30 // For trigger there is no mapping (mapping could be found in AliMUONTriggerCircuit)
31 // Ch. Finck, July 04
32 // Use memcpy instead of assignment elt by elt
33 // Introducing variable DSP numbers, real manu numbers per buspatch for st12
34 // Implemented scaler event for Trigger
35 // Ch. Finck, Jan. 06
36 // 
37 ////////////////////////////////////
38
39 #include "AliMUONRawWriter.h"
40
41 #include "AliBitPacking.h" 
42 #include "AliRawReader.h"
43 #include "AliLog.h"
44 #include "AliMUON.h"
45 #include "AliMUONConstants.h"
46
47 #include "AliMUONDarcHeader.h"
48 #include "AliMUONRegHeader.h"
49 #include "AliMUONLocalStruct.h"
50 #include "AliMUONDspHeader.h"
51 #include "AliMUONBlockHeader.h"
52
53 #include "AliMUONData.h"
54 #include "AliMUONDigit.h"
55 #include "AliMUONGlobalTrigger.h"
56 #include "AliMUONLocalTrigger.h"
57
58 #include "AliMpBusPatch.h"
59 #include "AliMpDEManager.h"
60 #include "AliMpPad.h"
61 #include "AliMpPlaneType.h"
62 #include "AliMpSegFactory.h"
63 #include "AliMpStationType.h"
64 #include "AliMpVSegmentation.h"
65
66 #include "TClonesArray.h"
67
68 ClassImp(AliMUONRawWriter) // Class implementation in ROOT context
69
70 Int_t AliMUONRawWriter::fgManuPerBusSwp1B[12]  = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 224, 232};
71 Int_t AliMUONRawWriter::fgManuPerBusSwp1NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 225, 233};
72
73 Int_t AliMUONRawWriter::fgManuPerBusSwp2B[12]  = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 226, 246};
74 Int_t AliMUONRawWriter::fgManuPerBusSwp2NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 227, 245};
75
76
77 //__________________________________________________________________________
78 AliMUONRawWriter::AliMUONRawWriter(AliMUONData* data)
79 : TObject(),
80   fScalerEvent(kFALSE)
81 {
82   //
83   // Standard Constructor
84   //
85   AliDebug(1,"Standard ctor");
86       
87   // initialize container
88   fMUONData  = data;
89
90   // initialize array
91   fBusArray = new TClonesArray("AliMUONBusStruct",1000);
92   fBusArray->SetOwner(kTRUE);
93
94   // ddl pointer
95   fBlockHeader     = new AliMUONBlockHeader();
96   fDspHeader       = new AliMUONDspHeader();
97   fBusStruct       = new AliMUONBusStruct();
98
99   fDarcHeader      = new AliMUONDarcHeader();
100   fRegHeader       = new AliMUONRegHeader();
101   fLocalStruct     = new AliMUONLocalStruct();
102
103   fBusPatchManager = new AliMpBusPatch();
104   fBusPatchManager->ReadBusPatchFile();
105
106   fSegFactory = new AliMpSegFactory();
107
108   fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
109   fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
110   fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
111   
112 }
113
114 //__________________________________________________________________________
115 AliMUONRawWriter::AliMUONRawWriter()
116   : TObject(),
117     fMUONData(0),
118     fBlockHeader(0),
119     fDspHeader(0),
120     fBusStruct(0),
121     fDarcHeader(0),
122     fRegHeader(0),
123     fLocalStruct(0),
124     fBusPatchManager(0),
125     fScalerEvent(kFALSE),
126     fSegFactory(0x0)
127 {
128   //
129   // Default Constructor
130   //
131   AliDebug(1,"Default ctor");   
132   fFile[0] = fFile[1] = 0x0;  
133   fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
134   fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
135   fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
136 }
137
138 //_______________________________________________________________________
139 AliMUONRawWriter::AliMUONRawWriter (const AliMUONRawWriter& rhs)
140   : TObject(rhs)
141 {
142   //
143   // Protected copy constructor
144   //
145   AliFatal("Not implemented.");
146 }
147
148 //_______________________________________________________________________
149 AliMUONRawWriter & 
150 AliMUONRawWriter::operator=(const AliMUONRawWriter& rhs)
151 {
152   //
153   // Protected assignement operator
154   //
155   if (this == &rhs) return *this;
156
157   AliFatal("Not implemented.");
158     
159   return *this;  
160 }
161
162 //__________________________________________________________________________
163 AliMUONRawWriter::~AliMUONRawWriter(void)
164 {
165   //
166   // Destructor
167   //
168   AliDebug(1,"dtor");
169   
170   delete fBusArray;
171   
172   delete fBlockHeader;
173   delete fDspHeader;
174   delete fBusStruct;
175   delete fDarcHeader;
176   delete fRegHeader;
177   delete fLocalStruct;
178
179   delete fBusPatchManager;
180   
181   delete fSegFactory;
182   
183   AliInfo(Form("Execution time for MUON tracker : R:%.2fs C:%.2fs",
184                fTrackerTimer.RealTime(),fTrackerTimer.CpuTime()));
185   AliInfo(Form("   Execution time for MUON tracker (mapping calls part) "
186                ": R:%.2fs C:%.2fs",
187                fMappingTimer.RealTime(),fMappingTimer.CpuTime()));
188   AliInfo(Form("Execution time for MUON trigger : R:%.2fs C:%.2fs",
189                fTriggerTimer.RealTime(),fTriggerTimer.CpuTime()));
190 }
191
192 //____________________________________________________________________
193 Int_t AliMUONRawWriter::Digits2Raw()
194 {
195   //
196   // convert digits of the current event to raw data
197   //
198   Int_t idDDL;
199   Char_t name[20];
200
201   fMUONData->GetLoader()->LoadDigits("READ");
202
203   fMUONData->SetTreeAddress("D,GLT");
204
205   fMUONData->ResetDigits();
206   fMUONData->ResetTrigger();
207   
208   // This will get both tracker and trigger digits.
209   fMUONData->GetDigits();
210   
211   // tracking chambers
212
213   for (Int_t ich = 0; ich < AliMUONConstants::NTrackingCh(); ich++) 
214   {
215     // open files
216     idDDL = ich * 2  + 0x900; // official number for MUON
217     sprintf(name, "MUON_%d.ddl",idDDL);
218     fFile[0] = fopen(name,"w");
219
220     idDDL = (ich * 2) + 1 + 0x900;
221     sprintf(name, "MUON_%d.ddl",idDDL);
222     fFile[1] = fopen(name,"w");
223     
224     WriteTrackerDDL(ich);
225   
226     // reset and close
227     fclose(fFile[0]);
228     fclose(fFile[1]);
229   }
230  
231   // trigger chambers
232  
233   // open files
234   idDDL = 0xA00;// official number for MUTR
235   sprintf(name, "MUTR_%d.ddl",idDDL);
236   fFile[0] = fopen(name,"w");
237
238   idDDL = 0xA00 + 1;
239   sprintf(name, "MUTR_%d.ddl",idDDL);
240   fFile[1] = fopen(name,"w");
241
242   WriteTriggerDDL();
243   
244   // reset and close
245   fclose(fFile[0]);
246   fclose(fFile[1]);
247
248   fMUONData->ResetDigits();
249   fMUONData->ResetTrigger();  
250   fMUONData->GetLoader()->UnloadDigits();
251
252   return kTRUE;
253 }
254
255 //____________________________________________________________________
256 Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iCh)
257 {
258   // writing DDL for tracker
259   // used inverse mapping
260   //
261   fTrackerTimer.Start(kFALSE);
262   
263
264   static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
265
266   // resets
267   TClonesArray* muonDigits = 0;
268
269   fBusArray->Delete();
270
271
272   //
273   TArrayI nbInBus;
274
275   nbInBus.Set(5000);
276
277   nbInBus.Reset();
278
279   // DDL header
280   Int_t headerSize = sizeof(fHeader)/4;
281
282   // DDL event one per half chamber
283
284   // raw data
285   Char_t parity = 0x4;
286   UShort_t manuId = 0;
287   UChar_t channelId = 0;
288   UShort_t charge = 0;
289   Int_t busPatchId = 0;
290   UInt_t word;
291
292   // block length
293   Int_t totalBlkLength;
294   Int_t blkLength; 
295   
296   // total DDL length
297   Int_t totalDDLLength;
298
299   // indexes
300   Int_t index;
301   Int_t indexDsp;
302   Int_t indexBlk;
303
304   // digits
305   Int_t nEntries = 0;
306   Int_t* buffer = 0;
307   Int_t padX;
308   Int_t padY;
309   Int_t cathode = 0;
310   Int_t detElemId;
311   Int_t nDigits;
312
313   const AliMUONDigit* digit;
314
315   AliDebug(3, Form("WriteDDL chamber %d\n", iCh+1));
316
317   muonDigits = fMUONData->Digits(iCh);
318
319   nDigits = muonDigits->GetEntriesFast();
320   AliDebug(3,Form("ndigits = %d\n",nDigits));
321  
322   // loop over digit
323   for (Int_t idig = 0; idig < nDigits; idig++) {
324
325     digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
326
327     padX = digit->PadX();
328     padY = digit->PadY();
329     charge = digit->ADC();
330     if ( charge > kMAXADC )
331     {
332       // This is most probably an error in the digitizer (which should insure
333       // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
334       AliError(Form("adc value %d above %x. Setting to %x",
335                       charge,kMAXADC,kMAXADC));
336       charge = kMAXADC;
337     }
338     cathode = digit->Cathode();
339     detElemId = digit->DetElemId();
340
341     // inverse mapping
342     busPatchId = GetBusPatch(*digit);
343     if (busPatchId<0) continue;
344
345     if ( digit->ManuId() > 0x7FF || digit->ManuId() < 0 ||
346          digit->ManuChannel() > 0x3F || digit->ManuChannel() < 0 )
347     {
348       StdoutToAliError(digit->Print(););
349       AliFatal("ManuId,ManuChannel are invalid for the digit above.");
350     }
351     
352     manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
353     channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
354
355     AliDebug(3,Form("input  IdDE %d busPatchId %d PadX %d PadY %d iCath %d \n", 
356                     detElemId, busPatchId, padX, padY, cathode));
357
358     AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", busPatchId, manuId, channelId ));
359
360     //packing word
361     AliBitPacking::PackWord((UInt_t)parity,word,29,31);
362     AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
363     AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
364     AliBitPacking::PackWord((UInt_t)charge,word,0,11);
365
366     // set sub Event
367     fBusStruct->SetLength(0);
368     fBusStruct->AddData(word);
369     fBusStruct->SetBusPatchId(busPatchId);
370        
371     // storing the number of identical buspatches
372     nbInBus[busPatchId]++;
373     AddData(*fBusStruct);
374    
375   }
376
377   // sorting by buspatch
378   fBusArray->Sort();
379
380   // gather datas from same bus patch
381   nEntries = fBusArray->GetEntriesFast();
382
383   for (Int_t i = 0; i < nEntries; i++) {
384     AliMUONBusStruct* temp = (AliMUONBusStruct*)fBusArray->At(i);
385     busPatchId = temp->GetBusPatchId();
386
387     // add bus patch header, length and total length managed by subevent class
388     temp->SetTriggerWord(0xdeadbeef);
389     for (Int_t j = 0; j < nbInBus[busPatchId]-1; j++) {
390       AliMUONBusStruct* temp1 =  (AliMUONBusStruct*)fBusArray->At(++i);
391       temp->AddData(temp1->GetData(0));
392       fBusArray->RemoveAt(i) ;
393     }
394   }
395   fBusArray->Compress();
396
397   if (AliLog::GetGlobalDebugLevel() == 3) {
398     nEntries = fBusArray->GetEntriesFast();
399     for (Int_t i = 0; i < nEntries; i++) {
400       AliMUONBusStruct* temp =  (AliMUONBusStruct*)fBusArray->At(i);
401       printf("busPatchid back %d\n",temp->GetBusPatchId());
402       for (Int_t j = 0; j < temp->GetLength(); j++) {
403         printf("manuId back %d, ",temp->GetManuId(j));
404         printf("channelId back %d, ",temp->GetChannelId(j));
405         printf("charge back %d\n",temp->GetCharge(j));
406       }
407     }
408     printf("\n");
409   }
410   
411   // getting info for the number of buspatches
412   Int_t iBusPatch;
413   Int_t length;
414   Int_t iBusPerDSP[5];//number of bus patches per DSP
415   Int_t iDspMax; //number max of DSP per block
416   Int_t iFile = 0;
417   fBusPatchManager->GetDspInfo(iCh, iDspMax, iBusPerDSP);
418
419   TArrayI* vec = fBusPatchManager->GetBusfromDE((iCh+1)*100);
420
421   Int_t iBus0AtCh = vec->At(0); //get first bus patch id for a given ich
422         
423   AliDebug(3,Form("iBus0AtCh %d", iBus0AtCh));
424
425   iBusPatch = iBus0AtCh - 1; // starting point for each chamber
426
427   // nEntries = fBusArray->GetEntriesFast();
428   AliMUONBusStruct* temp = 0x0;
429
430   // open DDL file, on per 1/2 chamber
431   for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
432     
433     totalDDLLength = 0;
434
435     // filling buffer
436     buffer = new Int_t [(2048+24)*50]; // 24 words in average for one buspatch and 2048 manu info at most
437
438     indexBlk = 0;
439     indexDsp = 0;
440     index = 0;
441
442     // two blocks A and B per DDL
443     for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
444
445       // block header
446       length = fBlockHeader->GetHeaderLength();
447       memcpy(&buffer[index],fBlockHeader->GetHeader(),length*4);
448       indexBlk = index;
449       index += length; 
450
451       // 5 DSP's max per block
452       for (Int_t iDsp = 0; iDsp < iDspMax; iDsp++) {
453
454         // DSP header
455         length = fDspHeader->GetHeaderLength();
456         memcpy(&buffer[index],fDspHeader->GetHeader(),length*4);
457         indexDsp = index;
458         index += length; 
459
460         // 5 buspatches max per DSP
461         for (Int_t i = 0; i < iBusPerDSP[iDsp]; i++) {
462
463           iBusPatch++;
464           if ((fBusPatchManager->GetDDLfromBus(iBusPatch) % 2) == 0) // comparing to DDL file
465             iFile = 1;
466           else
467             iFile = 0;
468
469           AliDebug(3,Form("iCh %d iDDL %d iBlock %d iDsp %d busPatchId %d", iCh, iDDL, iBlock, iDsp, iBusPatch));
470
471           nEntries = fBusArray->GetEntriesFast();
472           busPatchId = -1;
473           for (Int_t iEntries = 0; iEntries < nEntries; iEntries++) { // method "bourrique"...
474             temp = (AliMUONBusStruct*)fBusArray->At(iEntries);
475             busPatchId = temp->GetBusPatchId();
476             if (busPatchId == iBusPatch) break;
477             busPatchId = -1;
478             AliDebug(3,Form("busPatchId %d", temp->GetBusPatchId()));
479           } 
480          
481           // check if buspatchid has digit
482           if (busPatchId != -1) {
483             // add bus patch structure
484             length = temp->GetHeaderLength();
485             memcpy(&buffer[index],temp->GetBusPatchHeader(),length*4);
486             index += length;
487             for (Int_t j = 0; j < temp->GetLength(); j++) {
488               buffer[index++] =  temp->GetData(j);
489               AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", temp->GetBusPatchId(), 
490                               temp->GetManuId(j), temp->GetChannelId(j) ));
491             }
492             //        fBusArray->RemoveAt(iEntries);
493             //        fBusArray->Compress();
494           } else {
495             // writting anyhow buspatch structure (empty ones)
496             buffer[index++] = 4; // total length
497             buffer[index++] = 0; // raw data length
498             buffer[index++] = iBusPatch; // bus patch
499             buffer[index++] = 0xdeadbeef; // trigger word
500           }
501         } // bus patch
502
503         buffer[indexDsp]   = index - indexDsp; // dsp total length
504         buffer[indexDsp+1] = index - indexDsp - fDspHeader->GetHeaderLength();
505         if ((index - indexDsp) % 2 == 0) // event word
506           buffer[indexDsp+7] = 0;
507         else
508           buffer[indexDsp+7] = 1;
509
510       } // dsp
511
512       totalBlkLength  = index - indexBlk;
513       blkLength       = totalBlkLength - fBlockHeader->GetHeaderLength();
514       totalDDLLength += totalBlkLength;
515
516       buffer[indexBlk]   = totalBlkLength; // total block length
517       buffer[indexBlk+1] = blkLength;
518
519       if ((totalBlkLength % 2) == 1) { //add padding word for 64bits transfert
520         buffer[indexBlk]   +=  1; // correct length for padding word
521         buffer[indexBlk+1] +=  1;
522         totalDDLLength++;
523         index++;
524
525         Int_t indexCopy = indexBlk + fBlockHeader->GetHeaderLength();
526         Int_t *buf      = new Int_t [blkLength];
527
528         memcpy(&buf[0], &buffer[indexCopy], blkLength*4);// copy in tmp buffer
529         memcpy(&buffer[indexCopy+1], &buf[0], blkLength*4); // re-copy buffer one elt shifted 
530         delete [] buf;
531         buffer[indexCopy] = 0xDEAD; // mark padding word
532       } // padding condition
533
534     } // block
535     
536     //writting onto disk
537     // write DDL 1 & 2
538     fHeader.fSize = (totalDDLLength + headerSize) * 4;// total length in bytes
539     fwrite((char*)(&fHeader),headerSize*4,1,fFile[iFile]);
540     fwrite(buffer,sizeof(int),index,fFile[iFile]);
541    
542     delete[] buffer;
543   }
544
545   fTrackerTimer.Stop();
546   return kTRUE;
547 }
548
549 //____________________________________________________________________
550 Int_t AliMUONRawWriter::GetBusPatch(const AliMUONDigit& digit)
551 {
552   //
553   // Determine the BusPatch this digit belongs to.
554   //
555   fMappingTimer.Start(kFALSE);
556   
557   Int_t* ptr = 0;
558
559   // information from digits
560   Int_t detElemId  = digit.DetElemId();
561
562   AliMpVSegmentation* seg = 
563     fSegFactory->CreateMpSegmentationByElectronics(detElemId, digit.ManuId());
564   
565   AliMpPlaneType plane = seg->PlaneType();
566
567   AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
568
569   if ( stationType == kStation1 || stationType == kStation2 )
570   {
571     if (plane == kBendingPlane) 
572     {
573       ptr = &fgManuPerBusSwp1B[0];
574     }
575     else 
576     {
577       ptr = &fgManuPerBusSwp1NB[0];
578     }
579   }
580   else
581   {
582     if (plane == kBendingPlane)
583     {
584       ptr = &fgManuPerBusSwp2B[0];
585     }
586     else
587     {
588       ptr = &fgManuPerBusSwp2NB[0];
589     }
590   }
591
592   // Getting buspatch id
593   TArrayI* vec = fBusPatchManager->GetBusfromDE(detElemId);
594   Int_t pos = 0;
595
596   Int_t m = ( digit.ManuId() & 0x3FF ); // remove bit 10
597                                 //FIXME : how can we remove that condition
598   // on the 10-th bit ? All the rest need not any knowledge about it,
599   // can't we find a way to get manu<->buspatch transparent to this too ?
600   
601   if ( stationType == kStation1 || stationType == kStation2 )
602   {
603     for (Int_t i = 0; i < 12; i++)
604     {
605       if (m >= *(ptr + pos++)) break;
606     }
607   }
608   else 
609   {
610     // offset of 100 in manuId for following bus patch
611     pos = m/100;
612   }
613
614   if (pos >(Int_t) vec->GetSize())
615   {
616     AliError(Form("pos greater %d than size %d manuId %d detElemId %d \n", 
617                     pos, (Int_t)vec->GetSize(), digit.ManuId(), detElemId));
618     AliError(Form("Chamber %s Plane %s manuId %d m %d",
619                     StationTypeName(stationType).Data(),
620                     PlaneTypeName(plane).Data(),
621                     digit.ManuId(),
622                     m));
623     return -1;
624   }
625   
626   Int_t busPatchId = vec->At(pos);
627
628   fMappingTimer.Stop();
629   
630   return busPatchId;
631 }
632
633 //____________________________________________________________________
634 Int_t AliMUONRawWriter::WriteTriggerDDL()
635 {
636   //
637   // Write trigger DDL
638   //
639   fTriggerTimer.Start(kFALSE);
640   
641  // DDL event one per half chamber
642
643   // stored local id number 
644   TArrayI isFired(256);
645   isFired.Reset();
646
647
648  // DDL header size
649   Int_t headerSize = sizeof(AliRawDataHeader)/4;
650
651   TClonesArray* localTrigger;
652   TClonesArray* globalTrigger;
653   AliMUONGlobalTrigger* gloTrg;
654   AliMUONLocalTrigger* locTrg = 0x0;
655
656   // global trigger for trigger pattern
657   globalTrigger = fMUONData->GlobalTrigger(); 
658   gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
659   Int_t gloTrigPat = gloTrg->GetGlobalPattern();
660
661   // local trigger 
662   localTrigger = fMUONData->LocalTrigger();    
663
664   UInt_t word;
665   Int_t* buffer = 0;
666   Int_t index;
667   Int_t iEntries = 0;
668   Int_t iLocCard, locCard;
669   Char_t locDec, trigY, posY, posX,regOut;
670   Int_t devX;
671   Int_t version = 1; // software version
672   Int_t eventType = 1; // trigger type: 1 for physics ?
673   Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
674   Int_t globalFlag = 1; // set to 2 if global info present in DDL else set to 1
675
676   if(fScalerEvent)
677     eventType = 2; //set to generate scaler events
678
679   Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
680   // stored the local card id that's fired
681   for (Int_t i = 0; i <  nEntries; i++) {
682     locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
683     isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
684   }
685
686   if (!nEntries)
687     AliInfo("No Trigger information available");
688
689   if(fScalerEvent)
690     // [16(local)*51 words + 16 words]*8(reg) + 6 + 12 + 6 words scaler event 6672 words
691     buffer = new Int_t [6680];
692   else
693     // [16(local)*6 words + 5 words]*8(reg) + 10 words = 818 
694     buffer = new Int_t [818];
695
696
697   // open DDL file, on per 1/2 chamber
698   for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
699     
700     index = 0; 
701
702     word = 0;
703     // set darc status word
704     AliBitPacking::PackWord((UInt_t)iDDL+1,word,28,31); //see AliMUONDDLTrigger.h for details
705     AliBitPacking::PackWord((UInt_t)serialNb,word,24,27);
706     AliBitPacking::PackWord((UInt_t)version,word,16,23);
707     AliBitPacking::PackWord((UInt_t)eventType,word,12,15);
708
709     if (iDDL == 0) // suppose global info in DDL one
710       globalFlag = 2;
711     else 
712       globalFlag = 1;
713
714     AliBitPacking::PackWord((UInt_t)globalFlag,word,8,11);
715     fDarcHeader->SetWord(word);
716
717     memcpy(&buffer[index], fDarcHeader->GetHeader(), (fDarcHeader->GetDarcHeaderLength())*4); 
718     index += fDarcHeader->GetDarcHeaderLength();
719
720     if (iDDL == 0)
721      fDarcHeader->SetGlobalOutput(gloTrigPat);// no global input for the moment....
722     else 
723      fDarcHeader->SetGlobalOutput(0);
724
725     if (fScalerEvent) {
726       // 6 DARC scaler words
727       memcpy(&buffer[index], fDarcHeader->GetDarcScalers(),fDarcHeader->GetDarcScalerLength()*4);
728       index += fDarcHeader->GetDarcScalerLength();
729     }
730     // end of darc word
731     buffer[index++] = fDarcHeader->GetEndOfDarc();
732
733     // 4 words of global board input + Global board output
734     memcpy(&buffer[index], fDarcHeader->GetGlobalInput(), (fDarcHeader->GetGlobalHeaderLength())*4); 
735     index += fDarcHeader->GetGlobalHeaderLength(); 
736
737     if (fScalerEvent) {
738       // 10 Global scaler words
739       memcpy(fDarcHeader->GetGlobalScalers(), &buffer[index], fDarcHeader->GetGlobalScalerLength()*4);
740       index += fDarcHeader->GetGlobalScalerLength();
741     }
742
743     // end of global word
744     buffer[index++] = fDarcHeader->GetEndOfGlobal();
745
746     // 8 regional cards per DDL
747     for (Int_t iReg = 0; iReg < 8; iReg++) {
748
749       // Regional card header
750       word = 0;
751
752       // set darc status word
753       fRegHeader->SetDarcWord(word);
754
755       regOut  = 0;
756       AliBitPacking::PackWord((UInt_t)serialNb,word,24,28); //see  AliMUONLocalStruct.h for details
757       AliBitPacking::PackWord((UInt_t)version,word,16,23);
758       AliBitPacking::PackWord((UInt_t)iReg,word,12,15);
759       AliBitPacking::PackWord((UInt_t)regOut,word,0,7); // whenever regional output will be implemented
760
761       fRegHeader->SetWord(word);
762       memcpy(&buffer[index],fRegHeader->GetHeader(),fRegHeader->GetHeaderLength()*4);
763       index += fRegHeader->GetHeaderLength();
764
765       // 11 regional scaler word
766       if (fScalerEvent) {
767         memcpy(&buffer[index], fRegHeader->GetScalers(), fRegHeader->GetScalerLength()*4);
768         index += fRegHeader->GetScalerLength();
769       }
770
771       // end of regional word
772       buffer[index++] = fRegHeader->GetEndOfReg();
773
774       // 16 local card per regional board
775       for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
776
777         iLocCard = iLoc + iReg*16 + iDDL*128;
778
779         if (isFired[iLocCard]) {
780           locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
781           locCard = locTrg->LoCircuit();
782           locDec  = locTrg->GetLoDecision();
783           trigY = 0;
784           posY = locTrg->LoStripY();
785           posX = locTrg->LoStripX();
786           devX = locTrg->LoDev();
787           AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n", 
788                           locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
789         } else { //no trigger (see PRR chpt 3.4)
790           locCard = -1; // not possible on 4 bits
791           locDec = 0;
792           trigY = 1;
793           posY = 15;
794           posX = 0;
795           devX = 0x8;
796         }
797
798         //packing word
799         word = 0;
800         AliBitPacking::PackWord((UInt_t)(iLocCard % 16),word,19,22); //card id number in crate
801         AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
802         AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
803         AliBitPacking::PackWord((UInt_t)posY,word,10,13);
804         AliBitPacking::PackWord((UInt_t)devX,word,5,9);
805         AliBitPacking::PackWord((UInt_t)posX,word,0,4);
806
807         if (locCard == iLocCard) {
808           // add local cards structure
809           buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
810           buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
811           buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
812           buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
813           buffer[index++] = (Int_t)word; // data word
814           if (iEntries < nEntries-1)
815             iEntries++;
816         } else {
817           buffer[index++] = 0; // 4 words for x1, x2, y1, y2
818           buffer[index++] = 0; 
819           buffer[index++] = 0; 
820           buffer[index++] = 0; 
821           buffer[index++] = (Int_t)word; // data word
822
823         }
824         // 45 regional scaler word
825         if (fScalerEvent) {
826           memcpy(&buffer[index], fLocalStruct->GetScalers(), fLocalStruct->GetScalerLength()*4);
827           index += fLocalStruct->GetScalerLength();
828         }
829
830         // end of local structure words
831         buffer[index++] = fLocalStruct->GetEndOfLocal();
832
833       } // local card 
834
835     } // Regional card
836     
837
838     // writting onto disk
839     // write DDL 1
840     fHeader.fSize = (index + headerSize) * 4;// total length in bytes
841     fwrite((char*)(&fHeader),headerSize*4,1,fFile[iDDL]);
842     fwrite(buffer,sizeof(int),index,fFile[iDDL]);
843   
844   }
845   delete[] buffer;
846
847   fTriggerTimer.Stop();
848   
849   return kTRUE;
850 }