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