]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - FMD/AliFMDAltroMapping.cxx
New analysis modules
[u/mrichter/AliRoot.git] / FMD / AliFMDAltroMapping.cxx
index 11048dc3af0ece927292cdb650b655fb4c7eacb5..9231b43ad46afac96101ace966d2d3ba5ba844f2 100644 (file)
@@ -37,6 +37,9 @@
 #include "AliFMDAltroMapping.h"                // ALIFMDALTROMAPPING_H
 #include "AliFMDParameters.h"
 #include "AliLog.h"
+#include "AliFMDDebug.h"
+#include <iostream>
+#include <iomanip>
 
 //____________________________________________________________________
 ClassImp(AliFMDAltroMapping)
@@ -60,17 +63,19 @@ AliFMDAltroMapping::ReadMapping()
 }
 
 //_____________________________________________________________________________
-void
-AliFMDAltroMapping::DeleteMappingArrays()
+Bool_t
+AliFMDAltroMapping::CreateInvMapping()
 {
-  // Clear map in memory 
+  // Create inverse mapping - not used
+  return kTRUE;
 }
 
+
 //____________________________________________________________________
 Bool_t 
-AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl, UInt_t    addr
-                                     UShort_t& det, Char_t&   ring, 
-                                     UShort_t& sec, UShort_t& str) const
+AliFMDAltroMapping::Channel2StripBase(UShort_t  board, UShort_t  altro
+                                     UShort_t  chan,  Char_t&   ring, 
+                                     UShort_t& sec,   Short_t&  str) const
 {
   // Translate a hardware address to detector coordinates. 
   // The detector is simply 
@@ -91,7 +96,7 @@ AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl, UInt_t    addr,
   // the outer rings. 
   // 
   // The board number and ALTRO number together identifies the sensor,
-  // and hence.  The lower board number (0 or 2) are the first N / 2
+  // and hence.  The lower board number (0 or 16) are the first N / 2
   // sensors (where N is the number of sensors in the ring).  
   // 
   // There are 3 ALTRO's per card, and each ALTRO serves up to 4
@@ -121,53 +126,162 @@ AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl, UInt_t    addr,
   // number only.  For the inner rings, the map is 
   // 
   //    Channel 0                   -> Sector 0, strips   0-127
-  //    Channel 1                   -> Sector 1, strips   0-127
+  //    Channel 1                   -> Sector 1, strips 127-0
   //    Channel 3                   -> Sector 0, strips 128-255
-  //    Channel 4                   -> Sector 1, strips 128-255
+  //    Channel 4                   -> Sector 1, strips 255-128
   //    Channel 5                   -> Sector 0, strips 256-383
-  //    Channel 6                   -> Sector 1, strips 256-383
+  //    Channel 6                   -> Sector 1, strips 383-256
   //    Channel 7                   -> Sector 0, strips 384-511
-  //    Channel 8                   -> Sector 1, strips 384-511 
+  //    Channel 8                   -> Sector 1, strips 511-384
   // 
   // There are only half as many strips in the outer sensors, so there
   // only 4 channels are used for a full sensor.  The map is 
   // 
   //    Channel 0                   -> Sector 0, strips   0-127
-  //    Channel 1                   -> Sector 1, strips   0-127
+  //    Channel 1                   -> Sector 1, strips 127-0
   //    Channel 3                   -> Sector 0, strips 128-255
-  //    Channel 4                   -> Sector 1, strips 128-255
+  //    Channel 4                   -> Sector 1, strips 255-128
   // 
   // With this information, we can decode the hardware address to give
   // us detector coordinates, unique at least up a 128 strips.  We
-  // return the first strip in the given range. 
+  // return the first strip, as seen by the ALTRO channel, in the
+  // given range.  
   //
-  det          =  ddl + 1;
-  UInt_t board =  (addr >> 7) & 0x1F;
-  UInt_t altro =  (addr >> 4) & 0x7;
-  UInt_t chan  =  (addr & 0xf);
-  ring         =  (board % 2) == 0 ? 'I' : 'O';
+  ring          =  Board2Ring(board);
+  UShort_t fsec =  board < 16 ? 1 : 0;
   switch (ring) {
   case 'i':
   case 'I':
-    sec = ((board / 16) * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6) 
+    sec = (fsec * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6) 
           + 2 * (chan / 8) + chan % 2);
     str = ((chan % 8) / 2) * 128;
     break;
   case 'o':
   case 'O': 
-    sec = ((board / 16) * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12) 
+    sec = (fsec * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12) 
           + 2 * (chan / 4) + chan % 2);
     str = ((chan % 4) / 2) * 128;
     break;
   }
