Optimized rawdata reconstruction & removing effc++ warnings (Christian)
[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 // Using bus itr in DDL instead of simple incrementation
37 // treat correctly the DDL & buspatch for station 3.
38 // Using informations from AliMUONTriggerCrateStore for 
39 // empty slots and non-notified cards in trigger crates.
40 // Ch. Finck, August 06.
41 // 
42 ////////////////////////////////////
43
44 #include "AliMUONRawWriter.h"
45
46 #include "AliBitPacking.h" 
47 #include "AliRawReader.h"
48 #include "AliDAQ.h"
49 #include "AliLog.h"
50 #include "AliMUON.h"
51 #include "AliMUONConstants.h"
52
53 #include "AliMUONDarcHeader.h"
54 #include "AliMUONRegHeader.h"
55 #include "AliMUONLocalStruct.h"
56 #include "AliMUONDspHeader.h"
57 #include "AliMUONBlockHeader.h"
58
59 #include "AliMUONData.h"
60 #include "AliMUONDigit.h"
61 #include "AliMUONGlobalTrigger.h"
62 #include "AliMUONLocalTrigger.h"
63
64 #include "AliMpBusPatch.h"
65 #include "AliMUONTriggerCrateStore.h"
66 #include "AliMUONTriggerCrate.h"
67 #include "AliMUONLocalTriggerBoard.h"
68
69 #include "AliMpDEManager.h"
70 #include "AliMpPad.h"
71 #include "AliMpPlaneType.h"
72 #include "AliMpSegFactory.h"
73 #include "AliMpStationType.h"
74 #include "AliMpVSegmentation.h"
75
76 #include "TClonesArray.h"
77 #include "TObjArray.h"
78
79 ClassImp(AliMUONRawWriter) // Class implementation in ROOT context
80
81 Int_t AliMUONRawWriter::fgManuPerBusSwp1B[12]  = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 224, 232};
82 Int_t AliMUONRawWriter::fgManuPerBusSwp1NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 225, 233};
83
84 Int_t AliMUONRawWriter::fgManuPerBusSwp2B[12]  = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 226, 246};
85 Int_t AliMUONRawWriter::fgManuPerBusSwp2NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 227, 245};
86
87
88 //__________________________________________________________________________
89 AliMUONRawWriter::AliMUONRawWriter(AliMUONData* data)
90   : TObject(),
91     fMUONData(data),
92     fBusArray(new TClonesArray("AliMUONBusStruct",1000)),
93     fBlockHeader(new AliMUONBlockHeader()),
94     fDspHeader(new AliMUONDspHeader()),
95     fBusStruct(new AliMUONBusStruct()),
96     fDarcHeader(new AliMUONDarcHeader()),
97     fRegHeader(new AliMUONRegHeader()),
98     fLocalStruct(new AliMUONLocalStruct()),
99     fBusPatchManager(new AliMpBusPatch()),
100     fCrateManager(new AliMUONTriggerCrateStore()),
101     fScalerEvent(kFALSE),
102     fHeader(),
103     fTrackerTimer(),
104     fTriggerTimer(),
105     fMappingTimer(),
106     fSegFactory(new AliMpSegFactory())
107
108 {
109   //
110   // Standard Constructor
111   //
112   AliDebug(1,"Standard ctor");
113   fFile[0] = fFile[1] = 0x0;  
114   fFile[2] = fFile[3] = 0x0;  
115
116   // initialize array
117   fBusArray->SetOwner(kTRUE);
118
119   // setting data key to default value (only for writting)
120   fBlockHeader->SetDataKey(fBlockHeader->GetDefaultDataKey());
121   fDspHeader->SetDataKey(fDspHeader->GetDefaultDataKey());
122   fBusStruct->SetDataKey(fBusStruct->GetDefaultDataKey());
123
124   // bus patch managers
125   fBusPatchManager->ReadBusPatchFile();
126
127   // Crate manager
128   fCrateManager->ReadFromFile();
129
130   // timers
131   fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
132   fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
133   fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
134   
135 }
136
137 //__________________________________________________________________________
138 AliMUONRawWriter::AliMUONRawWriter()
139   : TObject(),
140     fMUONData(0),
141     fBusArray(0),
142     fBlockHeader(0),
143     fDspHeader(0),
144     fBusStruct(0),
145     fDarcHeader(0),
146     fRegHeader(0),
147     fLocalStruct(0),
148     fBusPatchManager(0),
149     fCrateManager(0x0),
150     fScalerEvent(kFALSE),
151     fHeader(),
152     fTrackerTimer(),
153     fTriggerTimer(),
154     fMappingTimer(),
155     fSegFactory(0x0)
156 {
157   //
158   // Default Constructor
159   //
160   AliDebug(1,"Default ctor");   
161   fFile[0] = fFile[1] = 0x0;  
162   fFile[2] = fFile[3] = 0x0;  
163
164   fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
165   fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
166   fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
167 }
168
169 //__________________________________________________________________________
170 AliMUONRawWriter::~AliMUONRawWriter(void)
171 {
172   //
173   // Destructor
174   //
175   AliDebug(1,"dtor");
176   
177   delete fBusArray;
178   
179   delete fBlockHeader;
180   delete fDspHeader;
181   delete fBusStruct;
182   delete fDarcHeader;
183   delete fRegHeader;
184   delete fLocalStruct;
185
186   delete fBusPatchManager;
187   delete fCrateManager;
188
189   delete fSegFactory;
190   
191   AliInfo(Form("Execution time for MUON tracker : R:%.2fs C:%.2fs",
192                fTrackerTimer.RealTime(),fTrackerTimer.CpuTime()));
193   AliInfo(Form("   Execution time for MUON tracker (mapping calls part) "
194                ": R:%.2fs C:%.2fs",
195                fMappingTimer.RealTime(),fMappingTimer.CpuTime()));
196   AliInfo(Form("Execution time for MUON trigger : R:%.2fs C:%.2fs",
197                fTriggerTimer.RealTime(),fTriggerTimer.CpuTime()));
198 }
199
200 //____________________________________________________________________
201 Int_t AliMUONRawWriter::Digits2Raw()
202 {
203   //
204   // convert digits of the current event to raw data
205   //
206   Int_t idDDL;
207   Char_t name[255];
208
209   fMUONData->GetLoader()->LoadDigits("READ");
210
211   fMUONData->SetTreeAddress("D,GLT");
212
213   fMUONData->ResetDigits();
214   fMUONData->ResetTrigger();
215   
216   // This will get both tracker and trigger digits.
217   fMUONData->GetDigits();
218   
219   // tracking chambers
220
221   for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; iSt++) {
222
223     // open files for one station
224     // cos station 3, 1/4 of DE's from 2 chambers has same DDL number 
225     idDDL = iSt * 4;
226     strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
227     fFile[0] = fopen(name,"w");
228
229     idDDL = (iSt * 4) + 1;
230     strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
231     fFile[1] = fopen(name,"w");
232
233     idDDL =  (iSt * 4) + 2;;
234     strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
235     fFile[2] = fopen(name,"w");
236
237     idDDL =  (iSt * 4) + 3;
238     strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
239     fFile[3] = fopen(name,"w");
240
241     WriteTrackerDDL(iSt);
242   
243     // reset and close when station has been processed
244     fclose(fFile[0]);
245     fclose(fFile[1]);
246     fclose(fFile[2]);
247     fclose(fFile[3]);
248      
249   }
250  
251   // trigger chambers
252  
253   // open files
254   idDDL = 0;// MUTR
255   strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
256   fFile[0] = fopen(name,"w");
257
258   idDDL = 1;// MUTR
259   strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
260   fFile[1] = fopen(name,"w");
261
262   WriteTriggerDDL();
263   
264   // reset and close
265   fclose(fFile[0]);
266   fclose(fFile[1]);
267
268   fMUONData->ResetDigits();
269   fMUONData->ResetTrigger();  
270   fMUONData->GetLoader()->UnloadDigits();
271
272   return kTRUE;
273 }
274
275 //____________________________________________________________________
276 Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iSt)
277 {
278   // writing DDL for tracker
279   // used inverse mapping
280   //
281   fTrackerTimer.Start(kFALSE);
282   
283
284   static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
285
286   // resets
287   TClonesArray* muonDigits = 0;
288
289   fBusArray->Delete();
290
291
292   //
293   TArrayI nbInBus;
294
295   nbInBus.Set(5000);
296
297   nbInBus.Reset();
298
299   // DDL header
300   Int_t headerSize = sizeof(fHeader)/4;
301
302   // DDL event one per half chamber
303
304   // raw data
305   Char_t parity = 0x4;
306   UShort_t manuId = 0;
307   UChar_t channelId = 0;
308   UShort_t charge = 0;
309   Int_t busPatchId = 0;
310   UInt_t word;
311
312
313   // Dsp length
314   Int_t totalDspLength;
315   Int_t dspLength;
316
317   // block length
318   Int_t totalBlkLength;
319   Int_t blkLength; 
320   
321   // total DDL length
322   Int_t totalDDLLength;
323
324   // indexes
325   Int_t index;
326   Int_t indexDsp;
327   Int_t indexBlk;
328
329   // digits
330   Int_t nEntries = 0;
331   Int_t* buffer = 0;
332   Int_t padX;
333   Int_t padY;
334   Int_t cathode = 0;
335   Int_t detElemId;
336   Int_t nDigits;
337
338   const AliMUONDigit* digit;
339
340   for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; iCh++) {
341
342     muonDigits = fMUONData->Digits(iCh);
343
344     nDigits = muonDigits->GetEntriesFast();
345     AliDebug(3,Form("ndigits = %d\n",nDigits));
346  
347     // loop over digit
348     for (Int_t idig = 0; idig < nDigits; idig++) {
349
350       digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
351
352       padX = digit->PadX();
353       padY = digit->PadY();
354       charge = digit->ADC();
355       if ( charge > kMAXADC )
356         {
357           // This is most probably an error in the digitizer (which should insure
358           // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
359           AliError(Form("adc value %d above %x. Setting to %x",
360                         charge,kMAXADC,kMAXADC));
361           charge = kMAXADC;
362         }
363       cathode = digit->Cathode();
364       detElemId = digit->DetElemId();
365
366       // inverse mapping
367       busPatchId = GetBusPatch(*digit);
368       if (busPatchId<0) continue;
369
370       if ( digit->ManuId() > 0x7FF || digit->ManuId() < 0 ||
371            digit->ManuChannel() > 0x3F || digit->ManuChannel() < 0 )
372         {
373           StdoutToAliError(digit->Print(););
374           AliFatal("ManuId,ManuChannel are invalid for the digit above.");
375         }
376     
377       manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
378       channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
379
380       AliDebug(3,Form("input  IdDE %d busPatchId %d PadX %d PadY %d iCath %d \n", 
381                       detElemId, busPatchId, padX, padY, cathode));
382
383       AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", busPatchId, manuId, 
384                       channelId ));
385
386       //packing word
387       word = 0;
388       AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
389       AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
390       AliBitPacking::PackWord((UInt_t)charge,word,0,11);
391
392       // parity word
393       parity = word & 0x1;
394       for (Int_t i = 1; i <= 30; i++) 
395         parity ^=  ((word >> i) & 0x1);
396       AliBitPacking::PackWord((UInt_t)parity,word,31,31);
397
398       // set sub Event
399       fBusStruct->SetLength(0);
400       fBusStruct->AddData(word);
401       fBusStruct->SetBusPatchId(busPatchId);
402        
403       // storing the number of identical buspatches
404       nbInBus[busPatchId]++;
405       AddData(*fBusStruct);
406    
407     }
408   } // loop over chamber in station
409
410   // sorting by buspatch
411   fBusArray->Sort();
412
413   // gather datas from same bus patch
414   nEntries = fBusArray->GetEntriesFast();
415
416   for (Int_t i = 0; i < nEntries; i++) {
417     AliMUONBusStruct* temp = (AliMUONBusStruct*)fBusArray->At(i);
418     busPatchId = temp->GetBusPatchId();
419
420     // add bus patch header, length and total length managed by subevent class
421     for (Int_t j = 0; j < nbInBus[busPatchId]-1; j++) {
422       AliMUONBusStruct* temp1 =  (AliMUONBusStruct*)fBusArray->At(++i);
423       temp->AddData(temp1->GetData(0));
424       fBusArray->RemoveAt(i) ;
425     }
426   }
427   fBusArray->Compress();
428
429   if (AliLog::GetGlobalDebugLevel() == 3) {
430     nEntries = fBusArray->GetEntriesFast();
431     for (Int_t i = 0; i < nEntries; i++) {
432       AliMUONBusStruct* temp =  (AliMUONBusStruct*)fBusArray->At(i);
433       printf("busPatchid back %d\n",temp->GetBusPatchId());
434       for (Int_t j = 0; j < temp->GetLength(); j++) {
435         printf("manuId back %d, ",temp->GetManuId(j));
436         printf("channelId back %d, ",temp->GetChannelId(j));
437         printf("charge back %d\n",temp->GetCharge(j));
438       }
439     }
440     printf("\n");
441   }
442   // end of TreeD reading and storing in TClonesArray
443   
444   // getting info for the number of buspatches
445   Int_t iBusPatch;
446   Int_t length;
447   Int_t iBusPerDSP[5];//number of bus patches per DSP
448   Int_t iDspMax; //number max of DSP per block
449   Int_t iFile = 0;
450
451   Int_t rEntry = -1;
452   AliMUONBusStruct* busStructPtr = 0x0;
453
454   // open DDL files, 4 per station
455   for (Int_t iDDL = iSt*4; iDDL < 4 + iSt*4; iDDL++) {
456
457     fBusPatchManager->ResetBusItr(iDDL);
458     fBusPatchManager->GetDspInfo(iDDL, iDspMax, iBusPerDSP);
459
460     totalDDLLength = 0;
461
462     // buffer size
463     // ((43 manus max*64 ch + 4 bus word) * 5 DSPs + 10 DSP word) * 2 blocks + 8 block words = 27588
464     static const Int_t kBufferSize = ((43*64 + 4)*5 + 10)*2 + 8;
465
466     // buffer allocation
467     buffer = new Int_t [kBufferSize];
468
469     indexBlk = 0;
470     indexDsp = 0;
471     index = 0;
472
473     // two blocks A and B per DDL
474     for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
475
476       // block header
477       length = fBlockHeader->GetHeaderLength();
478       memcpy(&buffer[index],fBlockHeader->GetHeader(),length*4);
479       indexBlk = index;
480       index += length; 
481
482       // 5 DSP's max per block
483       for (Int_t iDsp = 0; iDsp < iDspMax; iDsp++) {
484
485         // DSP header
486         length = fDspHeader->GetHeaderLength();
487         memcpy(&buffer[index],fDspHeader->GetHeader(),length*4);
488         indexDsp = index;
489         index += length; 
490
491         // 5 buspatches max per DSP
492         for (Int_t i = 0; i < iBusPerDSP[iDsp]; i++) {
493
494           // iteration over bus patch in DDL
495           if ((iBusPatch = fBusPatchManager->NextBusInDDL(iDDL)) == -1) {
496             AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
497             continue;
498           }
499
500           // 4 DDL's per station, condition needed for station 3
501           iFile = iDDL - iSt*4; // works only if DDL begins at zero (as it should be) !!!
502
503           AliDebug(3,Form("iSt %d iDDL %d iBlock %d iDsp %d busPatchId %d", iSt, iDDL, iBlock, 
504                           iDsp, iBusPatch));
505
506           nEntries = fBusArray->GetEntriesFast();
507           busPatchId = -1;
508
509           // checking buspatch structure not empty
510           for (Int_t iEntry = 0; iEntry < nEntries; iEntry++) { // method "bourrique"...
511             busStructPtr = (AliMUONBusStruct*)fBusArray->At(iEntry);
512             busPatchId = busStructPtr->GetBusPatchId();
513             if (busPatchId == iBusPatch) {
514               rEntry = iEntry;
515               break;
516             }
517             busPatchId = -1;
518             AliDebug(3,Form("busPatchId %d", busStructPtr->GetBusPatchId()));
519           } 
520          
521           // check if buspatchid has digit
522           if (busPatchId != -1) {
523             // add bus patch structure header
524             length = busStructPtr->GetHeaderLength();
525             memcpy(&buffer[index],busStructPtr->GetHeader(),length*4);
526             index += length;
527
528             // add bus patch data
529             length = busStructPtr->GetLength();
530             memcpy(&buffer[index],busStructPtr->GetData(),length*4);
531             index += length;
532
533             if (AliLog::GetGlobalDebugLevel() == 3) {
534               for (Int_t j = 0; j < busStructPtr->GetLength(); j++) {
535                 printf("busPatchId %d, manuId %d channelId %d\n", busStructPtr->GetBusPatchId(), 
536                        busStructPtr->GetManuId(j), busStructPtr->GetChannelId(j));
537               }
538             }
539             
540             fBusArray->RemoveAt(rEntry);
541             fBusArray->Compress();
542           } else {
543             // writting anyhow buspatch structure (empty ones)
544             buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
545             buffer[index++] = busStructPtr->GetHeaderLength(); // header length
546             buffer[index++] = 0; // raw data length
547             buffer[index++] = iBusPatch; // bus patch
548           }
549         } // bus patch
550
551         // check if totalLength even
552         // set padding word in case
553         // Add one word 0xBEEFFACE at the end of DSP structure
554         totalDspLength  = index - indexDsp;
555         if ((totalDspLength % 2) == 1) { 
556           buffer[indexDsp + fDspHeader->GetHeaderLength() - 2] = 1;
557           buffer[index++] = fDspHeader->GetDefaultPaddingWord();
558           totalDspLength++;
559         }
560
561         dspLength          = totalDspLength - fDspHeader->GetHeaderLength();
562
563         buffer[indexDsp+1] = totalDspLength; // dsp total length
564         buffer[indexDsp+2] = dspLength; // data length  
565            
566       } // dsp
567
568       totalBlkLength  = index - indexBlk;
569       blkLength       = totalBlkLength - fBlockHeader->GetHeaderLength();
570       totalDDLLength += totalBlkLength;
571
572       buffer[indexBlk+1] = totalBlkLength; // total block length
573       buffer[indexBlk+2] = blkLength;
574
575     } // block
576     
577     //writting onto disk
578     // write DDL 1 - 4
579     fHeader.fSize = (totalDDLLength + headerSize) * 4;// total length in bytes
580     fwrite((char*)(&fHeader),headerSize*4,1,fFile[iFile]);
581     fwrite(buffer,sizeof(int),index,fFile[iFile]);
582    
583     delete[] buffer;
584   }
585
586   fTrackerTimer.Stop();
587   return kTRUE;
588 }
589
590 //____________________________________________________________________
591 Int_t AliMUONRawWriter::GetBusPatch(const AliMUONDigit& digit)
592 {
593   //
594   // Determine the BusPatch this digit belongs to.
595   //
596   fMappingTimer.Start(kFALSE);
597   
598   Int_t* ptr = 0;
599
600   // information from digits
601   Int_t detElemId  = digit.DetElemId();
602
603   AliMpVSegmentation* seg = 
604     fSegFactory->CreateMpSegmentationByElectronics(detElemId, digit.ManuId());
605   
606   AliMpPlaneType plane = seg->PlaneType();
607
608   AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
609
610   if ( stationType == kStation1 || stationType == kStation2 )
611   {
612     if (plane == kBendingPlane) 
613     {
614       ptr = &fgManuPerBusSwp1B[0];
615     }
616     else 
617     {
618       ptr = &fgManuPerBusSwp1NB[0];
619     }
620   }
621   else
622   {
623     if (plane == kBendingPlane)
624     {
625       ptr = &fgManuPerBusSwp2B[0];
626     }
627     else
628     {
629       ptr = &fgManuPerBusSwp2NB[0];
630     }
631   }
632
633   // Getting buspatch id
634   TArrayI* vec = fBusPatchManager->GetBusfromDE(detElemId);
635   Int_t pos = 0;
636
637   Int_t m = ( digit.ManuId() & 0x3FF ); // remove bit 10
638                                 //FIXME : how can we remove that condition
639   // on the 10-th bit ? All the rest need not any knowledge about it,
640   // can't we find a way to get manu<->buspatch transparent to this too ?
641   
642   if ( stationType == kStation1 || stationType == kStation2 )
643   {
644     for (Int_t i = 0; i < 12; i++)
645     {
646       if (m >= *(ptr + pos++)) break;
647     }
648   }
649   else 
650   {
651     // offset of 100 in manuId for following bus patch
652     pos = m/100;
653   }
654
655   if (pos >(Int_t) vec->GetSize())
656   {
657     AliError(Form("pos greater %d than size %d manuId %d detElemId %d \n", 
658                     pos, (Int_t)vec->GetSize(), digit.ManuId(), detElemId));
659     AliError(Form("Chamber %s Plane %s manuId %d m %d",
660                     StationTypeName(stationType).Data(),
661                     PlaneTypeName(plane).Data(),
662                     digit.ManuId(),
663                     m));
664     return -1;
665   }
666   
667   Int_t busPatchId = vec->At(pos);
668
669   fMappingTimer.Stop();
670   
671   return busPatchId;
672 }
673
674 //____________________________________________________________________
675 Int_t AliMUONRawWriter::WriteTriggerDDL()
676 {
677   //
678   // Write trigger DDL
679   //
680   fTriggerTimer.Start(kFALSE);
681   
682  // DDL event one per half chamber
683
684   // stored local id number 
685   TArrayI isFired(256);
686   isFired.Reset();
687
688
689  // DDL header size
690   Int_t headerSize = sizeof(AliRawDataHeader)/4;
691
692   TClonesArray* localTrigger;
693   TClonesArray* globalTrigger;
694   AliMUONGlobalTrigger* gloTrg;
695   AliMUONLocalTrigger* locTrg = 0x0;
696
697   // global trigger for trigger pattern
698   globalTrigger = fMUONData->GlobalTrigger(); 
699   gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
700   Int_t gloTrigPat = gloTrg->GetGlobalPattern();
701
702   // local trigger 
703   localTrigger = fMUONData->LocalTrigger();    
704
705   UInt_t word;
706   Int_t* buffer = 0;
707   Int_t index;
708   Int_t iEntries = 0;
709   Int_t iLocCard, locCard;
710   Char_t locDec, trigY, posY, posX, regOut;
711   UInt_t regInpLpt;
712   UInt_t regInpHpt;
713
714   Int_t devX;
715   Int_t version = 1; // software version
716   Int_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
717   Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
718   Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
719
720   // size of headers
721   static const Int_t kDarcHeaderLength   = fDarcHeader->GetDarcHeaderLength();
722   static const Int_t kGlobalHeaderLength = fDarcHeader->GetGlobalHeaderLength();
723   static const Int_t kDarcScalerLength   = fDarcHeader->GetDarcScalerLength();
724   static const Int_t kGlobalScalerLength = fDarcHeader->GetGlobalScalerLength();
725   static const Int_t kRegHeaderLength    = fRegHeader->GetHeaderLength();
726   static const Int_t kRegScalerLength    = fRegHeader->GetScalerLength();
727   static const Int_t kLocHeaderLength    = fLocalStruct->GetLength();
728   static const Int_t kLocScalerLength    = fLocalStruct->GetScalerLength();
729
730   // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824 
731   static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) +  (kRegHeaderLength+1))* 8 
732       +  kDarcHeaderLength + kGlobalHeaderLength + 2;
733
734   // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
735   static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength +  kLocScalerLength +1) +  
736                                          (kRegHeaderLength + kRegScalerLength +1))* 8 +
737                                          (kDarcHeaderLength + kDarcScalerLength + 
738                                           kGlobalHeaderLength + kGlobalScalerLength + 2);
739   if(fScalerEvent)
740     eventPhys = 0; //set to generate scaler events
741
742   Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
743   // stored the local card id that's fired
744   for (Int_t i = 0; i <  nEntries; i++) {
745     locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
746     isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
747   }
748
749   if (!nEntries)
750     AliInfo("No Trigger information available");
751
752   if(fScalerEvent)
753     buffer = new Int_t [kScalerBufferSize];
754   else
755     buffer = new Int_t [kBufferSize];
756
757   // reset crate
758
759   // open DDL file, on per 1/2 chamber
760   for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
761
762     index = 0; 
763
764     if (iDDL == 0) // suppose global info in DDL one
765       globalFlag = 1;
766     else 
767       globalFlag = 0;
768
769     word = 0;
770     // set darc status word
771     // see AliMUONDarcHeader.h for details
772     AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
773     AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
774     AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
775     AliBitPacking::PackWord((UInt_t)version,word,12,19);
776     fDarcHeader->SetWord(word);
777
778     memcpy(&buffer[index], fDarcHeader->GetHeader(), (kDarcHeaderLength)*4); 
779     index += kDarcHeaderLength;
780
781     if (iDDL == 0)
782      fDarcHeader->SetGlobalOutput(gloTrigPat);// no global input for the moment....
783     else 
784      fDarcHeader->SetGlobalOutput(0);
785
786     if (fScalerEvent) {
787       // 6 DARC scaler words
788       memcpy(&buffer[index], fDarcHeader->GetDarcScalers(),kDarcScalerLength*4);
789       index += kDarcScalerLength;
790     }
791     // end of darc word
792     buffer[index++] = fDarcHeader->GetEndOfDarc();
793
794     // 4 words of global board input + Global board output
795     memcpy(&buffer[index], fDarcHeader->GetGlobalInput(), (kGlobalHeaderLength)*4); 
796     index += kGlobalHeaderLength; 
797
798     if (fScalerEvent) {
799       // 10 Global scaler words
800       memcpy(fDarcHeader->GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
801       index += kGlobalScalerLength;
802     }
803
804     // end of global word
805     buffer[index++] = fDarcHeader->GetEndOfGlobal();
806
807     // 8 regional cards per DDL
808     for (Int_t iReg = 0; iReg < 8; iReg++) {
809
810       // crate info
811       AliMUONTriggerCrate* crate = fCrateManager->Crate(iDDL, iReg);
812
813       if (!crate) 
814         AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
815
816       // Regional card header
817       word = 0;
818
819       // set darc status word
820       fRegHeader->SetDarcWord(word);
821
822       regOut    = 0;
823       regInpHpt = regInpLpt = 0;
824       // fill darc word, not darc status for the moment (empty)
825       //see  AliMUONRegHeader.h for details
826       AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31); 
827       AliBitPacking::PackWord((UInt_t)serialNb,word,19,24); 
828       AliBitPacking::PackWord((UInt_t)version,word,16,23);
829       AliBitPacking::PackWord((UInt_t)iReg,word,15,18);
830       AliBitPacking::PackWord((UInt_t)regOut,word,0,7); // waiting realistic output of AliMUONGlobalTrigger (oct 06 ?)
831       fRegHeader->SetWord(word);
832
833
834       // fill header later, need local response
835       Int_t indexReg = index;
836       index += kRegHeaderLength;
837
838       // 11 regional scaler word
839       if (fScalerEvent) {
840         memcpy(&buffer[index], fRegHeader->GetScalers(), kRegScalerLength*4);
841         index += kRegScalerLength;
842       }
843
844       // end of regional word
845       buffer[index++] = fRegHeader->GetEndOfReg();
846       
847       TObjArray *boards = crate->Boards();
848
849
850       // 16 local card per regional board
851       UShort_t localMask = 0x0;
852
853       for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
854
855         // slot zero for Regional card
856         AliMUONLocalTriggerBoard* localBoard = (AliMUONLocalTriggerBoard*)boards->At(iLoc+1);
857
858         if (localBoard) { // if not empty slot
859
860           if ((iLocCard = localBoard->GetNumber()) != 0) {// if notified board
861
862             localMask |= (0x1 << iLoc); // local mask
863             if (isFired[iLocCard]) { // if card has triggered
864               locTrg  = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
865               locCard = locTrg->LoCircuit();
866               locDec  = locTrg->GetLoDecision();
867               trigY = 0;
868               posY  = locTrg->LoStripY();
869               posX  = locTrg->LoStripX();
870               devX  = locTrg->LoDev();
871
872               AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n", 
873                               locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
874             } else { //no trigger (see PRR chpt 3.4)
875               locDec = 0;
876               trigY = 1;
877               posY = 15;
878               posX = 0;
879               devX = 0x8;
880               // set local card id to -1
881               locCard = -1; 
882             }
883             // calculate regional input High and low Pt
884             UInt_t tmp1 = (locDec >> 2) & 0x3;
885             UInt_t tmp2 =  locDec & 0x3;
886             
887             regInpHpt |= tmp1 << (30 - iLoc*2);
888             regInpLpt |= tmp2 << (30 - iLoc*2);
889            
890             //packing word
891             word = 0;
892             AliBitPacking::PackWord((UInt_t)iLoc,word,19,22); //card id number in crate
893             AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
894             AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
895             AliBitPacking::PackWord((UInt_t)posY,word,10,13);
896             AliBitPacking::PackWord((UInt_t)devX,word,5,9);
897             AliBitPacking::PackWord((UInt_t)posX,word,0,4);
898
899             if (locCard == iLocCard) {
900               // add local cards structure
901               buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
902               buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
903               buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
904               buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
905               buffer[index++] = (Int_t)word; // data word
906               if (iEntries < nEntries-1)
907                 iEntries++;
908             } else {
909               buffer[index++] = 0; // 4 words for x1, x2, y1, y2
910               buffer[index++] = 0; 
911               buffer[index++] = 0; 
912               buffer[index++] = 0; 
913               buffer[index++] = (Int_t)word; // data word
914
915             }
916           } else {// number!=0
917           // fill with 10CDEAD word for 'non-notified' slots
918           for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
919             buffer[index++] = fLocalStruct->GetDisableWord(); 
920           }
921         } else { 
922           // fill with 10CDEAD word for empty slots
923           for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
924             buffer[index++] = fLocalStruct->GetDisableWord(); 
925         }// condition localBoard
926
927         // 45 regional scaler word
928         if (fScalerEvent) {
929           memcpy(&buffer[index], fLocalStruct->GetScalers(), kLocScalerLength*4);
930           index += kLocScalerLength;
931         }
932
933         // end of local structure words
934         buffer[index++] = fLocalStruct->GetEndOfLocal();
935
936       } // local card 
937       // fill regional header with local output
938       fRegHeader->SetInput(regInpLpt, 0);
939       fRegHeader->SetInput(regInpHpt, 1);
940       fRegHeader->SetMask(localMask);
941       memcpy(&buffer[indexReg],fRegHeader->GetHeader(),kRegHeaderLength*4);
942
943     } // Regional card
944     
945
946     // writting onto disk
947     // write DDL's
948     fHeader.fSize = (index + headerSize) * 4;// total length in bytes
949     fwrite((char*)(&fHeader),headerSize*4,1,fFile[iDDL]);
950     fwrite(buffer,sizeof(int),index,fFile[iDDL]);
951   
952   }
953   delete[] buffer;
954
955   fTriggerTimer.Stop();
956   
957   return kTRUE;
958 }
959 //____________________________________________________________________
960 void AliMUONRawWriter::SetScalersNumbers()
961 {
962   // set numbers for scaler events for trigger headers
963   // since this is provided by the experiment
964   // put dummy numbers to check the monitoring
965
966   fDarcHeader->SetScalersNumbers();
967   fRegHeader->SetScalersNumbers();
968   fLocalStruct->SetScalersNumbers();
969  
970   fScalerEvent = kTRUE;
971 }
972