]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDAltroMapping.cxx
Fix Coverity leaks
[u/mrichter/AliRoot.git] / FMD / AliFMDAltroMapping.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 /* $Id$ */
16 /** @file    AliFMDAltroMapping.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Sun Mar 26 18:27:56 2006
19     @brief   Map HW to detector 
20 */
21 //____________________________________________________________________
22 //                                                                          
23 // Mapping of ALTRO hardware channel to detector coordinates 
24 //
25 // The hardware address consist of a DDL number and 12bits of ALTRO
26 // addresses.  The ALTRO address are formatted as follows. 
27 //
28 //    12              7         4            0
29 //    |---------------|---------|------------|
30 //    | Board #       | ALTRO # | Channel #  |
31 //    +---------------+---------+------------+
32 //
33 // The mapping is done purely by calculations.  In the future,
34 // however, we may need some hard-coded stuff, or an external file to
35 // read from.  
36 //
37 #include "AliFMDAltroMapping.h"         // ALIFMDALTROMAPPING_H
38 #include "AliFMDParameters.h"
39 #include "AliLog.h"
40 #include "AliFMDDebug.h"
41 #include <iostream>
42 #include <iomanip>
43
44 //____________________________________________________________________
45 ClassImp(AliFMDAltroMapping)
46 #if 0
47   ; // This is here to keep Emacs for indenting the next line
48 #endif
49
50 //_____________________________________________________________________________
51 AliFMDAltroMapping::AliFMDAltroMapping()
52 {
53   // Constructor 
54 }
55
56
57 //_____________________________________________________________________________
58 Bool_t
59 AliFMDAltroMapping::ReadMapping()
60 {
61   // Read map from file - not used
62   return kTRUE;
63 }
64
65 //_____________________________________________________________________________
66 Bool_t
67 AliFMDAltroMapping::CreateInvMapping()
68 {
69   // Create inverse mapping - not used
70   return kTRUE;
71 }
72
73
74 //____________________________________________________________________
75 Bool_t 
76 AliFMDAltroMapping::Channel2StripBase(UShort_t  board, UShort_t  altro, 
77                                       UShort_t  chan,  Char_t&   ring, 
78                                       UShort_t& sec,   Short_t&  str) const
79 {
80   // Translate a hardware address to detector coordinates. 
81   // The detector is simply 
82   // 
83   //    ddl + 1
84   // 
85   // The ring number, sector, and strip number is given by the addr
86   // argument.  The address argument, has the following format 
87   // 
88   //   12            7          4          0
89   //   +-------------+----------+----------+
90   //   | Board       | ALTRO    | Channel  |
91   //   +-------------+----------+----------+
92   // 
93   // The board number identifier among other things the ring.  There's
94   // up to 4 boards per DDL, and the two first (0 and 16) corresponds
95   // to the inner rings, while the two last (1 and 17) corresponds to
96   // the outer rings. 
97   // 
98   // The board number and ALTRO number together identifies the sensor,
99   // and hence.  The lower board number (0 or 16) are the first N / 2
100   // sensors (where N is the number of sensors in the ring).  
101   // 
102   // There are 3 ALTRO's per card, and each ALTRO serves up to 4
103   // sensors.  Which of sensor is determined by the channel number.
104   // For the inner rings, the map is
105   // 
106   //    ALTRO 0, Channel  0 to  7   -> Sensor 0 or 5
107   //    ALTRO 0, Channel  8 to 15   -> Sensor 1 or 6
108   //    ALTRO 1, Channel  0 to  7   -> Sensor 2 or 7 
109   //    ALTRO 2, Channel  0 to  7   -> Sensor 3 or 8
110   //    ALTRO 2, Channel  8 to 15   -> Sensor 4 or 9
111   // 
112   // For the outer rings, the map is 
113   // 
114   //    ALTRO 0, Channel  0 to  3   -> Sensor 0 or 10
115   //    ALTRO 0, Channel  4 to  7   -> Sensor 1 or 11
116   //    ALTRO 0, Channel  8 to 11   -> Sensor 2 or 12
117   //    ALTRO 0, Channel 12 to 15   -> Sensor 3 or 13
118   //    ALTRO 1, Channel  0 to  3   -> Sensor 4 or 14
119   //    ALTRO 1, Channel  4 to  7   -> Sensor 5 or 15
120   //    ALTRO 2, Channel  0 to  3   -> Sensor 6 or 16
121   //    ALTRO 2, Channel  4 to  7   -> Sensor 7 or 17
122   //    ALTRO 2, Channel  8 to 11   -> Sensor 8 or 18
123   //    ALTRO 2, Channel 12 to 15   -> Sensor 9 or 19
124   // 
125   // Which divison of the sensor we're in, depends on the channel
126   // number only.  For the inner rings, the map is 
127   // 
128   //    Channel 0                   -> Sector 0, strips   0-127
129   //    Channel 1                   -> Sector 1, strips 127-0
130   //    Channel 3                   -> Sector 0, strips 128-255
131   //    Channel 4                   -> Sector 1, strips 255-128
132   //    Channel 5                   -> Sector 0, strips 256-383
133   //    Channel 6                   -> Sector 1, strips 383-256
134   //    Channel 7                   -> Sector 0, strips 384-511
135   //    Channel 8                   -> Sector 1, strips 511-384
136   // 
137   // There are only half as many strips in the outer sensors, so there
138   // only 4 channels are used for a full sensor.  The map is 
139   // 
140   //    Channel 0                   -> Sector 0, strips   0-127
141   //    Channel 1                   -> Sector 1, strips 127-0
142   //    Channel 3                   -> Sector 0, strips 128-255
143   //    Channel 4                   -> Sector 1, strips 255-128
144   // 
145   // With this information, we can decode the hardware address to give
146   // us detector coordinates, unique at least up a 128 strips.  We
147   // return the first strip, as seen by the ALTRO channel, in the
148   // given range.  
149   //
150   ring          =  Board2Ring(board);
151   UShort_t fsec =  board < 16 ? 1 : 0;
152   switch (ring) {
153   case 'i':
154   case 'I':
155     sec = (fsec * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6) 
156            + 2 * (chan / 8) + chan % 2);
157     str = ((chan % 8) / 2) * 128;
158     break;
159   case 'o':
160   case 'O': 
161     sec = (fsec * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12) 
162            + 2 * (chan / 4) + chan % 2);
163     str = ((chan % 4) / 2) * 128;
164     break;
165   }
166   if (sec % 2) str += 127;
167   // AliFMDDebug(1, ("%02x/%x/%x Base strip = %d", board, altro, chan, str));
168   return kTRUE;
169 }
170
171 //____________________________________________________________________
172 void
173 AliFMDAltroMapping::Timebin2Strip(UShort_t  sec,         
174                                   UShort_t  timebin,
175                                   UShort_t  preSamples, 
176                                   UShort_t  sampleRate, 
177                                   Short_t&  stripOff,      
178                                   UShort_t& sample) const
179 {
180   // Compute the strip off-set in the current channel from the sector
181   // and timebin.   Also needed for this computation is the basic
182   // offset in timebins, as well as the sample rat. 
183   UShort_t t =  (timebin - preSamples);
184   sample     =  (t % sampleRate);
185   t          -= sample;
186   stripOff   =  (sec % 2 ? -1 : 1) * t / sampleRate;
187 }
188
189 //____________________________________________________________________
190 Bool_t 
191 AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,     UShort_t    board, 
192                                       UShort_t  altro,   UShort_t    chan,
193                                       UShort_t  timebin, UShort_t    preSamples,
194                                       UShort_t  sampleRate,
195                                       UShort_t& det,     Char_t&   ring, 
196                                       UShort_t& sec,     Short_t&  str,
197                                       UShort_t& sam) const
198 {
199   // Full conversion from hardware address, including timebin number,
200   // to detector coordinates and sample number.  Note, that this
201   // conversion depends on the oversampling rate and the number of
202   // pre-samples 
203   Short_t  baseStrip, stripOffset, tdet  = DDL2Detector(ddl);
204   if (tdet < 0) return kFALSE;
205   det = tdet;
206   if (!Channel2StripBase(board, altro, chan, ring, sec, baseStrip)) 
207     return kFALSE;
208   Timebin2Strip(sec, timebin, preSamples, sampleRate, stripOffset, sam);
209 #if 0
210   AliFMDDebug(1, ("0x%x/0x%02x/0x%x/0x%x/%04d -> FMD%d%c[%2d,%3d]-%d "
211                   "(pre=%d,rate=%d,base=%3d,off=%3d)", 
212                   ddl, 
213                   board, 
214                   altro, 
215                   chan, 
216                   timebin, 
217                   det, 
218                   ring, 
219                   sec, 
220                   str, 
221                   sam,
222                   preSamples, 
223                   sampleRate,
224                   baseStrip, 
225                   stripOffset));
226 #endif
227   str = baseStrip + stripOffset;
228   return kTRUE;
229 }
230
231 //____________________________________________________________________
232 Bool_t 
233 AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,       UShort_t addr,
234                                       UShort_t  timebin,   UShort_t preSamples, 
235                                       UShort_t  sampleRate,
236                                       UShort_t& det,       Char_t&   ring, 
237                                       UShort_t& sec,       Short_t&  str,
238                                       UShort_t& sam) const
239 {
240   // Translate a hardware address to detector coordinates. 
241   // 
242   // See also Hardware2Detector that accepts 4 inputs 
243   UShort_t board, altro, chan;
244   ChannelAddress(addr, board, altro, chan);
245   return Hardware2Detector(ddl, board, altro, chan, 
246                            timebin, preSamples, sampleRate, 
247                            det, ring, sec, str, sam);
248 }
249
250
251 //____________________________________________________________________
252 Short_t
253 AliFMDAltroMapping::Sector2Board(Char_t ring, UShort_t sec) const
254 {
255   //
256   // Return board address corresponding to a sector 
257   // 
258   // Parameters:
259   //    ring  Ring identifier 
260   //    sec   Sector number 
261   // Return:
262   //    The board number, or negative number in case of failure 
263   //
264   switch (ring) { 
265   case 'I': 
266   case 'i':
267     return (sec < 10 ? 16 : 0); // (sec / 10) * 16;
268   case 'O': 
269   case 'o': 
270     return (sec < 20 ? 16 : 0) + 1; // (sec / 20) * 16 + 1;
271   }
272   return -1;
273 }
274
275 //_____________________________________________ _______________________
276 Bool_t
277 AliFMDAltroMapping::Strip2Channel(Char_t    ring,  UShort_t  sec,   
278                                   UShort_t  str,   UShort_t& board,
279                                   UShort_t& altro, UShort_t& chan) const
280 {
281   // Translate detector coordinates to a hardware address.
282   // The ddl is simply 
283   // 
284   //    (det - 1)
285   // 
286   // The ring number, sector, and strip number must be encoded into a
287   // hardware address.  The address argument, will have the following
288   // format on output
289   // 
290   //   12            7          4          0
291   //   +-------------+----------+----------+
292   //   | Board       | ALTRO    | Channel  |
293   //   +-------------+----------+----------+
294   // 
295   // The board number is given by the ring and sector.  The inner
296   // rings board 0 and 16, while the outer are 1 and 17.  Which of these
297   // depends on the sector.  The map is 
298   // 
299   //    Ring I, sector  0- 9       ->   board 0 
300   //    Ring I, sector 10-19       ->   board 16
301   //    Ring O, sector  0-19       ->   board 1 
302   //    Ring O, sector 20-39       ->   board 17
303   // 
304   // There are 3 ALTRO's per board.  The ALTRO number is given by the
305   // sector number.  For the inner rings, these are given by
306   // 
307   //    Sector  0- 3  or  10-13    ->   ALTRO 0 
308   //    Sector  4- 5  or  14-15    ->   ALTRO 1 
309   //    Sector  6- 9  or  16-19    ->   ALTRO 2 
310   // 
311   // For the outers, it's given by 
312   // 
313   //    Sector  0- 7  or  20-27    ->   ALTRO 0 
314   //    Sector  8-11  or  28-31    ->   ALTRO 1 
315   //    Sector 12-19  or  32-39    ->   ALTRO 2 
316   //
317   // The channel number is given by the sector and strip number.  For
318   // the inners, the map is 
319   // 
320   //    Sector  0, strips   0-127  ->   Channel  0
321   //    Sector  0, strips 128-255  ->   Channel  2
322   //    Sector  0, strips 256-383  ->   Channel  4
323   //    Sector  0, strips 384-511  ->   Channel  6
324   //    Sector  1, strips 127-  0  ->   Channel  1
325   //    Sector  1, strips 255-128  ->   Channel  3
326   //    Sector  1, strips 383-256  ->   Channel  5
327   //    Sector  1, strips 511-384  ->   Channel  7
328   //    Sector  2, strips   0-127  ->   Channel  8
329   //    Sector  2, strips 128-255  ->   Channel 10
330   //    Sector  2, strips 256-383  ->   Channel 12
331   //    Sector  2, strips 384-511  ->   Channel 14
332   //    Sector  3, strips 127-  0  ->   Channel  9
333   //    Sector  3, strips 255-128  ->   Channel 11
334   //    Sector  3, strips 383-256  ->   Channel 13
335   //    Sector  3, strips 511-384  ->   Channel 15
336   // 
337   // and so on, up to sector 19.  For the outer, the map is 
338   // 
339   //    Sector  0, strips   0-127  ->   Channel  0
340   //    Sector  0, strips 128-255  ->   Channel  2
341   //    Sector  1, strips 127-  0  ->   Channel  1
342   //    Sector  1, strips 255-128  ->   Channel  3
343   //    Sector  2, strips   0-127  ->   Channel  4
344   //    Sector  2, strips 128-255  ->   Channel  6
345   //    Sector  3, strips 127-  0  ->   Channel  5
346   //    Sector  3, strips 255-128  ->   Channel  7
347   //    Sector  4, strips   0-127  ->   Channel  8
348   //    Sector  4, strips 128-255  ->   Channel 10
349   //    Sector  5, strips 127-  0  ->   Channel  9
350   //    Sector  5, strips 255-128  ->   Channel 11
351   //    Sector  6, strips   0-127  ->   Channel 12
352   //    Sector  6, strips 128-255  ->   Channel 14
353   //    Sector  7, strips 127-  0  ->   Channel 13
354   //    Sector  7, strips 255-128  ->   Channel 15
355   // 
356   // and so on upto sector 40. 
357   // 
358   // With this information, we can decode the detector coordinates to
359   // give us a unique hardware address 
360   //
361   UInt_t   tmp    = 0;
362   UShort_t fboard = 0;
363   switch (ring) {
364   case 'I':
365   case 'i':
366     fboard =  sec < 10 ? 1 : 0;
367     board  =  fboard * 16;
368     altro  =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
369     tmp    =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
370     chan   =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
371     break;
372   case 'O':
373   case 'o':
374     fboard =  sec < 20 ? 1 : 0;
375     board  =  fboard * 16 + 1;
376     altro  =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
377     tmp    =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
378     chan   =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
379     break;
380   }
381   return kTRUE;
382 }
383
384 //_____________________________________________ _______________________
385 UShort_t
386 AliFMDAltroMapping::Strip2Timebin(UShort_t sec, UShort_t strip, 
387                                   UShort_t sam, UShort_t preSamples, 
388                                   UShort_t sampleRate) const
389 {
390   //
391   // Get the timebin correspoding to a strip and sample 
392   // 
393   // Parameters:
394   //    sec        Sector number 
395   //    str        Strip number 
396   //    sam        Sample number 
397   //    preSamples Number of pre-samples. 
398   //    sampleRate The over-sampling rate 
399   // Return:
400   //    the timebin corresponding to the passed strip 
401   //
402   UShort_t timebin = preSamples;
403   if (sec % 2)  timebin += (127 - (strip % 128)) * sampleRate;
404   else          timebin += (strip % 128) * sampleRate;
405   timebin += sam;
406   return timebin;
407 }
408
409
410 //____________________________________________________________________
411 Bool_t 
412 AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t    ring, 
413                                       UShort_t  sec,        UShort_t  str,
414                                       UShort_t  sam, 
415                                       UShort_t  preSamples, 
416                                       UShort_t  sampleRate,
417                                       UShort_t& ddl,        UShort_t& board, 
418                                       UShort_t& altro,      UShort_t& channel, 
419                                       UShort_t& timebin) const
420 {
421   //
422   // Map a detector index into a hardware address. 
423   // 
424   // Parameters:
425   //    det         The detector #
426   //    ring        The ring ID
427   //    sec         The sector #
428   //    str         The strip #
429   //    sam         The sample number 
430   //    preSamples  Number of pre-samples
431   //    sampleRate  The oversampling rate 
432   //    ddl         On return, hardware DDL number 
433   //    board       On return, the FEC board address (local to DDL)
434   //    altro       On return, the ALTRO number (local to FEC)
435   //    channel     On return, the channel number (local to ALTRO)
436   //    timebin     On return, the timebin number (local to ALTRO)
437   // Return:
438   //    @c true on success, false otherwise 
439   //
440   ddl = Detector2DDL(det);
441   if (!Strip2Channel(ring,sec,str,board,altro,channel)) return kFALSE;
442   timebin = Strip2Timebin(sec, str, sam, preSamples, sampleRate);
443   return kTRUE;
444 }
445
446
447 //____________________________________________________________________
448 Bool_t 
449 AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t   ring, 
450                                       UShort_t  sec,        UShort_t str,
451                                       UShort_t  sam, 
452                                       UShort_t  preSamples, UShort_t sampleRate,
453                                       UShort_t& ddl,        UShort_t&  hwaddr, 
454                                       UShort_t& timebin) const
455 {
456   //
457   // Map a detector index into a hardware address. 
458   // 
459   // Parameters:
460   //    det         The detector #
461   //    ring        The ring ID
462   //    sec         The sector #
463   //    str         The strip #
464   //    sam         The sample number 
465   //    preSamples  Number of pre-samples
466   //    sampleRate  The oversampling rate 
467   //    ddl         On return, hardware DDL number 
468   //    hwaddr      On return, hardware address.  
469   //    timebin     On return, the timebin number (local to ALTRO)
470   // Return:
471   //    @c true on success, false otherwise 
472   //
473   UShort_t board = 0;
474   UShort_t altro = 0;
475   UShort_t chan  = 0;
476   if (!Detector2Hardware(det, ring, sec, str, sam, 
477                          preSamples, sampleRate, 
478                          ddl, board, altro, chan, timebin)) return kFALSE;
479   hwaddr =  ChannelAddress(board, altro, chan);
480   return kTRUE;
481 }
482
483       
484 //____________________________________________________________________
485 UInt_t 
486 AliFMDAltroMapping::ChannelAddress(UShort_t board, UShort_t altro, 
487                                    UShort_t channel) const
488 {
489   //
490   // Convert board, chip, channel to a hardware address 
491   // 
492   // Parameters:
493   //    board   Board number 
494   //    altro   Altro number 
495   //    channel Channel number 
496   // Return:
497   //    hardware address of a channel 
498   // 
499   return (((board & 0x1F) << 7) | ((altro & 0x7) << 4) | (channel & 0xF));
500 }
501
502 //____________________________________________________________________
503 void 
504 AliFMDAltroMapping::ChannelAddress(UShort_t hwaddr, UShort_t& board, 
505                                    UShort_t& altro, UShort_t& channel) const
506 {
507   //
508   // Convert a channel address to board, altro, channel fields 
509   // 
510   // Parameters:
511   //    hwaddr  Channel address
512   //    board   On return, the Board number 
513   //    altro   On return, the Altro number 
514   //    channel On return, the Channel number 
515   //
516   board   = ((hwaddr >> 7) & 0x1F);
517   altro   = ((hwaddr >> 4) & 0x07);
518   channel = ((hwaddr >> 0) & 0x0F);
519 }
520
521 //____________________________________________________________________
522 Int_t
523 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
524 {
525   // Return hardware address corresponding to sector sec, strip str,
526   // and ring ring.   Mapping from TPC to FMD coordinates are 
527   // 
528   //   TPC     | FMD
529   //   --------+------
530   //   padrow  | sector
531   //   pad     | strip
532   //   sector  | ring 
533   //
534   Char_t r = Char_t(ring);
535   UShort_t board, altro, channel;
536   Strip2Channel(r, sec, str, board, altro, channel);
537   return ChannelAddress(board, altro, channel);
538 }
539
540 //____________________________________________________________________
541 Int_t
542 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
543 {
544   // Return sector corresponding to hardware address hwaddr.  Mapping
545   // from TPC to FMD coordinates are  
546   // 
547   //   TPC     | FMD
548   //   --------+------
549   //   padrow  | sector
550   //   pad     | strip
551   //   sector  | ring 
552   //
553   Char_t   ring;
554   UShort_t board, altro, channel, sector;
555   Short_t  baseStrip;
556   ChannelAddress(hwaddr, board, altro, channel);
557   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
558     return -1;
559   return Int_t(sector);
560 }
561
562 //____________________________________________________________________
563 Int_t
564 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
565 {
566   // Return strip corresponding to hardware address hwaddr.  Mapping
567   // from TPC to FMD coordinates are  
568   // 
569   //   TPC     | FMD
570   //   --------+------
571   //   padrow  | sector
572   //   pad     | strip
573   //   sector  | ring 
574   //
575   Char_t   ring;
576   UShort_t board, altro, channel, sector;
577   Short_t  baseStrip;
578   ChannelAddress(hwaddr, board, altro, channel);
579   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
580     return -1;
581   return Int_t(baseStrip);
582 }
583   
584 //____________________________________________________________________
585 Int_t
586 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
587 {
588   // Return ring corresponding to hardware address hwaddr.  Mapping
589   // from TPC to FMD coordinates are  
590   // 
591   //   TPC     | FMD
592   //   --------+------
593   //   padrow  | sector
594   //   pad     | strip
595   //   sector  | ring 
596   //
597   Char_t   ring;
598   UShort_t board, altro, channel, sector;
599   Short_t  baseStrip;
600   ChannelAddress(hwaddr, board, altro, channel);
601   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
602     return -1;
603   return Int_t(ring);
604 }
605
606 //____________________________________________________________________
607 void
608 AliFMDAltroMapping::Print(Option_t* option) const
609 {
610   //
611   // Print map to standard out 
612   // 
613   // Parameters:
614   //    option Option string (hw, or det) 
615   //
616   TString opt(option);
617   opt.ToLower();
618   UShort_t ddl, board, chip, chan, addr;
619   UShort_t det, sec;
620   Short_t  strBase;
621   Char_t   rng;
622   
623   if (opt.Contains("hw") || opt.Contains("hardware")) { 
624     std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
625               << "=====+=======+======+======+=========+===============" 
626               << std::endl;
627     for (ddl = 0; ddl <= 2; ddl++) { 
628       Int_t  boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
629       Int_t* ptr      = boards;
630       det             = DDL2Detector(ddl);
631       while ((board = *(ptr++)) < 32) { 
632         for (chip = 0; chip <= 2; chip++) { 
633           UShort_t nchan = (chip == 1 ? 8 : 16);
634           for (chan = 0; chan < nchan; chan++) { 
635             Channel2StripBase(board, chip, chan, rng, sec, strBase);
636             addr = ChannelAddress(board, chip, chan);
637             std::cout << " "  
638                       << std::setw(3) << ddl     << " | " 
639                       << std::setfill('0')       << std::hex << " 0x"
640                       << std::setw(2) << board   << " |  0x"
641                       << std::setw(1) << chip    << " |  0x"
642                       << std::setw(1) << chan    << " |   0x" 
643                       << std::setw(3) << addr    << " | " 
644                       << std::setfill(' ')       << std::dec << " FMD" 
645                       << std::setw(1) << det     << rng << "[" 
646                       << std::setw(2) << sec     << "," 
647                       << std::setw(3) << strBase << "]" << std::endl;
648           } // for chan ...
649           if (chip == 2 && *ptr >= 32) continue;
650           std::cout << "     +       +      +      +         +              " 
651                     << std::endl;
652         } // for chip ... 
653       } // while board 
654       std::cout << "-----+-------+------+------+---------+---------------" 
655                 << std::endl;
656     } // for ddl ... 
657   } // if hw 
658   if (opt.Contains("det")) { 
659     std::cout << " Detector      | DDL | Board | Chip | Chan | Address\n"
660               << "===============+=====+=======+======+======+========"
661               << std::endl;
662     for (det = 1; det <= 3; det++) { 
663       Char_t  rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
664       Char_t* ptr     = rings;
665       ddl             = Detector2DDL(det);
666       while ((rng = *(ptr++)) != '\0') { 
667         UShort_t nsec = (rng == 'I' ?  20 :  40);
668         UShort_t nstr = (rng == 'I' ? 512 : 256);
669         for (sec = 0; sec < nsec; sec++) { 
670           for (strBase = 0; strBase < nstr; strBase += 128) {
671             Strip2Channel(rng, sec, strBase, board, chip, chan);
672             addr = ChannelAddress(board, chip, chan);
673             std::cout << std::setfill(' ')         << std::dec << " FMD" 
674                       << std::setw(1) << det       << rng      << "[" 
675                       << std::setw(2) << sec       << "," 
676                       << std::setw(3) << strBase   << "] | " 
677                       << std::setw(3) << ddl       << " |  0x"
678                       << std::setfill('0')         << std::hex  
679                       << std::setw(2) << board     << " |  0x"
680                       << std::setw(1) << chip      << " |  0x"
681                       << std::setw(1) << chan      << " |   0x" 
682                       << std::setw(3) << addr      << std::endl;
683           } // for str ...
684         } // for sec ... 
685         if (*ptr == '\0') continue;
686         std::cout << "               +     +       +      +      +        " 
687                   << std::endl;
688       } // while rng ... 
689       std::cout << "---------------+-----+-------+------+------+--------" 
690                 << std::endl;
691
692     } // for det ... 
693   } // if det 
694 }
695
696 //_____________________________________________________________________________
697 //
698 // EOF
699 //