+  if (sec % 2) str += 127;
+  // AliFMDDebug(1, ("%02x/%x/%x Base strip = %d", board, altro, chan, str));
+  return kTRUE;
+}
+
+//____________________________________________________________________
+void
+AliFMDAltroMapping::Timebin2Strip(UShort_t  sec,         
+                                 UShort_t  timebin,
+                                 UShort_t  preSamples, 
+                                 UShort_t  sampleRate, 
+                                 Short_t&  stripOff,      
+                                 UShort_t& sample) const
+{
+  // Compute the strip off-set in the current channel from the sector
+  // and timebin.   Also needed for this computation is the basic
+  // offset in timebins, as well as the sample rat. 
+  UShort_t t =  (timebin - preSamples);
+  sample     =  (t % sampleRate);
+  t          -= sample;
+  stripOff   =  (sec % 2 ? -1 : 1) * t / sampleRate;
+#if 0
+  AliInfo(Form("[%2d],%4d -> %d * (%4d - %d)-((%4d - %d) %% %d) / %d = %3d,%d",
+              sec,timebin, (sec % 2 ? -1 : 1), timebin, preSamples, 
+              timebin, preSamples, sampleRate, sampleRate, stripOff, sample));
+#endif
+}
+
+//____________________________________________________________________
+Bool_t 
+AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,     UShort_t    board, 
+                                     UShort_t  altro,   UShort_t    chan,
+                                     UShort_t  timebin, UShort_t    preSamples,
+                                     UShort_t  sampleRate,
+                                     UShort_t& det,     Char_t&   ring, 
+                                     UShort_t& sec,     Short_t&  str,
+                                     UShort_t& sam) const
+{
+  // Full conversion from hardware address, including timebin number,
+  // to detector coordinates and sample number.  Note, that this
+  // conversion depends on the oversampling rate and the number of
+  // pre-samples 
+  Short_t  baseStrip, stripOffset, tdet  = DDL2Detector(ddl);
+  if (tdet < 0) return kFALSE;
+  det = tdet;
+  if (!Channel2StripBase(board, altro, chan, ring, sec, baseStrip)) 
+    return kFALSE;
+  Timebin2Strip(sec, timebin, preSamples, sampleRate, stripOffset, sam);
+  {
+    AliFMDDebug(50, ("0x%x/0x%02x/0x%x/0x%x/%04d -> FMD%d%c[%2d,%3d]-%d "
+                   "(pre=%d,rate=%d,base=%3d,off=%3d)", 
+                    ddl, 
+                    board, 
+                    altro, 
+                    chan, 
+                    timebin, 
+                    det, 
+                    ring, 
+                    sec, 
+                    str, 
+                    sam,
+                    preSamples, 
+                    sampleRate,
+                    baseStrip, 
+                    stripOffset));
+  }
+  str = baseStrip + stripOffset;
   return kTRUE;
 }
 
 //____________________________________________________________________
 Bool_t 
