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