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