]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONTriggerIO.cxx
Flexible pt range for the efficiency histogramming
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerIO.cxx
index faca3d3d42bf6dca422a71bac495fe69e93d6196..e05b1022da503c91376c98c7d83009f33988ba3a 100644 (file)
 // $Id$
 
 #include "AliMUONTriggerIO.h"
+#include "AliMUONTriggerLut.h"
+#include "AliMUONCalibParamNI.h"
+#include "AliMUONVStore.h"
 
-#include "AliLog.h"
 #include "AliMpCDB.h"
+#include "AliMpHelper.h"
+#include "AliMpConstants.h"
+#include "AliMpDDL.h"
+#include "AliMpFiles.h"
 #include "AliMpDDLStore.h"
+#include "AliMpLocalBoard.h"
 #include "AliMpTriggerCrate.h"
-#include "AliMUONTriggerLut.h"
-#include "AliMUONCalibParamNI.h"
-#include "AliMUONVStore.h"
+#include "AliMUONGlobalCrateConfig.h"
+#include "AliMUONRegionalTriggerConfig.h"
+#include "AliMUONTriggerCrateConfig.h"
+
+#include "AliLog.h"
+
 #include <Riostream.h>
 #include <TSystem.h>
 
 /// Handles read/write of masks and LUT to/from online files, 
 /// to be used by Shuttle and Trigger DA.
 /// 
-/// \author Laurent Aphecetche, Subatech
+/// \author Laurent Aphecetche, Christian Finck Subatech
 /// \author Bogdan Vulpescu, LPC Clermont-Ferrand
 
+using std::endl;
+using std::cout;
+using std::ofstream;
 /// \cond CLASSIMP
 ClassImp(AliMUONTriggerIO)
 /// \endcond
 
+
+const UInt_t AliMUONTriggerIO::fgkLocalLutSize = 1 << 14; // 16384
+
 //_____________________________________________________________________________
-AliMUONTriggerIO::AliMUONTriggerIO() :
- TObject(), fLocalBoardIds(), fNofLocalBoards(0)
+AliMUONTriggerIO::AliMUONTriggerIO() 
+    : TObject(), 
+      fRegionalTrigger()
 {
   /// ctor
 }
 
 //_____________________________________________________________________________
-AliMUONTriggerIO::AliMUONTriggerIO(const char* regionalFileToRead) :
-TObject(), fLocalBoardIds(), fNofLocalBoards(0)
+AliMUONTriggerIO::AliMUONTriggerIO(const char* regionalFileToRead) 
+    :TObject(), 
+     fRegionalTrigger()
 {
   /// ctor
-  ReadRegional(regionalFileToRead,0);
+  ReadRegionalConfig(regionalFileToRead,0);
 }
 
 //_____________________________________________________________________________
@@ -61,7 +79,7 @@ AliMUONTriggerIO::~AliMUONTriggerIO()
 }
 
 //_____________________________________________________________________________
