]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDAltroMapping.cxx
Starting a collection of QA/Comparison macros
[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 #if 0
188   AliInfo(Form("[%2d],%4d -> %d * (%4d - %d)-((%4d - %d) %% %d) / %d = %3d,%d",
189                sec,timebin, (sec % 2 ? -1 : 1), timebin, preSamples, 
190                timebin, preSamples, sampleRate, sampleRate, stripOff, sample));
191 #endif
192 }
193
194 //____________________________________________________________________
195 Bool_t 
196 AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,     UShort_t    board, 
197                                       UShort_t  altro,   UShort_t    chan,
198                                       UShort_t  timebin, UShort_t    preSamples,
199                                       UShort_t  sampleRate,
200                                       UShort_t& det,     Char_t&   ring, 
201                                       UShort_t& sec,     Short_t&  str,
202                                       UShort_t& sam) const
203 {
204   // Full conversion from hardware address, including timebin number,
205   // to detector coordinates and sample number.  Note, that this
206   // conversion depends on the oversampling rate and the number of
207   // pre-samples 
208   Short_t  baseStrip, stripOffset, tdet  = DDL2Detector(ddl);
209   if (tdet < 0) return kFALSE;
210   det = tdet;
211   if (!Channel2StripBase(board, altro, chan, ring, sec, baseStrip)) 
212     return kFALSE;
213   Timebin2Strip(sec, timebin, preSamples, sampleRate, stripOffset, sam);
214   {
215     AliFMDDebug(50, ("0x%x/0x%02x/0x%x/0x%x/%04d -> FMD%d%c[%2d,%3d]-%d "
216                     "(pre=%d,rate=%d,base=%3d,off=%3d)", 
217                      ddl, 
218                      board, 
219                      altro, 
220                      chan, 
221                      timebin, 
222                      det, 
223                      ring, 
224                      sec, 
225                      str, 
226                      sam,
227                      preSamples, 
228                      sampleRate,
229                      baseStrip, 
230                      stripOffset));
231   }
232   str = baseStrip + stripOffset;
233   return kTRUE;
234 }
235
236 //____________________________________________________________________
237 Bool_t 
238 AliFMDAltroMapping::Hardware2Detector(UShort_t  ddl,       UShort_t addr,
239                                       UShort_t  timebin,   UShort_t preSamples, 
240                                       UShort_t  sampleRate,
241                                       UShort_t& det,       Char_t&   ring, 
242                                       UShort_t& sec,       Short_t&  str,
243                                       UShort_t& sam) const
244 {
245   // Translate a hardware address to detector coordinates. 
246   // 
247   // See also Hardware2Detector that accepts 4 inputs 
248   UShort_t board, altro, chan;
249   ChannelAddress(addr, board, altro, chan);
250   return Hardware2Detector(ddl, board, altro, chan, 
251                            timebin, preSamples, sampleRate, 
252                            det, ring, sec, str, sam);
253 }
254
255
256 //____________________________________________________________________
257 Short_t
258 AliFMDAltroMapping::Sector2Board(Char_t ring, UShort_t sec) const
259 {
260   //
261   // Return board address corresponding to a sector 
262   // 
263   // Parameters:
264   //    ring  Ring identifier 
265   //    sec   Sector number 
266   // Return:
267   //    The board number, or negative number in case of failure 
268   //
269   switch (ring) { 
270   case 'I': 
271   case 'i':
272     return (sec < 10 ? 16 : 0); // (sec / 10) * 16;
273   case 'O': 
274   case 'o': 
275     return (sec < 20 ? 16 : 0) + 1; // (sec / 20) * 16 + 1;
276   }
277   return -1;
278 }
279
280 //_____________________________________________ _______________________
281 Bool_t
282 AliFMDAltroMapping::Strip2Channel(Char_t    ring,  UShort_t  sec,   
283                                   UShort_t  str,   UShort_t& board,
284                                   UShort_t& altro, UShort_t& chan) const
285 {
286   // Translate detector coordinates to a hardware address.
287   // The ddl is simply 
288   // 
289   //    (det - 1)
290   // 
291   // The ring number, sector, and strip number must be encoded into a
292   // hardware address.  The address argument, will have the following
293   // format on output
294   // 
295   //   12            7          4          0
296   //   +-------------+----------+----------+
297   //   | Board       | ALTRO    | Channel  |
298   //   +-------------+----------+----------+
299   // 
300   // The board number is given by the ring and sector.  The inner
301   // rings board 0 and 16, while the outer are 1 and 17.  Which of these
302   // depends on the sector.  The map is 
303   // 
304   //    Ring I, sector  0- 9       ->   board 0 
305   //    Ring I, sector 10-19       ->   board 16
306   //    Ring O, sector  0-19       ->   board 1 
307   //    Ring O, sector 20-39       ->   board 17
308   // 
309   // There are 3 ALTRO's per board.  The ALTRO number is given by the
310   // sector number.  For the inner rings, these are given by
311   // 
312   //    Sector  0- 3  or  10-13    ->   ALTRO 0 
313   //    Sector  4- 5  or  14-15    ->   ALTRO 1 
314   //    Sector  6- 9  or  16-19    ->   ALTRO 2 
315   // 
316   // For the outers, it's given by 
317   // 
318   //    Sector  0- 7  or  20-27    ->   ALTRO 0 
319   //    Sector  8-11  or  28-31    ->   ALTRO 1 
320   //    Sector 12-19  or  32-39    ->   ALTRO 2 
321   //
322   // The channel number is given by the sector and strip number.  For
323   // the inners, the map is 
324   // 
325   //    Sector  0, strips   0-127  ->   Channel  0
326   //    Sector  0, strips 128-255  ->   Channel  2
327   //    Sector  0, strips 256-383  ->   Channel  4
328   //    Sector  0, strips 384-511  ->   Channel  6
329   //    Sector  1, strips 127-  0  ->   Channel  1
330   //    Sector  1, strips 255-128  ->   Channel  3
331   //    Sector  1, strips 383-256  ->   Channel  5
332   //    Sector  1, strips 511-384  ->   Channel  7
333   //    Sector  2, strips   0-127  ->   Channel  8
334   //    Sector  2, strips 128-255  ->   Channel 10
335   //    Sector  2, strips 256-383  ->   Channel 12
336   //    Sector  2, strips 384-511  ->   Channel 14
337   //    Sector  3, strips 127-  0  ->   Channel  9
338   //    Sector  3, strips 255-128  ->   Channel 11
339   //    Sector  3, strips 383-256  ->   Channel 13
340   //    Sector  3, strips 511-384  ->   Channel 15
341   // 
342   // and so on, up to sector 19.  For the outer, the map is 
343   // 
344   //    Sector  0, strips   0-127  ->   Channel  0
345   //    Sector  0, strips 128-255  ->   Channel  2
346   //    Sector  1, strips 127-  0  ->   Channel  1
347   //    Sector  1, strips 255-128  ->   Channel  3
348   //    Sector  2, strips   0-127  ->   Channel  4
349   //    Sector  2, strips 128-255  ->   Channel  6
350   //    Sector  3, strips 127-  0  ->   Channel  5
351   //    Sector  3, strips 255-128  ->   Channel  7
352   //    Sector  4, strips   0-127  ->   Channel  8
353   //    Sector  4, strips 128-255  ->   Channel 10
354   //    Sector  5, strips 127-  0  ->   Channel  9
355   //    Sector  5, strips 255-128  ->   Channel 11
356   //    Sector  6, strips   0-127  ->   Channel 12
357   //    Sector  6, strips 128-255  ->   Channel 14
358   //    Sector  7, strips 127-  0  ->   Channel 13
359   //    Sector  7, strips 255-128  ->   Channel 15
360   // 
361   // and so on upto sector 40. 
362   // 
363   // With this information, we can decode the detector coordinates to
364   // give us a unique hardware address 
365   //
366   UInt_t   tmp    = 0;
367   UShort_t fboard = 0;
368   switch (ring) {
369   case 'I':
370   case 'i':
371     fboard =  sec < 10 ? 1 : 0;
372     board  =  fboard * 16;
373     altro  =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
374     tmp    =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
375     chan   =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
376     break;
377   case 'O':
378   case 'o':
379     fboard =  sec < 20 ? 1 : 0;
380     board  =  fboard * 16 + 1;
381     altro  =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
382     tmp    =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
383     chan   =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
384     break;
385   }
386   return kTRUE;
387 }
388
389 //_____________________________________________ _______________________
390 UShort_t
391 AliFMDAltroMapping::Strip2Timebin(UShort_t sec, UShort_t strip, 
392                                   UShort_t sam, UShort_t preSamples, 
393                                   UShort_t sampleRate) const
394 {
395   //
396   // Get the timebin correspoding to a strip and sample 
397   // 
398   // Parameters:
399   //    sec        Sector number 
400   //    str        Strip number 
401   //    sam        Sample number 
402   //    preSamples Number of pre-samples. 
403   //    sampleRate The over-sampling rate 
404   // Return:
405   //    the timebin corresponding to the passed strip 
406   //
407   UShort_t timebin = preSamples;
408   if (sec % 2)  {
409     timebin += (127 - (strip % 128)) * sampleRate;
410 #if 0
411     AliInfo(Form("[%2d,%3d]-%d (%d)-> %d + (127 - (%d %% 128)) * %d + %d = %d", 
412                  sec, strip, sam, (strip % 128), 
413                  preSamples, strip, sampleRate, sam,
414                  timebin+sam));
415 #endif
416   }
417   else  {
418     timebin += (strip % 128) * sampleRate;
419 #if 0
420     AliInfo(Form("[%2d,%3d]-%d (%d)-> %d + (%d %% 128) * %d + %d = %d", 
421                  sec, strip, sam, (strip % 128), 
422                  preSamples, strip, sampleRate, sam, timebin+sam));
423 #endif
424   }
425   timebin += sam;
426   return timebin;
427 }
428
429
430 //____________________________________________________________________
431 Bool_t 
432 AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t    ring, 
433                                       UShort_t  sec,        UShort_t  str,
434                                       UShort_t  sam, 
435                                       UShort_t  preSamples, 
436                                       UShort_t  sampleRate,
437                                       UShort_t& ddl,        UShort_t& board, 
438                                       UShort_t& altro,      UShort_t& channel, 
439                                       UShort_t& timebin) const
440 {
441   //
442   // Map a detector index into a hardware address. 
443   // 
444   // Parameters:
445   //    det         The detector #
446   //    ring        The ring ID
447   //    sec         The sector #
448   //    str         The strip #
449   //    sam         The sample number 
450   //    preSamples  Number of pre-samples
451   //    sampleRate  The oversampling rate 
452   //    ddl         On return, hardware DDL number 
453   //    board       On return, the FEC board address (local to DDL)
454   //    altro       On return, the ALTRO number (local to FEC)
455   //    channel     On return, the channel number (local to ALTRO)
456   //    timebin     On return, the timebin number (local to ALTRO)
457   // Return:
458   //    @c true on success, false otherwise 
459   //
460   ddl = Detector2DDL(det);
461   if (!Strip2Channel(ring,sec,str,board,altro,channel)) return kFALSE;
462   timebin = Strip2Timebin(sec, str, sam, preSamples, sampleRate);
463   return kTRUE;
464 }
465
466
467 //____________________________________________________________________
468 Bool_t 
469 AliFMDAltroMapping::Detector2Hardware(UShort_t  det,        Char_t   ring, 
470                                       UShort_t  sec,        UShort_t str,
471                                       UShort_t  sam, 
472                                       UShort_t  preSamples, UShort_t sampleRate,
473                                       UShort_t& ddl,        UShort_t&  hwaddr, 
474                                       UShort_t& timebin) const
475 {
476   //
477   // Map a detector index into a hardware address. 
478   // 
479   // Parameters:
480   //    det         The detector #
481   //    ring        The ring ID
482   //    sec         The sector #
483   //    str         The strip #
484   //    sam         The sample number 
485   //    preSamples  Number of pre-samples
486   //    sampleRate  The oversampling rate 
487   //    ddl         On return, hardware DDL number 
488   //    hwaddr      On return, hardware address.  
489   //    timebin     On return, the timebin number (local to ALTRO)
490   // Return:
491   //    @c true on success, false otherwise 
492   //
493   UShort_t board = 0;
494   UShort_t altro = 0;
495   UShort_t chan  = 0;
496   if (!Detector2Hardware(det, ring, sec, str, sam, 
497                          preSamples, sampleRate, 
498                          ddl, board, altro, chan, timebin)) return kFALSE;
499   hwaddr =  ChannelAddress(board, altro, chan);
500   return kTRUE;
501 }
502
503       
504 //____________________________________________________________________
505 UInt_t 
506 AliFMDAltroMapping::ChannelAddress(UShort_t board, UShort_t altro, 
507                                    UShort_t channel) const
508 {
509   //
510   // Convert board, chip, channel to a hardware address 
511   // 
512   // Parameters:
513   //    board   Board number 
514   //    altro   Altro number 
515   //    channel Channel number 
516   // Return:
517   //    hardware address of a channel 
518   // 
519   return (((board & 0x1F) << 7) | ((altro & 0x7) << 4) | (channel & 0xF));
520 }
521
522 //____________________________________________________________________
523 void 
524 AliFMDAltroMapping::ChannelAddress(UShort_t hwaddr, UShort_t& board, 
525                                    UShort_t& altro, UShort_t& channel) const
526 {
527   //
528   // Convert a channel address to board, altro, channel fields 
529   // 
530   // Parameters:
531   //    hwaddr  Channel address
532   //    board   On return, the Board number 
533   //    altro   On return, the Altro number 
534   //    channel On return, the Channel number 
535   //
536   board   = ((hwaddr >> 7) & 0x1F);
537   altro   = ((hwaddr >> 4) & 0x07);
538   channel = ((hwaddr >> 0) & 0x0F);
539 }
540
541 //____________________________________________________________________
542 Int_t
543 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
544 {
545   // Return hardware address corresponding to sector sec, strip str,
546   // and ring ring.   Mapping from TPC to FMD coordinates are 
547   // 
548   //   TPC     | FMD
549   //   --------+------
550   //   padrow  | sector
551   //   pad     | strip
552   //   sector  | ring 
553   //
554   Char_t r = Char_t(ring);
555   UShort_t board, altro, channel;
556   Strip2Channel(r, sec, str, board, altro, channel);
557   return ChannelAddress(board, altro, channel);
558 }
559
560 //____________________________________________________________________
561 Int_t
562 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
563 {
564   // Return sector corresponding to hardware address hwaddr.  Mapping
565   // from TPC to FMD coordinates are  
566   // 
567   //   TPC     | FMD
568   //   --------+------
569   //   padrow  | sector
570   //   pad     | strip
571   //   sector  | ring 
572   //
573   Char_t   ring;
574   UShort_t board, altro, channel, sector;
575   Short_t  baseStrip;
576   ChannelAddress(hwaddr, board, altro, channel);
577   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
578     return -1;
579   return Int_t(sector);
580 }
581
582 //____________________________________________________________________
583 Int_t
584 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
585 {
586   // Return strip corresponding to hardware address hwaddr.  Mapping
587   // from TPC to FMD coordinates are  
588   // 
589   //   TPC     | FMD
590   //   --------+------
591   //   padrow  | sector
592   //   pad     | strip
593   //   sector  | ring 
594   //
595   Char_t   ring;
596   UShort_t board, altro, channel, sector;
597   Short_t  baseStrip;
598   ChannelAddress(hwaddr, board, altro, channel);
599   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
600     return -1;
601   return Int_t(baseStrip);
602 }
603   
604 //____________________________________________________________________
605 Int_t
606 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
607 {
608   // Return ring corresponding to hardware address hwaddr.  Mapping
609   // from TPC to FMD coordinates are  
610   // 
611   //   TPC     | FMD
612   //   --------+------
613   //   padrow  | sector
614   //   pad     | strip
615   //   sector  | ring 
616   //
617   Char_t   ring;
618   UShort_t board, altro, channel, sector;
619   Short_t  baseStrip;
620   ChannelAddress(hwaddr, board, altro, channel);
621   if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
622     return -1;
623   return Int_t(ring);
624 }
625
626 //____________________________________________________________________
627 void
628 AliFMDAltroMapping::Print(Option_t* option) const
629 {
630   //
631   // Print map to standard out 
632   // 
633   // Parameters:
634   //    option Option string (hw, or det) 
635   //
636   TString opt(option);
637   opt.ToLower();
638   UShort_t ddl, board, chip, chan, addr;
639   UShort_t det, sec;
640   Short_t  strBase;
641   Char_t   rng;
642   
643   if (opt.Contains("hw") || opt.Contains("hardware")) { 
644     std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
645               << "=====+=======+======+======+=========+===============" 
646               << std::endl;
647     for (ddl = 0; ddl <= 2; ddl++) { 
648       Int_t  boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
649       Int_t* ptr      = boards;
650       det             = DDL2Detector(ddl);
651       while ((board = *(ptr++)) < 32) { 
652         for (chip = 0; chip <= 2; chip++) { 
653           UShort_t nchan = (chip == 1 ? 8 : 16);
654           for (chan = 0; chan < nchan; chan++) { 
655             Channel2StripBase(board, chip, chan, rng, sec, strBase);
656             addr = ChannelAddress(board, chip, chan);
657             std::cout << " "  
658                       << std::setw(3) << ddl     << " | " 
659                       << std::setfill('0')       << std::hex << " 0x"
660                       << std::setw(2) << board   << " |  0x"
661                       << std::setw(1) << chip    << " |  0x"
662                       << std::setw(1) << chan    << " |   0x" 
663                       << std::setw(3) << addr    << " | " 
664                       << std::setfill(' ')       << std::dec << " FMD" 
665                       << std::setw(1) << det     << rng << "[" 
666                       << std::setw(2) << sec     << "," 
667                       << std::setw(3) << strBase << "]" << std::endl;
668           } // for chan ...
669           if (chip == 2 && *ptr >= 32) continue;
670           std::cout << "     +       +      +      +         +              " 
671                     << std::endl;
672         } // for chip ... 
673       } // while board 
674       std::cout << "-----+-------+------+------+---------+---------------" 
675                 << std::endl;
676     } // for ddl ... 
677   } // if hw 
678   if (opt.Contains("det")) { 
679     std::cout << " Detector      | DDL | Board | Chip | Chan | Address\n"
680               << "===============+=====+=======+======+======+========"
681               << std::endl;
682     for (det = 1; det <= 3; det++) { 
683       Char_t  rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
684       Char_t* ptr     = rings;
685       ddl             = Detector2DDL(det);
686       while ((rng = *(ptr++)) != '\0') { 
687         UShort_t nsec = (rng == 'I' ?  20 :  40);
688         UShort_t nstr = (rng == 'I' ? 512 : 256);
689         for (sec = 0; sec < nsec; sec++) { 
690           for (strBase = 0; strBase < nstr; strBase += 128) {
691             Strip2Channel(rng, sec, strBase, board, chip, chan);
692             addr = ChannelAddress(board, chip, chan);
693             std::cout << std::setfill(' ')         << std::dec << " FMD" 
694                       << std::setw(1) << det       << rng      << "[" 
695                       << std::setw(2) << sec       << "," 
696                       << std::setw(3) << strBase   << "] | " 
697                       << std::setw(3) << ddl       << " |  0x"
698                       << std::setfill('0')         << std::hex  
699                       << std::setw(2) << board     << " |  0x"
700                       << std::setw(1) << chip      << " |  0x"
701                       << std::setw(1) << chan      << " |   0x" 
702                       << std::setw(3) << addr      << std::endl;
703           } // for str ...
704         } // for sec ... 
705         if (*ptr == '\0') continue;
706         std::cout << "               +     +       +      +      +        " 
707                   << std::endl;
708       } // while rng ... 
709       std::cout << "---------------+-----+-------+------+------+--------" 
710                 << std::endl;
711
712     } // for det ... 
713   } // if det 
714 }
715
716 //_____________________________________________________________________________
717 //
718 // EOF
719 //