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