1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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
21 //____________________________________________________________________
23 // Mapping of ALTRO hardware channel to detector coordinates
25 // The hardware address consist of a DDL number and 12bits of ALTRO
26 // addresses. The ALTRO address are formatted as follows.
29 // |---------------|---------|------------|
30 // | Board # | ALTRO # | Channel # |
31 // +---------------+---------+------------+
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
37 #include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
38 #include "AliFMDParameters.h"
43 //____________________________________________________________________
44 ClassImp(AliFMDAltroMapping)
46 ; // This is here to keep Emacs for indenting the next line
49 //_____________________________________________________________________________
50 AliFMDAltroMapping::AliFMDAltroMapping()
56 //_____________________________________________________________________________
58 AliFMDAltroMapping::ReadMapping()
60 // Read map from file - not used
64 //_____________________________________________________________________________
66 AliFMDAltroMapping::CreateInvMapping()
68 // Create inverse mapping - not used
72 //____________________________________________________________________
74 AliFMDAltroMapping::Hardware2Detector(UInt_t ddl, UInt_t addr,
75 UShort_t& det, Char_t& ring,
76 UShort_t& sec, Short_t& str) const
78 // Translate a hardware address to detector coordinates.
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);
87 //____________________________________________________________________
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, Short_t& str) const
94 // Translate a hardware address to detector coordinates.
95 // The detector is simply
99 // The ring number, sector, and strip number is given by the addr
100 // argument. The address argument, has the following format
103 // +-------------+----------+----------+
104 // | Board | ALTRO | Channel |
105 // +-------------+----------+----------+
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
112 // The board number and ALTRO number together identifies the sensor,
113 // and hence. The lower board number (0 or 16) are the first N / 2
114 // sensors (where N is the number of sensors in the ring).
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
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
126 // For the outer rings, the map is
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
139 // Which divison of the sensor we're in, depends on the channel
140 // number only. For the inner rings, the map is
142 // Channel 0 -> Sector 0, strips 0-127
143 // Channel 1 -> Sector 1, strips 127-0
144 // Channel 3 -> Sector 0, strips 128-255
145 // Channel 4 -> Sector 1, strips 255-128
146 // Channel 5 -> Sector 0, strips 256-383
147 // Channel 6 -> Sector 1, strips 383-256
148 // Channel 7 -> Sector 0, strips 384-511
149 // Channel 8 -> Sector 1, strips 511-384
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
154 // Channel 0 -> Sector 0, strips 0-127
155 // Channel 1 -> Sector 1, strips 127-0
156 // Channel 3 -> Sector 0, strips 128-255
157 // Channel 4 -> Sector 1, strips 255-128
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, as seen by the ALTRO channel, in the
165 ring = (board % 2) == 0 ? 'I' : 'O';
169 sec = ((board / 16) * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6)
170 + 2 * (chan / 8) + chan % 2);
171 str = ((chan % 8) / 2) * 128;
175 sec = ((board / 16) * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12)
176 + 2 * (chan / 4) + chan % 2);
177 str = ((chan % 4) / 2) * 128;
180 if (sec % 2) str += 127;
184 //____________________________________________________________________
186 AliFMDAltroMapping::Hardware2Detector(UInt_t ddl, UInt_t addr,
187 UShort_t timebin, UShort_t preSamples,
189 UShort_t& det, Char_t& ring,
190 UShort_t& sec, Short_t& str,
193 // Translate a hardware address to detector coordinates.
195 // See also Hardware2Detector that accepts 4 inputs
196 UInt_t board = (addr >> 7) & 0x1F;
197 UInt_t altro = (addr >> 4) & 0x7;
198 UInt_t chan = (addr & 0xf);
199 return Hardware2Detector(ddl, board, altro, chan,
200 timebin, preSamples, sampleRate,
201 det, ring, sec, str, sam);
204 //____________________________________________________________________
206 AliFMDAltroMapping::Hardware2Detector(UInt_t ddl, UInt_t board,
207 UInt_t altro, UInt_t chan,
208 UInt_t timebin, UInt_t preSamples,
210 UShort_t& det, Char_t& ring,
211 UShort_t& sec, Short_t& str,
214 // Full conversion from hardware address, including timebin number,
215 // to detector coordinates and sample number. Note, that this
216 // conversion depends on the oversampling rate and the number of
218 if (!Hardware2Detector(ddl, board, altro, chan, det, ring, sec, str))
220 UShort_t t = (timebin - preSamples);
221 sam = (t % sampleRate);
223 str += (sec % 2 ? -1 : 1) * t / sampleRate;
224 // if (sec % 2) sam = sampleRate - 1 - sam;
226 AliFMDDebug(3, ("%d/0x%02x/0x%x/0x%x/%04d -> FMD%d%c[%02d,%03d]-%d"
227 " (pre=%2d, rate=%d)",
228 ddl, board, altro, chan, timebin,
229 det, ring, sec, str, sam, preSamples, sampleRate));
235 //____________________________________________________________________
237 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
238 UShort_t sec, UShort_t str,
239 UInt_t& ddl, UInt_t& board,
240 UInt_t& altro, UInt_t& chan) const
242 // Translate detector coordinates to a hardware address.
247 // The ring number, sector, and strip number must be encoded into a
248 // hardware address. The address argument, will have the following
252 // +-------------+----------+----------+
253 // | Board | ALTRO | Channel |
254 // +-------------+----------+----------+
256 // The board number is given by the ring and sector. The inner
257 // rings board 0 and 16, while the outer are 1 and 17. Which of these
258 // depends on the sector. The map is
260 // Ring I, sector 0- 9 -> board 0
261 // Ring I, sector 10-19 -> board 16
262 // Ring O, sector 0-19 -> board 1
263 // Ring O, sector 20-39 -> board 17
265 // There are 3 ALTRO's per board. The ALTRO number is given by the
266 // sector number. For the inner rings, these are given by
268 // Sector 0- 3 or 10-13 -> ALTRO 0
269 // Sector 4- 5 or 14-15 -> ALTRO 1
270 // Sector 6- 9 or 16-19 -> ALTRO 2
272 // For the outers, it's given by
274 // Sector 0- 7 or 20-27 -> ALTRO 0
275 // Sector 8-11 or 28-31 -> ALTRO 1
276 // Sector 12-19 or 32-39 -> ALTRO 2
278 // The channel number is given by the sector and strip number. For
279 // the inners, the map is
281 // Sector 0, strips 0-127 -> Channel 0
282 // Sector 0, strips 128-255 -> Channel 2
283 // Sector 0, strips 256-383 -> Channel 4
284 // Sector 0, strips 384-511 -> Channel 6
285 // Sector 1, strips 127- 0 -> Channel 1
286 // Sector 1, strips 255-128 -> Channel 3
287 // Sector 1, strips 383-256 -> Channel 5
288 // Sector 1, strips 511-384 -> Channel 7
289 // Sector 2, strips 0-127 -> Channel 8
290 // Sector 2, strips 128-255 -> Channel 10
291 // Sector 2, strips 256-383 -> Channel 12
292 // Sector 2, strips 384-511 -> Channel 14
293 // Sector 3, strips 127- 0 -> Channel 9
294 // Sector 3, strips 255-128 -> Channel 11
295 // Sector 3, strips 383-256 -> Channel 13
296 // Sector 3, strips 511-384 -> Channel 15
298 // and so on, up to sector 19. For the outer, the map is
300 // Sector 0, strips 0-127 -> Channel 0
301 // Sector 0, strips 128-255 -> Channel 2
302 // Sector 1, strips 127- 0 -> Channel 1
303 // Sector 1, strips 255-128 -> Channel 3
304 // Sector 2, strips 0-127 -> Channel 4
305 // Sector 2, strips 128-255 -> Channel 6
306 // Sector 3, strips 127- 0 -> Channel 5
307 // Sector 3, strips 255-128 -> Channel 7
308 // Sector 4, strips 0-127 -> Channel 8
309 // Sector 4, strips 128-255 -> Channel 10
310 // Sector 5, strips 127- 0 -> Channel 9
311 // Sector 5, strips 255-128 -> Channel 11
312 // Sector 6, strips 0-127 -> Channel 12
313 // Sector 6, strips 128-255 -> Channel 14
314 // Sector 7, strips 127- 0 -> Channel 13
315 // Sector 7, strips 255-128 -> Channel 15
317 // and so on upto sector 40.
319 // With this information, we can decode the detector coordinates to
320 // give us a unique hardware address
327 board = (sec / 10) * 16;
328 altro = (sec % 10) < 4 ? 0 : (sec % 10) < 6 ? 1 : 2;
329 tmp = (sec % 10) - (altro == 0 ? 0 : altro == 1 ? 4 : 6);
330 chan = 2 * (str / 128) + (sec % 2) + ((tmp / 2) % 2) * 8;
334 board = (sec / 20) * 16 + 1;
335 altro = (sec % 20) < 8 ? 0 : (sec % 20) < 12 ? 1 : 2;
336 tmp = (sec % 20) - (altro == 0 ? 0 : altro == 1 ? 8 : 12);
337 chan = 2 * (str / 128) + (sec % 2) + ((tmp / 2) % 4) * 4;
343 //____________________________________________________________________
345 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
346 UShort_t sec, UShort_t str,
347 UInt_t& ddl, UInt_t& addr) const
349 // Translate detector coordinates to a hardware address.
351 // See also Detector2Hardware that returns 4 parameters.
355 if (!Detector2Hardware(det,ring,sec,str,ddl,board,altro,chan)) return kFALSE;
356 addr = chan + (altro << 4) + (board << 7);
360 //____________________________________________________________________
362 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
363 UShort_t sec, UShort_t str,
365 UShort_t preSamples, UShort_t sampleRate,
366 UInt_t& ddl, UInt_t& board,
367 UInt_t& altro, UInt_t& channel,
368 UShort_t& timebin) const
370 if (!Detector2Hardware(det,ring,sec,str,ddl,board,altro,channel))
372 timebin = preSamples;
374 timebin += (127 - (str % 128)) * sampleRate;
376 timebin += (str % 128) * sampleRate;
382 //____________________________________________________________________
384 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
385 UShort_t sec, UShort_t str,
387 UShort_t preSamples, UShort_t sampleRate,
388 UInt_t& ddl, UInt_t& hwaddr,
389 UShort_t& timebin) const
394 if (!Detector2Hardware(det, ring, sec, str, sam,
395 preSamples, sampleRate,
396 ddl, board, altro, chan, timebin)) return kFALSE;
397 hwaddr = chan + (altro << 4) + (board << 7);
403 //____________________________________________________________________
405 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
407 // Return hardware address corresponding to sector sec, strip str,
408 // and ring ring. Mapping from TPC to FMD coordinates are
417 Char_t r = Char_t(ring);
418 if (!Detector2Hardware(1, r, sec, str, ddl, hwaddr))
423 //____________________________________________________________________
425 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
427 // Return sector corresponding to hardware address hwaddr. Mapping
428 // from TPC to FMD coordinates are
441 if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
445 //____________________________________________________________________
447 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
449 // Return strip corresponding to hardware address hwaddr. Mapping
450 // from TPC to FMD coordinates are
463 if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
467 //____________________________________________________________________
469 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
471 // Return ring corresponding to hardware address hwaddr. Mapping
472 // from TPC to FMD coordinates are
485 if (!Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) return -1;
489 //____________________________________________________________________
491 AliFMDAltroMapping::Print(Option_t* option) const
495 UInt_t ddl, board, chip, chan, addr;
500 if (opt.Contains("hw") || opt.Contains("hardware")) {
501 std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
502 << "=====+=======+======+======+=========+==============="
504 for (ddl = 0; ddl <= 2; ddl++) {
505 Int_t boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
507 while ((board = *(ptr++)) < 32) {
508 for (chip = 0; chip <= 2; chip++) {
509 UInt_t nchan = (chip == 1 ? 8 : 16);
510 for (chan = 0; chan < nchan; chan++) {
511 Hardware2Detector(ddl, board, chip, chan, det, rng, sec, str);
512 addr = ((board & 0x1f) << 7) | ((chip & 0x7) << 4) | (chan & 0xf);
514 << std::setw(3) << ddl << " | "
515 << std::setfill('0') << std::hex << " 0x"
516 << std::setw(2) << board << " | 0x"
517 << std::setw(1) << chip << " | 0x"
518 << std::setw(1) << chan << " | 0x"
519 << std::setw(3) << addr << " | "
520 << std::setfill(' ') << std::dec << " FMD"
521 << std::setw(1) << det << rng << "["
522 << std::setw(2) << sec << "," << std::setw(3) << str
525 if (chip == 2 && *ptr >= 32) continue;
526 std::cout << " + + + + + "
530 std::cout << "-----+-------+------+------+---------+---------------"
534 if (opt.Contains("det")) {
535 std::cout << " Detector | DDL | Board | Chip | Chan | Address\n"
536 << "===============+=====+=======+======+======+========"
538 for (det = 1; det <= 3; det++) {
539 Char_t rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
541 while ((rng = *(ptr++)) != '\0') {
542 UShort_t nsec = (rng == 'I' ? 20 : 40);
543 UShort_t nstr = (rng == 'I' ? 512 : 256);
544 for (sec = 0; sec < nsec; sec++) {
545 for (str = 0; str < nstr; str += 128) {
546 ddl = board = chip = chan;
547 Detector2Hardware(det,rng,sec,str,ddl,board,chip,chan);
548 addr = ((board & 0x1f) << 7) | ((chip & 0x7) << 4) | (chan & 0xf);
549 std::cout << std::setfill(' ') << std::dec << " FMD"
550 << std::setw(1) << det << rng << "["
551 << std::setw(2) << sec << ","
552 << std::setw(3) << str << "] | "
553 << std::setw(3) << ddl << " | 0x"
554 << std::setfill('0') << std::hex
555 << std::setw(2) << board << " | 0x"
556 << std::setw(1) << chip << " | 0x"
557 << std::setw(1) << chan << " | 0x"
558 << std::setw(3) << addr << std::endl;
561 if (*ptr == '\0') continue;
562 std::cout << " + + + + + "
565 std::cout << "---------------+-----+-------+------+------+--------"
572 //_____________________________________________________________________________