Adding first version of trigger LUT handling to Shuttle
[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
20 #include "AliLog.h"
21 #include "AliMpCDB.h"
22 #include "AliMpDDLStore.h"
23 #include "AliMpTriggerCrate.h"
24 #include "AliMUONTriggerLut.h"
25 #include "AliMUONCalibParamNI.h"
26 #include "AliMUONVStore.h"
27 #include <Riostream.h>
28 #include <TSystem.h>
29
30 /// \class AliMUONTriggerIO
31 ///
32 /// Handles read/write of masks and LUT to/from online files, 
33 /// to be used by Shuttle and Trigger DA.
34 /// 
35 /// \author Laurent Aphecetche, Subatech
36 /// \author Bogdan Vulpescu, LPC Clermont-Ferrand
37
38 /// \cond CLASSIMP
39 ClassImp(AliMUONTriggerIO)
40 /// \endcond
41
42 //_____________________________________________________________________________
43 AliMUONTriggerIO::AliMUONTriggerIO() :
44  TObject(), fLocalBoardIds(), fNofLocalBoards(0)
45 {
46   /// ctor
47 }
48
49 //_____________________________________________________________________________
50 AliMUONTriggerIO::AliMUONTriggerIO(const char* regionalFileToRead) :
51 TObject(), fLocalBoardIds(), fNofLocalBoards(0)
52 {
53   /// ctor
54   ReadRegional(regionalFileToRead,0);
55 }
56
57 //_____________________________________________________________________________
58 AliMUONTriggerIO::~AliMUONTriggerIO()
59 {
60   /// dtor
61 }
62
63 //_____________________________________________________________________________
64 void 
65 AliMUONTriggerIO::DeCompAddress(UChar_t &ypos, UChar_t &ytri, UChar_t &xdev, UChar_t &xpos, 
66                                 UShort_t address) const
67 {  
68   /// decompose the 15-bits address
69   
70   UChar_t bitsYpos = 4;
71   UChar_t bitsYtri = 1;
72   UChar_t bitsXdev = 5;
73   //  UChar_t bitsXpos = 5;
74   
75   UShort_t maskYpos = 0x000F; // ...0 00001111
76   UShort_t maskYtri = 0x0001; // ...0 00000001
77   UShort_t maskXdev = 0x001F; // ...0 00011111
78   UShort_t maskXpos = 0x001F; // ...0 00011111
79   
80   ypos =  address                                  & maskYpos;
81   ytri = (address >>  bitsYpos)                    & maskYtri;
82   xdev = (address >> (bitsYpos+bitsYtri))          & maskXdev;
83   xpos = (address >> (bitsYpos+bitsYtri+bitsXdev)) & maskXpos;
84 }
85
86 //_____________________________________________________________________________
87 void 
88 AliMUONTriggerIO::FillLut(AliMUONTriggerLut& lut,
89                           Int_t icirc, UChar_t istripX, UChar_t idev,  
90                           Int_t lutLpt[16][2], Int_t lutHpt[16][2]) 
91 {
92   /// Fill the LUT histograms
93   
94   if (icirc == 0 && istripX == 0 && idev == 0) 
95   {
96     AliDebug(1,"Copy board, not filled ...");
97     return;
98   }
99   
100   Short_t iLptPlus, iLptMinu, iLptUnde;
101   Short_t iHptPlus, iHptMinu, iHptUnde;
102
103   iLptPlus = iLptMinu = iLptUnde = 0;
104   iHptPlus = iHptMinu = iHptUnde = 0;
105   
106   for (Int_t istripY=0; istripY<16; istripY++) 
107   {
108     if (lutLpt[istripY][1] == 0 && lutLpt[istripY][0] ==1)
109       iLptMinu=iLptMinu+(1 << istripY);
110     if (lutLpt[istripY][1] == 1 && lutLpt[istripY][0] ==0)
111       iLptPlus=iLptPlus+(1 << istripY);
112     if (lutLpt[istripY][1] == 1 && lutLpt[istripY][0] ==1)
113       iLptUnde=iLptUnde+(1 << istripY);
114     
115     if (lutHpt[istripY][1] == 0 && lutHpt[istripY][0] ==1)
116       iHptMinu=iHptMinu+(1 << istripY);
117     if (lutHpt[istripY][1] == 1 && lutHpt[istripY][0] ==0)
118       iHptPlus=iHptPlus+(1 << istripY);
119     if (lutHpt[istripY][1] == 1 && lutHpt[istripY][0] ==1)
120       iHptUnde=iHptUnde+(1 << istripY);
121     
122   } // loop on istripY
123   
124   lut.SetContent("LptMinu",icirc,istripX,idev,iLptMinu);
125   lut.SetContent("LptUnde",icirc,istripX,idev,iLptUnde);
126   lut.SetContent("LptPlus",icirc,istripX,idev,iLptPlus);
127
128   lut.SetContent("HptMinu",icirc,istripX,idev,iLptMinu);
129   lut.SetContent("HptUnde",icirc,istripX,idev,iLptUnde);
130   lut.SetContent("HptPlus",icirc,istripX,idev,iLptPlus);
131 }
132
133 //_____________________________________________________________________________
134 Int_t 
135 AliMUONTriggerIO::LocalBoardId(Int_t index) const
136 {
137   /// Return the i-th localBoardId, or -1 if index is out of bounds
138   if ( index >= 0 && index < fNofLocalBoards ) 
139   {
140     return fLocalBoardIds[index];
141   }
142   return -1;
143 }
144
145 //_____________________________________________________________________________
146 Int_t
147 AliMUONTriggerIO::ReadLocalMasks(const char* localFile, AliMUONVStore& localMasks) const
148 {
149   /// Fills the local masks store from file
150   
151   if ( !NofLocalBoards() )
152   {
153     AliError("No local board to read");
154     return 0;
155   }
156   
157   FILE* fp = fopen(gSystem->ExpandPathName(localFile),"r");
158   if (!fp)
159   {
160     AliError(Form("Could not read file %s",localFile));
161     return 0;
162   }
163   
164   UShort_t maskBuffer[8];
165   
166   Int_t nLocalBoards(0);
167   
168   while ( fread ( maskBuffer, 2, 8, fp ) )
169   {
170     Int_t localBoardId = LocalBoardId(nLocalBoards);
171     AliDebug(1,Form("LB %03d X1 %4x X2 %4x X3 %4x X4 %4x "
172                     "Y1 %4x Y2 %4x Y3 %4x Y4 %4x",
173                     localBoardId,
174                     maskBuffer[0],
175                     maskBuffer[1],
176                     maskBuffer[2],
177                     maskBuffer[3],
178                     maskBuffer[4],
179                     maskBuffer[5],
180                     maskBuffer[6],
181                     maskBuffer[7]));
182     
183     if ( localBoardId ) 
184     {
185       AliMUONVCalibParam* localBoard = new AliMUONCalibParamNI(1,8,localBoardId,0,0);
186       for ( Int_t x = 0; x < 2; ++x )
187       {
188         for ( Int_t y = 0; y < 4; ++y )
189         {
190           Int_t index = x*4+y;
191           localBoard->SetValueAsInt(index,0,maskBuffer[index]);
192         }
193       }
194       localMasks.Add(localBoard);
195     }
196     
197     ++nLocalBoards;
198   }
199   
200   if ( nLocalBoards != NofLocalBoards() ) 
201   {
202     AliError(Form("Read %d out of %d local boards",
203                   nLocalBoards, NofLocalBoards()));
204   }
205   
206   fclose(fp);
207   
208   return nLocalBoards;
209 }
210
211 //_____________________________________________________________________________
212 void
213 AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
214                                Int_t localBoardId,
215                                FILE* flut)
216 {
217   /// Read the LUT for one local board from an online file
218
219   UShort_t address;
220   
221   UChar_t buffer;
222   UChar_t mask1 = 0xF0;
223   UChar_t mask2 = 0x0F;
224   UChar_t maskLpt = 0x0C;
225   UChar_t maskHpt = 0x03;
226   UChar_t lh, lpt, hpt;
227   
228   UChar_t xpos, xdev, ypos, ytri;
229   
230   Int_t lutLpt[16][2], lutHpt[16][2];
231
232   Int_t boardnr = localBoardId;
233   
234   AliDebug(1,Form("Reading LUT values for local board %d",boardnr));
235   
236   Int_t ny = 0;
237   
238   // create the 32767 addresses for the 4-bits lpt and hpt half-bytes
239   for (UShort_t ilut = 0; ilut < 0x7FFF; ilut += 2) 
240   {
241     // read two lut addresses at once
242     fread(&buffer,1,1,flut);
243     
244     // 1st 4-bits half-byte
245     address = ilut;   
246     lh = (buffer & mask1) >> 4;
247     
248     // Lpt and Hpt response
249     lpt = (lh & maskLpt) >> 2;
250     hpt =  lh & maskHpt;
251     
252     // decompose the 15-bits address
253     DeCompAddress(ypos,ytri,xdev,xpos,address);
254     
255     // calculate group of y-strips
256     if (ny < 16) 
257     {
258       lutLpt[ny][0] =  lpt & 1;
259       lutLpt[ny][1] = (lpt & 2) >> 1;
260       lutHpt[ny][0] =  hpt & 1;
261       lutHpt[ny][1] = (hpt & 2) >> 1;
262       ny++;
263       if (ny == 16) 
264       {
265         ny = 0;
266         // ytri == 1 means no trigger in y-direction
267         if (ytri == 0) 
268         {
269           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
270         }
271       }
272     }
273     
274     // 2nd 4-bits half-byte
275     address = ilut+1; 
276     lh = (buffer & mask2);
277     
278     // Lpt and Hpt response
279     lpt = (lh & maskLpt) >> 2;
280     hpt =  lh & maskHpt;
281     
282     // decompose the 15-bits address
283     DeCompAddress(ypos,ytri,xdev,xpos,address);
284     
285     // calculate group of y-strips
286     if (ny < 16) 
287     {
288       lutLpt[ny][0] =  lpt & 1;
289       lutLpt[ny][1] = (lpt & 2) >> 1;
290       lutHpt[ny][0] =  hpt & 1;
291       lutHpt[ny][1] = (hpt & 2) >> 1;
292       ny++;
293       if (ny == 16) 
294       {
295         ny = 0;
296         // ytri == 1 means no trigger in y-direction
297         if (ytri == 0) 
298         {
299           FillLut(lut,boardnr,xpos,xdev,lutLpt,lutHpt);
300         }
301       }
302     }
303   }
304 }
305
306 //_____________________________________________________________________________
307 Bool_t 
308 AliMUONTriggerIO::ReadLUT(const char* lutFileToRead, AliMUONTriggerLut& lut)
309 {
310   /// Fill the LUT object from online file
311   
312   if ( !NofLocalBoards() )
313   {
314     AliError("No local board id defined. Must read a regional file first");
315     return kFALSE;
316   }
317   
318   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToRead),"rb");
319   if (!flut) 
320   {
321     AliError(Form("Could not create output LUT file %s",lutFileToRead));
322     return kFALSE;
323   }   
324   
325   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
326   {
327     ReadLocalLUT(lut,LocalBoardId(i),flut);
328   }
329   
330   fclose(flut);
331   
332   return kTRUE;
333   
334 }
335
336 //_____________________________________________________________________________
337 Bool_t 
338 AliMUONTriggerIO::ReadMasks(const char* localFile,
339                             const char* regionalFile,
340                             const char* /* globalFile */,
341                             AliMUONVStore* localMasks,
342                             AliMUONVStore* regionalMasks,
343                             AliMUONVCalibParam* /* globalMasks */)
344 {
345   /// Fill the various masks store from files
346   
347   if ( !regionalFile ) 
348   {
349     AliError("Must have a regional file name to proceeed");
350     return kFALSE;
351   }
352   
353   Int_t nCrates = ReadRegional(regionalFile,regionalMasks);
354   
355   if (!nCrates) return kFALSE;
356   
357   if (localMasks && localFile)
358   {
359     Int_t nLocal = ReadLocalMasks(localFile,*localMasks);
360     AliDebug(1,Form("Read masks for %d local boards",nLocal));
361   }
362   
363   return kTRUE;
364 }
365
366 //_____________________________________________________________________________
367 Int_t
368 AliMUONTriggerIO::ReadRegional(const char* regionalFile, AliMUONVStore* regionalMasks)
369 {
370   /// Read regional file to fill the regional mask store *AND* 
371   /// determine the order in which local boards will appear in local 
372   /// and lut files.
373   
374   fLocalBoardIds.Reset();
375   fNofLocalBoards = 0;
376   
377   std::ifstream in(gSystem->ExpandPathName(regionalFile));
378   if (!in.good()) 
379   {
380     AliError(Form("Cannot read file %s",regionalFile));
381     return 0;
382   }
383
384   char name[80];
385   char line[80];
386   
387   Int_t nCrates(0);
388   
389   if (!AliMpDDLStore::Instance(kFALSE))
390   {
391     AliMpCDB::LoadDDLStore();
392   }
393   
394   while (!in.eof())
395   {
396     in.getline(name,80);
397     
398     if (!strlen(name)) break;
399
400     AliDebug(1,Form("Looking for crate %s",name));
401     
402     AliMpTriggerCrate* triggerCrate = AliMpDDLStore::Instance()->GetTriggerCrate(name);
403     
404     if (!triggerCrate)
405     {
406       AliError(Form("Mapping error : could not get crate %s",name));
407       return 0;
408     }
409     
410     ++nCrates;
411     
412     UShort_t id, mask;
413     Int_t mode, coincidence;
414     
415     in.getline(line,80);    
416     sscanf(line,"%hx",&id);
417
418     in.getline(line,80);
419     sscanf(line,"%d",&mode);
420     
421     in.getline(line,80);
422     sscanf(line,"%d",&coincidence);
423     
424     in.getline(line,80);
425     sscanf(line,"%hx",&mask);
426
427     if ( regionalMasks ) 
428     {
429       AliMUONVCalibParam* regionalBoard = new AliMUONCalibParamNI(1,16,id,0,0);
430       regionalBoard->SetValueAsInt(0,0,mask);
431       regionalMasks->Add(regionalBoard);
432       //FIXME: lines below should not be needed, as regionalMask should be only 1 16 bits word, not 16 16 bits word...
433       for ( Int_t j = 1; j < 16; ++j )
434       {
435         regionalBoard->SetValueAsInt(j,0,0x3F);
436       }      
437     }
438     
439     AliDebug(1,Form("Name %s ID %x Mode %d Coin %d Mask %x",
440                     name,id,mode,coincidence,mask));
441     
442     for ( Int_t i = 0; i < 16; ++i ) 
443     {
444       if ( (mask >> i ) & 0x1 )
445       {          
446         in.getline(line,80);
447         char localBoardName[20];
448         int j,localBoardId,switches;
449         sscanf(line,"%02d %s %03d %03x",&j,localBoardName,&localBoardId,&switches);
450         AliDebug(1,Form("%02d %s %03d %03x",j,localBoardName,localBoardId,switches));
451         fLocalBoardIds.Set(fNofLocalBoards+1);
452         fLocalBoardIds[fNofLocalBoards] = localBoardId;
453         ++fNofLocalBoards;
454       }
455     }
456   }
457   
458   return nCrates;  
459 }
460
461 //_____________________________________________________________________________
462 Bool_t 
463 AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
464                            const char* lutFileToWrite)
465 {
466   /// Convert an offline lut into an online (binary) lut file
467   
468   if ( !NofLocalBoards() )
469   {
470     AliError("No local board id defined. Must read a regional file first");
471     return kFALSE;
472   }
473   
474   FILE* flut = fopen(gSystem->ExpandPathName(lutFileToWrite),"wb");
475   if (!flut) 
476   {
477     AliError(Form("Could not create output LUT file %s",lutFileToWrite));
478     return kFALSE;
479   }   
480   
481   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
482   {
483     WriteLocalLUT(lut,LocalBoardId(i),flut);
484   }
485   
486   fclose(flut);
487   
488   return kTRUE;
489 }
490
491 //_____________________________________________________________________________
492 void
493 AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
494                                 Int_t localBoardId,
495                                 FILE* flut)
496 {
497   /// loop over the address for the 4-bits lpt and hpt decisions
498
499   const Int_t kMaskYpos = 0x0F;
500   const Int_t kMaskYtri = 0x01;
501   const Int_t kMaskXdev = 0x1F;
502   const Int_t kMaskXpos = 0x1F;
503   
504   for (Int_t i = 0; i < 32768; ++i) 
505   {
506     Int_t lutLpt[2] = { 0 };
507     Int_t lutHpt[2] = { 0 };
508     
509     // decompose address
510     Int_t iYpos =   i                    & kMaskYpos;   
511     Int_t iYtri = ( i >>   4           ) & kMaskYtri;
512     Int_t iXdev = ( i >> ( 4 + 1 )     ) & kMaskXdev;
513     Int_t iXpos = ( i >> ( 4 + 1 + 5 ) ) & kMaskXpos;
514     
515     // iYtri == 1 means no trigger in y-direction
516     if (iYtri == 0) 
517     {
518       lut.GetLutOutput(localBoardId,iXpos,iXdev,iYpos,lutLpt,lutHpt);
519     }
520     
521     UChar_t buffer;
522     
523     // fill byte
524     if (i%2 == 0) 
525     {
526       // upper half-byte
527       buffer = 0;           
528       buffer += lutLpt[1] << 7;
529       buffer += lutLpt[0] << 6;
530       buffer += lutHpt[1] << 5;
531       buffer += lutHpt[0] << 4;
532     } else {
533       // lower half-byte
534       buffer += lutLpt[1] << 3;
535       buffer += lutLpt[0] << 2;
536       buffer += lutHpt[1] << 1;
537       buffer += lutHpt[0] << 0;
538       fwrite(&buffer,1,1,flut);
539     }
540   }
541 }  
542