gondola_core/tof/
rb_paddle_id.rs

1// This file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6/// Squeze the rb channel - paddle mapping into 5 bytes
7/// for a single RB
8#[derive(Debug, Copy, Clone, PartialEq)]
9#[cfg_attr(feature="pybindings", pyclass)]
10pub struct RBPaddleID {
11  /// Paddle connected to RB channel 1/2
12  pub paddle_12     : u8,
13  /// Paddle connected to RB channel 3/4
14  pub paddle_34     : u8,
15  /// Paddle connected to RB channel 5/6
16  pub paddle_56     : u8,
17  /// Paddle connected to RB channel 7/8
18  pub paddle_78     : u8,
19  /// Order - 1 if the smaller channel is the 
20  /// A side, 2, if the smaller channel is the 
21  /// B side
22  pub channel_order : u8
23}
24
25impl Default for RBPaddleID {
26  fn default() -> Self {
27    Self::new()
28  }
29}
30
31impl fmt::Display for RBPaddleID {
32  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33    let mut repr = String::from("<RBPaddleID:");
34    for k in 1..9 {
35      let pid = self.get_paddle_id(k);
36      let ord = self.get_order_str(k);
37      repr += &(format!("\n  {k} -> {} ({ord})", pid.0)) 
38    }
39    repr += ">";
40    write!(f, "{}", repr)
41  }
42}
43
44impl RBPaddleID {
45  pub fn new() -> Self {
46    RBPaddleID {
47      paddle_12     : 0,
48      paddle_34     : 0,
49      paddle_56     : 0,
50      paddle_78     : 0,
51      channel_order : 0
52    }
53  }
54
55  pub fn to_u64(&self) -> u64 {
56    let val : u64 = (self.channel_order as u64) << 32 | (self.paddle_78 as u64) << 24 | (self.paddle_56 as u64) << 16 | (self.paddle_34 as u64) << 8 |  self.paddle_12 as u64;
57    val
58  }
59
60  /// Typically, the A-side will be connected to a lower channel id
61  ///
62  /// If the order is flipped, the lower channel will be connected to 
63  /// the B-side
64  ///
65  /// # Arguments
66  /// * channel : RB channel (1-8)
67  pub fn get_order_flipped(&self, channel : u8) -> bool {
68    match channel {
69      1 | 2 => {
70        return (self.channel_order & 1) == 1;
71      }
72      3 | 4 => {
73        return (self.channel_order & 2) == 2;
74      }
75      5 | 6 => {
76        return (self.channel_order & 4) == 4;
77      }
78      7 | 8 => {
79        return (self.channel_order & 8) == 8;
80      }
81      _ => {
82        error!("{} is not a valid RB channel!", channel);
83        return false;
84      }
85    }
86  }
87
88  pub fn get_order_str(&self, channel : u8) -> String {
89    if self.get_order_flipped(channel) {
90      return String::from("BA");
91    } else {
92      return String::from("AB");
93    }
94  }
95
96  pub fn is_a(&self, channel : u8) -> bool {
97    match channel {
98      1 => {
99        if self.get_order_flipped(channel) {
100          return false;
101        } else {
102          return true
103        }
104      }
105      2 => {
106        if self.get_order_flipped(channel) {
107          return true;
108        } else {
109          return false
110        }
111      }
112      3 => {
113        if self.get_order_flipped(channel) {
114          return false;
115        } else {
116          return true
117        }
118      }
119      4 => {
120        if self.get_order_flipped(channel) {
121          return true;
122        } else {
123          return false
124        }
125      }
126      5 => {
127        if self.get_order_flipped(channel) {
128          return false;
129        } else {
130          return true
131        }
132      }
133      6 => {
134        if self.get_order_flipped(channel) {
135          return true;
136        } else {
137          return false
138        }
139      }
140      7 => {
141        if self.get_order_flipped(channel) {
142          return false;
143        } else {
144          return true
145        }
146      }
147      8 => {
148        if self.get_order_flipped(channel) {
149          return true;
150        } else {
151          return false
152        }
153      }
154      _ => {
155        error!("{} is not a valid RB channel!", channel);
156        return false;
157      }
158    }
159  }
160
161  pub fn from_u64(val : u64) -> Self {
162    let paddle_12     : u8 = ((val & 0xFF)) as u8;
163    let paddle_34     : u8 = ((val & 0xFF00) >> 8) as u8;
164    let paddle_56     : u8 = ((val & 0xFF0000) >> 16) as u8;
165    let paddle_78     : u8 = ((val & 0xFF000000) >> 24) as u8; 
166    let channel_order : u8 = ((val & 0xFF00000000) >> 32) as u8;
167    Self {
168      paddle_12,
169      paddle_34,
170      paddle_56,
171      paddle_78,
172      channel_order,
173    }
174  }
175
176
177  /// Get the paddle id together with the information 
178  /// if this is the A side
179  ///
180  /// channel in rb channels (starts at 1)
181  pub fn get_paddle_id(&self, channel : u8) -> (u8, bool) {
182    let flipped = self.get_order_flipped(channel);
183    match channel {
184      1 | 2 => {
185        return (self.paddle_12, flipped); 
186      }
187      3 | 4 => {
188        return (self.paddle_34, flipped); 
189      }
190      5 | 6 => {
191        return (self.paddle_56, flipped); 
192      }
193      7 | 8 => {
194        return (self.paddle_78, flipped); 
195      }
196      _ => {
197        error!("{} is not a valid RB channel!", channel);
198        return (0,false);
199      }
200    }
201  }
202}
203
204
205#[cfg(feature="pybindings")]
206#[pymethods]
207impl RBPaddleID {
208  #[new]
209  fn new_py() -> Self {
210    Self::new()
211  }
212
213  #[pyo3(name="get_paddle_id")]
214  fn get_paddle_id_py(&self, channel : u8) -> (u8, bool) {
215    self.get_paddle_id(channel)
216  } 
217}
218
219#[cfg(feature="database")]
220impl RBPaddleID {
221
222  pub fn from_rb( rb : &ReadoutBoard) -> Self {
223    let mut rb_pid = RBPaddleID::new();
224    rb_pid.paddle_12 = rb.paddle12.paddle_id as u8;    
225    rb_pid.paddle_34 = rb.paddle34.paddle_id as u8;    
226    rb_pid.paddle_56 = rb.paddle56.paddle_id as u8;    
227    rb_pid.paddle_78 = rb.paddle78.paddle_id as u8;    
228    let mut flipped  = 0u8 ;
229    if rb.get_paddle12_chA() != 1 {
230      flipped |= 1;
231    }
232    if rb.get_paddle34_chA() != 3 {
233      flipped |= 2;
234    }
235    if rb.get_paddle56_chA() != 5 {
236      flipped |= 4;
237    }
238    if rb.get_paddle78_chA() != 7 {
239      flipped |= 8;
240    }
241    rb_pid.channel_order = flipped;
242    rb_pid
243  }
244}
245
246#[cfg(feature = "random")]
247impl FromRandom for RBPaddleID {
248    
249  fn from_random() -> Self {
250    let mut rb_pid  = Self::new();
251    let mut rng = rand::rng();
252    rb_pid.paddle_12   = rng.random::<u8>();
253    rb_pid.paddle_34   = rng.random::<u8>();
254    rb_pid.paddle_56   = rng.random::<u8>();
255    rb_pid.paddle_78   = rng.random::<u8>();
256    rb_pid.channel_order = rng.random::<u8>();
257    rb_pid
258  }
259}
260
261