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