In mapping:
[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 nLocalBoards(1);
213     
214   while ( fread ( maskBuffer, 2, 8, fp ) )
215   {
216     Int_t localBoardId = fRegionalTrigger.LocalBoardId(nLocalBoards);
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 ) 
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     
239     ++nLocalBoards;
240   }
241   
242   if ( nLocalBoards != NofLocalBoards() ) 
243   {
244     AliError(Form("Read %d out of %d local boards",
245                   nLocalBoards, NofLocalBoards()));
246   }
247   
248   fclose(fp);
249   
250   return nLocalBoards;
251 }
252
253 //_____________________________________________________________________________
254 void
255 AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
256                                Int_t localBoardId,
257                                FILE* flut)
258 {
259   /// Read the LUT for one local board from an online file
260
261   UShort_t address;
262   
263   UChar_t buffer[fgkLocalLutSize];   // 32768 hpt/lpt addresses divided by two
264   UChar_t mask1 = 0xF0;
265   UChar_t mask2 = 0x0F;
266   UChar_t maskHpt = 0x0C;
267   UChar_t maskLpt = 0x03;
268   UChar_t lh, lpt, hpt;
269   
270   UChar_t xpos, xdev, ypos, ytri;
271   
272   Int_t lutLpt[16][2], lutHpt[16][2];
273
274   Int_t boardnr = localBoardId;
275   
276   AliDebug(1,Form("Reading LUT values for local board %d",boardnr));
277   
278   Int_t ny = 0;
279   Bool_t trigx = kFALSE;
280   
281   // read two lut addresses at once, 32768/2=16384 times
282   fread(buffer,fgkLocalLutSize,1,flut);
283
284   // create the 32767 addresses for the 4-bits lpt and hpt half-bytes
285   for (UShort_t ilut = 0; ilut < fgkLocalLutSize*2; ilut += 2) 
286   {
287     
288     // 1st 4-bits half-byte
289     address = ilut;   
290     lh = (buffer[ilut/2] & mask1) >> 4;
291     
292     // Lpt and Hpt response
293     hpt = (lh & maskHpt) >> 2;
294     lpt =  lh & maskLpt;
295     
296     // decompose the 15-bits address
297     trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
298     
299     // calculate group of y-strips
300     if (trigx && (ny < 16)) 
301     {
302       lutLpt[ny][0] =  lpt & 1;
303       lutLpt[ny][1] = (lpt & 2) >> 1;
304       lutHpt[ny][0] =  hpt & 1;
305       lutHpt[ny][1] = (hpt & 2) >> 1;
306       ny++;
307       if (ny == 16) 
308       {
309         ny = 0;
310         // ytri == 1 means no trigger in y-direction
311         if (ytri == 0) 
312         {
313           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
314         }
315       }
316     }
317     
318     // 2nd 4-bits half-byte
319     address = ilut+1; 
320     lh = (buffer[ilut/2] & mask2);
321     
322     // Lpt and Hpt response
323     hpt = (lh & maskHpt) >> 2;
324     lpt =  lh & maskLpt;
325     
326     // decompose the 15-bits address
327     trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
328     
329     // calculate group of y-strips
330     if (trigx && (ny < 16)) 
331     {
332       lutLpt[ny][0] =  lpt & 1;
333       lutLpt[ny][1] = (lpt & 2) >> 1;
334       lutHpt[ny][0] =  hpt & 1;
335       lutHpt[ny][1] = (hpt & 2) >> 1;
336       ny++;
337       if (ny == 16) 
338       {
339         ny = 0;
340         // ytri == 1 means no trigger in y-direction
341         if (ytri == 0) 
342         {
343           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
344         }
345       }
346     }
347   }
348 }
349
350 //_____________________________________________________________________________
351 Bool_t 
352 AliMUONTriggerIO::ReadLUT(const char* lutFileToRead, AliMUONTriggerLut& lut)
353 {
354   /// Fill the LUT object from online file
355   
356   if ( !NofLocalBoards() )
357   {
358     AliError("No local board id defined. Must read a regional file first");
359     return kFALSE;
360   }
361   
362   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToRead),"rb");
363   if (!flut) 
364   {
365     AliError(Form("Could not read LUT file %s",lutFileToRead));
366     return kFALSE;
367   }   
368   
369   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
370   {
371     ReadLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
372   }
373   
374   fclose(flut);
375   
376   return kTRUE;
377   
378 }
379
380 //_____________________________________________________________________________
381 Bool_t 
382 AliMUONTriggerIO::ReadConfig(const char* localFile,
383                             const char* regionalFile,
384                             const char* globalFile,
385                             AliMUONVStore* localMasks,
386                             AliMUONRegionalTriggerConfig* regionalConfig,
387                             AliMUONGlobalCrateConfig* globalConfig)
388 {
389   /// Fill the various masks store from files
390   
391   if ( !regionalFile ) 
392   {
393     AliError("Must have a regional file name to proceeed");
394     return kFALSE;
395   }
396   
397   Int_t nCrates = ReadRegionalConfig(regionalFile, regionalConfig);
398
399   if (!nCrates) return kFALSE;
400   
401   if (localMasks && localFile)
402   {
403     Int_t nLocal = ReadLocalMasks(localFile,*localMasks);
404     AliDebug(1,Form("Read masks for %d local boards",nLocal));
405   }
406   
407   Int_t nDarc = ReadGlobalConfig(globalFile, globalConfig);
408   AliDebug(1,Form("Read disable for %d DARC boards",nDarc));
409   
410   if (!nDarc) return kFALSE;
411   
412   return kTRUE;
413 }
414
415
416
417 //_____________________________________________________________________________
418  Int_t 
419  AliMUONTriggerIO::ReadGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig)
420 {
421   /// read the global crate file
422   /// the masks are disable bit for each crate, 8 per darc board
423   /// bit value 0 means enable, 1 means disable                                                 * 
424   
425   Int_t nDarc = 0;
426   if ( !(nDarc = globalConfig->ReadData(globalFile)) ) return 0;
427   
428   return nDarc;
429 }
430  
431 //_____________________________________________________________________________
432 Int_t
433 AliMUONTriggerIO::ReadRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig)
434 {
435   /// Read regional file to fill  
436   Int_t nCrates = 0;
437   if ( !(nCrates = regionalConfig->ReadData(regionalFile)) ) return 0;
438
439   // read the mapping file also
440   if ( ! fRegionalTrigger.ReadData(regionalFile) ) return 0;
441
442   return nCrates;  
443 }
444
445
446 //_____________________________________________________________________________
447 Bool_t 
448 AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
449                            const char* lutFileToWrite)
450 {
451   /// Convert an offline lut into an online (binary) lut file
452   
453   if ( !NofLocalBoards() )
454   {
455     AliError("No local board id defined. Must read a regional file first");
456     return kFALSE;
457   }
458   
459   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToWrite),"wb");
460   if (!flut) 
461   {
462     AliError(Form("Could not create output LUT file %s",lutFileToWrite));
463     return kFALSE;
464   }   
465   
466   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
467   {
468     WriteLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
469   }
470   
471   fclose(flut);
472   
473   return kTRUE;
474 }
475
476
477 //_____________________________________________________________________________
478 Bool_t 
479 AliMUONTriggerIO::WriteConfig(const char* localFile,
480                              const char* regionalFile,
481                              const char* globalFile,
482                              AliMUONVStore* localMasks,
483                     AliMUONRegionalTriggerConfig* regionalConfig,
484                     AliMUONGlobalCrateConfig* globalConfig) const
485 {
486 /// write config files
487
488     Bool_t ok;
489     ok  = WriteLocalMasks(localFile, *localMasks, regionalConfig);
490     ok &= WriteRegionalConfig(regionalFile, regionalConfig);
491     ok &= WriteGlobalConfig(globalFile, globalConfig);
492     
493     return ok;
494
495
496 }
497
498  
499  //_____________________________________________________________________________
500 Bool_t 
501 AliMUONTriggerIO::WriteGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig) const
502 {
503     /// write global config
504
505   ofstream out;
506   Int_t disable = 0;
507   
508   out.open(globalFile);
509   if (!out.good())
510   {
511     AliError(Form("Could not create output global file %s", globalFile));
512     return kFALSE;
513   }
514    
515   out << globalConfig->GetName() << endl;
516   out << globalConfig->GetGlobalCrateEnable() << endl;
517   
518   // Jtag
519   out << globalConfig->GetJtagName() << endl;
520   out << Form("0x%08x", globalConfig->GetJtagVmeAddr()) << endl;
521   out << Form("%d %d %d", globalConfig->GetJtagClockDiv(), 
522               globalConfig->GetJtagRxPhase(), globalConfig->GetJtagRdDelay()) << endl;
523  
524   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
525     out << Form("%d ", globalConfig->GetEnableJtag(i));
526   out << endl;
527
528   
529   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
530   {
531     out << i << endl;
532     for (Int_t j = 0; j < globalConfig->GetJtagNofLines(); ++j)
533       out << Form(" %s", globalConfig->GetJtagCrateName(i,j).Data()) << endl;
534   }
535   
536   // first darc board
537   out << globalConfig->GetFirstDarcName() << endl;
538   out << Form("0x%08x", globalConfig->GetFirstDarcVmeAddr()) << endl;
539   out << globalConfig->GetFirstDarcType() << endl;
540   disable = globalConfig->GetFirstDarcDisable();
541   out << Form("0x%02x", disable) << endl;
542   out << Form("0x%x", globalConfig->GetFirstDarcL0Delay()) << endl;
543   out << Form("0x%x", globalConfig->GetFirstDarcL1TimeOut()) << endl;
544   out << Form("0x%x", globalConfig->GetFirstDarcGlobalL0()) << endl;
545   out << Form("0x%x", globalConfig->GetFirstDarcConfig()) << endl;
546   
547   // second darc board
548   out << globalConfig->GetSecondDarcName() << endl;
549   out << Form("0x%08x", globalConfig->GetSecondDarcVmeAddr()) << endl;
550   out << globalConfig->GetSecondDarcType() << endl;
551   disable = globalConfig->GetSecondDarcDisable();
552   out << Form("0x%02x", disable) << endl;
553   out << Form("0x%x", globalConfig->GetSecondDarcL0Delay()) << endl;
554   out << Form("0x%x", globalConfig->GetSecondDarcL1TimeOut()) << endl; 
555   out << Form("0x%x", globalConfig->GetSecondDarcGlobalL0()) << endl; 
556   out << Form("0x%x", globalConfig->GetSecondDarcConfig()) << endl; 
557   
558   // global board
559   out << globalConfig->GetGlobalName() << endl;
560   out << Form("0x%08x", globalConfig->GetGlobalVmeAddr()) << endl;
561   for (Int_t i = 0; i < globalConfig->GetGlobalNofRegisters(); ++i)
562     out << Form("0x%x", globalConfig->GetGlobalRegister(i)) << endl;
563   
564   // Fet board
565   out << globalConfig->GetFetName() << endl;
566   out << Form("0x%08x", globalConfig->GetFetVmeAddr()) << endl;
567   for (Int_t i = 0; i < globalConfig->GetFetNofRegisters(); ++i)
568     out << Form("0x%x", globalConfig->GetFetRegister(i)) << endl;
569   
570   return kTRUE;
571 }
572  
573 //_____________________________________________________________________________
574 Bool_t
575 AliMUONTriggerIO::WriteRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig) const
576 {
577
578     /// write regional mask with the current configuration
579    /// if regional masks not defined, take the one from current configuration
580
581     ofstream out;
582     out.open(regionalFile);
583           
584     if (!out.good())
585     {
586       AliError(Form("Could not create output regional file %s",regionalFile));
587       return kFALSE;
588     }
589
590     Int_t nCrate = fRegionalTrigger.GetNofTriggerCrates();
591     if (!nCrate)
592     {
593       AliError("Could not write regional no configuration in memory");
594       return kFALSE;
595     }
596     
597     TIter next(fRegionalTrigger.CreateCrateIterator());
598     AliMpTriggerCrate* crate;
599     while ( ( crate = static_cast<AliMpTriggerCrate*>(next()) ) )
600     {
601       AliMUONTriggerCrateConfig* crateConfig = regionalConfig->FindTriggerCrate(crate->GetName());
602       if (!crateConfig) 
603       {
604         AliError(Form("Cannot find crate %s in CDB", crate->GetName()));
605         return kFALSE;
606       }
607
608       out << crate->GetName()  << endl;
609       out << Form("%02x", crate->GetId())   << endl;
610       out << crateConfig->GetMode()  << endl;
611       out << crateConfig->GetCoinc() << endl;
612       out << Form("%04x", crateConfig->GetMask()) << endl;
613
614       for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
615       {
616         Int_t localBoardId = crate->GetLocalBoardId(iLocal);
617         
618         AliMpLocalBoard* board = fRegionalTrigger.FindLocalBoard(localBoardId);
619         
620         out << Form("%02d ", board->GetSlot())  
621             << board->GetName() 
622             << Form(" %03d ", localBoardId) 
623             << Form("%03x", board->GetSwitch()) 
624             << endl;
625  
626         out << " ";
627         for (Int_t i = 0; i < board->GetNofDEs(); ++i)
628           out << Form("%4d ", board->GetDEId(i));
629         out << endl;
630           
631         // print copy card numbers & TC
632         out << Form(" %4d %4d", board->GetInputXfrom(), board->GetInputXto());
633         out << Form(" %4d %4d", board->GetInputYfrom(), board->GetInputYto());
634         out << Form(" %4d",     board->GetTC()) << endl;
635       }
636     }
637     out.close();
638     
639     return kTRUE;
640 }
641
642
643 //_____________________________________________________________________________
644 Bool_t 
645 AliMUONTriggerIO::WriteLocalMasks(const char* localFile, AliMUONVStore& localMasks, AliMUONRegionalTriggerConfig* regionalConfig) const
646 {
647     /// write local mask
648     /// removing/adding enable for a local board need a update of the configuration 
649     /// before calling this method
650     /// mask are written for all boards including the copy card (Ch.F.)
651
652     FILE* fp = fopen(gSystem->ExpandPathName(localFile),"wb");
653     if (!fp) 
654     {
655       AliError(Form("Could not create output local file %s",localFile));
656       return kFALSE;
657     }   
658
659     UShort_t maskBuffer[8];
660
661     TIter next(regionalConfig->CreateCrateIterator());
662     AliMUONTriggerCrateConfig* crate;
663     
664     while ( ( crate = static_cast<AliMUONTriggerCrateConfig*>(next()) ) )
665     {      
666       UShort_t mask = crate->GetMask(); // getting mask from current config
667
668       for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
669       {
670         Int_t localBoardId = crate->GetLocalBoardId(iLocal);
671
672         if ( (mask >> iLocal ) & 0x1 ) 
673         {
674           AliMUONVCalibParam* localMask = 
675               static_cast<AliMUONVCalibParam*>(localMasks.FindObject(localBoardId));
676
677           for (Int_t index = 0; index < 8; ++index) 
678           {
679             maskBuffer[index] = localMask->ValueAsInt(index,0); 
680           }
681
682           fwrite ( maskBuffer, 2, 8, fp); 
683         }
684
685       }
686     }
687
688     fclose(fp);
689
690     return kTRUE;
691
692 }
693
694 //_____________________________________________________________________________
695 void
696 AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
697                                 Int_t localBoardId,
698                                 FILE* flut)
699 {
700   /// loop over the address for the 4-bits lpt and hpt decisions
701
702   const Int_t kMaskYpos = 0x0F;
703   const Int_t kMaskYtri = 0x01;
704   const Int_t kMaskXdev = 0x1F;
705   const Int_t kMaskXpos = 0x1F;
706
707   UChar_t buffer[fgkLocalLutSize];  // 32768 hpt/lpt addresses divided by two
708   Int_t bc = 0;
709   
710   for (UInt_t i = 0; i < fgkLocalLutSize*2; ++i) 
711   {
712     Int_t lutLpt[2] = { 0 };
713     Int_t lutHpt[2] = { 0 };
714     
715     // decompose address
716     Int_t iYpos =   i                    & kMaskYpos;   
717     Int_t iYtri = ( i >>   4           ) & kMaskYtri;
718     Int_t iXdev = ( i >> ( 4 + 1 )     ) & kMaskXdev;
719     Int_t iXpos = ( i >> ( 4 + 1 + 5 ) ) & kMaskXpos;
720     
721     // convert deviation format
722     // online: sign 1bit , dev 4bit
723     // sign    dev    trigger
724     // 0       1-15   mu-
725     // 1       1-15   mu+
726     // 0       0      mu+, mu- infinite momentum (unde)
727     // 1       0      no x-trigger
728     // offline: dev 5bit
729     // sign    dev    trigger
730     // -        0-14  mu-
731     // -       16-31  mu+
732     // -       15     mu+, mu- infinite momentum (unde)
733     Int_t iXdevOn  = 0;
734     Int_t iXdevOff = 0;
735     Int_t sign     = 0;
736     Bool_t trigx = kFALSE;
737     iXdevOn +=  iXdev & 0x0F;
738     sign    += (iXdev >> 4) & 0x01;
739     if (iXdevOn == 0) {
740       if (sign == 0) {
741         iXdevOff = 15;
742         trigx = kTRUE;
743       } else {
744         iXdevOff = 15;
745         trigx = kFALSE;
746       }
747     } else {
748       trigx = kTRUE;
749       if (sign == 0) {
750         iXdevOff = - iXdevOn + 15;  // gives range  0-14
751       } else {
752         iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
753       }
754     }
755     iXdev = iXdevOff;
756
757     // iYtri == 1 means no trigger in y-direction
758     if (iYtri == 0 && trigx) 
759     {
760       lut.GetLutOutput(localBoardId,iXpos,iXdev,iYpos,lutLpt,lutHpt);
761     }
762     
763     // fill byte
764     if (i%2 == 0) 
765     {
766       // upper half-byte
767       buffer[bc] = 0;       
768       buffer[bc] += lutHpt[1] << 7;
769       buffer[bc] += lutHpt[0] << 6;
770       buffer[bc] += lutLpt[1] << 5;
771       buffer[bc] += lutLpt[0] << 4;
772     } else {
773       // lower half-byte
774       buffer[bc] += lutHpt[1] << 3;
775       buffer[bc] += lutHpt[0] << 2;
776       buffer[bc] += lutLpt[1] << 1;
777       buffer[bc] += lutLpt[0] << 0;
778       bc++;
779     }
780   }
781   fwrite(&buffer,bc,1,flut);
782 }  
783
784 //_____________________________________________________________________________
785 Int_t 
786 AliMUONTriggerIO::LocalBoardId(Int_t index) const
787 {  
788   /// Return the i-th localBoardId, or -1 if index is out of bounds
789
790   return fRegionalTrigger.LocalBoardId(index);
791 }
792
793
794 //______________________________________________________________________________
795
796 Int_t AliMUONTriggerIO::LocalBoardId(Int_t ddlId, Int_t crateId, Int_t localId) const
797 {
798     /// Return local board id from crate and local indexes.
799     
800     Int_t nofDDLs = 0;
801     TString name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
802
803     AliMpTriggerCrate* crate = fRegionalTrigger.FindTriggerCrate(name, false);
804     return crate->GetLocalBoardId(localId);
805 }