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