Added the possibility to do diagnostics histograms.
[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
41 //____________________________________________________________________
42 ClassImp(AliFMDAltroMapping)
43 #if 0
44   ; // This is here to keep Emacs for indenting the next line
45 #endif
46
47 //_____________________________________________________________________________
48 AliFMDAltroMapping::AliFMDAltroMapping()
49 {
50   // Constructor 
51 }
52
53
54 //_____________________________________________________________________________
55 Bool_t
56 AliFMDAltroMapping::ReadMapping()
57 {
58   // Read map from file - not used
59   return kTRUE;
60 }
61
62 //_____________________________________________________________________________
63 void
64 AliFMDAltroMapping::DeleteMappingArrays()
65 {
66   // Clear map in memory 
67 }
68
69 //____________________________________________________________________
70 Bool_t 
71 AliFMDAltroMapping::Hardware2Detector(UInt_t    ddl, UInt_t    addr, 
72                                       UShort_t& det, Char_t&   ring, 
73                                       UShort_t& sec, UShort_t& str) const
74 {
75   // Translate a hardware address to detector coordinates. 
76   // The detector is simply 
77   // 
78   //    ddl + 1
79   // 
80   // The ring number, sector, and strip number is given by the addr
81   // argument.  The address argument, has the following format 
82   // 
83   //   12            7          4          0
84   //   +-------------+----------+----------+
85   //   | Board       | ALTRO    | Channel  |
86   //   +-------------+----------+----------+
87   // 
88   // The board number identifier among other things the ring.  There's
89   // up to 4 boards per DDL, and the two first (0 and 16) corresponds
90   // to the inner rings, while the two last (1 and 17) corresponds to
91   // the outer rings. 
92   // 
93   // The board number and ALTRO number together identifies the sensor,
94   // and hence.  The lower board number (0 or 2) are the first N / 2
95   // sensors (where N is the number of sensors in the ring).  
96   // 
97   // There are 3 ALTRO's per card, and each ALTRO serves up to 4
98   // sensors.  Which of sensor is determined by the channel number.
99   // For the inner rings, the map is
100   // 
101   //    ALTRO 0, Channel  0 to  7   -> Sensor 0 or 5
102   //    ALTRO 0, Channel  8 to 15   -> Sensor 1 or 6
103   //    ALTRO 1, Channel  0 to  7   -> Sensor 2 or 7 
104   //    ALTRO 2, Channel  0 to  7   -> Sensor 3 or 8
105   //    ALTRO 2, Channel  8 to 15   -> Sensor 4 or 9
106   // 
107   // For the outer rings, the map is 
108   // 
109   //    ALTRO 0, Channel  0 to  3   -> Sensor 0 or 10
110   //    ALTRO 0, Channel  4 to  7   -> Sensor 1 or 11
111   //    ALTRO 0, Channel  8 to 11   -> Sensor 2 or 12
112   //    ALTRO 0, Channel 12 to 15   -> Sensor 3 or 13
113   //    ALTRO 1, Channel  0 to  3   -> Sensor 4 or 14
114   //    ALTRO 1, Channel  4 to  7   -> Sensor 5 or 15
115   //    ALTRO 2, Channel  0 to  3   -> Sensor 6 or 16
116   //    ALTRO 2, Channel  4 to  7   -> Sensor 7 or 17
117   //    ALTRO 2, Channel  8 to 11   -> Sensor 8 or 18
118   //    ALTRO 2, Channel 12 to 15   -> Sensor 9 or 19
119   // 
120   // Which divison of the sensor we're in, depends on the channel
121   // number only.  For the inner rings, the map is 
122   // 
123   //    Channel 0                   -> Sector 0, strips   0-127
124   //    Channel 1                   -> Sector 1, strips   0-127
125   //    Channel 3                   -> Sector 0, strips 128-255
126   //    Channel 4                   -> Sector 1, strips 128-255
127   //    Channel 5                   -> Sector 0, strips 256-383
128   //    Channel 6                   -> Sector 1, strips 256-383
129   //    Channel 7                   -> Sector 0, strips 384-511
130   //    Channel 8                   -> Sector 1, strips 384-511 
131   // 
132   // There are only half as many strips in the outer sensors, so there
133   // only 4 channels are used for a full sensor.  The map is 
134   // 
135   //    Channel 0                   -> Sector 0, strips   0-127
136   //    Channel 1                   -> Sector 1, strips   0-127
137   //    Channel 3                   -> Sector 0, strips 128-255
138   //    Channel 4                   -> Sector 1, strips 128-255
139   // 
140   // With this information, we can decode the hardware address to give
141   // us detector coordinates, unique at least up a 128 strips.  We
142   // return the first strip in the given range. 
143   //
144   det          =  ddl + 1;
145   UInt_t board =  (addr >> 7) & 0x1F;
146   UInt_t altro =  (addr >> 4) & 0x7;
147   UInt_t chan  =  (addr & 0xf);
148   ring         =  (board % 2) == 0 ? 'I' : 'O';
149   switch (ring) {
150   case 'i':
151   case 'I':
152     sec = ((board / 16) * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6) 
153            + 2 * (chan / 8) + chan % 2);
154     str = ((chan % 8) / 2) * 128;
155     break;
156   case 'o':
157   case 'O': 
158     sec = ((board / 16) * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12) 
159            + 2 * (chan / 4) + chan % 2);
160     str = ((chan % 4) / 2) * 128;
161     break;
162   }
163   return kTRUE;
164 }
165
166 //____________________________________________________________________
167 Bool_t 
168 AliFMDAltroMapping::Detector2Hardware(UShort_t  det, Char_t    ring, 
169                                       UShort_t  sec, UShort_t  str,
170                                       UInt_t&   ddl, UInt_t&   addr) const
171 {
172   // Translate detector coordinates to a hardware address.
173   // The ddl is simply 
174   // 
175   //    (det - 1)
176   // 
177   // The ring number, sector, and strip number must be encoded into a
178   // hardware address.  The address argument, will have the following
179   // format on output
180   // 
181   //   12            7          4          0
182   //   +-------------+----------+----------+
183   //   | Board       | ALTRO    | Channel  |
184   //   +-------------+----------+----------+
185   // 
186   // The board number is given by the ring and sector.  The inner
187   // rings board 0 and 16, while the outer are 1 and 17.  Which of these
188   // depends on the sector.  The map is 
189   // 
190   //    Ring I, sector  0- 9       ->   board 0 
191   //    Ring I, sector 10-19       ->   board 16
192   //    Ring O, sector  0-19       ->   board 1 
193   //    Ring O, sector 20-39       ->   board 17
194   // 
195   // There are 3 ALTRO's per board.  The ALTRO number is given by the
196   // sector number.  For the inner rings, these are given by
197   // 
198   //    Sector  0- 3  or  10-13    ->   ALTRO 0 
199   //    Sector  4- 5  or  14-15    ->   ALTRO 1 
200   //    Sector  6- 9  or  16-19    ->   ALTRO 2 
201   // 
202   // For the outers, it's given by 
203   // 
204   //    Sector  0- 7  or  20-27    ->   ALTRO 0 
205   //    Sector  8-11  or  28-31    ->   ALTRO 1 
206   //    Sector 12-19  or  32-39    ->   ALTRO 2 
207   //
208   // The channel number is given by the sector and strip number.  For
209   // the inners, the map is 
210   // 
211   //    Sector  0, strips   0-127  ->   Channel  0
212   //    Sector  0, strips 128-255  ->   Channel  2
213   //    Sector  0, strips 256-383  ->   Channel  4
214   //    Sector  0, strips 384-511  ->   Channel  6
215   //    Sector  1, strips   0-127  ->   Channel  1
216   //    Sector  1, strips 128-255  ->   Channel  3
217   //    Sector  1, strips 256-383  ->   Channel  5
218   //    Sector  1, strips 384-511  ->   Channel  7
219   //    Sector  2, strips   0-127  ->   Channel  8
220   //    Sector  2, strips 128-255  ->   Channel 10
221   //    Sector  2, strips 256-383  ->   Channel 12
222   //    Sector  2, strips 384-511  ->   Channel 14
223   //    Sector  3, strips   0-127  ->   Channel  9
224   //    Sector  3, strips 128-255  ->   Channel 11
225   //    Sector  3, strips 256-383  ->   Channel 13
226   //    Sector  3, strips 384-511  ->   Channel 15
227   // 
228   // and so on, up to sector 19.  For the outer, the map is 
229   // 
230   //    Sector  0, strips   0-127  ->   Channel  0
231   //    Sector  0, strips 128-255  ->   Channel  2
232   //    Sector  1, strips   0-127  ->   Channel  1
233   //    Sector  1, strips 128-255  ->   Channel  3
234   //    Sector  2, strips   0-127  ->   Channel  4
235   //    Sector  2, strips 128-255  ->   Channel  6
236   //    Sector  3, strips   0-127  ->   Channel  5
237   //    Sector  3, strips 128-255  ->   Channel  7
238   //    Sector  4, strips   0-127  ->   Channel  8
239   //    Sector  4, strips 128-255  ->   Channel 10
240   //    Sector  5, strips   0-127  ->   Channel  9
241   //    Sector  5, strips 128-255  ->   Channel 11
242   //    Sector  6, strips   0-127  ->   Channel 12
243   //    Sector  6, strips 128-255  ->   Channel 14
244   //    Sector  7, strips   0-127  ->   Channel 13
245   //    Sector  7, strips 128-255  ->   Channel 15
246   // 
247   // and so on upto sector 40. 
248   // 
249   // With this information, we can decode the detector coordinates to
250   // give us a unique hardware address 
251   //
252   ddl          =  (det - 1);
253   UInt_t board = 0;
254   UInt_t altro = 0;
255   UInt_t chan  = 0;
256   UInt_t tmp   = 0;
257   switch (ring) {
258   case 'I':
259   case 'i':
260     board += (sec / 10) * 16;
261     altro =  (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
262     tmp   =  (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
263     chan  =  2  * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
264     break;
265   case 'O':
266   case 'o':
267     board += (sec / 20) * 20 + 1;
268     altro =  (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
269     tmp   =  (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
270     chan  =  2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
271     break;
272   }
273   addr         =  chan + (altro << 4) + (board << 7);
274   
275   return kTRUE;
276 }
277
278 //____________________________________________________________________
279 Int_t
280 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring) const
281 {
282   // Return hardware address corresponding to sector sec, strip str,
283   // and ring ring.   Mapping from TPC to FMD coordinates are 
284   // 
285   //   TPC     | FMD
286   //   --------+------
287   //   padrow  | sector
288   //   pad     | strip
289   //   sector  | ring 
290   //
291   UInt_t ddl, hwaddr;
292   Char_t r = Char_t(ring);
293   if (!Detector2Hardware(1, r, sec, str, ddl, hwaddr)) 
294     return -1;
295   return hwaddr;
296 }
297
298 //____________________________________________________________________
299 Int_t
300 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
301 {
302   // Return sector corresponding to hardware address hwaddr.  Mapping
303   // from TPC to FMD coordinates are  
304   // 
305   //   TPC     | FMD
306   //   --------+------
307   //   padrow  | sector
308   //   pad     | strip
309   //   sector  | ring 
310   //
311   UShort_t det;
312   Char_t   ring;
313   UShort_t sec;
314   UShort_t str;
315   Int_t    ddl = 0;
316   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
317   return Int_t(sec);
318 }
319
320 //____________________________________________________________________
321 Int_t
322 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
323 {
324   // Return strip corresponding to hardware address hwaddr.  Mapping
325   // from TPC to FMD coordinates are  
326   // 
327   //   TPC     | FMD
328   //   --------+------
329   //   padrow  | sector
330   //   pad     | strip
331   //   sector  | ring 
332   //
333   UShort_t det;
334   Char_t   ring;
335   UShort_t sec;
336   UShort_t str;
337   Int_t    ddl = 0;
338   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
339   return Int_t(str);
340 }
341   
342 //____________________________________________________________________
343 Int_t
344 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
345 {
346   // Return ring corresponding to hardware address hwaddr.  Mapping
347   // from TPC to FMD coordinates are  
348   // 
349   //   TPC     | FMD
350   //   --------+------
351   //   padrow  | sector
352   //   pad     | strip
353   //   sector  | ring 
354   //
355   UShort_t det;
356   Char_t   ring;
357   UShort_t sec;
358   UShort_t str;
359   Int_t    ddl = 0;
360   if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
361   return Int_t(ring);
362 }
363
364 //_____________________________________________________________________________
365 //
366 // EOF
367 //