]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTriggerIO.cxx
new QA plot (nunmber of clusters/track/species) by AlexW
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerIO.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 #include "AliMUONTriggerIO.h"
19 #include "AliMUONTriggerLut.h"
20 #include "AliMUONCalibParamNI.h"
21 #include "AliMUONVStore.h"
22
23 #include "AliMpCDB.h"
24 #include "AliMpHelper.h"
25 #include "AliMpConstants.h"
26 #include "AliMpDDL.h"
27 #include "AliMpFiles.h"
28 #include "AliMpDDLStore.h"
29 #include "AliMpLocalBoard.h"
30 #include "AliMpTriggerCrate.h"
31 #include "AliMUONGlobalCrateConfig.h"
32 #include "AliMUONRegionalTriggerConfig.h"
33 #include "AliMUONTriggerCrateConfig.h"
34
35 #include "AliLog.h"
36
37 #include <Riostream.h>
38 #include <TSystem.h>
39
40 /// \class AliMUONTriggerIO
41 ///
42 /// Handles read/write of masks and LUT to/from online files, 
43 /// to be used by Shuttle and Trigger DA.
44 /// 
45 /// \author Laurent Aphecetche, Christian Finck Subatech
46 /// \author Bogdan Vulpescu, LPC Clermont-Ferrand
47
48 /// \cond CLASSIMP
49 ClassImp(AliMUONTriggerIO)
50 /// \endcond
51
52
53 const UInt_t AliMUONTriggerIO::fgkLocalLutSize = 1 << 14; // 16384
54
55 //_____________________________________________________________________________
56 AliMUONTriggerIO::AliMUONTriggerIO() 
57     : TObject(), 
58       fRegionalTrigger()
59 {
60   /// ctor
61 }
62
63 //_____________________________________________________________________________
64 AliMUONTriggerIO::AliMUONTriggerIO(const char* regionalFileToRead) 
65     :TObject(), 
66      fRegionalTrigger()
67 {
68   /// ctor
69   ReadRegionalConfig(regionalFileToRead,0);
70 }
71
72 //_____________________________________________________________________________
73 AliMUONTriggerIO::~AliMUONTriggerIO()
74 {
75   /// dtor
76 }
77
78 //_____________________________________________________________________________
79 Bool_t 
80 AliMUONTriggerIO::DeCompAddress(UChar_t &ypos, UChar_t &ytri, UChar_t &xdev, UChar_t &xpos, 
81                                 UShort_t address) const
82 {  
83   /// decompose the 15-bits address
84   
85   UChar_t bitsYpos = 4;
86   UChar_t bitsYtri = 1;
87   UChar_t bitsXdev = 5;
88   //  UChar_t bitsXpos = 5;
89   
90   UShort_t maskYpos = 0x000F; // ...0 00001111
91   UShort_t maskYtri = 0x0001; // ...0 00000001
92   UShort_t maskXdev = 0x001F; // ...0 00011111
93   UShort_t maskXpos = 0x001F; // ...0 00011111
94   
95   ypos =  address                                  & maskYpos;
96   ytri = (address >>  bitsYpos)                    & maskYtri;
97   xdev = (address >> (bitsYpos+bitsYtri))          & maskXdev;
98   xpos = (address >> (bitsYpos+bitsYtri+bitsXdev)) & maskXpos;
99
100   // convert deviation format
101   // online: sign 1bit , dev 4bit
102   // sign    dev    trigger
103   // 0       1-15   mu-
104   // 1       1-15   mu+
105   // 0       0      mu+, mu- infinite momentum (unde)
106   // 1       0      no x-trigger
107   // offline: dev 5bit
108   // sign    dev    trigger
109   // -        0-14  mu-
110   // -       16-31  mu+
111   // -       15     mu+, mu- infinite momentum (unde)
112
113   Int_t iXdevOff, iXdevOn, iXdev, sign;
114   Bool_t trigx;
115
116   iXdev = xdev;
117
118   iXdevOn = sign = 0;
119   iXdevOn +=  iXdev & 0x0F;
120   sign    += (iXdev >> 4) & 0x01;
121   if (iXdevOn == 0) {
122     if (sign == 0) {
123       iXdevOff = 15;
124       trigx = kTRUE;
125     } else {
126       iXdevOff = 15;
127       trigx = kFALSE;
128     }
129   } else {
130     trigx = kTRUE;
131     if (sign == 0) {
132       iXdevOff = - iXdevOn + 15;  // gives range  0-14
133     } else {
134       iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
135     }
136   }
137
138   xdev = iXdevOff;
139
140   return trigx;
141
142 }
143
144 //_____________________________________________________________________________
145 void 
146 AliMUONTriggerIO::FillLut(AliMUONTriggerLut& lut,
147                           Int_t icirc, UChar_t istripX, UChar_t idev,  
148                           Int_t lutLpt[16][2], Int_t lutHpt[16][2]) 
149 {
150   /// Fill the LUT histograms
151   
152   if (icirc == 0 && istripX == 0 && idev == 0) 
153   {
154     AliDebug(1,"Copy board, not filled ...");
155     return;
156   }
157   
158   Short_t iLptPlus, iLptMinu, iLptUnde;
159   Short_t iHptPlus, iHptMinu, iHptUnde;
160
161   iLptPlus = iLptMinu = iLptUnde = 0;
162   iHptPlus = iHptMinu = iHptUnde = 0;
163   
164   for (Int_t istripY=0; istripY<16; istripY++) 
165   {
166     if (lutLpt[istripY][1] == 0 && lutLpt[istripY][0] ==1)
167       iLptMinu=iLptMinu+(1 << istripY);
168     if (lutLpt[istripY][1] == 1 && lutLpt[istripY][0] ==0)
169       iLptPlus=iLptPlus+(1 << istripY);
170     if (lutLpt[istripY][1] == 1 && lutLpt[istripY][0] ==1)
171       iLptUnde=iLptUnde+(1 << istripY);
172     
173     if (lutHpt[istripY][1] == 0 && lutHpt[istripY][0] ==1)
174       iHptMinu=iHptMinu+(1 << istripY);
175     if (lutHpt[istripY][1] == 1 && lutHpt[istripY][0] ==0)
176       iHptPlus=iHptPlus+(1 << istripY);
177     if (lutHpt[istripY][1] == 1 && lutHpt[istripY][0] ==1)
178       iHptUnde=iHptUnde+(1 << istripY);
179     
180   } // loop on istripY
181   
182   lut.SetContent("LptMinu",icirc,istripX,idev,iLptMinu);
183   lut.SetContent("LptUnde",icirc,istripX,idev,iLptUnde);
184   lut.SetContent("LptPlus",icirc,istripX,idev,iLptPlus);
185
186   lut.SetContent("HptMinu",icirc,istripX,idev,iHptMinu);
187   lut.SetContent("HptUnde",icirc,istripX,idev,iHptUnde);
188   lut.SetContent("HptPlus",icirc,istripX,idev,iHptPlus);
189 }
190
191 //_____________________________________________________________________________
192 Int_t
193 AliMUONTriggerIO::ReadLocalMasks(const char* localFile, AliMUONVStore& localMasks) const
194 {
195   /// Fills the local masks store from file
196   
197   if ( !NofLocalBoards() )
198   {
199     AliError("No local board to read");
200     return 0;
201   }
202   
203   FILE* fp = fopen(gSystem->ExpandPathName(localFile),"r");
204   if (!fp)
205   {
206     AliError(Form("Could not read file %s",localFile));
207     return 0;
208   }
209   
210   UShort_t maskBuffer[8];
211   
212   Int_t localBoardIndex(0);
213     
214   while ( fread ( maskBuffer, 2, 8, fp ) )
215   {
216     Int_t localBoardId = fRegionalTrigger.LocalBoardId(localBoardIndex);
217     AliDebug(1,Form("LB %03d X1 %4x X2 %4x X3 %4x X4 %4x "
218                     "Y1 %4x Y2 %4x Y3 %4x Y4 %4x",
219                     localBoardId,
220                     maskBuffer[0],
221                     maskBuffer[1],
222                     maskBuffer[2],
223                     maskBuffer[3],
224                     maskBuffer[4],
225                     maskBuffer[5],
226                     maskBuffer[6],
227                     maskBuffer[7]));
228     
229     if ( localBoardId > 0 ) 
230     {
231       AliMUONVCalibParam* localBoard = new AliMUONCalibParamNI(1,8,localBoardId,0,0);
232       for ( Int_t index = 0; index < 8; ++index )
233       {
234         localBoard->SetValueAsInt(index,0,maskBuffer[index]);
235       }
236       localMasks.Add(localBoard);
237     }
238     else
239     {
240       AliError(Form("Oups. Got localBoardId=%d for index=%d",localBoardId,localBoardIndex));
241     }
242     
243     ++localBoardIndex;
244   }
245   
246   if ( localBoardIndex != NofLocalBoards() ) 
247   {
248     AliError(Form("Read %d out of %d local boards",
249                   localBoardIndex, NofLocalBoards()));
250   }
251   
252   fclose(fp);
253   
254   return localBoardIndex+1;
255 }
256
257 //_____________________________________________________________________________
258 void
259 AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
260                                Int_t localBoardId,
261                                FILE* flut)
262 {
263   /// Read the LUT for one local board from an online file
264
265   UShort_t address;
266   
267   UChar_t buffer[fgkLocalLutSize];   // 32768 hpt/lpt addresses divided by two
268   UChar_t mask1 = 0xF0;
269   UChar_t mask2 = 0x0F;
270   UChar_t maskHpt = 0x0C;
271   UChar_t maskLpt = 0x03;
272   UChar_t lh, lpt, hpt;
273   
274   UChar_t xpos, xdev, ypos, ytri;
275   
276   Int_t lutLpt[16][2], lutHpt[16][2];
277
278   Int_t boardnr = localBoardId;
279   
280   AliDebug(1,Form("Reading LUT values for local board %d",boardnr));
281   
282   Int_t ny = 0;
283   Bool_t trigx = kFALSE;
284   
285   // read two lut addresses at once, 32768/2=16384 times
286   fread(buffer,fgkLocalLutSize,1,flut);
287
288   // create the 32767 addresses for the 4-bits lpt and hpt half-bytes
289   for (UShort_t ilut = 0; ilut < fgkLocalLutSize*2; ilut += 2) 
290   {
291     
292     // 1st 4-bits half-byte
293     address = ilut;   
294     lh = (buffer[ilut/2] & mask1) >> 4;
295     
296     // Lpt and Hpt response
297     hpt = (lh & maskHpt) >> 2;
298     lpt =  lh & maskLpt;
299     
300     // decompose the 15-bits address
301     trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
302     
303     // calculate group of y-strips
304     if (trigx && (ny < 16)) 
305     {
306       lutLpt[ny][0] =  lpt & 1;
307       lutLpt[ny][1] = (lpt & 2) >> 1;
308       lutHpt[ny][0] =  hpt & 1;
309       lutHpt[ny][1] = (hpt & 2) >> 1;
310       ny++;
311       if (ny == 16) 
312       {
313         ny = 0;
314         // ytri == 1 means no trigger in y-direction
315         if (ytri == 0) 
316         {
317           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
318         }
319       }
320     }
321     
322     // 2nd 4-bits half-byte
323     address = ilut+1; 
324     lh = (buffer[ilut/2] & mask2);
325     
326     // Lpt and Hpt response
327     hpt = (lh & maskHpt) >> 2;
328     lpt =  lh & maskLpt;
329     
330     // decompose the 15-bits address
331     trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
332     
333     // calculate group of y-strips
334     if (trigx && (ny < 16)) 
335     {
336       lutLpt[ny][0] =  lpt & 1;
337       lutLpt[ny][1] = (lpt & 2) >> 1;
338       lutHpt[ny][0] =  hpt & 1;
339       lutHpt[ny][1] = (hpt & 2) >> 1;
340       ny++;
341       if (ny == 16) 
342       {
343         ny = 0;
344         // ytri == 1 means no trigger in y-direction
345         if (ytri == 0) 
346         {
347           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
348         }
349       }
350     }
351   }
352 }
353
354 //_____________________________________________________________________________
355 Bool_t 
356 AliMUONTriggerIO::ReadLUT(const char* lutFileToRead, AliMUONTriggerLut& lut)
357 {
358   /// Fill the LUT object from online file
359   
360   if ( !NofLocalBoards() )
361   {
362     AliError("No local board id defined. Must read a regional file first");
363     return kFALSE;
364   }
365   
366   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToRead),"rb");
367   if (!flut) 
368   {
369     AliError(Form("Could not read LUT file %s",lutFileToRead));
370     return kFALSE;
371   }   
372   
373   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
374   {
375     ReadLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
376   }
377   
378   fclose(flut);
379   
380   return kTRUE;
381   
382 }
383
384 //_____________________________________________________________________________
385 Bool_t 
386 AliMUONTriggerIO::ReadConfig(const char* localFile,
387                             const char* regionalFile,
388                             const char* globalFile,
389                             AliMUONVStore* localMasks,
390                             AliMUONRegionalTriggerConfig* regionalConfig,
391                             AliMUONGlobalCrateConfig* globalConfig)
392 {
393   /// Fill the various masks store from files
394   
395   if ( !regionalFile ) 
396   {
397     AliError("Must have a regional file name to proceeed");
398     return kFALSE;
399   }
400   
401   AliDebug(1,Form("regionalConfig=%p",regionalConfig));
402   
403   Int_t nCrates = ReadRegionalConfig(regionalFile, regionalConfig);
404
405   if (!nCrates) 
406   {
407     AliError("nCrates=0 !");
408     return kFALSE;
409   }
410   
411   if (localMasks && localFile)
412   {
413     Int_t nLocal = ReadLocalMasks(localFile,*localMasks);
414     AliDebug(1,Form("Read masks for %d local boards",nLocal));
415   }
416   
417   Int_t nDarc = ReadGlobalConfig(globalFile, globalConfig);
418   AliDebug(1,Form("Read config for %d DARC boards",nDarc));
419   
420   if (!nDarc) return kFALSE;
421   
422   return kTRUE;
423 }
424
425
426
427 //_____________________________________________________________________________
428  Int_t 
429  AliMUONTriggerIO::ReadGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig)
430 {
431   /// read the global crate file
432   /// the masks are disable bit for each crate, 8 per darc board
433   /// bit value 0 means enable, 1 means disable                                                 * 
434   
435   Int_t nDarc = 0;
436   if ( !(nDarc = globalConfig->ReadData(globalFile)) ) return 0;
437   
438   return nDarc;
439 }
440  
441 //_____________________________________________________________________________
442 Int_t
443 AliMUONTriggerIO::ReadRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig)
444 {
445   /// Read regional file to fill  
446   
447   AliDebug(1,Form("regionalConfig=%p",regionalConfig));
448   
449   Int_t nCrates = 0;
450   if ( !(nCrates = regionalConfig->ReadData(regionalFile)) ) return 0;
451
452   // read the mapping file also
453   if ( ! fRegionalTrigger.ReadData(regionalFile) ) return 0;
454
455   return nCrates;  
456 }
457
458
459 //_____________________________________________________________________________
460 Bool_t 
461 AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
462                            const char* lutFileToWrite)
463 {
464   /// Convert an offline lut into an online (binary) lut file
465   
466   if ( !NofLocalBoards() )
467   {
468     AliError("No local board id defined. Must read a regional file first");
469     return kFALSE;
470   }
471   
472   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToWrite),"wb");
473   if (!flut) 
474   {
475     AliError(Form("Could not create output LUT file %s",lutFileToWrite));
476     return kFALSE;
477   }   
478   
479   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
480   {
481     WriteLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
482   }
483   
484   fclose(flut);
485   
486   return kTRUE;
487 }
488
489
490 //_____________________________________________________________________________
491 Bool_t 
492 AliMUONTriggerIO::WriteConfig(const char* localFile,
493                              const char* regionalFile,
494                              const char* globalFile,
495                              AliMUONVStore* localMasks,
496                     AliMUONRegionalTriggerConfig* regionalConfig,
497                     AliMUONGlobalCrateConfig* globalConfig) const
498 {
499 /// write config files
500
501     Bool_t ok;
502     ok  = WriteLocalMasks(localFile, *localMasks, regionalConfig);
503     ok &= WriteRegionalConfig(regionalFile, regionalConfig);
504     ok &= WriteGlobalConfig(globalFile, globalConfig);
505     
506     return ok;
507
508
509 }
510
511  
512  //_____________________________________________________________________________
513 Bool_t 
514 AliMUONTriggerIO::WriteGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig) const
515 {
516     /// write global config
517
518   ofstream out;
519   Int_t disable = 0;
520   
521   out.open(globalFile);
522   if (!out.good())
523   {
524     AliError(Form("Could not create output global file %s", globalFile));
525     return kFALSE;
526   }
527    
528   out << globalConfig->GetName() << endl;
529   out << globalConfig->GetGlobalCrateEnable() << endl;
530   
531   // Jtag
532   out << globalConfig->GetJtagName() << endl;
533   out << Form("0x%08x", globalConfig->GetJtagVmeAddr()) << endl;
534   out << Form("%d %d %d", globalConfig->GetJtagClockDiv(), 
535               globalConfig->GetJtagRxPhase(), globalConfig->GetJtagRdDelay()) << endl;
536  
537   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
538     out << Form("%d ", globalConfig->GetEnableJtag(i));
539   out << endl;
540
541   
542   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
543   {
544     out << i << endl;
545     for (Int_t j = 0; j < globalConfig->GetJtagNofLines(); ++j)
546       out << Form(" %s", globalConfig->GetJtagCrateName(i,j).Data()) << endl;
547   }
548   
549   // first darc board
550   out << globalConfig->GetFirstDarcName() << endl;
551   out << Form("0x%08x", globalConfig->GetFirstDarcVmeAddr()) << endl;
552   out << globalConfig->GetFirstDarcType() << endl;
553   disable = globalConfig->GetFirstDarcDisable();
554   out << Form("0x%02x", disable) << endl;
555   out << Form("0x%x", globalConfig->GetFirstDarcL0Delay()) << endl;
556   out << Form("0x%x", globalConfig->GetFirstDarcL1TimeOut()) << endl;
557   out << Form("0x%x", globalConfig->GetFirstDarcGlobalL0()) << endl;
558   out << Form("0x%x", globalConfig->GetFirstDarcConfig()) << endl;
559   
560   // second darc board
561   out << globalConfig->GetSecondDarcName() << endl;
562   out << Form("0x%08x", globalConfig->GetSecondDarcVmeAddr()) << endl;
563   out << globalConfig->GetSecondDarcType() << endl;
564   disable = globalConfig->GetSecondDarcDisable();
565   out << Form("0x%02x", disable) << endl;
566   out << Form("0x%x", globalConfig->GetSecondDarcL0Delay()) << endl;
567   out << Form("0x%x", globalConfig->GetSecondDarcL1TimeOut()) << endl; 
568   out << Form("0x%x", globalConfig->GetSecondDarcGlobalL0()) << endl; 
569   out << Form("0x%x", globalConfig->GetSecondDarcConfig()) << endl; 
570   
571   // global board
572   out << globalConfig->GetGlobalName() << endl;
573   out << Form("0x%08x", globalConfig->GetGlobalVmeAddr()) << endl;
574   for (Int_t i = 0; i < globalConfig->GetGlobalNofRegisters(); ++i)
575     out << Form("0x%x", globalConfig->GetGlobalRegister(i)) << endl;
576   
577   // Fet board
578   out << globalConfig->GetFetName() << endl;
579   out << Form("0x%08x", globalConfig->GetFetVmeAddr()) << endl;
580   for (Int_t i = 0; i < globalConfig->GetFetNofRegisters(); ++i)
581     out << Form("0x%x", globalConfig->GetFetRegister(i)) << endl;
582   
583   return kTRUE;
584 }
585  
586 //_____________________________________________________________________________
587 Bool_t
588 AliMUONTriggerIO::WriteRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig) const
589 {
590
591     /// write regional mask with the current configuration
592    /// if regional masks not defined, take the one from current configuration
593
594     ofstream out;
595     out.open(regionalFile);
596           
597     if (!out.good())
598     {
599       AliError(Form("Could not create output regional file %s",regionalFile));
600       return kFALSE;
601     }
602
603     Int_t nCrate = fRegionalTrigger.GetNofTriggerCrates();
604     if (!nCrate)
605     {
606       AliError("Could not write regional no configuration in memory");
607       return kFALSE;
608     }
609     
610     TIter next(fRegionalTrigger.CreateCrateIterator());
611     AliMpTriggerCrate* crate;
612     while ( ( crate = static_cast<AliMpTriggerCrate*>(next()) ) )
613     {
614       AliMUONTriggerCrateConfig* crateConfig = regionalConfig->FindTriggerCrate(crate->GetName());
615       if (!crateConfig) 
616       {
617         AliError(Form("Cannot find crate %s in CDB", crate->GetName()));
618         return kFALSE;
619       }
620
621       out << crate->GetName()  << endl;
622       out << Form("%02x", crate->GetId())   << endl;
623       out << crateConfig->GetMode()  << endl;
624       out << crateConfig->GetCoinc() << endl;
625       out << Form("%04x", crateConfig->GetMask()) << endl;
626
627       for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
628       {
629         Int_t localBoardId = crate->GetLocalBoardId(iLocal);
630         
631         AliMpLocalBoard* board = fRegionalTrigger.FindLocalBoard(localBoardId);
632         
633         out << Form("%02d ", board->GetSlot())  
634             << board->GetName() 
635             << Form(" %03d ", localBoardId) 
636             << Form("%03x", board->GetSwitch()) 
637             << endl;
638  
639         out << " ";
640         for (Int_t i = 0; i < board->GetNofDEs(); ++i)
641           out << Form("%4d ", board->GetDEId(i));
642         out << endl;
643           
644         // print copy card numbers & TC
645         out << Form(" %4d %4d", board->GetInputXfrom(), board->GetInputXto());
646         out << Form(" %4d %4d", board->GetInputYfrom(), board->GetInputYto());
647         out << Form(" %4d",     board->GetTC()) << endl;
648       }
649     }
650     out.close();
651     
652     return kTRUE;
653 }
654
655
656 //_____________________________________________________________________________
657 Bool_t 
658 AliMUONTriggerIO::WriteLocalMasks(const char* localFile, AliMUONVStore& localMasks, AliMUONRegionalTriggerConfig* regionalConfig) const
659 {
660     /// write local mask
661     /// removing/adding enable for a local board need a update of the configuration 
662     /// before calling this method
663     /// mask are written for all boards including the copy card (Ch.F.)
664
665     FILE* fp = fopen(gSystem->ExpandPathName(localFile),"wb");
666     if (!fp) 
667     {
668       AliError(Form("Could not create output local file %s",localFile));
669       return kFALSE;
670     }   
671
672     UShort_t maskBuffer[8];
673
674     TIter next(regionalConfig->CreateCrateIterator());
675     AliMUONTriggerCrateConfig* crate;
676     
677     while ( ( crate = static_cast<AliMUONTriggerCrateConfig*>(next()) ) )
678     {      
679       UShort_t mask = crate->GetMask(); // getting mask from current config
680
681       for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
682       {
683         Int_t localBoardId = crate->GetLocalBoardId(iLocal);
684
685         if ( (mask >> iLocal ) & 0x1 ) 
686         {
687           AliMUONVCalibParam* localMask = 
688               static_cast<AliMUONVCalibParam*>(localMasks.FindObject(localBoardId));
689
690           for (Int_t index = 0; index < 8; ++index) 
691           {
692             maskBuffer[index] = localMask->ValueAsInt(index,0); 
693           }
694
695           fwrite ( maskBuffer, 2, 8, fp); 
696         }
697
698       }
699     }
700
701     fclose(fp);
702
703     return kTRUE;
704
705 }
706
707 //_____________________________________________________________________________
708 void
709 AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
710                                 Int_t localBoardId,
711                                 FILE* flut)
712 {
713   /// loop over the address for the 4-bits lpt and hpt decisions
714
715   const Int_t kMaskYpos = 0x0F;
716   const Int_t kMaskYtri = 0x01;
717   const Int_t kMaskXdev = 0x1F;
718   const Int_t kMaskXpos = 0x1F;
719
720   UChar_t buffer[fgkLocalLutSize];  // 32768 hpt/lpt addresses divided by two
721   Int_t bc = 0;
722   
723   for (UInt_t i = 0; i < fgkLocalLutSize*2; ++i) 
724   {
725     Int_t lutLpt[2] = { 0 };
726     Int_t lutHpt[2] = { 0 };
727     
728     // decompose address
729     Int_t iYpos =   i                    & kMaskYpos;   
730     Int_t iYtri = ( i >>   4           ) & kMaskYtri;
731     Int_t iXdev = ( i >> ( 4 + 1 )     ) & kMaskXdev;
732     Int_t iXpos = ( i >> ( 4 + 1 + 5 ) ) & kMaskXpos;
733     
734     // convert deviation format
735     // online: sign 1bit , dev 4bit
736     // sign    dev    trigger
737     // 0       1-15   mu-
738     // 1       1-15   mu+
739     // 0       0      mu+, mu- infinite momentum (unde)
740     // 1       0      no x-trigger
741     // offline: dev 5bit
742     // sign    dev    trigger
743     // -        0-14  mu-
744     // -       16-31  mu+
745     // -       15     mu+, mu- infinite momentum (unde)
746     Int_t iXdevOn  = 0;
747     Int_t iXdevOff = 0;
748     Int_t sign     = 0;
749     Bool_t trigx = kFALSE;
750     iXdevOn +=  iXdev & 0x0F;
751     sign    += (iXdev >> 4) & 0x01;
752     if (iXdevOn == 0) {
753       if (sign == 0) {
754         iXdevOff = 15;
755         trigx = kTRUE;
756       } else {
757         iXdevOff = 15;
758         trigx = kFALSE;
759       }
760     } else {
761       trigx = kTRUE;
762       if (sign == 0) {
763         iXdevOff = - iXdevOn + 15;  // gives range  0-14
764       } else {
765         iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
766       }
767     }
768     iXdev = iXdevOff;
769
770     // iYtri == 1 means no trigger in y-direction
771     if (iYtri == 0 && trigx) 
772     {
773       lut.GetLutOutput(localBoardId,iXpos,iXdev,iYpos,lutLpt,lutHpt);
774     }
775     
776     // fill byte
777     if (i%2 == 0) 
778     {
779       // upper half-byte
780       buffer[bc] = 0;       
781       buffer[bc] += lutHpt[1] << 7;
782       buffer[bc] += lutHpt[0] << 6;
783       buffer[bc] += lutLpt[1] << 5;
784       buffer[bc] += lutLpt[0] << 4;
785     } else {
786       // lower half-byte
787       buffer[bc] += lutHpt[1] << 3;
788       buffer[bc] += lutHpt[0] << 2;
789       buffer[bc] += lutLpt[1] << 1;
790       buffer[bc] += lutLpt[0] << 0;
791       bc++;
792     }
793   }
794   fwrite(&buffer,bc,1,flut);
795 }  
796
797 //_____________________________________________________________________________
798 Int_t 
799 AliMUONTriggerIO::LocalBoardId(Int_t index) const
800 {  
801   /// Return the i-th localBoardId, or -1 if index is out of bounds
802
803   return fRegionalTrigger.LocalBoardId(index);
804 }
805
806
807 //______________________________________________________________________________
808
809 Int_t AliMUONTriggerIO::LocalBoardId(Int_t ddlId, Int_t crateId, Int_t localId) const
810 {
811     /// Return local board id from crate and local indexes.
812     
813     Int_t nofDDLs = 0;
814     TString name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
815
816     AliMpTriggerCrate* crate = fRegionalTrigger.FindTriggerCrate(name, false);
817     return crate->GetLocalBoardId(localId);
818 }