tof_dataclasses/commands/
config.rs

1//! Payloads for commands that configure an entity of 
2//! the TOF system.
3//!
4
5use std::fmt;
6
7#[cfg(feature = "pybindings")]
8use pyo3::pyclass;
9
10use crate::serialization::{
11  Serialization,
12  SerializationError,
13  Packable,
14  parse_bool, 
15  parse_u8,
16  parse_u16,
17  parse_u32,
18  parse_f32,
19  parse_usize
20};
21
22use crate::packets::PacketType;
23use crate::events::DataType;
24use crate::commands::TofOperationMode;
25
26use crate::events::TriggerType;
27
28cfg_if::cfg_if! {
29  if #[cfg(feature = "random")]  {
30    use crate::FromRandom;
31    use rand::Rng;
32  }
33}
34
35/// Build Strategy
36/// 
37#[derive(Debug, Copy, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
38#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
39pub enum BuildStrategy {
40  Unknown,
41  Smart,
42  /// adjust the number of boards based on nrbes/mtb
43  Adaptive,
44  /// Same as adaptive, but check if the rb events follow the 
45  /// mapping
46  AdaptiveThorough,
47  /// like adaptive, but add usize to the expected number of boards
48  AdaptiveGreedy,
49  WaitForNBoards
50}
51
52impl fmt::Display for BuildStrategy {
53  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54    let r = serde_json::to_string(self).unwrap_or(
55      String::from("N.A. - Invalid BuildStrategy (error)"));
56    write!(f, "<BuildStrategy: {}>", r)
57  }
58}
59
60impl BuildStrategy {
61  pub fn to_u8(&self) -> u8 {
62    match self {
63      BuildStrategy::Unknown => {
64        return 0;
65      }
66      BuildStrategy::Smart => {
67        return 100;
68      }
69      BuildStrategy::Adaptive => {
70        return 101;
71      }
72      BuildStrategy::AdaptiveThorough => {
73        return 102;
74      }
75      BuildStrategy::AdaptiveGreedy => {
76        return 1;
77      }
78      BuildStrategy::WaitForNBoards => {
79        return 2;
80      }
81    }
82  }
83}
84
85impl From<u8> for BuildStrategy {
86  fn from(value: u8) -> Self {
87    match value {
88      0   => BuildStrategy::Unknown,
89      100 => BuildStrategy::Smart,
90      101 => BuildStrategy::Adaptive,
91      102 => BuildStrategy::AdaptiveThorough,
92      1   => BuildStrategy::AdaptiveGreedy,
93      2   => BuildStrategy::WaitForNBoards,
94      _   => BuildStrategy::Unknown
95    }
96  }
97}
98
99#[cfg(feature = "random")]
100impl FromRandom for BuildStrategy {
101  
102  fn from_random() -> Self {
103    let choices = [
104      BuildStrategy::Unknown,
105      BuildStrategy::Smart,
106      BuildStrategy::Adaptive,
107      BuildStrategy::AdaptiveThorough,
108      BuildStrategy::AdaptiveGreedy,
109      BuildStrategy::WaitForNBoards,
110    ];
111    let mut rng  = rand::thread_rng();
112    let idx = rng.gen_range(0..choices.len());
113    choices[idx]
114  }
115}
116
117//////////////////////////////////////////////////
118
119/// Set preamp voltages
120#[derive(Copy, Clone, Debug, PartialEq)]
121pub struct PreampBiasConfig {
122  pub rb_id   : u8,
123  pub biases  : [f32;16]
124}
125
126impl PreampBiasConfig {
127  pub fn new() -> Self { 
128    Self {
129      rb_id   : 0,
130      biases  : [0.0;16]
131    }
132  }
133}
134
135impl Default for PreampBiasConfig {
136  fn default() -> Self {
137    Self::new()
138  }
139}
140
141impl fmt::Display for PreampBiasConfig {
142  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143    //let cc = RBCommand::command_code_to_string(self.command_code);
144    let mut repr = String::from("<PreampBiasConfig");
145    repr += &(format!("\n  RB ID      : {}", self.rb_id)); 
146    repr += "  -- biases per channel:";
147    for k in 0..self.biases.len() {
148      repr += &(format!("\n    Ch{} : {:.2}", k+1, self.biases[k]));
149    }
150    write!(f, "{}", repr)
151  }
152}
153
154impl Packable for PreampBiasConfig {
155  const PACKET_TYPE : PacketType = PacketType::PreampBiasConfig;
156}
157
158impl Serialization for PreampBiasConfig {
159  
160  const HEAD : u16 = 0xAAAA;
161  const TAIL : u16 = 0x5555;
162  const SIZE : usize = 69; // nice! 
163  
164  fn from_bytestream(stream    : &Vec<u8>, 
165                     pos       : &mut usize) 
166    -> Result<Self, SerializationError>{
167    Self::verify_fixed(stream, pos)?;  
168    let mut cfg = PreampBiasConfig::new();
169    cfg.rb_id   = parse_u8(stream, pos);
170    for k in 0..16 {
171      cfg.biases[k] = parse_f32(stream, pos);
172    }
173    *pos += 2;
174    Ok(cfg)
175  }
176  
177  fn to_bytestream(&self) -> Vec<u8> {
178    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
179    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
180    bs.push(self.rb_id);
181    for k in 0..16 {
182      bs.extend_from_slice(&self.biases[k].to_le_bytes());
183    }
184    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
185    bs
186  }
187}
188
189#[cfg(feature = "random")]
190impl FromRandom for PreampBiasConfig {
191  fn from_random() -> Self {
192    let mut cfg  = PreampBiasConfig::new();
193    let mut rng      = rand::thread_rng();
194    cfg.rb_id  = rng.gen::<u8>();
195    for k in 0..16 {
196      cfg.biases[k] = rng.gen::<f32>();
197    }
198    cfg
199  }
200}
201
202/////////////////////////////////////////////////////
203
204#[derive(Copy, Clone, Debug, PartialEq)]
205pub struct RBChannelMaskConfig {
206  pub rb_id       : u8,
207  pub channels      : [bool;9],
208}
209
210impl RBChannelMaskConfig {
211  pub fn new() -> Self {
212    Self {
213      rb_id     : 0,
214      channels    : [false;9],
215    }
216  }
217}
218
219impl Default for RBChannelMaskConfig {
220  fn default() -> Self {
221    Self::new()
222  }
223}
224
225impl fmt::Display for RBChannelMaskConfig {
226  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227    let mut repr = String::from("<RBCHannelMaskConfig");
228    repr += &(format!("\n  RB ID      : {}", self.rb_id));
229    repr += &(format!("\n Problematic Channels >:( {:?}", self.channels));
230    write!(f, "{}", repr)
231  }
232}
233
234impl Packable for RBChannelMaskConfig {
235  const PACKET_TYPE : PacketType = PacketType::RBChannelMaskConfig;
236}
237
238impl Serialization for RBChannelMaskConfig {
239
240  const HEAD : u16 = 0xAAAA;
241  const TAIL : u16 = 0x5555;
242  const SIZE : usize = 14;
243
244  fn from_bytestream(stream     : &Vec<u8>,
245                     pos        : &mut usize)
246    -> Result<Self, SerializationError>{
247      Self::verify_fixed(stream, pos)?;
248      let mut cfg = RBChannelMaskConfig::new();
249      cfg.rb_id   = parse_u8(stream, pos);
250      for k in 0..9 {
251        cfg.channels[k] = parse_bool(stream, pos);
252      }
253      *pos += 2;
254      Ok(cfg)
255    }
256
257  fn to_bytestream(&self) -> Vec<u8> {
258    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
259    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
260    bs.push(self.rb_id);
261    for k in 0..9 {
262      bs.push(self.channels[k] as u8);
263    }
264    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
265    bs
266  }
267} 
268
269#[cfg(feature = "random")]
270impl FromRandom for RBChannelMaskConfig {
271  fn from_random() -> Self {
272    let mut cfg   = RBChannelMaskConfig::new();
273    let mut rng   = rand::thread_rng();
274    cfg.rb_id     = rng.gen::<u8>();
275    for k in 0..9 {
276      cfg.channels[k] = rng.gen::<bool>();
277    }
278    cfg
279  }
280}
281
282///////////////////////////////////////////////////////
283
284
285/// Set ltb thresholds
286#[derive(Copy, Clone, Debug, PartialEq)]
287pub struct LTBThresholdConfig {
288  pub rb_id       : u8,
289  pub thresholds  : [f32;3]
290}
291
292impl LTBThresholdConfig {
293  pub fn new() -> Self {
294    Self {
295      rb_id       : 0,
296      thresholds  : [0.0;3]
297    }
298  }
299}
300
301impl Default for LTBThresholdConfig {
302  fn default() -> Self {
303    Self::new()
304  }
305}
306
307impl fmt::Display for LTBThresholdConfig {
308  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
309    let mut repr = String::from("<LTBThresholdConfig");
310    repr += &(format!("\n  RB ID      : {}", self.rb_id));
311    repr += "  -- thresholds per channel:";
312    for k in 0..self.thresholds.len() {
313      repr += &(format!("\n    Ch{} : {:.3}", k, self.thresholds[k]));
314    }
315    write!(f, "{}", repr)
316  }
317}
318
319impl Packable for LTBThresholdConfig {
320  const PACKET_TYPE : PacketType = PacketType::LTBThresholdConfig;
321}
322
323impl Serialization for LTBThresholdConfig {
324
325  const HEAD : u16 = 0xAAAA;
326  const TAIL : u16 = 0x5555;
327  const SIZE : usize = 17;
328
329  fn from_bytestream(stream     : &Vec<u8>,
330                     pos        : &mut usize)
331    -> Result<Self, SerializationError>{
332      Self::verify_fixed(stream, pos)?;
333      let mut cfg = LTBThresholdConfig::new();
334      cfg.rb_id   = parse_u8(stream, pos);
335      for k in 0..3 {
336        cfg.thresholds[k] = parse_f32(stream, pos);
337      }
338      *pos += 2;
339      Ok(cfg)
340    }
341
342  fn to_bytestream(&self) -> Vec<u8> {
343    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
344    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
345    bs.push(self.rb_id);
346    for k in 0..3 {
347      bs.extend_from_slice(&self.thresholds[k].to_le_bytes());
348    }
349    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
350    bs
351  }
352}
353
354#[cfg(feature = "random")]
355impl FromRandom for LTBThresholdConfig {
356  fn from_random() -> Self {
357    let mut cfg   = LTBThresholdConfig::new();
358    let mut rng   = rand::thread_rng();
359    cfg.rb_id     = rng.gen::<u8>();
360    for k in 0..3 {
361      cfg.thresholds[k] = rng.gen::<f32>();
362    }
363    cfg
364  }
365}
366
367
368/// Readoutboard configuration for a specific run
369#[derive(Debug, Copy, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
370pub struct RunConfig {
371  /// an unique identifier for this run
372  pub runid                   : u32,
373  /// start/stop run
374  /// <div class="warning">This might get deprecated in a future version!</div>
375  pub is_active               : bool,
376  /// limit run to number of events
377  pub nevents                 : u32,
378  /// limit run time to number of seconds
379  pub nseconds                : u32,
380  /// tof operation mode - either "StreamAny",
381  /// "RequestReply" or "RBHighThroughput"
382  pub tof_op_mode             : TofOperationMode,
383  /// if different from 0, activate RB self trigger
384  /// in poisson mode
385  pub trigger_poisson_rate    : u32,
386  /// if different from 0, activate RB self trigger 
387  /// with fixed rate setting
388  pub trigger_fixed_rate      : u32,
389  /// Either "Physics" or a calibration related 
390  /// data type, e.g. "VoltageCalibration".
391  /// <div class="warning">This might get deprecated in a future version!</div>
392  pub data_type               : DataType,
393  /// The value when the readout of the RB buffers is triggered.
394  /// This number is in size of full events, which correspond to 
395  /// 18530 bytes. Maximum buffer size is a bit more than 3000 
396  /// events. Smaller buffer allows for a more snappy reaction, 
397  /// but might require more CPU resources (on the board)
398  pub rb_buff_size            : u16
399}
400
401impl RunConfig {
402
403  pub fn new() -> Self {
404    Self {
405      runid                   : 0,
406      is_active               : false,
407      nevents                 : 0,
408      nseconds                : 0,
409      tof_op_mode             : TofOperationMode::Default,
410      trigger_poisson_rate    : 0,
411      trigger_fixed_rate      : 0,
412      data_type               : DataType::Unknown, 
413      rb_buff_size            : 0,
414    }
415  }
416}
417
418impl Serialization for RunConfig {
419  const HEAD               : u16   = 43690; //0xAAAA
420  const TAIL               : u16   = 21845; //0x5555
421  const SIZE               : usize = 29; // bytes including HEADER + FOOTER
422  
423  fn from_bytestream(bytestream : &Vec<u8>,
424                     pos        : &mut usize)
425    -> Result<Self, SerializationError> {
426    let mut pars = Self::new();
427    Self::verify_fixed(bytestream, pos)?;
428    pars.runid                   = parse_u32 (bytestream, pos);
429    pars.is_active               = parse_bool(bytestream, pos);
430    pars.nevents                 = parse_u32 (bytestream, pos);
431    pars.nseconds                = parse_u32 (bytestream, pos);
432    pars.tof_op_mode           
433      = TofOperationMode::try_from(
434          parse_u8(bytestream, pos))
435      .unwrap_or_else(|_| TofOperationMode::Unknown);
436    pars.trigger_poisson_rate    = parse_u32 (bytestream, pos);
437    pars.trigger_fixed_rate      = parse_u32 (bytestream, pos);
438    pars.data_type    
439      = DataType::try_from(parse_u8(bytestream, pos))
440      .unwrap_or_else(|_| DataType::Unknown);
441    pars.rb_buff_size = parse_u16(bytestream, pos);
442    *pos += 2; // for the tail 
443    //_ = parse_u16(bytestream, pos);
444    Ok(pars)
445  }
446  
447  fn to_bytestream(&self) -> Vec<u8> {
448    let mut stream = Vec::<u8>::with_capacity(Self::SIZE);
449    stream.extend_from_slice(&Self::HEAD.to_le_bytes());
450    stream.extend_from_slice(&self.runid.to_le_bytes());
451    stream.extend_from_slice(&u8::from(self.  is_active).to_le_bytes());
452    stream.extend_from_slice(&self.nevents.to_le_bytes());    
453    stream.extend_from_slice(&self.  nseconds.to_le_bytes());
454    stream.extend_from_slice(&(self.tof_op_mode as u8).to_le_bytes());
455    stream.extend_from_slice(&self.trigger_poisson_rate.to_le_bytes());
456    stream.extend_from_slice(&self.trigger_fixed_rate.to_le_bytes());
457    stream.extend_from_slice(&(self.data_type as u8).to_le_bytes());
458    stream.extend_from_slice(&self.rb_buff_size.to_le_bytes());
459    stream.extend_from_slice(&Self::TAIL.to_le_bytes());
460    stream
461  }
462}
463
464impl Default for RunConfig {
465  fn default() -> Self {
466    Self::new()
467  }
468}
469
470impl fmt::Display for RunConfig {
471  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
472    if !self.is_active {
473      return write!(f, "<RunConfig -- is_active : false>");
474    } else {
475      write!(f, 
476"<RunConfig -- is_active : true
477    nevents      : {}
478    nseconds     : {}
479    TOF op. mode : {}
480    data type    : {}
481    tr_poi_rate  : {}
482    tr_fix_rate  : {}
483    buff size    : {} [events]>",
484      self.nevents,
485      self.nseconds,
486      self.tof_op_mode,
487      self.data_type,
488      self.trigger_poisson_rate,
489      self.trigger_fixed_rate,
490      self.rb_buff_size)
491    }
492  }
493}
494
495impl Packable for RunConfig {
496  const PACKET_TYPE : PacketType = PacketType::RunConfig;
497}
498
499#[cfg(feature = "random")]
500impl FromRandom for RunConfig {
501    
502  fn from_random() -> Self {
503    let mut cfg = Self::new();
504    let mut rng  = rand::thread_rng();
505    cfg.runid                   = rng.gen::<u32>();
506    cfg.is_active               = rng.gen::<bool>();
507    cfg.nevents                 = rng.gen::<u32>();
508    cfg.nseconds                = rng.gen::<u32>();
509    cfg.tof_op_mode             = TofOperationMode::from_random();
510    cfg.trigger_poisson_rate    = rng.gen::<u32>();
511    cfg.trigger_fixed_rate      = rng.gen::<u32>();
512    cfg.data_type               = DataType::from_random();
513    cfg.rb_buff_size            = rng.gen::<u16>();
514    cfg
515  }
516}
517
518
519
520#[derive(Copy, Clone, Debug, PartialEq)]
521pub struct TriggerConfig{
522  /// When we create the LiftofConfig from 
523  /// the TriggerConfig, this allows us to 
524  /// deactivate fields, so we would can 
525  /// only change a single field
526  pub active_fields          : u32,
527  /// Shall the gaps trigger use beta?
528  pub gaps_trigger_use_beta  : Option<bool>, //1
529  pub prescale               : Option<f32>, //4
530  pub trigger_type           : Option<TriggerType>, //1 
531  pub use_combo_trigger      : Option<bool>,
532  pub combo_trigger_type     : Option<TriggerType>,
533  pub combo_trigger_prescale : Option<f32>,
534  pub trace_suppression      : Option<bool>,
535  pub mtb_moni_interval      : Option<u16>,
536  pub tiu_ignore_busy        : Option<bool>,
537  pub hb_send_interval       : Option<u16>,
538}
539
540impl TriggerConfig {
541  pub fn new() -> Self { 
542    Self {
543      active_fields           : 0,
544      gaps_trigger_use_beta   : None,
545      prescale                : None,
546      trigger_type            : None,
547      use_combo_trigger       : None,
548      combo_trigger_type      : None,
549      combo_trigger_prescale  : None,
550      trace_suppression       : None,
551      mtb_moni_interval       : None,
552      tiu_ignore_busy         : None,
553      hb_send_interval        : None,
554    }
555  }
556
557  pub fn set_gaps_trigger_use_beta(&mut self, use_it : bool) {
558    self.active_fields |= 1;
559    self.gaps_trigger_use_beta = Some(use_it);
560  }
561
562  pub fn set_prescale(&mut self, prescale : f32) {
563    self.active_fields |= 2;
564    self.prescale = Some(prescale);
565  }
566
567  pub fn set_trigger_type(&mut self, ttype : TriggerType) {
568    self.active_fields |= 4;
569    self.trigger_type = Some(ttype);
570  }
571
572  pub fn set_use_combo_trigger(&mut self, combo : bool) {
573    self.active_fields |= 8;
574    self.use_combo_trigger = Some(combo);
575  }
576
577  pub fn set_combo_trigger_type(&mut self, ttype : TriggerType) {
578    self.active_fields |= 16;
579    self.combo_trigger_type = Some(ttype)
580  }
581
582  pub fn set_combo_trigger_prescale(&mut self, prescale : f32) {
583    self.active_fields |= 32;
584    self.combo_trigger_prescale = Some(prescale);
585  }
586
587  pub fn set_trace_suppression(&mut self, tsup : bool) {
588    self.active_fields |= 64;
589    self.trace_suppression = Some(tsup);
590  }
591
592  pub fn set_mtb_moni_interval(&mut self, interval : u16) {
593    self.active_fields |= 128;
594    self.mtb_moni_interval = Some(interval);
595  }
596
597  pub fn set_tiu_ignore_busy(&mut self, busy : bool) {
598    self.active_fields |= 256;
599    self.tiu_ignore_busy = Some(busy);
600  }
601
602  pub fn set_hb_send_interval(&mut self, interval : u16) {
603    self.active_fields |= 512;
604    self.hb_send_interval = Some(interval);
605  }
606}
607
608impl Default for TriggerConfig {
609  fn default() -> Self {
610    Self::new()
611  }
612}
613
614impl fmt::Display for TriggerConfig {
615  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
616    let mut repr = String::from("<TriggerConfig: ");
617    repr += &(format!("(active fields {:x})", self.active_fields));
618    if self. gaps_trigger_use_beta.is_some() {
619        repr += &(format!("\n  Beta is used by trigger      : {}", self.gaps_trigger_use_beta.unwrap())); 
620    }
621    if self. prescale.is_some() {
622      repr += &(format!("\n  Prescale           : {:.3}", self.prescale.unwrap()));
623    }
624    if self.trigger_type.is_some() {
625      repr += &(format!("\n  Trigger type       : {}",    self.trigger_type.unwrap()));
626    }
627    if self.use_combo_trigger.is_some() {
628      if self.use_combo_trigger.unwrap() {
629        repr += &(format!("\n  -- using combo trigger!"));
630      } 
631    }
632    if self.combo_trigger_prescale.is_some() {
633      repr += &(format!("\n  -- -- Combo Prescale     : {:.3}", self.combo_trigger_prescale.unwrap()));
634    }
635    if self.combo_trigger_type.is_some() { 
636      repr += &(format!("\n  -- -- Combo Trigger type : {}",    self.combo_trigger_type.unwrap()));
637    }
638    if self. trace_suppression.is_some() {
639      repr += &(format!("\n  trace_suppression       : {}", self.trace_suppression.unwrap()));
640    }
641    if self.mtb_moni_interval.is_some() {
642      repr += &(format!("\n  mtb_moni_interval       : {}", self.mtb_moni_interval.unwrap()));
643    }
644    if self.tiu_ignore_busy.is_some() {
645      repr += &(format!("\n  tiu_ignore_busy         : {}", self.tiu_ignore_busy.unwrap()));
646    }
647    if self.hb_send_interval.is_some() {
648      repr += &(format!("\n  hb_send_interval        : {}", self.hb_send_interval.unwrap()));
649    }
650    repr += ">";
651    write!(f, "{}", repr)
652  }
653}
654
655impl Packable for TriggerConfig {
656  const PACKET_TYPE : PacketType = PacketType::TriggerConfig;
657}
658
659impl Serialization for TriggerConfig {
660  
661  const HEAD : u16 = 0xAAAA;
662  const TAIL : u16 = 0x5555;
663  const SIZE : usize = 26; 
664  
665  fn from_bytestream(stream    : &Vec<u8>, 
666                     pos       : &mut usize) 
667    -> Result<Self, SerializationError>{
668    Self::verify_fixed(stream, pos)?;  
669    let mut cfg = TriggerConfig::new();
670    cfg.active_fields          = parse_u32(stream, pos);
671    cfg.gaps_trigger_use_beta  = Some(parse_bool(stream, pos));
672    cfg.prescale               = Some(parse_f32 (stream, pos));
673    cfg.trigger_type           = Some(TriggerType::from(parse_u8(stream, pos)));
674    cfg.use_combo_trigger      = Some(parse_bool(stream, pos));
675    cfg.combo_trigger_type     = Some(TriggerType::from(parse_u8(stream, pos)));
676    cfg.combo_trigger_prescale = Some(parse_f32(stream, pos));
677    cfg.trace_suppression      = Some(parse_bool(stream, pos));
678    cfg.mtb_moni_interval      = Some(parse_u16(stream, pos));
679    cfg.tiu_ignore_busy        = Some(parse_bool(stream, pos));
680    cfg.hb_send_interval       = Some(parse_u16(stream, pos));
681    // disable fields which where not explicitly marked as 
682    // active
683    if cfg.active_fields & 1 != 1 {
684      cfg.gaps_trigger_use_beta = None;
685    }
686    if cfg.active_fields & 2 != 2 {
687      cfg.prescale = None;
688    }
689    if cfg.active_fields & 4 != 4 {
690      cfg.trigger_type = None;
691    }
692    if cfg.active_fields & 8 != 8 {
693      cfg.use_combo_trigger = None;
694    }
695    if cfg.active_fields & 16 != 16 {
696      cfg.combo_trigger_type = None;
697    }
698    if cfg.active_fields & 32 != 32 {
699      cfg.combo_trigger_prescale = None;
700    }
701    if cfg.active_fields & 64 != 64 {
702      cfg.trace_suppression = None;
703    }
704    if cfg.active_fields & 128 != 128 {
705      cfg.mtb_moni_interval = None;
706    }
707    if cfg.active_fields & 256 != 256 {
708      cfg.tiu_ignore_busy   = None;
709    }
710    if cfg.active_fields & 512 != 512 {
711      cfg.hb_send_interval  = None;
712    }
713    *pos += 2;
714    Ok(cfg)
715  }
716
717  fn to_bytestream(&self) -> Vec<u8> {
718    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
719    bs.extend_from_slice(&Self::HEAD        .to_le_bytes());
720    bs.extend_from_slice(&self.active_fields.to_le_bytes());
721    bs.push             (self.gaps_trigger_use_beta.unwrap_or(false) as u8);
722    bs.extend_from_slice(&self.prescale.unwrap_or(0.0)     .to_le_bytes());
723    bs.push             (self.trigger_type.unwrap_or(TriggerType::Unknown)  .to_u8());
724    bs.push             (self.use_combo_trigger.unwrap_or(false) as u8);
725    bs.push             (self.combo_trigger_type.unwrap_or(TriggerType::Unknown) as u8);
726    bs.extend_from_slice(&self.combo_trigger_prescale.unwrap_or(0.0).to_le_bytes());
727    bs.push             (self.trace_suppression.unwrap_or(false) as u8);
728    bs.extend_from_slice(&self.mtb_moni_interval.unwrap_or(30).to_le_bytes());
729    bs.push             (self.tiu_ignore_busy.unwrap_or(false) as u8);
730    bs.extend_from_slice(&self.hb_send_interval.unwrap_or(30).to_le_bytes());
731    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
732    bs
733  }
734}
735
736#[cfg(feature = "random")]
737impl FromRandom for TriggerConfig {
738  fn from_random() -> Self {
739    let mut cfg                 = TriggerConfig::new();
740    let mut rng                 = rand::thread_rng();
741    let active_fields           = rng.gen::<u32>();
742    cfg.active_fields           = active_fields;
743    if active_fields & 1 == 1 {
744      cfg.gaps_trigger_use_beta   = Some(rng.gen::<bool>());
745    } else {
746      cfg.gaps_trigger_use_beta = None;
747    }
748    if active_fields & 2 == 2 {
749      cfg.prescale                = Some(rng.gen::<f32>());
750    } else {
751      cfg.prescale = None;
752    }
753    if active_fields & 4 == 4 {
754      cfg.trigger_type            = Some(TriggerType::from_random());
755    } else {
756      cfg.trigger_type = None;
757    }
758    if active_fields & 8 == 8 {
759      cfg.use_combo_trigger       = Some(rng.gen::<bool>());
760    } else {
761      cfg.use_combo_trigger = None;
762    }
763    if active_fields & 16 == 16 {
764      cfg.combo_trigger_type      = Some(TriggerType::from_random());
765    } else {
766      cfg.combo_trigger_type = None;
767    }
768    if active_fields & 32 == 32 {
769      cfg.combo_trigger_prescale  = Some(rng.gen::<f32>());
770    } else {
771      cfg.combo_trigger_prescale = None;
772    }
773    if active_fields & 64 == 64 {
774      cfg.trace_suppression       = Some(rng.gen::<bool>());
775    } else {
776      cfg.trace_suppression = None;
777    }
778    if active_fields & 128 == 128 {
779      cfg.mtb_moni_interval       = Some(rng.gen::<u16>());
780    } else {
781      cfg.mtb_moni_interval = None;
782    }
783    if active_fields & 256 == 256 {
784      cfg.tiu_ignore_busy         = Some(rng.gen::<bool>());
785    } else {
786      cfg.tiu_ignore_busy = None;
787    }
788    if active_fields & 512 == 512 {
789      cfg.hb_send_interval        = Some(rng.gen::<u16>());
790    } else {
791      cfg.hb_send_interval = None;
792    }
793    cfg
794  }
795}
796
797#[derive(Copy, Clone, Debug, PartialEq)]
798pub struct TofRunConfig {
799  pub active_fields            : u32,
800  pub runtime                  : Option<u32>, 
801}
802
803impl TofRunConfig {
804  pub fn new() -> Self {
805    Self {
806      active_fields : 0,
807      runtime       : None
808    }
809  }
810
811  pub fn set_runtime(&mut self, runtime : u32) {
812    self.active_fields |= 1;
813    self.runtime = Some(runtime);
814  }
815}
816
817impl Default for TofRunConfig {
818  fn default() -> Self {
819    Self::new()
820  }
821}
822
823impl fmt::Display for TofRunConfig {
824  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
825    let mut repr = String::from("<TofRunConfig: ");
826    repr += &(format!("(active fields {:x})", self.active_fields));
827    if self.runtime.is_some() {
828      repr += &(format!("\n  Run time        : {} [s]", self.runtime.unwrap())); 
829    }
830    repr += ">";
831    write!(f, "{}", repr)
832  }
833}
834
835impl Packable for TofRunConfig {
836  const PACKET_TYPE : PacketType = PacketType::TofRunConfig;
837}
838
839impl Serialization for TofRunConfig {
840  
841  const HEAD : u16   = 0xAAAA;
842  const TAIL : u16   = 0x5555;
843  const SIZE : usize = 12; 
844  
845  fn from_bytestream(stream    : &Vec<u8>, 
846                     pos       : &mut usize) 
847    -> Result<Self, SerializationError>{
848    Self::verify_fixed(stream, pos)?;  
849    let mut cfg        = TofRunConfig::new();
850    cfg.active_fields  = parse_u32(stream, pos);
851    cfg.runtime        = Some(parse_u32 (stream, pos));
852    // disable fields which where not explicitly marked as 
853    // active
854    if cfg.active_fields & 1 != 1 {
855      cfg.runtime = None;
856    }
857    *pos += 2;
858    Ok(cfg)
859  }
860
861  fn to_bytestream(&self) -> Vec<u8> {
862    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
863    bs.extend_from_slice(&Self::HEAD        .to_le_bytes());
864    bs.extend_from_slice(&self.active_fields.to_le_bytes());
865    bs.extend_from_slice(&self.runtime.unwrap_or(0).to_le_bytes());
866    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
867    bs
868  }
869}
870
871#[cfg(feature = "random")]
872impl FromRandom for TofRunConfig {
873  fn from_random() -> Self {
874    let mut cfg                 = Self::new();
875    let mut rng                 = rand::thread_rng();
876    let active_fields           = rng.gen::<u32>();
877    cfg.active_fields           = active_fields;
878    if active_fields & 1 == 1 {
879      cfg.runtime   = Some(rng.gen::<u32>());
880    }
881    cfg
882  }
883}
884
885//////////////////////////////////////////
886
887#[derive(Copy, Clone, Debug, PartialEq)]
888pub struct TofRBConfig {
889  pub active_fields                  : u32,
890  pub rb_moni_interval               : Option<u32>, 
891  pub pb_moni_every_x                : Option<u32>,
892  pub pa_moni_every_x                : Option<u32>,
893  pub ltb_moni_every_x               : Option<u32>,
894  pub drs_deadtime_instead_fpga_temp : Option<bool>,
895}
896
897impl TofRBConfig {
898  pub fn new() -> Self {
899    Self {
900     active_fields                 : 0,
901     rb_moni_interval               : None, 
902     pb_moni_every_x                : None,
903     pa_moni_every_x                : None,
904     ltb_moni_every_x               : None,
905     drs_deadtime_instead_fpga_temp : None,
906    }
907  }
908
909  pub fn set_rb_moni_interval(&mut self, interval : u32) {
910    self.active_fields |= 1;
911    self.rb_moni_interval = Some(interval);
912  }
913  
914  pub fn set_pb_moni_every_x(&mut self, interval : u32) {
915    self.active_fields |= 2;
916    self.pb_moni_every_x = Some(interval);
917  }
918  
919  pub fn set_pa_moni_every_x(&mut self, interval : u32) {
920    self.active_fields |= 4;
921    self.pa_moni_every_x = Some(interval);
922  }
923  
924  pub fn set_ltb_moni_every_x(&mut self, interval : u32) {
925    self.active_fields |= 8;
926    self.ltb_moni_every_x = Some(interval);
927  }
928  
929  pub fn set_drs_deadtime_instead_fpga_temp(&mut self, apply : bool) {
930    self.active_fields |= 16;
931    self.drs_deadtime_instead_fpga_temp = Some(apply);
932  }
933}
934
935impl Default for TofRBConfig {
936  fn default() -> Self {
937    Self::new()
938  }
939}
940
941impl fmt::Display for TofRBConfig {
942  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
943    let mut repr = String::from("<TofRBConfig: ");
944    repr += &(format!("(active fields {:x})", self.active_fields));
945    if self.rb_moni_interval.is_some() {
946      repr += &(format!("\n  RBMoni interval : {} [s]", self.rb_moni_interval.unwrap())); 
947    }
948    if self.pa_moni_every_x.is_some() {
949      repr += &(format!("\n  PAMoni interval : {} [xRBMoni]", self.pa_moni_every_x.unwrap())); 
950    }
951    if self.pb_moni_every_x.is_some() {
952      repr += &(format!("\n  PBMoni interval : {} [xRBMoni]", self.pb_moni_every_x.unwrap())); 
953    }
954    if self.ltb_moni_every_x.is_some() {
955      repr += &(format!("\n  LTBMoni interval : {} [xRBMoni]", self.ltb_moni_every_x.unwrap())); 
956    }
957    if self.drs_deadtime_instead_fpga_temp.is_some() {
958      if self.drs_deadtime_instead_fpga_temp.unwrap() {
959        repr += &(format!("\n  -- using the fpga temp field to store drs deadtime values")); 
960      } 
961    }
962    repr += ">";
963    write!(f, "{}", repr)
964  }
965}
966
967impl Packable for TofRBConfig {
968  const PACKET_TYPE : PacketType = PacketType::TofRBConfig;
969}
970
971impl Serialization for TofRBConfig {
972  
973  const HEAD : u16   = 0xAAAA;
974  const TAIL : u16   = 0x5555;
975  const SIZE : usize = 25; 
976  
977  fn from_bytestream(stream    : &Vec<u8>, 
978                     pos       : &mut usize) 
979    -> Result<Self, SerializationError>{
980    Self::verify_fixed(stream, pos)?;  
981    let mut cfg          = Self::new();
982    cfg.active_fields    = parse_u32(stream, pos);
983    cfg.rb_moni_interval = Some(parse_u32 (stream, pos));
984    cfg.pa_moni_every_x = Some(parse_u32 (stream, pos));
985    cfg.pb_moni_every_x = Some(parse_u32 (stream, pos));
986    cfg.ltb_moni_every_x = Some(parse_u32 (stream, pos));
987    cfg.drs_deadtime_instead_fpga_temp = Some(parse_bool (stream, pos));
988    // disable fields which where not explicitly marked as 
989    // active
990    if cfg.active_fields & 1 != 1 {
991      cfg.rb_moni_interval = None;
992    }
993    if cfg.active_fields & 2 != 2 {
994      cfg.pa_moni_every_x = None;
995    }
996    if cfg.active_fields & 4 != 4 {
997      cfg.pb_moni_every_x = None;
998    }
999    if cfg.active_fields & 8 != 8 {
1000      cfg.ltb_moni_every_x = None;
1001    }
1002    if cfg.active_fields & 16 != 16 {
1003      cfg.drs_deadtime_instead_fpga_temp = None;
1004    }
1005    *pos += 2;
1006    Ok(cfg)
1007  }
1008
1009  fn to_bytestream(&self) -> Vec<u8> {
1010    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
1011    bs.extend_from_slice(&Self::HEAD        .to_le_bytes());
1012    bs.extend_from_slice(&self.active_fields.to_le_bytes());
1013    bs.extend_from_slice(&self.rb_moni_interval.unwrap_or(0).to_le_bytes());
1014    bs.extend_from_slice(&self.pa_moni_every_x.unwrap_or(0).to_le_bytes());
1015    bs.extend_from_slice(&self.pb_moni_every_x.unwrap_or(0).to_le_bytes());
1016    bs.extend_from_slice(&self.ltb_moni_every_x.unwrap_or(0).to_le_bytes());
1017    bs.push             (self.drs_deadtime_instead_fpga_temp.unwrap_or(false) as u8);
1018    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
1019    bs
1020  }
1021}
1022
1023#[cfg(feature = "random")]
1024impl FromRandom for TofRBConfig {
1025  fn from_random() -> Self {
1026    let mut cfg          = Self::new();
1027    let mut rng          = rand::thread_rng();
1028    let active_fields    = rng.gen::<u32>();
1029    cfg.active_fields    = active_fields;
1030    if active_fields & 1 == 1 {
1031      cfg.rb_moni_interval   = Some(rng.gen::<u32>());
1032    }
1033    if active_fields & 2 == 2 {
1034      cfg.pa_moni_every_x   = Some(rng.gen::<u32>());
1035    }
1036    if active_fields & 4 == 4 {
1037      cfg.pb_moni_every_x   = Some(rng.gen::<u32>());
1038    }
1039    if active_fields & 8 == 8 {
1040      cfg.ltb_moni_every_x   = Some(rng.gen::<u32>());
1041    }
1042    if active_fields & 16 == 16 {
1043      cfg.drs_deadtime_instead_fpga_temp  = Some(rng.gen::<bool>());
1044    }
1045    cfg
1046  }
1047}
1048
1049/////////////////////////////////////
1050
1051
1052
1053#[derive(Copy, Clone, Debug, PartialEq)]
1054pub struct DataPublisherConfig {
1055  pub active_fields            : u32,
1056  pub mbytes_per_file          : Option<u16>,
1057  pub discard_event_fraction   : Option<f32>, 
1058  pub send_mtb_event_packets   : Option<bool>,
1059  pub send_rbwaveform_packets  : Option<bool>,
1060  pub send_rbwf_every_x_event  : Option<u32>,
1061  pub send_tof_summary_packets : Option<bool>,
1062  pub send_tof_event_packets   : Option<bool>,
1063  pub hb_send_interval         : Option<u16>,
1064}
1065
1066impl DataPublisherConfig {
1067  pub fn new() -> Self {
1068    Self {
1069      active_fields            : 0,
1070      mbytes_per_file          : None, 
1071      discard_event_fraction   : None, 
1072      send_mtb_event_packets   : None, 
1073      send_rbwaveform_packets  : None, 
1074      send_rbwf_every_x_event  : None, 
1075      send_tof_summary_packets : None, 
1076      send_tof_event_packets   : None, 
1077      hb_send_interval         : None, 
1078    }
1079  }
1080      
1081  pub fn set_mbytes_per_file(&mut self, mbytes : u16) {
1082    self.active_fields |= 1;
1083    self.mbytes_per_file = Some(mbytes);
1084  }
1085
1086  pub fn set_discard_event_fraction(&mut self, frac : f32) {
1087    self.active_fields |= 2;
1088    self.discard_event_fraction = Some(frac);
1089  }
1090
1091  pub fn set_send_mtb_event_packets(&mut self, send : bool) {
1092    self.active_fields |= 4;
1093    self.send_mtb_event_packets = Some(send);
1094  }
1095
1096  pub fn set_send_rbwaveform_packets(&mut self, send : bool) {
1097    self.active_fields |= 8;
1098    self.send_rbwaveform_packets = Some(send);
1099  }
1100
1101  pub fn set_send_rbwf_every_x_event(&mut self, x : u32) {
1102    self.active_fields |= 16;
1103    self.send_rbwf_every_x_event = Some(x);
1104  }
1105
1106  pub fn set_send_tof_summary_packets(&mut self, send : bool) {
1107    self.active_fields |= 32;
1108    self.send_tof_summary_packets = Some(send);
1109  }
1110  
1111  pub fn send_tof_event_packets(&mut self, send : bool) {
1112    self.active_fields |= 64;
1113    self.send_tof_event_packets = Some(send);
1114  }
1115
1116  pub fn set_hb_send_interval(&mut self, interval : u16) {
1117    self.active_fields |= 128;
1118    self.hb_send_interval = Some(interval);
1119  }
1120}
1121
1122impl Default for DataPublisherConfig {
1123  fn default() -> Self {
1124    Self::new()
1125  }
1126}
1127
1128impl fmt::Display for DataPublisherConfig {
1129  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1130    let mut repr = String::from("<DataPublisherConfig: ");
1131    repr += &(format!("(active fields {:x})", self.active_fields));
1132    if self.mbytes_per_file.is_some() {
1133      repr += &(format!("\n  MBytes/FIle        : {}", self.mbytes_per_file.unwrap())); 
1134    }
1135    if self.discard_event_fraction.is_some() {
1136      repr += &(format!("\n  DIsc. event frac   : {}", self.discard_event_fraction.unwrap())); 
1137    }
1138    if self.send_mtb_event_packets.is_some() {
1139      repr += &(format!("\n  Send MTBPack       : {}", self.send_mtb_event_packets.unwrap())); 
1140    }
1141    if self.send_rbwaveform_packets.is_some() {
1142      repr += &(format!("\n  Send RBWfPack      : {}", self.send_rbwaveform_packets.unwrap())); 
1143    }
1144    if self.send_rbwf_every_x_event.is_some() {
1145      repr += &(format!("\n  RBWf every x event : {}", self.send_rbwf_every_x_event.unwrap())); 
1146    }
1147    if self.send_tof_summary_packets.is_some() {
1148      repr += &(format!("\n  Send TofSum        : {}", self.send_tof_summary_packets.unwrap())); 
1149    }
1150    if self.send_tof_event_packets.is_some() {
1151      repr += &(format!("\n  Send TOfEvent      : {}", self.send_tof_event_packets.unwrap())); 
1152    }
1153    if self.hb_send_interval.is_some() {
1154      repr += &(format!("\n  HeartBeat send int  : {}", self.hb_send_interval.unwrap())); 
1155    }
1156    repr += ">";
1157    write!(f, "{}", repr)
1158  }
1159}
1160
1161impl Packable for DataPublisherConfig {
1162  const PACKET_TYPE : PacketType = PacketType::DataPublisherConfig;
1163}
1164
1165impl Serialization for DataPublisherConfig {
1166  
1167  const HEAD : u16 = 0xAAAA;
1168  const TAIL : u16 = 0x5555;
1169  const SIZE : usize = 24; 
1170  
1171  fn from_bytestream(stream    : &Vec<u8>, 
1172                     pos       : &mut usize) 
1173    -> Result<Self, SerializationError>{
1174    Self::verify_fixed(stream, pos)?;  
1175    let mut cfg                = DataPublisherConfig::new();
1176    cfg.active_fields          = parse_u32(stream, pos);
1177    cfg.mbytes_per_file          = Some(parse_u16 (stream, pos));
1178    cfg.discard_event_fraction   = Some(parse_f32 (stream, pos));
1179    cfg.send_mtb_event_packets   = Some(parse_bool(stream, pos));
1180    cfg.send_rbwaveform_packets  = Some(parse_bool(stream, pos));
1181    cfg.send_rbwf_every_x_event  = Some(parse_u32 (stream, pos));
1182    cfg.send_tof_summary_packets = Some(parse_bool(stream, pos));
1183    cfg.send_tof_event_packets   = Some(parse_bool(stream, pos));
1184    cfg.hb_send_interval         = Some(parse_u16 (stream, pos));
1185    // disable fields which where not explicitly marked as 
1186    // active
1187    if cfg.active_fields & 1 != 1 {
1188      cfg.mbytes_per_file = None;
1189    }
1190    if cfg.active_fields & 2 != 2 {
1191      cfg.discard_event_fraction = None;
1192    }
1193    if cfg.active_fields & 4 != 4 {
1194      cfg.send_mtb_event_packets = None;
1195    }
1196    if cfg.active_fields & 8 != 8 {
1197      cfg.send_rbwaveform_packets = None;
1198    }
1199    if cfg.active_fields & 16 != 16 {
1200      cfg.send_rbwf_every_x_event = None;
1201    }
1202    if cfg.active_fields & 32 != 32 {
1203      cfg.send_tof_summary_packets = None;
1204    }
1205    if cfg.active_fields & 64 != 64 {
1206      cfg.send_tof_event_packets = None;
1207    }
1208    if cfg.active_fields & 128 != 128 {
1209      cfg.hb_send_interval = None;
1210    }
1211    *pos += 2;
1212    Ok(cfg)
1213  }
1214
1215  fn to_bytestream(&self) -> Vec<u8> {
1216    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
1217    bs.extend_from_slice(&Self::HEAD        .to_le_bytes());
1218    bs.extend_from_slice(&self.active_fields.to_le_bytes());
1219    bs.extend_from_slice(&self.mbytes_per_file.unwrap_or(0).to_le_bytes());
1220    bs.extend_from_slice(&self.discard_event_fraction.unwrap_or(0.0).to_le_bytes());
1221    bs.push             (self .send_mtb_event_packets.unwrap_or(false)  as u8);
1222    bs.push             (self .send_rbwaveform_packets.unwrap_or(false) as u8);
1223    bs.extend_from_slice(&self.send_rbwf_every_x_event.unwrap_or(0).to_le_bytes());
1224    bs.push             (self.send_tof_summary_packets.unwrap_or(false) as u8);
1225    bs.push             (self .send_tof_event_packets.unwrap_or(false) as u8);
1226    bs.extend_from_slice(&self.hb_send_interval.unwrap_or(30).to_le_bytes());
1227    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
1228    bs
1229  }
1230}
1231
1232#[cfg(feature = "random")]
1233impl FromRandom for DataPublisherConfig {
1234  fn from_random() -> Self {
1235    let mut cfg                 = DataPublisherConfig::new();
1236    let mut rng                 = rand::thread_rng();
1237    let active_fields           = rng.gen::<u32>();
1238    cfg.active_fields           = active_fields;
1239    if active_fields & 1 == 1 {
1240      cfg.mbytes_per_file   = Some(rng.gen::<u16>());
1241    } else {
1242      cfg.mbytes_per_file = None;
1243    }
1244    if active_fields & 2 == 2 {
1245      cfg.discard_event_fraction = Some(rng.gen::<f32>());
1246    } else {
1247      cfg.discard_event_fraction = None;
1248    }
1249    if active_fields & 4 == 4 {
1250      cfg.send_mtb_event_packets = Some(rng.gen::<bool>());
1251    } else {
1252      cfg.send_mtb_event_packets = None;
1253    }
1254    if active_fields & 8 == 8 {
1255      cfg.send_rbwaveform_packets = Some(rng.gen::<bool>());
1256    } else {
1257      cfg.send_rbwaveform_packets = None;
1258    }
1259    if active_fields & 16 == 16 {
1260      cfg.send_rbwf_every_x_event = Some(rng.gen::<u32>());
1261    } else {
1262      cfg.send_rbwf_every_x_event = None;
1263    }
1264    if active_fields & 32 == 32 {
1265      cfg.send_tof_summary_packets  = Some(rng.gen::<bool>());
1266    } else {
1267      cfg.send_tof_summary_packets = None;
1268    }
1269    if active_fields & 64 == 64 {
1270      cfg.send_tof_event_packets       = Some(rng.gen::<bool>());
1271    } else {
1272      cfg.send_tof_event_packets = None;
1273    }
1274    if active_fields & 128 == 128 {
1275      cfg.hb_send_interval       = Some(rng.gen::<u16>());
1276    } else {
1277      cfg.hb_send_interval = None;
1278    }
1279    cfg
1280  }
1281}
1282
1283
1284
1285///Analysis Engine Config
1286/// Settings to change the configuration of the analysis engine 
1287/// (pulse extraction)
1288#[derive(Copy, Clone, Debug, PartialEq)]
1289pub struct AnalysisEngineConfig{
1290  pub integration_start : f32, //4
1291  pub integration_window : f32, //4
1292  pub pedestal_thresh : f32, //4
1293  pub pedestal_begin_bin : usize, //8
1294  pub pedestal_win_bins : usize, //8
1295  pub use_zscore : bool, //1
1296  pub find_pks_t_start : f32, //4
1297  pub find_pks_t_window : f32, //4
1298  pub min_peak_size : usize, //8
1299  pub find_pks_thresh : f32, //4
1300  pub max_peaks : usize, //8
1301  pub cfd_fraction : f32 //4
1302}
1303
1304impl AnalysisEngineConfig {
1305  pub fn new() -> Self {
1306    Self {
1307      integration_start         : 270.0,
1308      integration_window        : 70.0, 
1309      pedestal_thresh           : 10.0,
1310      pedestal_begin_bin        : 10,
1311      pedestal_win_bins         : 50,
1312      use_zscore                : false,
1313      find_pks_t_start          : 270.0,
1314      find_pks_t_window         : 70.0,
1315      min_peak_size             : 3,
1316      find_pks_thresh           : 10.0,
1317      max_peaks                 : 5, //max peak size?? ask
1318      cfd_fraction              : 0.2
1319    }
1320  }
1321}
1322
1323impl Default for AnalysisEngineConfig {
1324  fn default() -> Self {
1325    Self::new()
1326  }
1327}
1328
1329impl fmt::Display for AnalysisEngineConfig {
1330  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1331    let mut repr: String = String::from("<AnalysisEngineConfig");
1332    repr += &(format!("\n Integration start         : {:.1}", self.integration_start));
1333    repr += &(format!("\n Integration window        : {:.1}", self.integration_window));
1334    repr += &(format!("\n Pedestal threshold        : {:.1}", self.pedestal_thresh));
1335    repr += &(format!("\n Pedestal start bin        : {}", self.pedestal_begin_bin));
1336    repr += &(format!("\n Pedestal window num. bins : {}", self.pedestal_win_bins));
1337    repr += &(format!("\n Use zscore?               : {}", self.use_zscore));
1338    repr += &(format!("\n Peakfinder start time     : {:.1}", self.find_pks_t_start));
1339    repr += &(format!("\n Peakfinder window         : {:.1}", self.find_pks_t_window));
1340    repr += &(format!("\n Peakfinder threshold      : {:.1}", self.find_pks_thresh));
1341    repr += &(format!("\n Min. peak size            : {}", self.min_peak_size));
1342    repr += &(format!("\n Max num. peaks            : {}", self.max_peaks));
1343    repr += &(format!("\n CFD fraction              : {:.2}", self.cfd_fraction));
1344    write!(f, "{}", repr)
1345  }
1346}
1347
1348impl Packable for AnalysisEngineConfig {
1349  const PACKET_TYPE : PacketType = PacketType::AnalysisEngineConfig;
1350}
1351
1352impl Serialization for AnalysisEngineConfig {
1353  
1354  const HEAD : u16 = 0xAAAA; //2
1355  const TAIL : u16 = 0x5555; //2
1356  const SIZE : usize = 65; //61+2+2 = 65
1357  
1358  fn from_bytestream(stream    : &Vec<u8>, 
1359                     pos       : &mut usize) 
1360    -> Result<Self, SerializationError>{
1361    Self::verify_fixed(stream, pos)?;  
1362    let mut cfg: AnalysisEngineConfig = AnalysisEngineConfig::new();
1363      cfg.integration_start = parse_f32(stream, pos);
1364      cfg.integration_window = parse_f32(stream, pos);
1365      cfg.pedestal_thresh = parse_f32(stream, pos);
1366      cfg.pedestal_begin_bin = parse_usize(stream, pos);
1367      cfg.pedestal_win_bins = parse_usize(stream, pos);
1368      cfg.use_zscore = parse_bool(stream, pos);
1369      cfg.find_pks_t_start = parse_f32(stream, pos);
1370      cfg.find_pks_t_window = parse_f32(stream, pos);
1371      cfg.find_pks_thresh = parse_f32(stream, pos);
1372      cfg.min_peak_size = parse_usize(stream, pos);
1373      cfg.max_peaks = parse_usize(stream, pos);
1374      cfg.cfd_fraction = parse_f32(stream, pos);
1375    *pos += 2;
1376    Ok(cfg)
1377  }
1378
1379  fn to_bytestream(&self) -> Vec<u8> {
1380    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
1381    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
1382    bs.extend_from_slice(&self.integration_start.to_le_bytes());
1383    bs.extend_from_slice(&self.integration_window.to_le_bytes());
1384    bs.extend_from_slice(&self.pedestal_thresh.to_le_bytes());
1385    bs.extend_from_slice(&self.pedestal_begin_bin.to_le_bytes());
1386    bs.extend_from_slice(&self.pedestal_win_bins.to_le_bytes());
1387    bs.push(self.use_zscore as u8);
1388    bs.extend_from_slice(&self.find_pks_t_start.to_le_bytes());
1389    bs.extend_from_slice(&self.find_pks_t_window.to_le_bytes());
1390    bs.extend_from_slice(&self.find_pks_thresh.to_le_bytes());
1391    bs.extend_from_slice(&self.min_peak_size.to_le_bytes());
1392    bs.extend_from_slice(&self.max_peaks.to_le_bytes());
1393    bs.extend_from_slice(&self.cfd_fraction.to_le_bytes());
1394    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
1395    bs
1396  }
1397}
1398
1399#[cfg(feature = "random")]
1400impl FromRandom for AnalysisEngineConfig {
1401  fn from_random() -> Self {
1402    let mut cfg  = AnalysisEngineConfig::new();
1403    let mut rng      = rand::thread_rng();
1404    cfg.integration_start = rng.gen::<f32>();
1405    cfg.integration_window = rng.gen::<f32>();
1406    cfg.pedestal_thresh = rng.gen::<f32>();
1407    cfg.pedestal_begin_bin = rng.gen::<usize>();
1408    cfg.pedestal_win_bins = rng.gen::<usize>();
1409    cfg.use_zscore = rng.gen::<bool>();
1410    cfg.find_pks_t_start = rng.gen::<f32>();
1411    cfg.find_pks_t_window = rng.gen::<f32>();
1412    cfg.find_pks_thresh = rng.gen::<f32>();
1413    cfg.min_peak_size = rng.gen::<usize>();
1414    cfg.max_peaks = rng.gen::<usize>();
1415    cfg.cfd_fraction = rng.gen::<f32>();
1416    cfg
1417  }
1418}
1419
1420#[cfg(feature = "random")]
1421#[test]
1422fn pack_analysisengineconfig() {
1423  for _ in 0..100 {
1424    let cfg  = AnalysisEngineConfig::from_random();
1425    let test : AnalysisEngineConfig = cfg.pack().unpack().unwrap();
1426    assert_eq!(cfg, test);
1427  }
1428}
1429
1430/// TOF Event Builder Settings
1431/// Configuring the TOF event builder during flight
1432/// If a setting is set to None, it will keep the 
1433/// previous setting
1434#[derive(Copy, Clone, Debug, PartialEq)]
1435pub struct TOFEventBuilderConfig{
1436  pub active_fields    : u32, // supports up to 32 active components
1437  pub cachesize        : Option<u32>, 
1438  pub n_mte_per_loop   : Option<u32>, 
1439  pub n_rbe_per_loop   : Option<u32>, 
1440  pub te_timeout_sec   : Option<u32>, 
1441  pub sort_events      : Option<bool>,
1442  pub build_strategy   : Option<BuildStrategy>, 
1443  pub wait_nrb         : Option<u8>, 
1444  pub greediness       : Option<u8>, 
1445  pub hb_send_interval : Option<u16>,
1446  // NEW - mark events as not to be sent!
1447  pub only_save_interesting : Option<bool>,
1448  pub thr_n_hits_umb        : Option<u8>,
1449  pub thr_n_hits_cbe        : Option<u8>,
1450  pub thr_n_hits_cor        : Option<u8>,
1451  pub thr_tot_edep_umb      : Option<f32>,
1452  pub thr_tot_edep_cbe      : Option<f32>,
1453  pub thr_tot_edep_cor      : Option<f32>
1454
1455}
1456
1457impl TOFEventBuilderConfig {
1458  pub fn new() -> Self { 
1459    Self {
1460      active_fields         : 0,
1461      cachesize             : None,
1462      n_mte_per_loop        : None,
1463      n_rbe_per_loop        : None,
1464      te_timeout_sec        : None,
1465      sort_events           : None,
1466      build_strategy        : None,
1467      wait_nrb              : None, 
1468      greediness            : None,  
1469      hb_send_interval      : None,
1470      only_save_interesting : None,
1471      thr_n_hits_umb        : None,
1472      thr_n_hits_cbe        : None,
1473      thr_n_hits_cor        : None,
1474      thr_tot_edep_umb      : None,
1475      thr_tot_edep_cbe      : None,
1476      thr_tot_edep_cor      : None,
1477    }
1478  }
1479      
1480  pub fn set_cachesize(&mut self, csize : u32) {
1481    self.active_fields |= 1;
1482    self.cachesize = Some(csize);
1483  }
1484  
1485  pub fn set_n_mte_per_loop(&mut self, n : u32) {
1486    self.active_fields |= 2;
1487    self.n_mte_per_loop = Some(n);
1488  }
1489
1490  pub fn set_n_rbe_per_loop(&mut self, n : u32) {
1491    self.active_fields |= 4;
1492    self.n_rbe_per_loop = Some(n);
1493  }
1494
1495  pub fn set_te_timeout_sec(&mut self, te : u32) {
1496    self.active_fields |= 8;
1497    self.te_timeout_sec = Some(te);
1498  }
1499
1500  pub fn set_sort_events(&mut self, sort : bool) {
1501    self.active_fields |= 16;
1502    self.sort_events = Some(sort);
1503  }
1504
1505  pub fn set_build_strategy(&mut self, bs : BuildStrategy) {
1506    self.active_fields |= 32;
1507    self.build_strategy = Some(bs);
1508  }
1509
1510  pub fn set_wait_nrb(&mut self, nrb : u8) {
1511    self.active_fields |= 64;
1512    self.wait_nrb = Some(nrb);
1513  }
1514
1515  pub fn set_greediness(&mut self, greed : u8) {
1516    self.active_fields |= 128;
1517    self.greediness = Some(greed);
1518  }
1519
1520  pub fn set_hb_send_interval(&mut self, interval : u16) {
1521    self.active_fields |= 256;
1522    self.hb_send_interval = Some(interval);
1523  }
1524
1525  pub fn set_only_save_interesting(&mut self, do_it : bool) {
1526    self.active_fields |= 512;
1527    self.only_save_interesting = Some(do_it);
1528  }
1529
1530  pub fn thr_n_hits_umb(&mut self, nhit : u8) {
1531    self.active_fields |= 1024;
1532    self.thr_n_hits_umb = Some(nhit);
1533  }
1534  
1535  pub fn thr_n_hits_cbe(&mut self, nhit : u8) {
1536    self.active_fields |= 2048;
1537    self.thr_n_hits_cbe = Some(nhit);
1538  }
1539  
1540  pub fn thr_n_hits_cor(&mut self, nhit : u8) {
1541    self.active_fields |= 2u32.pow(12);
1542    self.thr_n_hits_cor = Some(nhit);
1543  }
1544  
1545  pub fn thr_tot_edep_umb(&mut self, thr : f32) {
1546    self.active_fields |= 2u32.pow(13);
1547    self.thr_tot_edep_umb = Some(thr);
1548  }
1549  
1550  pub fn thr_tot_edep_cbe(&mut self, thr : f32) {
1551    self.active_fields |= 2u32.pow(14);
1552    self.thr_tot_edep_cbe = Some(thr);
1553  }
1554  
1555  pub fn thr_tot_edep_cor(&mut self, thr : f32) {
1556    self.active_fields |= 2u32.pow(15);
1557    self.thr_tot_edep_cor = Some(thr);
1558  }
1559}
1560
1561impl Default for TOFEventBuilderConfig {
1562  fn default() -> Self {
1563    Self::new()
1564  }
1565}
1566
1567impl fmt::Display for TOFEventBuilderConfig {
1568  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1569    let mut repr = String::from("<TOFEventBuilderConfig");
1570    repr += &(format!(" (active_fields {:x}", self.active_fields)); 
1571    if self.cachesize.is_some() {
1572      repr += &(format!("\n Cache size                              : {}", self.cachesize.unwrap())); 
1573    }
1574    if self.n_mte_per_loop.is_some() {
1575      repr += &(format!("\n Num. master trigger events per loop     : {}", self.n_mte_per_loop.unwrap()));
1576    }
1577    if self.n_rbe_per_loop.is_some() {
1578      repr += &(format!("\n Num. readout board events per loop      : {}", self.n_rbe_per_loop.unwrap()));
1579    }
1580    if self.te_timeout_sec.is_some() {
1581      repr += &(format!("\n TOF Event timeout window [sec]          : {:.3}", self.te_timeout_sec.unwrap()));
1582    }
1583    if self.sort_events.is_some() {
1584      repr += &(format!("\n Sort events by ID (high resource load!) : {}", self.sort_events.unwrap()));
1585    }
1586    if self.build_strategy.is_some() {
1587      repr += &(format!("\n Build strategy                          : {}", self.build_strategy.unwrap()));
1588      if self.build_strategy.unwrap() == BuildStrategy::AdaptiveGreedy {
1589        if self.greediness.is_some() {
1590          repr += &(format!("\n Additional RBs considered (greediness)  : {}", self.greediness.unwrap()));
1591        }
1592      } else if self.build_strategy.unwrap() == BuildStrategy::WaitForNBoards {
1593        if self.wait_nrb.is_some() {
1594          repr += &(format!("\n Waiting for {} boards", self.wait_nrb.unwrap()))
1595        }
1596      }
1597    }
1598    if self.hb_send_interval.is_some() {
1599      repr += &(format!("\n Heartbeat send interval : {}", self.hb_send_interval.unwrap()));
1600    }
1601    if self.only_save_interesting.is_some() {
1602      repr += &(format!("\n Saving only interesting events : {}", self.only_save_interesting.unwrap()));
1603    }
1604    if self.thr_n_hits_umb.is_some() {
1605      repr += &(format!("\n Interesting threshold for nhit umb : {}", self.thr_n_hits_umb.unwrap()));
1606    }
1607    if self.thr_n_hits_cbe.is_some() {
1608      repr += &(format!("\n Interesting threshold for nhit cbe : {}", self.thr_n_hits_cbe.unwrap()));
1609    }
1610    if self.thr_n_hits_cor.is_some() {
1611      repr += &(format!("\n Interesting threshold for nhit cor : {}", self.thr_n_hits_cor.unwrap()));
1612    }
1613    if self.thr_tot_edep_umb.is_some() {
1614      repr += &(format!("\n Interesting threshold for tot edep umb : {}", self.thr_tot_edep_umb.unwrap()));
1615    }
1616    if self.thr_tot_edep_cbe.is_some() {
1617      repr += &(format!("\n Interesting threshold for tot edep cbe : {}", self.thr_tot_edep_cbe.unwrap()));
1618    }
1619    if self.thr_tot_edep_cor.is_some() {
1620      repr += &(format!("\n Interesting threshold for tot edep cor : {}", self.thr_tot_edep_cor.unwrap()));
1621    }
1622    write!(f, "{}", repr)
1623  }
1624}
1625
1626impl Packable for TOFEventBuilderConfig {
1627  const PACKET_TYPE : PacketType = PacketType::TOFEventBuilderConfig;
1628}
1629
1630impl Serialization for TOFEventBuilderConfig {
1631  
1632  const HEAD : u16 = 0xAAAA;
1633  const TAIL : u16 = 0x5555;
1634  const SIZE : usize = 46; 
1635  
1636  fn from_bytestream(stream    : &Vec<u8>, 
1637                     pos       : &mut usize) 
1638    -> Result<Self, SerializationError> {
1639    Self::verify_fixed(stream, pos)?;  
1640    let mut cfg = TOFEventBuilderConfig::new();
1641    cfg.active_fields    = parse_u32(stream, pos);
1642    cfg.cachesize        = Some(parse_u32(stream, pos));
1643    cfg.n_mte_per_loop   = Some(parse_u32(stream, pos));
1644    cfg.n_rbe_per_loop   = Some(parse_u32(stream, pos));
1645    cfg.te_timeout_sec   = Some(parse_u32(stream, pos));
1646    cfg.sort_events      = Some(parse_bool(stream, pos));
1647    cfg.build_strategy   = Some(BuildStrategy::from(parse_u8(stream, pos)));
1648    cfg.wait_nrb         = Some(parse_u8(stream, pos));
1649    cfg.greediness       = Some(parse_u8(stream, pos));
1650    cfg.hb_send_interval = Some(parse_u16(stream, pos));
1651    // new stuff
1652    cfg.only_save_interesting = Some(parse_bool(stream, pos));
1653    cfg.thr_n_hits_umb = Some(parse_u8(stream, pos));
1654    cfg.thr_n_hits_cbe = Some(parse_u8(stream, pos));
1655    cfg.thr_n_hits_cor = Some(parse_u8(stream, pos));
1656    cfg.thr_tot_edep_umb = Some(parse_f32(stream, pos));
1657    cfg.thr_tot_edep_cbe = Some(parse_f32(stream, pos));
1658    cfg.thr_tot_edep_cor = Some(parse_f32(stream, pos));
1659    
1660    if cfg.active_fields & 1 != 1 {
1661      cfg.cachesize      = None;
1662    }
1663    if cfg.active_fields & 2 != 2 {
1664      cfg.n_mte_per_loop = None;
1665    }
1666    if cfg.active_fields & 4 != 4 {
1667      cfg.n_rbe_per_loop = None;
1668    }
1669    if cfg.active_fields & 8 != 8 {
1670      cfg.te_timeout_sec = None;
1671    }
1672    if cfg.active_fields & 16 != 16 {
1673      cfg.sort_events    = None;
1674    }
1675    if cfg.active_fields & 32 != 32 {
1676      cfg.build_strategy = None;
1677    }
1678    if cfg.active_fields & 64 != 64 {
1679      cfg.wait_nrb       = None;
1680    }
1681    if cfg.active_fields & 128 != 128 {
1682      cfg.greediness     = None;
1683    }
1684    if cfg.active_fields & 256 != 256 {
1685      cfg.hb_send_interval = None;
1686    }
1687    if cfg.active_fields & 512 != 512 {
1688      cfg.only_save_interesting = None;
1689    }
1690    if cfg.active_fields & 1024 != 1024 {
1691      cfg.thr_n_hits_umb = None;
1692    }
1693    if cfg.active_fields & 2048 != 2048 {
1694      cfg.thr_n_hits_cbe = None;
1695    }
1696    if cfg.active_fields & 2u32.pow(12) != 2u32.pow(12) {
1697      cfg.thr_n_hits_cor = None;
1698    }
1699    if cfg.active_fields & 2u32.pow(13) != 2u32.pow(13) {
1700      cfg.thr_tot_edep_umb = None;
1701    }
1702    if cfg.active_fields & 2u32.pow(14) != 2u32.pow(14) {
1703      cfg.thr_tot_edep_cbe = None;
1704    }
1705    if cfg.active_fields & 2u32.pow(15) != 2u32.pow(15) {
1706      cfg.thr_tot_edep_cor = None;
1707    }
1708    *pos += 2;
1709    Ok(cfg)
1710  }
1711 
1712  fn to_bytestream(&self) -> Vec<u8> {
1713    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
1714    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
1715    bs.extend_from_slice(&self.active_fields.to_le_bytes());
1716    bs.extend_from_slice(&self.cachesize.unwrap_or(0).to_le_bytes());
1717    bs.extend_from_slice(&self.n_mte_per_loop.unwrap_or(0).to_le_bytes());
1718    bs.extend_from_slice(&self.n_rbe_per_loop.unwrap_or(0).to_le_bytes());
1719    bs.extend_from_slice(&self.te_timeout_sec.unwrap_or(0).to_le_bytes());
1720    bs.push(self.sort_events.unwrap_or(false) as u8);
1721    bs.push(self.build_strategy.unwrap_or(BuildStrategy::Unknown).to_u8());
1722    bs.push(self.wait_nrb.unwrap_or(0));
1723    bs.push(self.greediness.unwrap_or(0));
1724    bs.extend_from_slice(&self.hb_send_interval.unwrap_or(0).to_le_bytes());
1725    // new stuff
1726    bs.push(self.only_save_interesting.unwrap_or(false) as u8);
1727    bs.extend_from_slice(&self.thr_n_hits_umb.unwrap_or(0).to_le_bytes());
1728    bs.extend_from_slice(&self.thr_n_hits_cbe.unwrap_or(0).to_le_bytes());
1729    bs.extend_from_slice(&self.thr_n_hits_cor.unwrap_or(0).to_le_bytes());
1730    bs.extend_from_slice(&self.thr_tot_edep_umb.unwrap_or(0.0).to_le_bytes());
1731    bs.extend_from_slice(&self.thr_tot_edep_cbe.unwrap_or(0.0).to_le_bytes());
1732    bs.extend_from_slice(&self.thr_tot_edep_cor.unwrap_or(0.0).to_le_bytes());
1733    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
1734    bs
1735  }
1736}
1737
1738#[cfg(feature = "random")]
1739impl FromRandom for TOFEventBuilderConfig {
1740  fn from_random() -> Self {
1741    let mut cfg             = TOFEventBuilderConfig::new();
1742    let mut rng             = rand::thread_rng();
1743    cfg.active_fields       = rng.gen::<u32>();
1744    if cfg.active_fields & 1 == 1 {
1745      cfg.cachesize         = Some(rng.gen::<u32>());
1746    }
1747    if cfg.active_fields & 2 == 2 {
1748      cfg.n_mte_per_loop      = Some(rng.gen::<u32>());
1749    }
1750    if cfg.active_fields & 4 == 4 {
1751      cfg.n_rbe_per_loop      = Some(rng.gen::<u32>());
1752    }
1753    if cfg.active_fields & 8 == 8 {
1754      cfg.te_timeout_sec      = Some(rng.gen::<u32>());
1755    }
1756    if cfg.active_fields & 16 == 16 {
1757      cfg.sort_events         = Some(rng.gen::<bool>());
1758    }
1759    if cfg.active_fields & 32 == 32 {
1760      cfg.build_strategy      = Some(BuildStrategy::from_random());
1761    }
1762    if cfg.active_fields & 64 == 64 {
1763      cfg.wait_nrb = Some(rng.gen::<u8>());
1764    }
1765    if cfg.active_fields & 128 == 128 {
1766      cfg.greediness = Some(rng.gen::<u8>());
1767    }
1768    if cfg.active_fields & 256 == 256 {
1769      cfg.hb_send_interval = Some(rng.gen::<u16>());
1770    }
1771    if cfg.active_fields & 512 == 512 {
1772      cfg.only_save_interesting = Some(rng.gen::<bool>());
1773    }
1774    if cfg.active_fields & 1024 == 1024 {
1775      cfg.thr_n_hits_umb = Some(rng.gen::<u8>());
1776    }
1777    if cfg.active_fields & 2048 == 2048 {
1778      cfg.thr_n_hits_cbe = Some(rng.gen::<u8>());
1779    }
1780    if cfg.active_fields & 2u32.pow(12) == 2u32.pow(12) {
1781      cfg.thr_n_hits_cor = Some(rng.gen::<u8>());
1782    }
1783    if cfg.active_fields & 2u32.pow(13) == 2u32.pow(13) {
1784      cfg.thr_tot_edep_umb = Some(rng.gen::<f32>());
1785    }
1786    if cfg.active_fields & 2u32.pow(14) == 2u32.pow(14) {
1787      cfg.thr_tot_edep_cbe = Some(rng.gen::<f32>());
1788    }
1789    if cfg.active_fields & 2u32.pow(15) == 2u32.pow(15) {
1790      cfg.thr_tot_edep_cor = Some(rng.gen::<f32>());
1791    }
1792    cfg
1793  }
1794}
1795
1796
1797//////////////////////////////////////////
1798// TESTS
1799
1800#[cfg(feature = "random")]
1801#[test]
1802fn pack_preampbiasconfig() {
1803  for _ in 0..100 {
1804    let cfg  = PreampBiasConfig::from_random();
1805    let test : PreampBiasConfig = cfg.pack().unpack().unwrap();
1806    assert_eq!(cfg, test);
1807  }
1808}
1809
1810#[cfg(feature = "random")]
1811#[test]
1812fn pack_rb_channel_mask_config() {
1813  for _ in 0..100 {
1814    let cfg   = RBChannelMaskConfig::from_random();
1815    let test : RBChannelMaskConfig = cfg.pack().unpack().unwrap();
1816    assert_eq!(cfg, test);
1817  }
1818}
1819
1820
1821#[cfg(feature = "random")]
1822#[test]
1823fn pack_ltbthresholdconfig() {
1824  for _ in 0..100 {
1825    let cfg   = LTBThresholdConfig::from_random();
1826    let test : LTBThresholdConfig = cfg.pack().unpack().unwrap();
1827    assert_eq!(cfg, test);
1828  }
1829}
1830
1831#[cfg(feature = "random")]
1832#[test]
1833fn pack_runconfig() {
1834  for _ in 0..100 {
1835    let cfg  = RunConfig::from_random();
1836    let test = cfg.pack().unpack().unwrap();
1837    //let test = RunConfig::from_bytestream(&cfg.to_bytestream(), &mut 0).unwrap();
1838    assert_eq!(cfg, test);
1839
1840    let cfg_json = serde_json::to_string(&cfg).unwrap();
1841    let test_json 
1842      = serde_json::from_str::<RunConfig>(&cfg_json).unwrap();
1843    assert_eq!(cfg, test_json);
1844  }
1845}
1846
1847#[cfg(feature = "random")]
1848#[test]
1849fn pack_triggerconfig() {
1850  for _ in 0..100 {
1851    let cfg  = TriggerConfig::from_random();
1852    let test : TriggerConfig = cfg.pack().unpack().unwrap();
1853    assert_eq!(cfg, test);
1854  }
1855}
1856
1857#[cfg(feature = "random")]
1858#[test]
1859fn pack_tofeventbuilderconfig() {
1860  for _ in 0..100 {
1861    let cfg  = TOFEventBuilderConfig::from_random();
1862    let test : TOFEventBuilderConfig = cfg.pack().unpack().unwrap();
1863    assert_eq!(cfg, test);
1864  }
1865}
1866
1867#[cfg(feature = "random")]
1868#[test]
1869fn pack_datapublisherconfig() {
1870  for _ in 0..100 {
1871    let cfg  = DataPublisherConfig::from_random();
1872    let test : DataPublisherConfig = cfg.pack().unpack().unwrap();
1873    assert_eq!(cfg, test);
1874  }
1875}
1876
1877#[cfg(feature = "random")]
1878#[test]
1879fn pack_tofrunconfig() {
1880  for _ in 0..100 {
1881    let cfg  = TofRunConfig::from_random();
1882    let test : TofRunConfig = cfg.pack().unpack().unwrap();
1883    assert_eq!(cfg, test);
1884  }
1885}
1886
1887#[cfg(feature = "random")]
1888#[test]
1889fn pack_tofrbconfig() {
1890  for _ in 0..100 {
1891    let cfg  = TofRBConfig::from_random();
1892    let test : TofRBConfig = cfg.pack().unpack().unwrap();
1893    assert_eq!(cfg, test);
1894  }
1895}
1896