-AliFMDAltroMapping::Detector2Hardware(UShort_t  det, Char_t    ring, 
-                                     UShort_t  sec, UShort_t  str,
-                                     UInt_t&   ddl, UInt_t&   addr) const
+AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,       UShort_t addr,
+                                     UShort_t  timebin,   UShort_t preSamples, 
+                                     UShort_t  sampleRate,
+                                     UShort_t& det,       Char_t&   ring, 
+                                     UShort_t& sec,       Short_t&  str,
+                                     UShort_t& sam) const
+{
+  // Translate a hardware address to detector coordinates. 
+  // 
+  // See also Hardware2Detector that accepts 4 inputs 
+  UShort_t board, altro, chan;
+  ChannelAddress(addr, board, altro, chan);
+  return Hardware2Detector(ddl, board, altro, chan, 
+                          timebin, preSamples, sampleRate, 
+                          det, ring, sec, str, sam);
+}
+
+
+//____________________________________________________________________
+Short_t
+AliFMDAltroMapping::Sector2Board(Char_t ring, UShort_t sec) const
+{
+  //
+  // Return board address corresponding to a sector 
+  // 
+  // Parameters:
+  //    ring  Ring identifier 
+  //    sec   Sector number 
+  // Return:
+  //    The board number, or negative number in case of failure 
+  //
+  switch (ring) { 
+  case 'I': 
+  case 'i':
+    return (sec < 10 ? 16 : 0); // (sec / 10) * 16;
+  case 'O': 
+  case 'o': 
+    return (sec < 20 ? 16 : 0) + 1; // (sec / 20) * 16 + 1;
+  }
+  return -1;
+}
+
+//_____________________________________________ _______________________
+Bool_t
+AliFMDAltroMapping::Strip2Channel(Char_t    ring,  UShort_t  sec,   
+                                 UShort_t  str,   UShort_t& board,
+                                 UShort_t& altro, UShort_t& chan) const
 {
   // Translate detector coordinates to a hardware address.
   // The ddl is simply 
@@ -212,72 +326,221 @@ AliFMDAltroMapping::Detector2Hardware(UShort_t  det, Char_t    ring,
   //    Sector  0, strips 128-255  ->   Channel  2
   //    Sector  0, strips 256-383  ->   Channel  4
   //    Sector  0, strips 384-511  ->   Channel  6
-  //    Sector  1, strips   0-127  ->   Channel  1
-  //    Sector  1, strips 128-255  ->   Channel  3
-  //    Sector  1, strips 256-383  ->   Channel  5
-  //    Sector  1, strips 384-511  ->   Channel  7
+  //    Sector  1, strips 127-  0  ->   Channel  1
+  //    Sector  1, strips 255-128  ->   Channel  3
+  //    Sector  1, strips 383-256  ->   Channel  5
+  //    Sector  1, strips 511-384  ->   Channel  7
   //    Sector  2, strips   0-127  ->   Channel  8
   //    Sector  2, strips 128-255  ->   Channel 10
   //    Sector  2, strips 256-383  ->   Channel 12
   //    Sector  2, strips 384-511  ->   Channel 14
-  //    Sector  3, strips   0-127  ->   Channel  9
-  //    Sector  3, strips 128-255  ->   Channel 11
-  //    Sector  3, strips 256-383  ->   Channel 13
-  //    Sector  3, strips 384-511  ->   Channel 15
+  //    Sector  3, strips 127-  0  ->   Channel  9
+  //    Sector  3, strips 255-128  ->   Channel 11
+  //    Sector  3, strips 383-256  ->   Channel 13
+  //    Sector  3, strips 511-384  ->   Channel 15
   // 
   // and so on, up to sector 19.  For the outer, the map is 
   // 
   //    Sector  0, strips   0-127  ->   Channel  0
   //    Sector  0, strips 128-255  ->   Channel  2
-  //    Sector  1, strips   0-127  ->   Channel  1
-  //    Sector  1, strips 128-255  ->   Channel  3
+  //    Sector  1, strips 127-  0  ->   Channel  1
+  //    Sector  1, strips 255-128  ->   Channel  3
   //    Sector  2, strips   0-127  ->   Channel  4
   //    Sector  2, strips 128-255  ->   Channel  6
-  //    Sector  3, strips   0-127  ->   Channel  5
-  //    Sector  3, strips 128-255  ->   Channel  7
+  //    Sector  3, strips 127-  0  ->   Channel  5
+  //    Sector  3, strips 255-128  ->   Channel  7
   //    Sector  4, strips   0-127  ->   Channel  8
   //    Sector  4, strips 128-255  ->   Channel 10
-  //    Sector  5, strips   0-127  ->   Channel  9
-  //    Sector  5, strips 128-255  ->   Channel 11
+  //    Sector  5, strips 127-  0  ->   Channel  9
+  //    Sector  5, strips 255-128  ->   Channel 11
   //    Sector  6, strips   0-127  ->   Channel 12
   //    Sector  6, strips 128-255  ->   Channel 14
-  //    Sector  7, strips   0-127  ->   Channel 13
-  //    Sector  7, strips 128-255  ->   Channel 15
+  //    Sector  7, strips 127-  0  ->   Channel 13
+  //    Sector  7, strips 255-128  ->   Channel 15
   // 
   // and so on upto sector 40. 
   // 
   // With this information, we can decode the detector coordinates to
   // give us a unique hardware address 
   //
-  ddl          =  (det - 1);
-  UInt_t board = 0;
-  UInt_t altro = 0;
-  UInt_t chan  = 0;
-  UInt_t tmp   = 0;
+  UInt_t   tmp    = 0;
+  UShort_t fboard = 0;
   switch (ring) {
   case 'I':
   case 'i':
-    board += (sec / 10) * 16;
-    altro =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
-    tmp   =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
-    chan  =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
+    fboard =  sec < 10 ? 1 : 0;
+    board  =  fboard * 16;
+    altro  =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
+    tmp    =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
+    chan   =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
     break;
   case 'O':
   case 'o':
-    board += (sec / 20) * 20 + 1;
-    altro =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
-    tmp   =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
-    chan  =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
+    fboard =  sec < 20 ? 1 : 0;
+    board  =  fboard * 16 + 1;
+    altro  =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
+    tmp    =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
+    chan   =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
     break;
   }
-  addr         =  chan + (altro << 4) + (board << 7);
-  
   return kTRUE;
 }
 
+//_____________________________________________ _______________________
+UShort_t
+AliFMDAltroMapping::Strip2Timebin(UShort_t sec, UShort_t strip, 
+                                 UShort_t sam, UShort_t preSamples, 
+                                 UShort_t sampleRate) const
+{
+  //
+  // Get the timebin correspoding to a strip and sample 
+  // 
+  // Parameters:
+  //    sec        Sector number 
+  //    str        Strip number 
+  //    sam        Sample number 
+  //    preSamples Number of pre-samples. 
+  //    sampleRate The over-sampling rate 
+  // Return:
+  //    the timebin corresponding to the passed strip 
+  //
+  UShort_t timebin = preSamples;
+  if (sec % 2)  {
+    timebin += (127 - (strip % 128)) * sampleRate;
+#if 0
+    AliInfo(Form("[%2d,%3d]-%d (%d)-> %d + (127 - (%d %% 128)) * %d + %d = %d", 
+                sec, strip, sam, (strip % 128), 
+                preSamples, strip, sampleRate, sam,
+                timebin+sam));
+#endif
+  }
+  else  {
+    timebin += (strip % 128) * sampleRate;
+#if 0
+    AliInfo(Form("[%2d,%3d]-%d (%d)-> %d + (%d %% 128) * %d + %d = %d", 
+                sec, strip, sam, (strip % 128), 
+                preSamples, strip, sampleRate, sam, timebin+sam));
+#endif
+  }
+  timebin += sam;
+  return timebin;
+}
+
+
+//____________________________________________________________________
+Bool_t 
+AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t    ring, 
+                                     UShort_t  sec,        UShort_t  str,
+                                     UShort_t  sam, 
+                                     UShort_t  preSamples, 
+                                     UShort_t  sampleRate,
+                                     UShort_t& ddl,        UShort_t& board, 
+                                     UShort_t& altro,      UShort_t& channel, 
+                                     UShort_t& timebin) const
+{
+  //
+  // Map a detector index into a hardware address. 
+  // 
+  // Parameters:
+  //    det         The detector #
+  //    ring        The ring ID
+  //    sec         The sector #
+  //    str         The strip #
+  //    sam         The sample number 
+  //    preSamples  Number of pre-samples
+  //    sampleRate  The oversampling rate 
+  //    ddl         On return, hardware DDL number 
+  //    board       On return, the FEC board address (local to DDL)
+  //    altro       On return, the ALTRO number (local to FEC)
+  //    channel     On return, the channel number (local to ALTRO)
+  //    timebin     On return, the timebin number (local to ALTRO)
+  // Return:
+  //    @c true on success, false otherwise 
+  //
+  ddl = Detector2DDL(det);
+  if (!Strip2Channel(ring,sec,str,board,altro,channel)) return kFALSE;
+  timebin = Strip2Timebin(sec, str, sam, preSamples, sampleRate);
+  return kTRUE;
+}
+
+
+//____________________________________________________________________
+Bool_t 
+AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t   ring, 
+                                     UShort_t  sec,        UShort_t str,
+                                     UShort_t  sam, 
+                                     UShort_t  preSamples, UShort_t sampleRate,
+                                     UShort_t& ddl,        UShort_t&  hwaddr, 
+                                     UShort_t& timebin) const
+{
+  //
+  // Map a detector index into a hardware address. 
+  // 
+  // Parameters:
+  //    det         The detector #
+  //    ring        The ring ID
+  //    sec         The sector #
+  //    str         The strip #
+  //    sam         The sample number 
+  //    preSamples  Number of pre-samples
+  //    sampleRate  The oversampling rate 
+  //    ddl         On return, hardware DDL number 
+  //    hwaddr      On return, hardware address.  
+  //    timebin     On return, the timebin number (local to ALTRO)
+  // Return:
+  //    @c true on success, false otherwise 
+  //
+  UShort_t board = 0;
+  UShort_t altro = 0;
+  UShort_t chan  = 0;
+  if (!Detector2Hardware(det, ring, sec, str, sam, 
+                        preSamples, sampleRate, 
+                        ddl, board, altro, chan, timebin)) return kFALSE;
+  hwaddr =  ChannelAddress(board, altro, chan);
+  return kTRUE;
+}
+
+      
+//____________________________________________________________________
+UInt_t 
+AliFMDAltroMapping::ChannelAddress(UShort_t board, UShort_t altro, 
+                                  UShort_t channel) const
+{
+  //
+  // Convert board, chip, channel to a hardware address 
+  // 
+  // Parameters:
+  //    board   Board number 
+  //    altro   Altro number 
+  //    channel Channel number 
+  // Return:
+  //    hardware address of a channel 
+  // 
+  return (((board & 0x1F) << 7) | ((altro & 0x7) << 4) | (channel & 0xF));
+}
+
+//____________________________________________________________________
+void 
+AliFMDAltroMapping::ChannelAddress(UShort_t hwaddr, UShort_t& board, 
+                                  UShort_t& altro, UShort_t& channel) const
+{
+  //
+  // Convert a channel address to board, altro, channel fields 
+  // 
+  // Parameters:
+  //    hwaddr  Channel address
+  //    board   On return, the Board number 
+  //    altro   On return, the Altro number 
+  //    channel On return, the Channel number 
+  //
+  board   = ((hwaddr >> 7) & 0x1F);
+  altro   = ((hwaddr >> 4) & 0x07);
+  channel = ((hwaddr >> 0) & 0x0F);
+}
+
 //____________________________________________________________________
 Int_t
-AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring) const
+AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
 {
   // Return hardware address corresponding to sector sec, strip str,
   // and ring ring.   Mapping from TPC to FMD coordinates are 
@@ -288,11 +551,10 @@ AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring) const
   //   pad     | strip
   //   sector  | ring 
   //
-  UInt_t ddl, hwaddr;
   Char_t r = Char_t(ring);
-  if (!Detector2Hardware(1, r, sec, str, ddl, hwaddr)) 
-    return -1;
-  return hwaddr;
+  UShort_t board, altro, channel;
+  Strip2Channel(r, sec, str, board, altro, channel);
+  return ChannelAddress(board, altro, channel);
 }
 
 //____________________________________________________________________
@@ -308,13 +570,13 @@ AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
   //   pad     | strip
   //   sector  | ring 
   //
-  UShort_t det;
   Char_t   ring;
-  UShort_t sec;
-  UShort_t str;
-  Int_t    ddl = 0;
-  if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
-  return Int_t(sec);
+  UShort_t board, altro, channel, sector;
+  Short_t  baseStrip;
+  ChannelAddress(hwaddr, board, altro, channel);
+  if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
+    return -1;
+  return Int_t(sector);
 }
 
 //____________________________________________________________________
@@ -330,13 +592,13 @@ AliFMDAltroMapping::GetPad(Int_t hwaddr) const
   //   pad     | strip
   //   sector  | ring 
   //
