Reading muon trigger scalers with the DA of the muon trigger and transfer
[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   UInt_t bftmpUI;
674   ULong64_t bftmpUL;
675
676   AliInfo(Form("Data buffer length = %d",bufflen));
677
678   Int_t entries = scalers.GetEntries();
679   Int_t ibr, isc = 0;
680   for (; isc < entries; isc++) {
681     ibr = 0;
682     AliMUONTriggerScalers *sc = (AliMUONTriggerScalers*)scalers.At(isc);
683     nCalibEvents = sc->GetNCalibEvents();
684     AliInfo(Form("nCalibEvents = %d",sc->GetNCalibEvents()));
685     buffer[ibr++] = (nCalibEvents >> 24) & 0xFF;
686     buffer[ibr++] = (nCalibEvents >> 16) & 0xFF;
687     buffer[ibr++] = (nCalibEvents >>  8) & 0xFF;
688     buffer[ibr++] = (nCalibEvents >>  0) & 0xFF;
689     deltaT = sc->GetDeltaT();
690     buffer[ibr++] = (deltaT >> 24) & 0xFF;
691     buffer[ibr++] = (deltaT >> 16) & 0xFF;
692     buffer[ibr++] = (deltaT >>  8) & 0xFF;
693     buffer[ibr++] = (deltaT >>  0) & 0xFF;
694     for (Int_t bit = 0; bit < 6; bit++) {
695       glSc[bit] = sc->GetGloScal(bit);
696       buffer[ibr++] = (glSc[bit] >> 24) & 0xFF;
697       buffer[ibr++] = (glSc[bit] >> 16) & 0xFF;
698       buffer[ibr++] = (glSc[bit] >>  8) & 0xFF;
699       buffer[ibr++] = (glSc[bit] >>  0) & 0xFF;
700     }
701     for (Int_t iLoc = 0; iLoc < nLocBoards; iLoc++) {
702       locLptScaler[iLoc] = sc->GetLocScalLpt(iLoc);
703       buffer[ibr++] = (locLptScaler[iLoc] >> 24) & 0xFF;
704       buffer[ibr++] = (locLptScaler[iLoc] >> 16) & 0xFF;
705       buffer[ibr++] = (locLptScaler[iLoc] >>  8) & 0xFF;
706       buffer[ibr++] = (locLptScaler[iLoc] >>  0) & 0xFF;
707       for (Int_t iCath = 0; iCath < nCathodes; iCath++) {
708         for (Int_t iCha = 0; iCha < nTriChambers; iCha++) {
709           locStripScaler[iCath][iCha][iLoc] = sc->GetLocScalStrip(iCath,iCha,iLoc);
710           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 56) & 0xFF;
711           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 48) & 0xFF;
712           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 40) & 0xFF;
713           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 32) & 0xFF;
714           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 24) & 0xFF;
715           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >> 16) & 0xFF;
716           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >>  8) & 0xFF;
717           buffer[ibr++] = (locStripScaler[iCath][iCha][iLoc] >>  0) & 0xFF;
718           locStripOver[iCath][iCha][iLoc] = sc->GetLocScalStripOver(iCath,iCha,iLoc);
719           buffer[ibr++] = (locStripOver[iCath][iCha][iLoc] >> 24) & 0xFF;
720           buffer[ibr++] = (locStripOver[iCath][iCha][iLoc] >> 16) & 0xFF;
721           buffer[ibr++] = (locStripOver[iCath][iCha][iLoc] >>  8) & 0xFF;
722           buffer[ibr++] = (locStripOver[iCath][iCha][iLoc] >>  0) & 0xFF;
723         }
724       }
725     }
726
727     fwrite(buffer,ibr,1,fp);
728     //AliInfo("Read to buffer %d bytes",ibr);
729     
730   }
731
732   fclose(fp);
733
734   return kTRUE;
735
736 }
737
738 //_____________________________________________________________________________
739 Bool_t 
740 AliMUONTriggerIO::WriteConfig(const char* localFile,
741                              const char* regionalFile,
742                              const char* globalFile,
743                              const AliMUONVStore* localMasks,
744                     AliMUONRegionalTriggerConfig* regionalConfig,
745                     AliMUONGlobalCrateConfig* globalConfig) const
746 {
747 /// write config files
748
749     Bool_t ok;
750     ok  = WriteLocalMasks(localFile, *localMasks);
751     ok &= WriteRegionalConfig(regionalFile, regionalConfig);
752     ok &= WriteGlobalConfig(globalFile, globalConfig);
753     
754     return ok;
755
756
757 }
758
759  
760  //_____________________________________________________________________________
761 Bool_t 
762 AliMUONTriggerIO::WriteGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig) const
763 {
764     /// write global config
765
766   ofstream out;
767   Int_t disable = 0;
768   
769   out.open(globalFile);
770   if (!out.good())
771   {
772     AliError(Form("Could not create output global file %s", globalFile));
773     return kFALSE;
774   }
775    
776   out << globalConfig->GetName() << endl;
777   out << Form("0x%x",globalConfig->GetGlobalCrateEnable()) << endl;
778   
779   // Jtag
780   out << globalConfig->GetJtagName() << endl;
781   out << Form("0x%08lx", globalConfig->GetJtagVmeAddr()) << endl;
782   out << Form("%d %d %d", globalConfig->GetJtagClockDiv(), 
783               globalConfig->GetJtagRxPhase(), globalConfig->GetJtagRdDelay()) << endl;
784  
785   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
786     out << Form("%d ", globalConfig->GetEnableJtag(i));
787   out << endl;
788
789   
790   for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
791   {
792     out << i << endl;
793     for (Int_t j = 0; j < globalConfig->GetJtagNofLines(); ++j)
794       out << Form(" %s", globalConfig->GetJtagCrateName(i,j).Data()) << endl;
795   }
796   
797   // first darc board
798   out << globalConfig->GetFirstDarcName() << endl;
799   out << Form("0x%08lx", globalConfig->GetFirstDarcVmeAddr()) << endl;
800   out << globalConfig->GetFirstDarcType() << endl;
801   disable = globalConfig->GetFirstDarcDisable();
802   out << Form("0x%02x", disable) << endl;
803   out << Form("0x%x", globalConfig->GetFirstDarcL0Delay()) << endl;
804   out << Form("0x%x", globalConfig->GetFirstDarcL1TimeOut()) << endl;
805   out << Form("0x%x", globalConfig->GetFirstDarcGlobalL0()) << endl;
806   out << Form("0x%x", globalConfig->GetFirstDarcConfig()) << endl;
807   
808   // second darc board
809   out << globalConfig->GetSecondDarcName() << endl;
810   out << Form("0x%08lx", globalConfig->GetSecondDarcVmeAddr()) << endl;
811   out << globalConfig->GetSecondDarcType() << endl;
812   disable = globalConfig->GetSecondDarcDisable();
813   out << Form("0x%02x", disable) << endl;
814   out << Form("0x%x", globalConfig->GetSecondDarcL0Delay()) << endl;
815   out << Form("0x%x", globalConfig->GetSecondDarcL1TimeOut()) << endl; 
816   out << Form("0x%x", globalConfig->GetSecondDarcGlobalL0()) << endl; 
817   out << Form("0x%x", globalConfig->GetSecondDarcConfig()) << endl; 
818   
819   // global board
820   out << globalConfig->GetGlobalName() << endl;
821   out << Form("0x%08lx", globalConfig->GetGlobalVmeAddr()) << endl;
822   for (Int_t i = 0; i < globalConfig->GetGlobalNofRegisters(); ++i)
823     out << Form("0x%x", globalConfig->GetGlobalRegister(i)) << endl;
824   
825   // Fet board
826   out << globalConfig->GetFetName() << endl;
827   out << Form("0x%08lx", globalConfig->GetFetVmeAddr()) << endl;
828   for (Int_t i = 0; i < globalConfig->GetFetNofRegisters(); ++i)
829     out << Form("0x%x", globalConfig->GetFetRegister(i)) << endl;
830   
831   return kTRUE;
832 }
833  
834 //_____________________________________________________________________________
835 Bool_t
836 AliMUONTriggerIO::WriteRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig) const
837 {
838
839     /// write regional mask with the current configuration
840    /// if regional masks not defined, take the one from current configuration
841
842     ofstream out;
843     out.open(regionalFile);
844           
845     if (!out.good())
846     {
847       AliError(Form("Could not create output regional file %s",regionalFile));
848       return kFALSE;
849     }
850
851     Int_t nCrate = fRegionalTrigger.GetNofTriggerCrates();
852     if (!nCrate)
853     {
854       AliError("Could not write regional no configuration in memory");
855       return kFALSE;
856     }
857
858     Int_t nofDDLs = 0;
859     TString name;
860     AliMpTriggerCrate* crate;
861     for (Int_t ddlId = 0; ddlId < 2; ddlId++) // right & left side            
862       {
863         for (Int_t crateId = 0; crateId < 8; crateId++) // 8 crates/regional boards for each side.
864           {
865             
866             name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
867             
868             crate = fRegionalTrigger.FindTriggerCrate(name, false);
869             
870             AliMUONTriggerCrateConfig* crateConfig = regionalConfig->FindTriggerCrate(crate->GetName());
871             if (!crateConfig) 
872               {
873                 AliError(Form("Cannot find crate %s in CDB", crate->GetName()));
874                 return kFALSE;
875               }
876             
877             out << crate->GetName()  << endl;
878             out << Form("%02x", crate->GetId())   << endl;
879             out << crateConfig->GetMode()  << endl;
880             out << crateConfig->GetCoinc() << endl;
881             out << Form("%04x", crateConfig->GetMask()) << endl;
882             out << Form("%02d",crate->GetNofLocalBoards()) << endl;
883             
884             for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
885               {
886                 Int_t localBoardId = crate->GetLocalBoardId(iLocal);
887                 
888                 AliMpLocalBoard* board = fRegionalTrigger.FindLocalBoard(localBoardId);
889                 
890                 out << Form("%02d ", board->GetSlot())  
891                     << board->GetName() 
892                     << Form(" %03d ", localBoardId) 
893                     << Form("%03x", board->GetSwitch()) 
894                     << endl;
895                 
896                 out << " ";
897                 
898                 if (board->IsNotified()) {
899                   for (Int_t i = 0; i < board->GetNofDEs(); ++i)
900                     out << Form("%4d ", board->GetDEId(i));
901                 } else {
902                   out << Form("%4d ", 0);
903                 }
904                 out << endl;
905                 
906                 // print copy card numbers & TC
907                 out << Form(" %4d %4d", board->GetInputXfrom(), board->GetInputXto());
908                 out << Form(" %4d %4d", board->GetInputYfrom(), board->GetInputYto());
909                 out << Form(" %4d",     board->GetTC()) << endl;
910               }
911           }
912       }
913
914     out.close();
915     
916     return kTRUE;
917 }
918
919
920 //_____________________________________________________________________________
921 Bool_t 
922 AliMUONTriggerIO::WriteLocalMasks(const char* localFile, const AliMUONVStore& localMasks) const
923 {
924     /// write local mask
925     /// removing/adding enable for a local board need a update of the configuration 
926     /// before calling this method
927     /// mask are written for all boards including the copy card (Ch.F.)
928
929     FILE* fp = fopen(gSystem->ExpandPathName(localFile),"wb");
930     if (!fp) 
931     {
932       AliError(Form("Could not create output local file %s",localFile));
933       return kFALSE;
934     }   
935
936     UShort_t maskBuffer[8];
937     Int_t localBoardIndex(0);
938     while (localBoardIndex < NofLocalBoards()) {
939
940       Int_t localBoardId = fRegionalTrigger.LocalBoardId(localBoardIndex);
941
942       AliMUONVCalibParam* localMask = 
943         static_cast<AliMUONVCalibParam*>(localMasks.FindObject(localBoardId));
944
945       for (Int_t index = 0; index < 8; ++index) 
946         {
947           maskBuffer[index] = localMask->ValueAsInt(index,0); 
948         }
949       
950       fwrite ( maskBuffer, 2, 8, fp); 
951
952       ++localBoardIndex;
953
954     }
955
956     fclose(fp);
957
958     return kTRUE;
959
960 }
961
962 //_____________________________________________________________________________
963 void
964 AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
965                                 Int_t localBoardId,
966                                 FILE* flut)
967 {
968   /// loop over the address for the 4-bits lpt and hpt decisions
969
970   const Int_t kMaskYpos = 0x0F;
971   const Int_t kMaskYtri = 0x01;
972   const Int_t kMaskXdev = 0x1F;
973   const Int_t kMaskXpos = 0x1F;
974
975   UChar_t buffer[fgkLocalLutSize];  // 32768 hpt/lpt addresses divided by two
976   Int_t bc = 0;
977   
978   for (UInt_t i = 0; i < fgkLocalLutSize*2; ++i) 
979   {
980     Int_t lutLpt[2] = { 0 };
981     Int_t lutHpt[2] = { 0 };
982     
983     // decompose address
984     Int_t iYpos =   i                    & kMaskYpos;   
985     Int_t iYtri = ( i >>   4           ) & kMaskYtri;
986     Int_t iXdev = ( i >> ( 4 + 1 )     ) & kMaskXdev;
987     Int_t iXpos = ( i >> ( 4 + 1 + 5 ) ) & kMaskXpos;
988     
989     // convert deviation format
990     // online: sign 1bit , dev 4bit
991     // sign    dev    trigger
992     // 0       1-15   mu-
993     // 1       1-15   mu+
994     // 0       0      mu+, mu- infinite momentum (unde)
995     // 1       0      no x-trigger
996     // offline: dev 5bit
997     // sign    dev    trigger
998     // -        0-14  mu-
999     // -       16-31  mu+
1000     // -       15     mu+, mu- infinite momentum (unde)
1001     Int_t iXdevOn  = 0;
1002     Int_t iXdevOff = 0;
1003     Int_t sign     = 0;
1004     Bool_t trigx = kFALSE;
1005     iXdevOn +=  iXdev & 0x0F;
1006     sign    += (iXdev >> 4) & 0x01;
1007     if (iXdevOn == 0) {
1008       if (sign == 0) {
1009         iXdevOff = 15;
1010         trigx = kTRUE;
1011       } else {
1012         iXdevOff = 15;
1013         trigx = kFALSE;
1014       }
1015     } else {
1016       trigx = kTRUE;
1017       if (sign == 0) {
1018         iXdevOff = - iXdevOn + 15;  // gives range  0-14
1019       } else {
1020         iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
1021       }
1022     }
1023     iXdev = iXdevOff;
1024
1025     // iYtri == 1 means no trigger in y-direction
1026     if (iYtri == 0 && trigx) 
1027     {
1028       lut.GetLutOutput(localBoardId,iXpos,iXdev,iYpos,lutLpt,lutHpt);
1029     }
1030     
1031     // fill byte
1032     if (i%2 == 0) 
1033     {
1034       // upper half-byte
1035       buffer[bc] = 0;       
1036       buffer[bc] += lutHpt[1] << 7;
1037       buffer[bc] += lutHpt[0] << 6;
1038       buffer[bc] += lutLpt[1] << 5;
1039       buffer[bc] += lutLpt[0] << 4;
1040     } else {
1041       // lower half-byte
1042       buffer[bc] += lutHpt[1] << 3;
1043       buffer[bc] += lutHpt[0] << 2;
1044       buffer[bc] += lutLpt[1] << 1;
1045       buffer[bc] += lutLpt[0] << 0;
1046       bc++;
1047     }
1048   }
1049   fwrite(&buffer,bc,1,flut);
1050 }  
1051
1052 //_____________________________________________________________________________
1053 Int_t 
1054 AliMUONTriggerIO::LocalBoardId(Int_t index) const
1055 {  
1056   /// Return the i-th localBoardId, or -1 if index is out of bounds
1057
1058   return fRegionalTrigger.LocalBoardId(index);
1059 }
1060
1061
1062 //______________________________________________________________________________
1063
1064 Int_t AliMUONTriggerIO::LocalBoardId(Int_t ddlId, Int_t crateId, Int_t localId) const
1065 {
1066     /// Return local board id from crate and local indexes.
1067     
1068     Int_t nofDDLs = 0;
1069     TString name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
1070
1071     AliMpTriggerCrate* crate = fRegionalTrigger.FindTriggerCrate(name, false);
1072     return crate->GetLocalBoardId(localId);
1073 }