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