First V0 MC Analysis from H.Ricaud
[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 <iostream>
41 #include <iomanip>
42
43 //____________________________________________________________________
44 ClassImp(AliFMDAltroMapping)
45 #if 0
46   ; // This is here to keep Emacs for indenting the next line
47 #endif
48
49 //_____________________________________________________________________________
50 AliFMDAltroMapping::AliFMDAltroMapping()
51 {
52   // Constructor 
53 }
54
55
56 //_____________________________________________________________________________
57 Bool_t
58 AliFMDAltroMapping::ReadMapping()
59 {
60   // Read map from file - not used
61   return kTRUE;
62 }
63
64 //_____________________________________________________________________________
65 Bool_t
66 AliFMDAltroMapping::CreateInvMapping()
67 {
68   // Create inverse mapping - not used
69   return kTRUE;
70 }
71
72 //____________________________________________________________________
73 Bool_t 
74 AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl, UInt_t    addr, 
75                                       UShort_t& det, Char_t&   ring, 
76                                       UShort_t& sec, UShort_t& str) const
77 {
78   // Translate a hardware address to detector coordinates. 
79   // 
80   // See also Hardware2Detector that accepts 4 inputs 
81   UInt_t board =  (addr >> 7) & 0x1F;
82   UInt_t altro =  (addr >> 4) & 0x7;
83   UInt_t chan  =  (addr & 0xf);
84   return Hardware2Detector(ddl, board, altro, chan, det, ring, sec, str);
85 }
86
87 //____________________________________________________________________
88 Bool_t 
89 AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl,   UInt_t    board, 
90                                       UInt_t    altro, UInt_t    chan,
91                                       UShort_t& det,   Char_t&   ring, 
92                                       UShort_t& sec,   UShort_t& str) const
93 {
94   // Translate a hardware address to detector coordinates. 
95   // The detector is simply 
96   // 
97   //    ddl + 1
98   // 
99   // The ring number, sector, and strip number is given by the addr
100   // argument.  The address argument, has the following format 
101   // 
102   //   12            7          4          0
103   //   +-------------+----------+----------+
104   //   | Board       | ALTRO    | Channel  |
105   //   +-------------+----------+----------+
106   // 
107   // The board number identifier among other things the ring.  There's
108   // up to 4 boards per DDL, and the two first (0 and 16) corresponds
109   // to the inner rings, while the two last (1 and 17) corresponds to
110   // the outer rings. 
111   // 
112   // The board number and ALTRO number together identifies the sensor,
113   // and hence.  The lower board number (0 or 2) are the first N / 2
114   // sensors (where N is the number of sensors in the ring).  
115   // 
116   // There are 3 ALTRO's per card, and each ALTRO serves up to 4
117   // sensors.  Which of sensor is determined by the channel number.
118   // For the inner rings, the map is
119   // 
120   //    ALTRO 0, Channel  0 to  7   -> Sensor 0 or 5
121   //    ALTRO 0, Channel  8 to 15   -> Sensor 1 or 6
122   //    ALTRO 1, Channel  0 to  7   -> Sensor 2 or 7 
123   //    ALTRO 2, Channel  0 to  7   -> Sensor 3 or 8
124   //    ALTRO 2, Channel  8 to 15   -> Sensor 4 or 9
125   // 
126   // For the outer rings, the map is 
127   // 
128   //    ALTRO 0, Channel  0 to  3   -> Sensor 0 or 10
129   //    ALTRO 0, Channel  4 to  7   -> Sensor 1 or 11
130   //    ALTRO 0, Channel  8 to 11   -> Sensor 2 or 12
131   //    ALTRO 0, Channel 12 to 15   -> Sensor 3 or 13
132   //    ALTRO 1, Channel  0 to  3   -> Sensor 4 or 14
133   //    ALTRO 1, Channel  4 to  7   -> Sensor 5 or 15
134   //    ALTRO 2, Channel  0 to  3   -> Sensor 6 or 16
135   //    ALTRO 2, Channel  4 to  7   -> Sensor 7 or 17
136   //    ALTRO 2, Channel  8 to 11   -> Sensor 8 or 18
137   //    ALTRO 2, Channel 12 to 15   -> Sensor 9 or 19
138   // 
139   // Which divison of the sensor we're in, depends on the channel
140   // number only.  For the inner rings, the map is 
141   // 
142   //    Channel 0                   -> Sector 0, strips   0-127
143   //    Channel 1                   -> Sector 1, strips   0-127
144   //    Channel 3                   -> Sector 0, strips 128-255
145   //    Channel 4                   -> Sector 1, strips 128-255
146   //    Channel 5                   -> Sector 0, strips 256-383
147   //    Channel 6                   -> Sector 1, strips 256-383
148   //    Channel 7                   -> Sector 0, strips 384-511
149   //    Channel 8                   -> Sector 1, strips 384-511 
150   // 
151   // There are only half as many strips in the outer sensors, so there
152   // only 4 channels are used for a full sensor.  The map is 
153   // 
154   //    Channel 0                   -> Sector 0, strips   0-127
155   //    Channel 1                   -> Sector 1, strips   0-127
156   //    Channel 3                   -> Sector 0, strips 128-255
157   //    Channel 4                   -> Sector 1, strips 128-255
158   // 
159   // With this information, we can decode the hardware address to give
160   // us detector coordinates, unique at least up a 128 strips.  We
161   // return the first strip in the given range. 
162   //
163   det          =  ddl + 1;
164   ring         =  (board % 2) == 0 ? 'I' : 'O';
165   switch (ring) {
166   case 'i':
167   case 'I':
168     sec = ((board / 16) * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6) 
169            + 2 * (chan / 8) + chan % 2);
170     str = ((chan % 8) / 2) * 128;
171     break;
172   case 'o':
173   case 'O': 
174     sec = ((board / 16) * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12) 
175            + 2 * (chan / 4) + chan % 2);
176     str = ((chan % 4) / 2) * 128;
177     break;
178   }
179   return kTRUE;
180 }
181
182 //____________________________________________________________________
183 Bool_t 
184 AliFMDAltroMapping::Detector2Hardware(UShort_t  det,   Char_t    ring, 
185                                       UShort_t  sec,   UShort_t  str,
186                                       UInt_t&   ddl,   UInt_t&   board,
187                                       UInt_t&   altro, UInt_t&   chan) const
188 {
189   // Translate detector coordinates to a hardware address.
190   // The ddl is simply 
191   // 
192   //    (det - 1)
193   // 
194   // The ring number, sector, and strip number must be encoded into a
195   // hardware address.  The address argument, will have the following
196   // format on output
197   // 
198   //   12            7          4          0
199   //   +-------------+----------+----------+
200   //   | Board       | ALTRO    | Channel  |
201   //   +-------------+----------+----------+
202   // 
203   // The board number is given by the ring and sector.  The inner
204   // rings board 0 and 16, while the outer are 1 and 17.  Which of these
205   // depends on the sector.  The map is 
206   // 
207   //    Ring I, sector  0- 9       ->   board 0 
208   //    Ring I, sector 10-19       ->   board 16
209   //    Ring O, sector  0-19       ->   board 1 
210   //    Ring O, sector 20-39       ->   board 17
211   // 
212   // There are 3 ALTRO's per board.  The ALTRO number is given by the
213   // sector number.  For the inner rings, these are given by
214   // 
215   //    Sector  0- 3  or  10-13    ->   ALTRO 0 
216   //    Sector  4- 5  or  14-15    ->   ALTRO 1 
217   //    Sector  6- 9  or  16-19    ->   ALTRO 2 
218   // 
219   // For the outers, it's given by 
220   // 
221   //    Sector  0- 7  or  20-27    ->   ALTRO 0 
222   //    Sector  8-11  or  28-31    ->   ALTRO 1 
223   //    Sector 12-19  or  32-39    ->   ALTRO 2 
224   //
225   // The channel number is given by the sector and strip number.  For
226   // the inners, the map is 
227   // 
228   //    Sector  0, strips   0-127  ->   Channel  0
229   //    Sector  0, strips 128-255  ->   Channel  2
230   //    Sector  0, strips 256-383  ->   Channel  4
231   //    Sector  0, strips 384-511  ->   Channel  6
232   //    Sector  1, strips   0-127  ->   Channel  1
233   //    Sector  1, strips 128-255  ->   Channel  3
234   //    Sector  1, strips 256-383  ->   Channel  5
235   //    Sector  1, strips 384-511  ->   Channel  7
236   //    Sector  2, strips   0-127  ->   Channel  8
237   //    Sector  2, strips 128-255  ->   Channel 10
238   //    Sector  2, strips 256-383  ->   Channel 12
239   //    Sector  2, strips 384-511  ->   Channel 14
240   //    Sector  3, strips   0-127  ->   Channel  9
241   //    Sector  3, strips 128-255  ->   Channel 11
242   //    Sector  3, strips 256-383  ->   Channel 13
243   //    Sector  3, strips 384-511  ->   Channel 15
244   // 
245   // and so on, up to sector 19.  For the outer, the map is 
246   // 
247   //    Sector  0, strips   0-127  ->   Channel  0
248   //    Sector  0, strips 128-255  ->   Channel  2
249   //    Sector  1, strips   0-127  ->   Channel  1
250   //    Sector  1, strips 128-255  ->   Channel  3
251   //    Sector  2, strips   0-127  ->   Channel  4
252   //    Sector  2, strips 128-255  ->   Channel  6
253   //    Sector  3, strips   0-127  ->   Channel  5
254   //    Sector  3, strips 128-255  ->   Channel  7
255   //    Sector  4, strips   0-127  ->   Channel  8
256   //    Sector  4, strips 128-255  ->   Channel 10
257   //    Sector  5, strips   0-127  ->   Channel  9
258   //    Sector  5, strips 128-255  ->   Channel 11
259   //    Sector  6, strips   0-127  ->   Channel 12
260   //    Sector  6, strips 128-255  ->   Channel 14
261   //    Sector  7, strips   0-127  ->   Channel 13
262   //    Sector  7, strips 128-255  ->   Channel 15
263   // 
264   // and so on upto sector 40. 
265   // 
266   // With this information, we can decode the detector coordinates to
267   // give us a unique hardware address 
268   //
269   ddl          =  (det - 1);
270   UInt_t tmp   = 0;
271   switch (ring) {
272   case 'I':
273   case 'i':
274     board =  (sec / 10) * 16;
275     altro =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
276     tmp   =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
277     chan  =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
278     break;
279   case 'O':
280   case 'o':
281     board =  (sec / 20) * 16 + 1;
282     altro =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
283     tmp   =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
284     chan  =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
285     break;
286   }
287   return kTRUE;
288 }
289
290 //____________________________________________________________________
291 Bool_t 
292 AliFMDAltroMapping::Detector2Hardware(UShort_t  det, Char_t    ring, 
293                                       UShort_t  sec, UShort_t  str,
294                                       UInt_t&   ddl, UInt_t&   addr) const
295 {
296   // Translate detector coordinates to a hardware address.  
297   // 
298   // See also Detector2Hardware that returns 4 parameters.  
299   UInt_t board = 0;
300   UInt_t altro = 0;
301   UInt_t chan  = 0;
302   if (!Detector2Hardware(det,ring,sec,str,ddl,board,altro,chan)) return kFALSE;
303   addr =  chan + (altro << 4) + (board << 7);
304   return kTRUE;
305 }
306
307 //____________________________________________________________________
308 Int_t
309 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
310 {
311   // Return hardware address corresponding to sector sec, strip str,
312   // and ring ring.   Mapping from TPC to FMD coordinates are 
313   // 
314   //   TPC     | FMD
315   //   --------+------
316   //   padrow  | sector
317   //   pad     | strip
318   //   sector  | ring 
319   //
320   UInt_t ddl, hwaddr;
321   Char_t r = Char_t(ring);
322   if (!Detector2Hardware(1, r, sec, str, ddl, hwaddr)) 
323     return -1;
324   return hwaddr;
325 }
326
327 //____________________________________________________________________
328 Int_t
329 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
330 {
331   // Return sector corresponding to hardware address hwaddr.  Mapping
332   // from TPC to FMD coordinates are  
333   // 
334   //   TPC     | FMD
335   //   --------+------
336   //   padrow  | sector
337   //   pad     | strip
338   //   sector  | ring 
339   //
340   UShort_t det;
341   Char_t   ring;
342   UShort_t sec;
343   UShort_t str;
344   Int_t    ddl = 0;
345   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
346   return Int_t(sec);
347 }
348
349 //____________________________________________________________________
350 Int_t
351 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
352 {
353   // Return strip corresponding to hardware address hwaddr.  Mapping
354   // from TPC to FMD coordinates are  
355   // 
356   //   TPC     | FMD
357   //   --------+------
358   //   padrow  | sector
359   //   pad     | strip
360   //   sector  | ring 
361   //
362   UShort_t det;
363   Char_t   ring;
364   UShort_t sec;
365   UShort_t str;
366   Int_t    ddl = 0;
367   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
368   return Int_t(str);
369 }
370   
371 //____________________________________________________________________
372 Int_t
373 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
374 {
375   // Return ring corresponding to hardware address hwaddr.  Mapping
376   // from TPC to FMD coordinates are  
377   // 
378   //   TPC     | FMD
379   //   --------+------
380   //   padrow  | sector
381   //   pad     | strip
382   //   sector  | ring 
383   //
384   UShort_t det;
385   Char_t   ring;
386   UShort_t sec;
387   UShort_t str;
388   Int_t    ddl = 0;
389   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
390   return Int_t(ring);
391 }
392
393 //____________________________________________________________________
394 void
395 AliFMDAltroMapping::Print(Option_t* option) const
396 {
397   TString opt(option);
398   opt.ToLower();
399   UInt_t ddl, board, chip, chan, addr;
400   UShort_t det, sec, str;
401   Char_t   rng;
402   
403   if (opt.Contains("hw") || opt.Contains("hardware")) { 
404     std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
405               << "=====+=======+======+======+=========+===============" 
406               << std::endl;
407     for (ddl = 0; ddl <= 2; ddl++) { 
408       Int_t  boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
409       Int_t* ptr      = boards;
410       while ((board = *(ptr++)) < 32) { 
411         for (chip = 0; chip <= 2; chip++) { 
412           UInt_t nchan = (chip == 1 ? 8 : 16);
413           for (chan = 0; chan < nchan; chan++) { 
414             Hardware2Detector(ddl, board, chip, chan, det, rng, sec, str);
415             addr = ((board & 0x1f) << 7) | ((chip & 0x7) << 4) | (chan & 0xf);
416             std::cout << " "  
417                       << std::setw(3) << ddl   << " | " 
418                       << std::setfill('0')     << std::hex << " 0x"
419                       << std::setw(2) << board << " |  0x"
420                       << std::setw(1) << chip  << " |  0x"
421                       << std::setw(1) << chan  << " |   0x" 
422                       << std::setw(3) << addr  << " | " 
423                       << std::setfill(' ')     << std::dec << " FMD" 
424                       << std::setw(1) << det << rng << "[" 
425                       << std::setw(2) << sec << "," << std::setw(3) << str
426                       << "]" << std::endl;
427           } // for chan ...
428           if (chip == 2 && *ptr >= 32) continue;
429           std::cout << "     +       +      +      +         +              " 
430                     << std::endl;
431         } // for chip ... 
432       } // while board 
433       std::cout << "-----+-------+------+------+---------+---------------" 
434                 << std::endl;
435     } // for ddl ... 
436   } // if hw 
437   if (opt.Contains("det")) { 
438     std::cout << " Detector      | DDL | Board | Chip | Chan | Address\n"
439               << "===============+=====+=======+======+======+========"
440               << std::endl;
441     for (det = 1; det <= 3; det++) { 
442       Char_t  rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
443       Char_t* ptr     = rings;
444       while ((rng = *(ptr++)) != '\0') { 
445         UShort_t nsec = (rng == 'I' ?  20 :  40);
446         UShort_t nstr = (rng == 'I' ? 512 : 256);
447         for (sec = 0; sec < nsec; sec++) { 
448           for (str = 0; str < nstr; str += 128) {
449             ddl = board = chip = chan;
450             Detector2Hardware(det,rng,sec,str,ddl,board,chip,chan);
451             addr = ((board & 0x1f) << 7) | ((chip & 0x7) << 4) | (chan & 0xf);
452             std::cout << std::setfill(' ')     << std::dec << " FMD" 
453                       << std::setw(1) << det   << rng      << "[" 
454                       << std::setw(2) << sec   << "," 
455                       << std::setw(3) << str   << "] | " 
456                       << std::setw(3) << ddl   << " |  0x"
457                       << std::setfill('0')     << std::hex  
458                       << std::setw(2) << board << " |  0x"
459                       << std::setw(1) << chip  << " |  0x"
460                       << std::setw(1) << chan  << " |   0x" 
461                       << std::setw(3) << addr  << std::endl;
462           } // for str ...
463         } // for sec ... 
464         if (*ptr == '\0') continue;
465         std::cout << "               +     +       +      +      +        " 
466                   << std::endl;
467       } // while rng ... 
468       std::cout << "---------------+-----+-------+------+------+--------" 
469                 << std::endl;
470
471     } // for det ... 
472   } // if det 
473 }
474
475 //_____________________________________________________________________________
476 //
477 // EOF
478 //