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