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