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