-void 
+Bool_t 
 AliMUONTriggerIO::DeCompAddress(UChar_t &ypos, UChar_t &ytri, UChar_t &xdev, UChar_t &xpos, 
                                 UShort_t address) const
 {  
@@ -81,6 +99,49 @@ AliMUONTriggerIO::DeCompAddress(UChar_t &ypos, UChar_t &ytri, UChar_t &xdev, UCh
   ytri = (address >>  bitsYpos)                    & maskYtri;
   xdev = (address >> (bitsYpos+bitsYtri))          & maskXdev;
   xpos = (address >> (bitsYpos+bitsYtri+bitsXdev)) & maskXpos;
+
+  // convert deviation format
+  // online: sign 1bit , dev 4bit
+  // sign    dev    trigger
+  // 0       1-15   mu-
+  // 1       1-15   mu+
+  // 0       0      mu+, mu- infinite momentum (unde)
+  // 1       0      no x-trigger
+  // offline: dev 5bit
+  // sign    dev    trigger
+  // -        0-14  mu-
+  // -       16-31  mu+
+  // -       15     mu+, mu- infinite momentum (unde)
+
+  Int_t iXdevOff, iXdevOn, iXdev, sign;
+  Bool_t trigx;
+
+  iXdev = xdev;
+
+  iXdevOn = sign = 0;
+  iXdevOn +=  iXdev & 0x0F;
+  sign    += (iXdev >> 4) & 0x01;
+  if (iXdevOn == 0) {
+    if (sign == 0) {
+      iXdevOff = 15;
+      trigx = kTRUE;
+    } else {
+      iXdevOff = 15;
+      trigx = kFALSE;
+    }
+  } else {
+    trigx = kTRUE;
+    if (sign == 0) {
+      iXdevOff = - iXdevOn + 15;  // gives range  0-14
+    } else {
+      iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
+    }
+  }
+
+  xdev = iXdevOff;
+
+  return trigx;
+
 }
 
 //_____________________________________________________________________________
@@ -125,21 +186,9 @@ AliMUONTriggerIO::FillLut(AliMUONTriggerLut& lut,
   lut.SetContent("LptUnde",icirc,istripX,idev,iLptUnde);
   lut.SetContent("LptPlus",icirc,istripX,idev,iLptPlus);
 
-  lut.SetContent("HptMinu",icirc,istripX,idev,iLptMinu);
-  lut.SetContent("HptUnde",icirc,istripX,idev,iLptUnde);
-  lut.SetContent("HptPlus",icirc,istripX,idev,iLptPlus);
-}
-
-//_____________________________________________________________________________
-Int_t 
-AliMUONTriggerIO::LocalBoardId(Int_t index) const
-{
-  /// Return the i-th localBoardId, or -1 if index is out of bounds
-  if ( index >= 0 && index < fNofLocalBoards ) 
-  {
-    return fLocalBoardIds[index];
-  }
-  return -1;
+  lut.SetContent("HptMinu",icirc,istripX,idev,iHptMinu);
+  lut.SetContent("HptUnde",icirc,istripX,idev,iHptUnde);
+  lut.SetContent("HptPlus",icirc,istripX,idev,iHptPlus);
 }
 
 //_____________________________________________________________________________
@@ -163,11 +212,11 @@ AliMUONTriggerIO::ReadLocalMasks(const char* localFile, AliMUONVStore& localMask
   
   UShort_t maskBuffer[8];
   
-  Int_t nLocalBoards(0);
-  
+  Int_t localBoardIndex(0);
+    
   while ( fread ( maskBuffer, 2, 8, fp ) )
   {
-    Int_t localBoardId = LocalBoardId(nLocalBoards);
+    Int_t localBoardId = fRegionalTrigger.LocalBoardId(localBoardIndex);
     AliDebug(1,Form("LB %03d X1 %4x X2 %4x X3 %4x X4 %4x "
                     "Y1 %4x Y2 %4x Y3 %4x Y4 %4x",
                     localBoardId,
@@ -180,32 +229,32 @@ AliMUONTriggerIO::ReadLocalMasks(const char* localFile, AliMUONVStore& localMask
                     maskBuffer[6],
                     maskBuffer[7]));
     
-    if ( localBoardId ) 
+    if ( localBoardId > 0 
     {
       AliMUONVCalibParam* localBoard = new AliMUONCalibParamNI(1,8,localBoardId,0,0);
-      for ( Int_t x = 0; x < 2; ++x )
+      for ( Int_t index = 0; index < 8; ++index )
       {
-        for ( Int_t y = 0; y < 4; ++y )
-        {
-          Int_t index = x*4+y;
-          localBoard->SetValueAsInt(index,0,maskBuffer[index]);
-        }
+        localBoard->SetValueAsInt(index,0,maskBuffer[index]);
       }
       localMasks.Add(localBoard);
     }
+    else
+    {
+      AliError(Form("Oups. Got localBoardId=%d for index=%d",localBoardId,localBoardIndex));
+    }
     
-    ++nLocalBoards;
+    ++localBoardIndex;
   }
   
-  if ( nLocalBoards != NofLocalBoards() ) 
+  if ( localBoardIndex != NofLocalBoards() ) 
   {
     AliError(Form("Read %d out of %d local boards",
-                  nLocalBoards, NofLocalBoards()));
+                  localBoardIndex, NofLocalBoards()));
   }
   
   fclose(fp);
   
-  return nLocalBoards;
+  return localBoardIndex+1;
 }
 
 //_____________________________________________________________________________
@@ -218,11 +267,11 @@ AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
 
   UShort_t address;
   
-  UChar_t buffer;
+  UChar_t buffer[fgkLocalLutSize];   // 32768 hpt/lpt addresses divided by two
   UChar_t mask1 = 0xF0;
   UChar_t mask2 = 0x0F;
-  UChar_t maskLpt = 0x0C;
-  UChar_t maskHpt = 0x03;
+  UChar_t maskHpt = 0x0C;
+  UChar_t maskLpt = 0x03;
   UChar_t lh, lpt, hpt;
   
   UChar_t xpos, xdev, ypos, ytri;
@@ -234,26 +283,31 @@ AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
   AliDebug(1,Form("Reading LUT values for local board %d",boardnr));
   
   Int_t ny = 0;
+  Bool_t trigx = kFALSE;
   
+  // read two lut addresses at once, 32768/2=16384 times
+  if (fread(buffer,fgkLocalLutSize,1,flut) == 0) {
+    AliWarning("Error reading the LUT file");
+    return;
+  }
+
   // create the 32767 addresses for the 4-bits lpt and hpt half-bytes
-  for (UShort_t ilut = 0; ilut < 0x7FFF; ilut += 2) 
+  for (UShort_t ilut = 0; ilut < fgkLocalLutSize*2; ilut += 2) 
   {
-    // read two lut addresses at once
-    fread(&buffer,1,1,flut);
     
     // 1st 4-bits half-byte
     address = ilut;   
-    lh = (buffer & mask1) >> 4;
+    lh = (buffer[ilut/2] & mask1) >> 4;
     
     // Lpt and Hpt response
-    lpt = (lh & maskLpt) >> 2;
-    hpt =  lh & maskHpt;
+    hpt = (lh & maskHpt) >> 2;
+    lpt =  lh & maskLpt;
     
     // decompose the 15-bits address
-    DeCompAddress(ypos,ytri,xdev,xpos,address);
+    trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
     
     // calculate group of y-strips
-    if (ny < 16
+    if (trigx && (ny < 16)
     {
       lutLpt[ny][0] =  lpt & 1;
       lutLpt[ny][1] = (lpt & 2) >> 1;
@@ -273,17 +327,17 @@ AliMUONTriggerIO::ReadLocalLUT(AliMUONTriggerLut& lut,
     
     // 2nd 4-bits half-byte
     address = ilut+1; 
-    lh = (buffer & mask2);
+    lh = (buffer[ilut/2] & mask2);
     
     // Lpt and Hpt response
-    lpt = (lh & maskLpt) >> 2;
-    hpt =  lh & maskHpt;
+    hpt = (lh & maskHpt) >> 2;
+    lpt =  lh & maskLpt;
     
     // decompose the 15-bits address
-    DeCompAddress(ypos,ytri,xdev,xpos,address);
+    trigx = DeCompAddress(ypos,ytri,xdev,xpos,address);
     
     // calculate group of y-strips
-    if (ny < 16
+    if (trigx && (ny < 16)
     {
       lutLpt[ny][0] =  lpt & 1;
       lutLpt[ny][1] = (lpt & 2) >> 1;
@@ -324,140 +378,112 @@ AliMUONTriggerIO::ReadLUT(const char* lutFileToRead, AliMUONTriggerLut& lut)
   
   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
   {
-    ReadLocalLUT(lut,LocalBoardId(i),flut);
+    ReadLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
   }
   
+  // 
+  // 1st/2nd cut code   pt cut [GeV/c]
+  //
+  // 0                 0.5 (a.k.a. Apt)
+  // 1                 1.0 (a.k.a. Lpt)
+  // 2                 1.7 (a.k.a. Hpt)
+  // 3                 4.2 (a.k.a. infinity)
+  // 4                 free
+  // .
+  // .
+  // .
+  //15                 default (for backward compatibility)
+
+  UChar_t lutCode = 0xFF;
+
+  if (!fread(&lutCode,1,1,flut)) {
+    AliWarning("No LUT info in the file (old version)");
+  }
+  AliInfo(Form("LUT code: 0x%02x",lutCode));
+
   fclose(flut);
-  
+
+  lut.SetLutCode(lutCode);
+
   return kTRUE;
   
 }
 
 //_____________________________________________________________________________
 Bool_t 
-AliMUONTriggerIO::ReadMasks(const char* localFile,
-                            const char* regionalFile,
-                            const char* /* globalFile */,
-                            AliMUONVStore* localMasks,
-                            AliMUONVStore* regionalMasks,
-                            AliMUONVCalibParam* /* globalMasks */)
+AliMUONTriggerIO::ReadConfig(const char* localFile,
+                             const char* regionalFile,
+                             const char* globalFile,
+                             AliMUONVStore* localMasks,
+                             AliMUONRegionalTriggerConfig* regionalConfig,
+                             AliMUONGlobalCrateConfig* globalConfig)
 {
   /// Fill the various masks store from files
   
-  if ( !regionalFile ) 
+  if ( !regionalConfig || !regionalFile || strlen(regionalFile)==0 ) 
   {
     AliError("Must have a regional file name to proceeed");
     return kFALSE;
   }
   
-  Int_t nCrates = ReadRegional(regionalFile,regionalMasks);
+  AliDebug(1,Form("regionalConfig=%p",regionalConfig));
   
-  if (!nCrates) return kFALSE;
+  Int_t nCrates = ReadRegionalConfig(regionalFile, regionalConfig);
+
+  if (!nCrates) 
+  {
+    AliError("nCrates=0 !");
+    return kFALSE;
+  }
   
-  if (localMasks && localFile)
+  if (localMasks && localFile && strlen(localFile) > 0 )
   {
     Int_t nLocal = ReadLocalMasks(localFile,*localMasks);
     AliDebug(1,Form("Read masks for %d local boards",nLocal));
   }
   
+  Int_t nDarc = ReadGlobalConfig(globalFile, globalConfig);
+  AliDebug(1,Form("Read config for %d DARC boards",nDarc));
+  
+  if (!nDarc) return kFALSE;
+  
   return kTRUE;
 }
 
+
+
 //_____________________________________________________________________________
-Int_t
-AliMUONTriggerIO::ReadRegional(const char* regionalFile, AliMUONVStore* regionalMasks)
+ Int_t 
+ AliMUONTriggerIO::ReadGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig) const
 {
-  /// Read regional file to fill the regional mask store *AND* 
-  /// determine the order in which local boards will appear in local 
-  /// and lut files.
+  /// read the global crate file
+  /// the masks are disable bit for each crate, 8 per darc board
+  /// bit value 0 means enable, 1 means disable                                                 * 
   
-  fLocalBoardIds.Reset();
-  fNofLocalBoards = 0;
+  Int_t nDarc = 0;
+  if ( !(nDarc = globalConfig->ReadData(globalFile)) ) return 0;
   
-  std::ifstream in(gSystem->ExpandPathName(regionalFile));
-  if (!in.good()) 
-  {
-    AliError(Form("Cannot read file %s",regionalFile));
-    return 0;
-  }
-
-  char name[80];
-  char line[80];
-  
-  Int_t nCrates(0);
+  return nDarc;
+}
+//_____________________________________________________________________________
+Int_t
+AliMUONTriggerIO::ReadRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig)
+{
+  /// Read regional file to fill  
   
-  if (!AliMpDDLStore::Instance(kFALSE))
-  {
-    AliMpCDB::LoadDDLStore();
-  }
+  AliDebug(1,Form("regionalConfig=%p",regionalConfig));
   
-  while (!in.eof())
-  {
-    in.getline(name,80);
-    
-    if (!strlen(name)) break;
-
-    AliDebug(1,Form("Looking for crate %s",name));
-    
-    AliMpTriggerCrate* triggerCrate = AliMpDDLStore::Instance()->GetTriggerCrate(name);
-    
-    if (!triggerCrate)
-    {
-      AliError(Form("Mapping error : could not get crate %s",name));
-      return 0;
-    }
-    
-    ++nCrates;
-    
-    UShort_t id, mask;
-    Int_t mode, coincidence;
-    
-    in.getline(line,80);    
-    sscanf(line,"%hx",&id);
+  Int_t nCrates = 0;
+  if ( !(nCrates = regionalConfig->ReadData(regionalFile)) ) return 0;
 
-    in.getline(line,80);
-    sscanf(line,"%d",&mode);
-    
-    in.getline(line,80);
-    sscanf(line,"%d",&coincidence);
-    
-    in.getline(line,80);
-    sscanf(line,"%hx",&mask);
+  // read the mapping file also
+  if ( ! fRegionalTrigger.ReadData(regionalFile) ) return 0;
 
-    if ( regionalMasks ) 
-    {
-      AliMUONVCalibParam* regionalBoard = new AliMUONCalibParamNI(1,16,id,0,0);
-      regionalBoard->SetValueAsInt(0,0,mask);
-      regionalMasks->Add(regionalBoard);
-      //FIXME: lines below should not be needed, as regionalMask should be only 1 16 bits word, not 16 16 bits word...
-      for ( Int_t j = 1; j < 16; ++j )
-      {
-        regionalBoard->SetValueAsInt(j,0,0x3F);
-      }      
-    }
-    
-    AliDebug(1,Form("Name %s ID %x Mode %d Coin %d Mask %x",
-                    name,id,mode,coincidence,mask));
-    
-    for ( Int_t i = 0; i < 16; ++i ) 
-    {
-      if ( (mask >> i ) & 0x1 )
-      {          
-        in.getline(line,80);
-        char localBoardName[20];
-        int j,localBoardId,switches;
-        sscanf(line,"%02d %s %03d %03x",&j,localBoardName,&localBoardId,&switches);
-        AliDebug(1,Form("%02d %s %03d %03x",j,localBoardName,localBoardId,switches));
-        fLocalBoardIds.Set(fNofLocalBoards+1);
-        fLocalBoardIds[fNofLocalBoards] = localBoardId;
-        ++fNofLocalBoards;
-      }
-    }
-  }
-  
   return nCrates;  
 }
 
+
 //_____________________________________________________________________________
 Bool_t 
 AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
@@ -480,7 +506,7 @@ AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
   
   for ( Int_t i = 0; i < NofLocalBoards(); ++i ) 
   {
-    WriteLocalLUT(lut,LocalBoardId(i),flut);
+    WriteLocalLUT(lut,fRegionalTrigger.LocalBoardId(i),flut);
   }
   
   fclose(flut);
@@ -488,6 +514,231 @@ AliMUONTriggerIO::WriteLUT(const AliMUONTriggerLut& lut,
   return kTRUE;
 }
 
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONTriggerIO::WriteConfig(const char* localFile,
+                            const char* regionalFile,
+                            const char* globalFile,
+                            const AliMUONVStore* localMasks,
+                    AliMUONRegionalTriggerConfig* regionalConfig,
+                    AliMUONGlobalCrateConfig* globalConfig) const
+{
+/// write config files
+
+    Bool_t ok;
+    ok  = WriteLocalMasks(localFile, *localMasks);
+    ok &= WriteRegionalConfig(regionalFile, regionalConfig);
+    ok &= WriteGlobalConfig(globalFile, globalConfig);
+    
+    return ok;
+
+
+}
+
+ //_____________________________________________________________________________
+Bool_t 
+AliMUONTriggerIO::WriteGlobalConfig(const char* globalFile, AliMUONGlobalCrateConfig* globalConfig) const
+{
+    /// write global config
+
+  ofstream out;
+  Int_t disable = 0;
+  
+  out.open(globalFile);
+  if (!out.good())
+  {
+    AliError(Form("Could not create output global file %s", globalFile));
+    return kFALSE;
+  }
+   
+  out << globalConfig->GetName() << endl;
+  out << Form("0x%x",globalConfig->GetGlobalCrateEnable()) << endl;
+  
+  // Jtag
+  out << globalConfig->GetJtagName() << endl;
+  out << Form("0x%08lx", globalConfig->GetJtagVmeAddr()) << endl;
+  out << Form("%d %d %d", globalConfig->GetJtagClockDiv(), 
+              globalConfig->GetJtagRxPhase(), globalConfig->GetJtagRdDelay()) << endl;
+  for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
+    out << Form("%d ", globalConfig->GetEnableJtag(i));
+  out << endl;
+
+  
+  for (Int_t i = 0; i < globalConfig->GetJtagNofLines(); ++i)
+  {
+    out << i << endl;
+    for (Int_t j = 0; j < globalConfig->GetJtagNofLines(); ++j)
+      out << Form(" %s", globalConfig->GetJtagCrateName(i,j).Data()) << endl;
+  }
+  
+  // first darc board
+  out << globalConfig->GetFirstDarcName() << endl;
+  out << Form("0x%08lx", globalConfig->GetFirstDarcVmeAddr()) << endl;
+  out << globalConfig->GetFirstDarcType() << endl;
+  disable = globalConfig->GetFirstDarcDisable();
+  out << Form("0x%02x", disable) << endl;
+  out << Form("0x%x", globalConfig->GetFirstDarcL0Delay()) << endl;
+  out << Form("0x%x", globalConfig->GetFirstDarcL1TimeOut()) << endl;
+  out << Form("0x%x", globalConfig->GetFirstDarcGlobalL0()) << endl;
+  out << Form("0x%x", globalConfig->GetFirstDarcConfig()) << endl;
+  
+  // second darc board
+  out << globalConfig->GetSecondDarcName() << endl;
+  out << Form("0x%08lx", globalConfig->GetSecondDarcVmeAddr()) << endl;
+  out << globalConfig->GetSecondDarcType() << endl;
+  disable = globalConfig->GetSecondDarcDisable();
+  out << Form("0x%02x", disable) << endl;
+  out << Form("0x%x", globalConfig->GetSecondDarcL0Delay()) << endl;
+  out << Form("0x%x", globalConfig->GetSecondDarcL1TimeOut()) << endl; 
+  out << Form("0x%x", globalConfig->GetSecondDarcGlobalL0()) << endl; 
+  out << Form("0x%x", globalConfig->GetSecondDarcConfig()) << endl; 
+  
+  // global board
+  out << globalConfig->GetGlobalName() << endl;
+  out << Form("0x%08lx", globalConfig->GetGlobalVmeAddr()) << endl;
+  for (Int_t i = 0; i < globalConfig->GetGlobalNofRegisters(); ++i)
+    out << Form("0x%x", globalConfig->GetGlobalRegister(i)) << endl;
+  
+  // Fet board
+  out << globalConfig->GetFetName() << endl;
+  out << Form("0x%08lx", globalConfig->GetFetVmeAddr()) << endl;
+  for (Int_t i = 0; i < globalConfig->GetFetNofRegisters(); ++i)
+    out << Form("0x%x", globalConfig->GetFetRegister(i)) << endl;
+  
+  return kTRUE;
+}
+//_____________________________________________________________________________
+Bool_t
+AliMUONTriggerIO::WriteRegionalConfig(const char* regionalFile, AliMUONRegionalTriggerConfig* regionalConfig) const
+{
+
+    /// write regional mask with the current configuration
+   /// if regional masks not defined, take the one from current configuration
+
+    ofstream out;
+    out.open(regionalFile);
+          
+    if (!out.good())
+    {
+      AliError(Form("Could not create output regional file %s",regionalFile));
+      return kFALSE;
+    }
+
+    Int_t nCrate = fRegionalTrigger.GetNofTriggerCrates();
+    if (!nCrate)
+    {
+      AliError("Could not write regional no configuration in memory");
+      return kFALSE;
+    }
+
+    Int_t nofDDLs = 0;
+    TString name;
+    AliMpTriggerCrate* crate;
+    for (Int_t ddlId = 0; ddlId < 2; ddlId++) // right & left side            
+      {
+       for (Int_t crateId = 0; crateId < 8; crateId++) // 8 crates/regional boards for each side.
+         {
+           
+           name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
+           
+           crate = fRegionalTrigger.FindTriggerCrate(name, false);
+           
+           AliMUONTriggerCrateConfig* crateConfig = regionalConfig->FindTriggerCrate(crate->GetName());
+           if (!crateConfig) 
+             {
+               AliError(Form("Cannot find crate %s in CDB", crate->GetName()));
+               return kFALSE;
+             }
+           
+           out << crate->GetName()  << endl;
+           out << Form("%02x", crate->GetId())   << endl;
+           out << crateConfig->GetMode()  << endl;
+           out << crateConfig->GetCoinc() << endl;
+           out << Form("%04x", crateConfig->GetMask()) << endl;
+           out << Form("%02d",crate->GetNofLocalBoards()) << endl;
+           
+           for (Int_t iLocal = 0; iLocal < crate->GetNofLocalBoards(); ++iLocal) 
+             {
+               Int_t localBoardId = crate->GetLocalBoardId(iLocal);
+               
+               AliMpLocalBoard* board = fRegionalTrigger.FindLocalBoard(localBoardId);
+               
+               out << Form("%02d ", board->GetSlot())  
+                   << board->GetName() 
+                   << Form(" %03d ", localBoardId) 
+                   << Form("%03x", board->GetSwitch()) 
+                   << endl;
+               
+               out << " ";
+               
+               if (board->IsNotified()) {
+                 for (Int_t i = 0; i < board->GetNofDEs(); ++i)
+                   out << Form("%4d ", board->GetDEId(i));
+               } else {
+                 out << Form("%4d ", 0);
+               }
+               out << endl;
+               
+               // print copy card numbers & TC
+               out << Form(" %4d %4d", board->GetInputXfrom(), board->GetInputXto());
+               out << Form(" %4d %4d", board->GetInputYfrom(), board->GetInputYto());
+               out << Form(" %4d",     board->GetTC()) << endl;
+             }
+         }
+      }
+
+    out.close();
+    
+    return kTRUE;
+}
+
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONTriggerIO::WriteLocalMasks(const char* localFile, const AliMUONVStore& localMasks) const
+{
+    /// write local mask
+    /// removing/adding enable for a local board need a update of the configuration 
+    /// before calling this method
+    /// mask are written for all boards including the copy card (Ch.F.)
+
+    FILE* fp = fopen(gSystem->ExpandPathName(localFile),"wb");
+    if (!fp) 
+    {
+      AliError(Form("Could not create output local file %s",localFile));
+      return kFALSE;
+    }   
+
+    UShort_t maskBuffer[8];
+    Int_t localBoardIndex(0);
+    while (localBoardIndex < NofLocalBoards()) {
+
+      Int_t localBoardId = fRegionalTrigger.LocalBoardId(localBoardIndex);
+
+      AliMUONVCalibParam* localMask = 
+       static_cast<AliMUONVCalibParam*>(localMasks.FindObject(localBoardId));
+
+      for (Int_t index = 0; index < 8; ++index) 
+       {
+         maskBuffer[index] = localMask->ValueAsInt(index,0); 
+       }
+      
+      fwrite ( maskBuffer, 2, 8, fp); 
+
+      ++localBoardIndex;
+
+    }
+
+    fclose(fp);
+
+    return kTRUE;
+
+}
+
 //_____________________________________________________________________________
 void
 AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
@@ -500,8 +751,11 @@ AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
   const Int_t kMaskYtri = 0x01;
   const Int_t kMaskXdev = 0x1F;
   const Int_t kMaskXpos = 0x1F;
+
+  UChar_t buffer[fgkLocalLutSize];  // 32768 hpt/lpt addresses divided by two
+  Int_t bc = 0;
   
-  for (Int_t i = 0; i < 32768; ++i) 
+  for (UInt_t i = 0; i < fgkLocalLutSize*2; ++i) 
   {
     Int_t lutLpt[2] = { 0 };
     Int_t lutHpt[2] = { 0 };
@@ -512,31 +766,88 @@ AliMUONTriggerIO::WriteLocalLUT(const AliMUONTriggerLut& lut,
     Int_t iXdev = ( i >> ( 4 + 1 )     ) & kMaskXdev;
     Int_t iXpos = ( i >> ( 4 + 1 + 5 ) ) & kMaskXpos;
     
+    // convert deviation format
+    // online: sign 1bit , dev 4bit
+    // sign    dev    trigger
+    // 0       1-15   mu-
+    // 1       1-15   mu+
+    // 0       0      mu+, mu- infinite momentum (unde)
+    // 1       0      no x-trigger
+    // offline: dev 5bit
+    // sign    dev    trigger
+    // -        0-14  mu-
+    // -       16-31  mu+
+    // -       15     mu+, mu- infinite momentum (unde)
+    Int_t iXdevOn  = 0;
+    Int_t iXdevOff = 0;
+    Int_t sign     = 0;
+    Bool_t trigx = kFALSE;
+    iXdevOn +=  iXdev & 0x0F;
+    sign    += (iXdev >> 4) & 0x01;
+    if (iXdevOn == 0) {
+      if (sign == 0) {
+       iXdevOff = 15;
+       trigx = kTRUE;
+      } else {
+       iXdevOff = 15;
+       trigx = kFALSE;
+      }
+    } else {
+      trigx = kTRUE;
+      if (sign == 0) {
+       iXdevOff = - iXdevOn + 15;  // gives range  0-14
+      } else {
+       iXdevOff = + iXdevOn + 15;  // gives range 16-30 !
+      }
+    }
+    iXdev = iXdevOff;
+
     // iYtri == 1 means no trigger in y-direction
-    if (iYtri == 0) 
+    if (iYtri == 0 && trigx
     {
       lut.GetLutOutput(localBoardId,iXpos,iXdev,iYpos,lutLpt,lutHpt);
     }
     
-    UChar_t buffer;
-    
     // fill byte
     if (i%2 == 0) 
     {
       // upper half-byte
-      buffer = 0;          
-      buffer += lutLpt[1] << 7;
-      buffer += lutLpt[0] << 6;
-      buffer += lutHpt[1] << 5;
-      buffer += lutHpt[0] << 4;
+      buffer[bc] = 0;      
+      buffer[bc] += lutHpt[1] << 7;
+      buffer[bc] += lutHpt[0] << 6;
+      buffer[bc] += lutLpt[1] << 5;
+      buffer[bc] += lutLpt[0] << 4;
     } else {
       // lower half-byte
-      buffer += lutLpt[1] << 3;
-      buffer += lutLpt[0] << 2;
-      buffer += lutHpt[1] << 1;
-      buffer += lutHpt[0] << 0;
-      fwrite(&buffer,1,1,flut);
+      buffer[bc] += lutHpt[1] << 3;
+      buffer[bc] += lutHpt[0] << 2;
+      buffer[bc] += lutLpt[1] << 1;
+      buffer[bc] += lutLpt[0] << 0;
+      bc++;
     }
   }
+  fwrite(&buffer,bc,1,flut);
 }  
-  
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONTriggerIO::LocalBoardId(Int_t index) const
+{  
+  /// Return the i-th localBoardId, or -1 if index is out of bounds
+
+  return fRegionalTrigger.LocalBoardId(index);
+}
+
+
+//______________________________________________________________________________
+
+Int_t AliMUONTriggerIO::LocalBoardId(Int_t ddlId, Int_t crateId, Int_t localId) const
+{
+    /// Return local board id from crate and local indexes.
+    
+    Int_t nofDDLs = 0;
+    TString name = AliMpTriggerCrate::GenerateName(crateId, ddlId, nofDDLs);
+
+    AliMpTriggerCrate* crate = fRegionalTrigger.FindTriggerCrate(name, false);
+    return crate->GetLocalBoardId(localId);
+}