-  UShort_t det;
   Char_t   ring;
-  UShort_t sec;
-  UShort_t str;
-  Int_t    ddl = 0;
-  if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
-  return Int_t(str);
+  UShort_t board, altro, channel, sector;
+  Short_t  baseStrip;
+  ChannelAddress(hwaddr, board, altro, channel);
+  if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
+    return -1;
+  return Int_t(baseStrip);
 }
   
 //____________________________________________________________________
@@ -352,15 +614,105 @@ AliFMDAltroMapping::GetSector(Int_t hwaddr) const
   //   pad     | strip
   //   sector  | ring 
   //
-  UShort_t det;
   Char_t   ring;
-  UShort_t sec;
-  UShort_t str;
-  Int_t    ddl = 0;
-  if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
+  UShort_t board, altro, channel, sector;
+  Short_t  baseStrip;
+  ChannelAddress(hwaddr, board, altro, channel);
+  if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
+    return -1;
   return Int_t(ring);
 }
 
+//____________________________________________________________________
+void
+AliFMDAltroMapping::Print(Option_t* option) const
+{
+  //
+  // Print map to standard out 
+  // 
+  // Parameters:
+  //    option Option string (hw, or det) 
+  //
+  TString opt(option);
+  opt.ToLower();
+  UShort_t ddl, board, chip, chan, addr;
+  UShort_t det, sec;
+  Short_t  strBase;
+  Char_t   rng;
+  
+  if (opt.Contains("hw") || opt.Contains("hardware")) { 
+    std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
+             << "=====+=======+======+======+=========+===============" 
+             << std::endl;
+    for (ddl = 0; ddl <= 2; ddl++) { 
+      Int_t  boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
+      Int_t* ptr      = boards;
+      det             = DDL2Detector(ddl);
+      while ((board = *(ptr++)) < 32) { 
+       for (chip = 0; chip <= 2; chip++) { 
+         UShort_t nchan = (chip == 1 ? 8 : 16);
+         for (chan = 0; chan < nchan; chan++) { 
+           Channel2StripBase(board, chip, chan, rng, sec, strBase);
+           addr = ChannelAddress(board, chip, chan);
+           std::cout << " "  
+                     << std::setw(3) << ddl     << " | " 
+                     << std::setfill('0')       << std::hex << " 0x"
+                     << std::setw(2) << board   << " |  0x"
+                     << std::setw(1) << chip    << " |  0x"
+                     << std::setw(1) << chan    << " |   0x" 
+                     << std::setw(3) << addr    << " | " 
+                     << std::setfill(' ')       << std::dec << " FMD" 
+                     << std::setw(1) << det     << rng << "[" 
+                     << std::setw(2) << sec     << "," 
+                     << std::setw(3) << strBase << "]" << std::endl;
+         } // for chan ...
+         if (chip == 2 && *ptr >= 32) continue;
+         std::cout << "     +       +      +      +         +              " 
+                   << std::endl;
+       } // for chip ... 
+      } // while board 
+      std::cout << "-----+-------+------+------+---------+---------------" 
+               << std::endl;
+    } // for ddl ... 
+  } // if hw 
+  if (opt.Contains("det")) { 
+    std::cout << " Detector      | DDL | Board | Chip | Chan | Address\n"
+             << "===============+=====+=======+======+======+========"
+             << std::endl;
+    for (det = 1; det <= 3; det++) { 
+      Char_t  rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
+      Char_t* ptr     = rings;
+      ddl             = Detector2DDL(det);
+      while ((rng = *(ptr++)) != '\0') { 
+       UShort_t nsec = (rng == 'I' ?  20 :  40);
+       UShort_t nstr = (rng == 'I' ? 512 : 256);
+       for (sec = 0; sec < nsec; sec++) { 
+         for (strBase = 0; strBase < nstr; strBase += 128) {
+           Strip2Channel(rng, sec, strBase, board, chip, chan);
+           addr = ChannelAddress(board, chip, chan);
+           std::cout << std::setfill(' ')         << std::dec << " FMD" 
+                     << std::setw(1) << det       << rng      << "[" 
+                     << std::setw(2) << sec       << "," 
+                     << std::setw(3) << strBase   << "] | " 
+                     << std::setw(3) << ddl       << " |  0x"
+                     << std::setfill('0')         << std::hex  
+                     << std::setw(2) << board     << " |  0x"
+                     << std::setw(1) << chip      << " |  0x"
+                     << std::setw(1) << chan      << " |   0x" 
+                     << std::setw(3) << addr      << std::endl;
+         } // for str ...
+       } // for sec ... 
+       if (*ptr == '\0') continue;
+       std::cout << "               +     +       +      +      +        " 
+                 << std::endl;
+      } // while rng ... 
+      std::cout << "---------------+-----+-------+------+------+--------" 
+               << std::endl;
+
+    } // for det ... 
+  } // if det 
+}
+
 //_____________________________________________________________________________
 //
 // EOF