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"
40 #include "AliFMDDebug.h"
44 //____________________________________________________________________
45 ClassImp(AliFMDAltroMapping)
47 ; // This is here to keep Emacs for indenting the next line
50 //_____________________________________________________________________________
51 AliFMDAltroMapping::AliFMDAltroMapping()
57 //_____________________________________________________________________________
59 AliFMDAltroMapping::ReadMapping()
61 // Read map from file - not used
65 //_____________________________________________________________________________
67 AliFMDAltroMapping::CreateInvMapping()
69 // Create inverse mapping - not used
74 //____________________________________________________________________
76 AliFMDAltroMapping::Channel2StripBase(UShort_t board, UShort_t altro,
77 UShort_t chan, Char_t& ring,
78 UShort_t& sec, Short_t& str) const
80 // Translate a hardware address to detector coordinates.
81 // The detector is simply
85 // The ring number, sector, and strip number is given by the addr
86 // argument. The address argument, has the following format
89 // +-------------+----------+----------+
90 // | Board | ALTRO | Channel |
91 // +-------------+----------+----------+
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
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).
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
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
112 // For the outer rings, the map is
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
125 // Which divison of the sensor we're in, depends on the channel
126 // number only. For the inner rings, the map is
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
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
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
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
150 ring = Board2Ring(board);
151 UShort_t fsec = board < 16 ? 1 : 0;
155 sec = (fsec * 10 + (altro < 1 ? 0 : altro < 2 ? 4 : 6)
156 + 2 * (chan / 8) + chan % 2);
157 str = ((chan % 8) / 2) * 128;
161 sec = (fsec * 20 + (altro < 1 ? 0 : altro < 2 ? 8 : 12)
162 + 2 * (chan / 4) + chan % 2);
163 str = ((chan % 4) / 2) * 128;
166 if (sec % 2) str += 127;
167 // AliFMDDebug(1, ("%02x/%x/%x Base strip = %d", board, altro, chan, str));
171 //____________________________________________________________________
173 AliFMDAltroMapping::Timebin2Strip(UShort_t sec,
178 UShort_t& sample) const
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);
186 stripOff = (sec % 2 ? -1 : 1) * t / sampleRate;
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));
194 //____________________________________________________________________
196 AliFMDAltroMapping::Hardware2Detector(UShort_t ddl, UShort_t board,
197 UShort_t altro, UShort_t chan,
198 UShort_t timebin, UShort_t preSamples,
200 UShort_t& det, Char_t& ring,
201 UShort_t& sec, Short_t& str,
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
208 Short_t baseStrip, stripOffset, tdet = DDL2Detector(ddl);
209 if (tdet < 0) return kFALSE;
211 if (!Channel2StripBase(board, altro, chan, ring, sec, baseStrip))
213 Timebin2Strip(sec, timebin, preSamples, sampleRate, stripOffset, sam);
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)",
232 str = baseStrip + stripOffset;
236 //____________________________________________________________________
238 AliFMDAltroMapping::Hardware2Detector(UShort_t ddl, UShort_t addr,
239 UShort_t timebin, UShort_t preSamples,
241 UShort_t& det, Char_t& ring,
242 UShort_t& sec, Short_t& str,
245 // Translate a hardware address to detector coordinates.
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);
256 //____________________________________________________________________
258 AliFMDAltroMapping::Sector2Board(Char_t ring, UShort_t sec) const
261 // Return board address corresponding to a sector
264 // ring Ring identifier
267 // The board number, or negative number in case of failure
272 return (sec < 10 ? 16 : 0); // (sec / 10) * 16;
275 return (sec < 20 ? 16 : 0) + 1; // (sec / 20) * 16 + 1;
280 //_____________________________________________ _______________________
282 AliFMDAltroMapping::Strip2Channel(Char_t ring, UShort_t sec,
283 UShort_t str, UShort_t& board,
284 UShort_t& altro, UShort_t& chan) const
286 // Translate detector coordinates to a hardware address.
291 // The ring number, sector, and strip number must be encoded into a
292 // hardware address. The address argument, will have the following
296 // +-------------+----------+----------+
297 // | Board | ALTRO | Channel |
298 // +-------------+----------+----------+
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
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
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
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
316 // For the outers, it's given by
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
322 // The channel number is given by the sector and strip number. For
323 // the inners, the map is
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
342 // and so on, up to sector 19. For the outer, the map is
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
361 // and so on upto sector 40.
363 // With this information, we can decode the detector coordinates to
364 // give us a unique hardware address
371 fboard = sec < 10 ? 1 : 0;
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;
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;
389 //_____________________________________________ _______________________
391 AliFMDAltroMapping::Strip2Timebin(UShort_t sec, UShort_t strip,
392 UShort_t sam, UShort_t preSamples,
393 UShort_t sampleRate) const
396 // Get the timebin correspoding to a strip and sample
402 // preSamples Number of pre-samples.
403 // sampleRate The over-sampling rate
405 // the timebin corresponding to the passed strip
407 UShort_t timebin = preSamples;
409 timebin += (127 - (strip % 128)) * sampleRate;
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,
418 timebin += (strip % 128) * sampleRate;
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));
430 //____________________________________________________________________
432 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
433 UShort_t sec, UShort_t str,
437 UShort_t& ddl, UShort_t& board,
438 UShort_t& altro, UShort_t& channel,
439 UShort_t& timebin) const
442 // Map a detector index into a hardware address.
445 // det The detector #
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)
458 // @c true on success, false otherwise
460 ddl = Detector2DDL(det);
461 if (!Strip2Channel(ring,sec,str,board,altro,channel)) return kFALSE;
462 timebin = Strip2Timebin(sec, str, sam, preSamples, sampleRate);
467 //____________________________________________________________________
469 AliFMDAltroMapping::Detector2Hardware(UShort_t det, Char_t ring,
470 UShort_t sec, UShort_t str,
472 UShort_t preSamples, UShort_t sampleRate,
473 UShort_t& ddl, UShort_t& hwaddr,
474 UShort_t& timebin) const
477 // Map a detector index into a hardware address.
480 // det The detector #
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)
491 // @c true on success, false otherwise
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);
504 //____________________________________________________________________
506 AliFMDAltroMapping::ChannelAddress(UShort_t board, UShort_t altro,
507 UShort_t channel) const
510 // Convert board, chip, channel to a hardware address
513 // board Board number
514 // altro Altro number
515 // channel Channel number
517 // hardware address of a channel
519 return (((board & 0x1F) << 7) | ((altro & 0x7) << 4) | (channel & 0xF));
522 //____________________________________________________________________
524 AliFMDAltroMapping::ChannelAddress(UShort_t hwaddr, UShort_t& board,
525 UShort_t& altro, UShort_t& channel) const
528 // Convert a channel address to board, altro, channel fields
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
536 board = ((hwaddr >> 7) & 0x1F);
537 altro = ((hwaddr >> 4) & 0x07);
538 channel = ((hwaddr >> 0) & 0x0F);
541 //____________________________________________________________________
543 AliFMDAltroMapping::GetHWAddress(Int_t sec, Int_t str, Int_t ring)
545 // Return hardware address corresponding to sector sec, strip str,
546 // and ring ring. Mapping from TPC to FMD coordinates are
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);
560 //____________________________________________________________________
562 AliFMDAltroMapping::GetPadRow(Int_t hwaddr) const
564 // Return sector corresponding to hardware address hwaddr. Mapping
565 // from TPC to FMD coordinates are
574 UShort_t board, altro, channel, sector;
576 ChannelAddress(hwaddr, board, altro, channel);
577 if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
579 return Int_t(sector);
582 //____________________________________________________________________
584 AliFMDAltroMapping::GetPad(Int_t hwaddr) const
586 // Return strip corresponding to hardware address hwaddr. Mapping
587 // from TPC to FMD coordinates are
596 UShort_t board, altro, channel, sector;
598 ChannelAddress(hwaddr, board, altro, channel);
599 if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
601 return Int_t(baseStrip);
604 //____________________________________________________________________
606 AliFMDAltroMapping::GetSector(Int_t hwaddr) const
608 // Return ring corresponding to hardware address hwaddr. Mapping
609 // from TPC to FMD coordinates are
618 UShort_t board, altro, channel, sector;
620 ChannelAddress(hwaddr, board, altro, channel);
621 if (!Channel2StripBase(board, altro, channel, ring, sector, baseStrip))
626 //____________________________________________________________________
628 AliFMDAltroMapping::Print(Option_t* option) const
631 // Print map to standard out
634 // option Option string (hw, or det)
638 UShort_t ddl, board, chip, chan, addr;
643 if (opt.Contains("hw") || opt.Contains("hardware")) {
644 std::cout << " DDL | Board | Chip | Chan | Address | Detector\n"
645 << "=====+=======+======+======+=========+==============="
647 for (ddl = 0; ddl <= 2; ddl++) {
648 Int_t boards[] = { 0, 16, (ddl == 0 ? 32 : 1), 17, 32};
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);
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;
669 if (chip == 2 && *ptr >= 32) continue;
670 std::cout << " + + + + + "
674 std::cout << "-----+-------+------+------+---------+---------------"
678 if (opt.Contains("det")) {
679 std::cout << " Detector | DDL | Board | Chip | Chan | Address\n"
680 << "===============+=====+=======+======+======+========"
682 for (det = 1; det <= 3; det++) {
683 Char_t rings[] = { 'I', (det == 1 ? '\0' : 'O'),'\0' };
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;
705 if (*ptr == '\0') continue;
706 std::cout << " + + + + + "
709 std::cout << "---------------+-----+-------+------+------+--------"
716 //_____________________________________________________________________________