1use std::fs::File;
12use std::io::{
13 Write,
14 Read,
15};
16use std::fmt;
17use std::collections::HashMap;
18
19use tof_dataclasses::commands::config::{
20 BuildStrategy,
21 TriggerConfig,
22 TOFEventBuilderConfig,
23 TofRunConfig,
24 TofRBConfig,
25 DataPublisherConfig,
26};
27use tof_dataclasses::events::master_trigger::TriggerType;
28
29use tof_dataclasses::events::DataType;
31#[cfg(feature="database")]
32use tof_dataclasses::packets::TofPacket;
33use tof_dataclasses::commands::TofOperationMode;
34#[cfg(feature="database")]
35use tof_dataclasses::commands::TofCommandV2;
36#[cfg(feature="database")]
37use tof_dataclasses::commands::TofCommandCode;
38
39use tof_dataclasses::commands::config::RunConfig;
40#[cfg(feature="database")]
41use tof_dataclasses::database::RAT;
42#[cfg(feature="database")]
43use tof_dataclasses::commands::config::PreampBiasConfig;
44#[cfg(feature="database")]
45use tof_dataclasses::commands::config::LTBThresholdConfig;
46#[cfg(feature="database")]
47use tof_dataclasses::commands::config::RBChannelMaskConfig;
48
49use tof_dataclasses::serialization::{
50 parse_u8,
51 parse_u16,
52 parse_u32,
53 Serialization,
55 SerializationError,
56};
57
58#[cfg(feature="database")]
59use tof_dataclasses::serialization::Packable;
60
61#[derive(Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
62pub enum ParameterSetStrategy {
63 ControlServer,
64 Board
65}
66
67#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
81pub struct MTBSettings {
82 pub trigger_type : TriggerType,
84 pub trigger_prescale : f32,
91 pub use_combo_trigger : bool,
93 pub global_trigger_type : TriggerType,
96 pub global_trigger_prescale : f32,
98
99 pub poisson_trigger_rate : u32,
101 pub gaps_trigger_use_beta : bool,
104 pub trace_suppression : bool,
120 pub mtb_timeout_sec : u64,
124 pub mtb_moni_interval : u64,
127 pub rb_int_window : u8,
128 pub tiu_emulation_mode : bool,
129 pub tiu_ignore_busy : bool,
130 pub tofbot_webhook : String,
131 pub hb_send_interval : u64,
132}
133
134impl MTBSettings {
135 pub fn new() -> Self {
136 Self {
137 trigger_type : TriggerType::Unknown,
138 trigger_prescale : 0.0,
139 poisson_trigger_rate : 0,
140 gaps_trigger_use_beta : true,
141 trace_suppression : true,
142 mtb_timeout_sec : 60,
143 mtb_moni_interval : 30,
144 rb_int_window : 1,
145 tiu_emulation_mode : false,
146 tiu_ignore_busy : false,
147 tofbot_webhook : String::from(""),
148 hb_send_interval : 30,
149 use_combo_trigger : false,
150 global_trigger_type : TriggerType::Unknown,
151 global_trigger_prescale : 1.0,
152 }
153 }
154
155 pub fn emit_triggerconfig(&self) -> TriggerConfig {
158 let mut cfg = TriggerConfig::new();
159 cfg.active_fields = u32::MAX;
163 cfg.gaps_trigger_use_beta = Some(self.gaps_trigger_use_beta);
164 cfg.prescale = Some(self.trigger_prescale);
165 cfg.trigger_type = Some(self.trigger_type);
166 cfg.use_combo_trigger = Some(self.use_combo_trigger);
167 cfg.combo_trigger_type = Some(self.global_trigger_type);
168 cfg.combo_trigger_prescale = Some(self.global_trigger_prescale);
169 cfg.trace_suppression = Some(self.trace_suppression);
170 cfg.mtb_moni_interval = Some((self.mtb_moni_interval & 0xffff) as u16);
171 cfg.tiu_ignore_busy = Some(self.tiu_ignore_busy);
172 cfg.hb_send_interval = Some((self.hb_send_interval & 0xffff) as u16);
173 cfg
174 }
175
176 pub fn from_triggerconfig(&mut self, cfg : &TriggerConfig) {
178 if cfg.gaps_trigger_use_beta.is_some() {
179 self.gaps_trigger_use_beta = cfg.gaps_trigger_use_beta.unwrap() ;
180 }
181 if cfg.prescale.is_some() {
182 self.trigger_prescale = cfg.prescale.unwrap() ;
183 }
184 if cfg.trigger_type.is_some() {
185 self.trigger_type = cfg.trigger_type.unwrap() ;
186 }
187 if cfg.use_combo_trigger.is_some() {
188 self.use_combo_trigger = cfg.use_combo_trigger.unwrap() ;
189 }
190 if cfg.combo_trigger_type.is_some() {
191 self.global_trigger_type = cfg.combo_trigger_type.unwrap() ;
192 }
193 if cfg.combo_trigger_prescale.is_some() {
194 self.global_trigger_prescale = cfg.combo_trigger_prescale.unwrap();
195 }
196 if cfg.trace_suppression.is_some() {
197 self.trace_suppression = cfg.trace_suppression.unwrap() ;
198 }
199 if cfg.mtb_moni_interval.is_some() {
200 self.mtb_moni_interval = cfg.mtb_moni_interval.unwrap() as u64;
201 }
202 if cfg.tiu_ignore_busy.is_some() {
203 self.tiu_ignore_busy = cfg.tiu_ignore_busy.unwrap() ;
204 }
205 if cfg.hb_send_interval.is_some() {
206 self.hb_send_interval = cfg.hb_send_interval.unwrap() as u64;
207 }
208 }
209}
210
211impl fmt::Display for MTBSettings {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 let disp = toml::to_string(self).unwrap_or(
214 String::from("-- DESERIALIZATION ERROR! --"));
215 write!(f, "<MTBSettings :\n{}>", disp)
216 }
217}
218
219impl Default for MTBSettings {
220 fn default() -> Self {
221 Self::new()
222 }
223}
224
225#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
226pub struct PreampSettings {
227 pub set_preamp_voltages : bool,
229 pub set_strategy : ParameterSetStrategy,
232 pub rat_preamp_biases : HashMap<String, [f32;16]>
234}
235
236impl PreampSettings {
237 pub fn new() -> Self {
238 let default_biases = HashMap::from([
240 (String::from("RAT01"), [58.0;16]),
241 (String::from("RAT02"), [58.0;16]),
242 (String::from("RAT03"), [58.0;16]),
243 (String::from("RAT04"), [58.0;16]),
244 (String::from("RAT05"), [58.0;16]),
245 (String::from("RAT06"), [58.0;16]),
246 (String::from("RAT07"), [58.0;16]),
247 (String::from("RAT08"), [58.0;16]),
248 (String::from("RAT09"), [58.0;16]),
249 (String::from("RAT10"), [58.0;16]),
250 (String::from("RAT11"), [58.0;16]),
251 (String::from("RAT12"), [58.0;16]),
252 (String::from("RAT13"), [58.0;16]),
253 (String::from("RAT14"), [58.0;16]),
254 (String::from("RAT15"), [58.0;16]),
255 (String::from("RAT16"), [58.0;16]),
256 (String::from("RAT17"), [58.0;16]),
257 (String::from("RAT18"), [58.0;16]),
258 (String::from("RAT19"), [58.0;16]),
259 (String::from("RAT20"), [58.0;16])]);
260
261 Self {
262 set_preamp_voltages : false,
263 set_strategy : ParameterSetStrategy::ControlServer,
264 rat_preamp_biases : default_biases,
265 }
266 }
267
268 #[cfg(feature="database")]
269 pub fn emit_pb_settings_packets(&self, rats : &HashMap<u8,RAT>) -> Vec<TofPacket> {
270 let mut packets = Vec::<TofPacket>::new();
271 for k in rats.keys() {
272 let rat = &rats[&k];
273 let rat_key = format!("RAT{:2}", rat);
274 let mut cmd = TofCommandV2::new();
275 cmd.command_code = TofCommandCode::SetPreampBias;
276 let mut payload = PreampBiasConfig::new();
277 payload.rb_id = rat.rb2_id as u8;
278 if *k as usize >= self.rat_preamp_biases.len() {
279 error!("RAT ID {k} larger than 20!");
280 continue;
281 }
282 payload.biases = self.rat_preamp_biases[&rat_key];
283 cmd.payload = payload.to_bytestream();
284 let tp = cmd.pack();
285 packets.push(tp);
286 }
287 packets
288 }
289}
290
291impl fmt::Display for PreampSettings {
292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293 let disp : String;
294 match toml::to_string(self) {
295 Err(err) => {
296 error!("Deserialization error! {err}");
297 disp = String::from("-- DESERIALIZATION ERROR! --");
298 }
299 Ok(_disp) => {
300 disp = _disp;
301 }
302 }
303 write!(f, "<PreampBiasSettings :\n{}>", disp)
304 }
305}
306
307impl Default for PreampSettings {
308 fn default() -> Self {
309 Self::new()
310 }
311}
312
313#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
314pub struct LTBThresholdSettings {
315 pub set_ltb_thresholds : bool,
317 pub set_strategy : ParameterSetStrategy,
320 pub rat_ltb_thresholds : HashMap<String, [f32;3]>
322}
323
324impl LTBThresholdSettings {
325 pub fn new() -> Self {
326 let default_thresholds = HashMap::from([
327 (String::from("RAT01"), [40.0,32.0,375.0]),
328 (String::from("RAT02"), [40.0,32.0,375.0]),
329 (String::from("RAT03"), [40.0,32.0,375.0]),
330 (String::from("RAT04"), [40.0,32.0,375.0]),
331 (String::from("RAT05"), [40.0,32.0,375.0]),
332 (String::from("RAT06"), [40.0,32.0,375.0]),
333 (String::from("RAT07"), [40.0,32.0,375.0]),
334 (String::from("RAT08"), [40.0,32.0,375.0]),
335 (String::from("RAT09"), [40.0,32.0,375.0]),
336 (String::from("RAT10"), [40.0,32.0,375.0]),
337 (String::from("RAT11"), [40.0,32.0,375.0]),
338 (String::from("RAT12"), [40.0,32.0,375.0]),
339 (String::from("RAT13"), [40.0,32.0,375.0]),
340 (String::from("RAT14"), [40.0,32.0,375.0]),
341 (String::from("RAT15"), [40.0,32.0,375.0]),
342 (String::from("RAT16"), [40.0,32.0,375.0]),
343 (String::from("RAT17"), [40.0,32.0,375.0]),
344 (String::from("RAT18"), [40.0,32.0,375.0]),
345 (String::from("RAT19"), [40.0,32.0,375.0]),
346 (String::from("RAT20"), [40.0,32.0,375.0])]);
347
348 Self {
349 set_ltb_thresholds : false,
350 set_strategy : ParameterSetStrategy::ControlServer,
351 rat_ltb_thresholds : default_thresholds,
352 }
353 }
354
355 #[cfg(feature="database")]
356 pub fn emit_ltb_settings_packets(&self, rats : &HashMap<u8,RAT>) -> Vec<TofPacket> {
357 let mut packets = Vec::<TofPacket>::new();
358 for k in rats.keys() {
359 let rat = &rats[&k];
360 let rat_key = format!("RAT{:2}", rat);
361 let mut cmd = TofCommandV2::new();
362 cmd.command_code = TofCommandCode::SetLTBThresholds;
363 let mut payload = LTBThresholdConfig::new();
364 payload.rb_id = rat.rb1_id as u8;
365 if *k as usize >= self.rat_ltb_thresholds.len() {
366 error!("RAT ID {k} larger than 20!");
367 continue;
368 }
369 payload.thresholds = self.rat_ltb_thresholds[&rat_key];
370 cmd.payload = payload.to_bytestream();
371 let tp = cmd.pack();
372 packets.push(tp);
373 }
374 packets
375 }
376}
377
378impl fmt::Display for LTBThresholdSettings {
379 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380 let disp : String;
381 match toml::to_string(self) {
382 Err(err) => {
383 error!("Deserialization error! {err}");
384 disp = String::from("-- DESERIALIZATION ERROR! --");
385 }
386 Ok(_disp) => {
387 disp = _disp;
388 }
389 }
390 write!(f, "<LTBThresholdSettings :\n{}>", disp)
391 }
392}
393
394impl Default for LTBThresholdSettings {
395 fn default() -> Self {
396 Self::new()
397 }
398}
399
400#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
401pub struct CommandDispatcherSettings {
402 pub cmd_log_path : String,
407 pub cc_server_address : String,
413 pub fc_sub_address : String,
417 pub cmd_listener_interval_sec : u64,
419 pub deny_all_requests : bool
422}
423
424impl CommandDispatcherSettings {
425 pub fn new() -> Self {
426 Self {
427 cmd_log_path : String::from("/home/gaps/log"),
428 cc_server_address : String::from("tcp://10.0.1.10:42000"),
429 fc_sub_address : String::from("tcp://192.168.37.200:41662"),
430 cmd_listener_interval_sec : 1,
431 deny_all_requests : false
432 }
433 }
434}
435
436impl fmt::Display for CommandDispatcherSettings {
437 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438 let disp = toml::to_string(self).unwrap_or(
439 String::from("-- DESERIALIZATION ERROR! --"));
440 write!(f, "<CommandDispatcherSettings :\n{}>", disp)
441 }
442}
443
444impl Default for CommandDispatcherSettings {
445 fn default() -> Self {
446 Self::new()
447 }
448}
449
450#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
452pub enum RBBufferStrategy {
453 NEvents(u16),
456 AdaptToRate(u16),
460}
461
462impl fmt::Display for RBBufferStrategy {
463 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464 let r = serde_json::to_string(self).unwrap_or(
465 String::from("N.A. - Invalid RBBufferStrategy (error)"));
466 write!(f, "<RBBufferStrategy: {}>", r)
467 }
468}
469
470
471#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
473pub struct RBSettings {
474 pub only_perfect_events : bool,
478 pub calc_crc32 : bool,
481 pub tof_op_mode : TofOperationMode,
484 pub trigger_poisson_rate : u32,
487 pub trigger_fixed_rate : u32,
490 pub data_type : DataType,
500 pub rb_buff_strategy : RBBufferStrategy,
511 pub rb_moni_interval : f32,
514 pub pb_moni_every_x : f32,
516 pub pa_moni_every_x : f32,
518 pub ltb_moni_every_x : f32,
520 pub drs_deadtime_instead_fpga_temp : bool
522}
523
524impl RBSettings {
525 pub fn new() -> Self {
526 Self {
527 only_perfect_events : false,
528 calc_crc32 : false,
529 tof_op_mode : TofOperationMode::Default,
530 trigger_fixed_rate : 0,
531 trigger_poisson_rate : 0,
532 data_type : DataType::Physics,
533 rb_buff_strategy : RBBufferStrategy::AdaptToRate(5),
534 rb_moni_interval : 0.0,
535 pb_moni_every_x : 0.0,
536 pa_moni_every_x : 0.0,
537 ltb_moni_every_x : 0.0,
538 drs_deadtime_instead_fpga_temp : false
539 }
540 }
541
542 pub fn from_tofrbconfig(&mut self, cfg : &TofRBConfig) {
543 if cfg.rb_moni_interval.is_some() {
544 self.rb_moni_interval = cfg.rb_moni_interval.unwrap() as f32;
545 }
546 if cfg.rb_moni_interval.is_some() {
547 self.pb_moni_every_x = cfg.pb_moni_every_x.unwrap() as f32;
548 }
549 if cfg.rb_moni_interval.is_some() {
550 self.pa_moni_every_x = cfg.pa_moni_every_x.unwrap() as f32;
551 }
552 if cfg.rb_moni_interval.is_some() {
553 self.ltb_moni_every_x = cfg.ltb_moni_every_x.unwrap() as f32;
554 }
555 if cfg.rb_moni_interval.is_some() {
556 self.drs_deadtime_instead_fpga_temp = cfg.drs_deadtime_instead_fpga_temp.unwrap();
557 }
558 }
559
560 pub fn get_runconfig(&self) -> RunConfig {
561 let mut rcfg = RunConfig::new();
564 rcfg.is_active = true;
565 rcfg.tof_op_mode = self.tof_op_mode.clone();
566 rcfg.trigger_fixed_rate = self.trigger_fixed_rate;
567 rcfg.trigger_poisson_rate = self.trigger_poisson_rate;
568 rcfg.data_type = self.data_type.clone();
569 let buffer_trip : u16;
570 match self.rb_buff_strategy {
571 RBBufferStrategy::NEvents(buff_size) => {
572 buffer_trip = buff_size;
573 },
574 RBBufferStrategy::AdaptToRate(_) => {
575 buffer_trip = 50;
578 }
588 }
589 rcfg.rb_buff_size = buffer_trip as u16;
590 rcfg
591 }
592}
593
594impl fmt::Display for RBSettings {
595 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
596 let disp = toml::to_string(self).unwrap_or(
597 String::from("-- DESERIALIZATION ERROR! --"));
598 write!(f, "<RBSettings :\n{}>", disp)
599 }
600}
601
602impl Default for RBSettings {
603 fn default() -> Self {
604 Self::new()
605 }
606}
607
608
609#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
612pub struct AnalysisEngineSettings {
613 pub integration_start : f32,
615 pub integration_window : f32,
617 pub pedestal_thresh : f32,
619 pub pedestal_begin_bin : usize,
621 pub pedestal_win_bins : usize,
623 pub use_zscore : bool,
626 pub find_pks_t_start : f32,
628 pub find_pks_t_window : f32,
630 pub min_peak_size : usize,
632 pub find_pks_thresh : f32,
634 pub max_peaks : usize,
636 pub cfd_fraction : f32
638}
639
640impl AnalysisEngineSettings {
641 pub fn new() -> Self {
642 Self {
643 integration_start : 270.0,
644 integration_window : 70.0,
645 pedestal_thresh : 10.0,
646 pedestal_begin_bin : 10,
647 pedestal_win_bins : 50,
648 use_zscore : false,
649 find_pks_t_start : 270.0,
650 find_pks_t_window : 70.0,
651 min_peak_size : 3,
652 find_pks_thresh : 10.0,
653 max_peaks : 5,
654 cfd_fraction : 0.2
655 }
656 }
657}
658
659impl fmt::Display for AnalysisEngineSettings {
660 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
661 let disp = toml::to_string(self).unwrap_or(
662 String::from("-- DESERIALIZATION ERROR! --"));
663 write!(f, "<AnalysisEngineSettings :\n{}>", disp)
664 }
665}
666
667impl Default for AnalysisEngineSettings {
668 fn default() -> Self {
669 Self::new()
670 }
671}
672
673#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
675pub struct TofEventBuilderSettings {
676 pub cachesize : u32,
677 pub n_mte_per_loop : u32,
678 pub n_rbe_per_loop : u32,
679 pub te_timeout_sec : u32,
682 pub sort_events : bool,
684 pub build_strategy : BuildStrategy,
685 pub greediness : u8,
686 pub wait_nrb : u8,
687 pub hb_send_interval : u16,
688 pub only_save_interesting : bool,
692 pub thr_n_hits_umb : u8,
693 pub thr_n_hits_cbe : u8,
694 pub thr_n_hits_cor : u8,
695 pub thr_tot_edep_umb : f32,
696 pub thr_tot_edep_cbe : f32,
697 pub thr_tot_edep_cor : f32,
698}
699
700impl TofEventBuilderSettings {
701 pub fn new() -> TofEventBuilderSettings {
702 TofEventBuilderSettings {
703 cachesize : 100000,
704 n_mte_per_loop : 1,
705 n_rbe_per_loop : 40,
706 te_timeout_sec : 30,
707 sort_events : false,
708 build_strategy : BuildStrategy::Adaptive,
709 greediness : 3,
710 wait_nrb : 40,
711 hb_send_interval : 30,
712 only_save_interesting : false,
713 thr_n_hits_umb : 0,
714 thr_n_hits_cbe : 0,
715 thr_n_hits_cor : 0,
716 thr_tot_edep_umb : 0.0,
717 thr_tot_edep_cbe : 0.0,
718 thr_tot_edep_cor : 0.0,
719 }
720 }
721
722 pub fn from_tofeventbuilderconfig(&mut self, cfg : &TOFEventBuilderConfig) {
723 if cfg.cachesize.is_some() {
724 self.cachesize = cfg.cachesize.unwrap();
725 }
726 if cfg.n_mte_per_loop.is_some() {
727 self.n_mte_per_loop = cfg.n_mte_per_loop.unwrap();
728 }
729 if cfg.n_rbe_per_loop.is_some() {
730 self.n_rbe_per_loop = cfg.n_rbe_per_loop.unwrap();
731 }
732 if cfg.te_timeout_sec.is_some() {
733 self.te_timeout_sec = cfg.te_timeout_sec.unwrap();
734 }
735 if cfg.sort_events.is_some() {
736 self.sort_events = cfg.sort_events.unwrap();
737 }
738 if cfg.build_strategy.is_some() {
739 self.build_strategy = cfg.build_strategy.unwrap();
740 }
741 if cfg.greediness.is_some() {
742 self.greediness = cfg.greediness.unwrap();
743 }
744 if cfg.wait_nrb.is_some() {
745 self.wait_nrb = cfg.wait_nrb.unwrap();
746 }
747 if cfg.hb_send_interval.is_some() {
748 self.hb_send_interval = cfg.hb_send_interval.unwrap();
749 }
750 if cfg.only_save_interesting.is_some() {
751 self.only_save_interesting = cfg.only_save_interesting.unwrap();
752 }
753 if cfg.thr_n_hits_umb.is_some() {
754 self.thr_n_hits_umb = cfg.thr_n_hits_umb.unwrap();
755 }
756 if cfg.thr_n_hits_cbe.is_some() {
757 self.thr_n_hits_cbe = cfg.thr_n_hits_cbe.unwrap();
758 }
759 if cfg.thr_n_hits_cor.is_some() {
760 self.thr_n_hits_cor = cfg.thr_n_hits_cor.unwrap();
761 }
762 if cfg.thr_tot_edep_umb.is_some() {
763 self.thr_tot_edep_umb = cfg.thr_tot_edep_umb.unwrap();
764 }
765 if cfg.thr_tot_edep_cbe.is_some() {
766 self.thr_tot_edep_cbe = cfg.thr_tot_edep_cbe.unwrap();
767 }
768 if cfg.thr_tot_edep_cor.is_some() {
769 self.thr_tot_edep_cor = cfg.thr_tot_edep_cor.unwrap();
770 }
771 }
772}
773
774impl fmt::Display for TofEventBuilderSettings {
775 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
776 let disp = toml::to_string(self).unwrap_or(
777 String::from("-- DESERIALIZATION ERROR! --"));
778 write!(f, "<TofEventBuilderSettings :\n{}>", disp)
779 }
780}
781
782impl Default for TofEventBuilderSettings {
783 fn default() -> Self {
784 Self::new()
785 }
786}
787
788#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
790pub struct DataPublisherSettings {
791 pub data_dir : String,
793 pub mbytes_per_file : usize,
796 pub fc_pub_address : String,
799 pub discard_event_fraction : f32,
803 pub send_mtb_event_packets : bool,
813 pub send_rbwaveform_packets : bool,
816 pub send_rbwf_every_x_event : u32,
819 pub send_tof_summary_packets : bool,
820 pub send_tof_event_packets : bool,
821 pub send_cali_packets : bool,
823 pub hb_send_interval : u16,
824}
825
826impl DataPublisherSettings {
827 pub fn new() -> Self {
828 Self {
829 data_dir : String::from(""),
830 mbytes_per_file : 420,
831 fc_pub_address : String::from(""),
832 discard_event_fraction : 0.0,
833 send_mtb_event_packets : false,
834 send_rbwaveform_packets : false,
835 send_rbwf_every_x_event : 1,
836 send_tof_summary_packets : true,
837 send_tof_event_packets : false,
838 send_cali_packets : true,
839 hb_send_interval : 30,
840 }
841 }
842
843 pub fn from_datapublisherconfig(&mut self, cfg : &DataPublisherConfig) {
844 if cfg.mbytes_per_file.is_some() {
845 self.mbytes_per_file = cfg.mbytes_per_file.unwrap() as usize;
846 }
847 if cfg.discard_event_fraction.is_some() {
848 self.discard_event_fraction = cfg.discard_event_fraction.unwrap();
849 }
850 if cfg.send_mtb_event_packets.is_some() {
851 self.send_mtb_event_packets = cfg.send_mtb_event_packets.unwrap();
852 }
853 if cfg.send_rbwaveform_packets.is_some() {
854 self.send_rbwaveform_packets = cfg.send_rbwaveform_packets.unwrap();
855 }
856 if cfg.send_rbwf_every_x_event.is_some() {
857 self.send_rbwf_every_x_event = cfg.send_rbwf_every_x_event.unwrap();
858 }
859 if cfg.send_tof_summary_packets.is_some() {
860 self.send_tof_summary_packets = cfg.send_tof_summary_packets.unwrap();
861 }
862 if cfg.send_tof_event_packets.is_some() {
863 self.send_tof_event_packets = cfg.send_tof_event_packets.unwrap();
864 }
865 if cfg.hb_send_interval.is_some() {
866 self.hb_send_interval = cfg.hb_send_interval.unwrap();
867 }
868 }
869}
870
871impl fmt::Display for DataPublisherSettings {
872 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
873 let disp = toml::to_string(self).unwrap_or(
874 String::from("-- DESERIALIZATION ERROR! --"));
875 write!(f, "<DataPublisherSettings :\n{}>", disp)
876 }
877}
878
879impl Default for DataPublisherSettings {
880 fn default() -> Self {
881 Self::new()
882 }
883}
884
885
886#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
887pub struct LiftofSettings {
888 pub staging_dir : String,
891 pub calibration_dir : String,
893 pub db_path : String,
895 pub runtime_sec : u64,
897 pub mtb_address : String,
900 pub cpu_moni_interval_sec : u64,
903 pub rb_ignorelist_always : Vec<u8>,
906 pub rb_ignorelist_run : Vec<u8>,
908 pub run_analysis_engine : bool,
910 pub pre_run_calibration : bool,
913 pub save_cali_wf : bool,
916 pub verification_runtime_sec : u32,
922 pub mtb_settings : MTBSettings,
924 pub event_builder_settings : TofEventBuilderSettings,
926 pub analysis_engine_settings : AnalysisEngineSettings,
928 pub data_publisher_settings : DataPublisherSettings,
930 pub cmd_dispatcher_settings : CommandDispatcherSettings,
932 pub rb_settings : RBSettings,
934 pub rb_channel_mask : ChannelMaskSettings,
937 pub preamp_settings : PreampSettings,
939 pub ltb_settings : LTBThresholdSettings
941}
942
943impl LiftofSettings {
944 pub fn new() -> Self {
945 LiftofSettings {
946 staging_dir : String::from("/home/gaps/liftof-staging"),
947 calibration_dir : String::from(""),
948 db_path : String::from("/home/gaps/config/gaps_flight.db"),
949 runtime_sec : 0,
950 mtb_address : String::from("10.0.1.10:50001"),
951 cpu_moni_interval_sec : 60,
952 rb_ignorelist_always : Vec::<u8>::new(),
953 rb_ignorelist_run : Vec::<u8>::new(),
954 run_analysis_engine : true,
955 pre_run_calibration : false,
956 save_cali_wf : false,
957 verification_runtime_sec : 0, mtb_settings : MTBSettings::new(),
959 event_builder_settings : TofEventBuilderSettings::new(),
960 analysis_engine_settings : AnalysisEngineSettings::new(),
961 data_publisher_settings : DataPublisherSettings::new(),
962 cmd_dispatcher_settings : CommandDispatcherSettings::new(),
963 rb_settings : RBSettings::new(),
964 rb_channel_mask : ChannelMaskSettings::new(),
965 preamp_settings : PreampSettings::new(),
966 ltb_settings : LTBThresholdSettings::new(),
967 }
968 }
969
970 pub fn from_tofrunconfig(&mut self, cfg : &TofRunConfig) {
973 if cfg.runtime.is_some() {
974 self.runtime_sec = cfg.runtime.unwrap() as u64;
975 }
976 }
977
978 #[deprecated(since="0.10.0", note="This is a dev deadend and will be nuked!")]
982 pub fn set_by_key(&mut self, key : &str, value : String) {
983 match key {
984 "runtime_sec" => {
985 if let Ok(val) = value.parse::<u64>() {
986 self.runtime_sec = val;
987 } else {
988 error!("Unable to parse {value}!");
989 }
990 }
991 "cpu_moni_interval_sec" => {
992 if let Ok(val) = value.parse::<u64>() {
993 self.cpu_moni_interval_sec = val;
994 } else {
995 error!("Unable to parse {value}!");
996 }
997 }
998 "rb_ignorelist_run" => {
999 }
1000 "run_analysis_engine" => {
1001 if let Ok(val) = value.parse::<bool>() {
1002 self.run_analysis_engine = val;
1003 } else {
1004 error!("Unable to parse {value}!");
1005 }
1006 }
1007 "pre_run_calibration" => {
1008 if let Ok(val) = value.parse::<bool>() {
1009 self.pre_run_calibration = val;
1010 } else {
1011 error!("Unable to parse {value}!");
1012 }
1013 }
1014 "save_cali_wf" => {
1015 if let Ok(val) = value.parse::<bool>() {
1016 self.save_cali_wf = val;
1017 } else {
1018 error!("Unable to parse {value}!");
1019 }
1020 }
1021 "verification_runtime_sec" => {
1022 if let Ok(val) = value.parse::<u32>() {
1023 self.verification_runtime_sec = val;
1024 } else {
1025 error!("Unable to parse {value}!");
1026 }
1027 }
1028 _ => error!("Set by key for {} is not implemented!", key)
1029 }
1030 }
1031
1032 pub fn to_toml(&self, mut filename : String) {
1034 if !filename.ends_with(".toml") {
1035 filename += ".toml";
1036 }
1037 info!("Will write to file {}!", filename);
1038 match File::create(&filename) {
1039 Err(err) => {
1040 error!("Unable to open file {}! {}", filename, err);
1041 }
1042 Ok(mut file) => {
1043 match toml::to_string_pretty(&self) {
1044 Err(err) => {
1045 error!("Unable to serialize toml! {err}");
1046 }
1047 Ok(toml_string) => {
1048 match file.write_all(toml_string.as_bytes()) {
1049 Err(err) => error!("Unable to write to file {}! {}", filename, err),
1050 Ok(_) => debug!("Wrote settings to {}!", filename)
1051 }
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058 pub fn to_json(&self, mut filename : String) {
1060 if !filename.ends_with(".json") {
1061 filename += ".json";
1062 }
1063 info!("Will write to file {}!", filename);
1064 match File::create(&filename) {
1065 Err(err) => {
1066 error!("Unable to open file {}! {}", filename, err);
1067 }
1068 Ok(file) => {
1069 match serde_json::to_writer_pretty(file, &self) {
1070 Err(err) => {
1071 error!("Unable to serialize json! {err}");
1072 }
1073 Ok(_) => debug!("Wrote settings to {}!", filename)
1074 }
1075 }
1076 }
1077 }
1078
1079 pub fn from_toml(filename : &str) -> Result<LiftofSettings, SerializationError> {
1080 match File::open(filename) {
1081 Err(err) => {
1082 error!("Unable to open {}! {}", filename, err);
1083 return Err(SerializationError::TomlDecodingError);
1084 }
1085 Ok(mut file) => {
1086 let mut toml_string = String::from("");
1087 match file.read_to_string(&mut toml_string) {
1088 Err(err) => {
1089 error!("Unable to read {}! {}", filename, err);
1090 return Err(SerializationError::TomlDecodingError);
1091 }
1092 Ok(_) => {
1093 match toml::from_str(&toml_string) {
1094 Err(err) => {
1095 error!("Can't interpret toml! {}", err);
1096 return Err(SerializationError::TomlDecodingError);
1097 }
1098 Ok(settings) => {
1099 return Ok(settings);
1100 }
1101 }
1102 }
1103 }
1104 }
1105 }
1106 }
1107}
1108
1109impl fmt::Display for LiftofSettings {
1110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1111 let disp : String;
1112 match toml::to_string(self) {
1113 Err(err) => {
1114 println!("Deserialization error! {err}");
1115 disp = String::from("-- DESERIALIZATION ERROR! --");
1116 }
1117 Ok(_disp) => {
1118 disp = _disp;
1119 }
1120 }
1121 write!(f, "<LiftofSettings :\n{}>", disp)
1122 }
1123}
1124
1125impl Default for LiftofSettings {
1126 fn default() -> Self {
1127 Self::new()
1128 }
1129}
1130
1131#[derive(Debug, Copy, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
1133pub struct LiftofRBConfig {
1134 pub nseconds : u32,
1136 pub tof_op_mode : TofOperationMode,
1139 pub trigger_poisson_rate : u32,
1142 pub trigger_fixed_rate : u32,
1145 pub data_type : DataType,
1149 pub rb_buff_size : u16
1155}
1156
1157impl LiftofRBConfig {
1158
1159 pub fn new() -> Self {
1160 Self {
1161 nseconds : 0,
1162 tof_op_mode : TofOperationMode::Default,
1163 trigger_poisson_rate : 0,
1164 trigger_fixed_rate : 0,
1165 data_type : DataType::Unknown,
1166 rb_buff_size : 0,
1167 }
1168 }
1169}
1170
1171impl Serialization for LiftofRBConfig {
1172 const HEAD : u16 = 43690; const TAIL : u16 = 21845; const SIZE : usize = 24; fn from_bytestream(bytestream : &Vec<u8>,
1177 pos : &mut usize)
1178 -> Result<Self, SerializationError> {
1179 let mut pars = Self::new();
1180 Self::verify_fixed(bytestream, pos)?;
1181 pars.nseconds = parse_u32 (bytestream, pos);
1182 pars.tof_op_mode
1183 = TofOperationMode::try_from(
1184 parse_u8(bytestream, pos))
1185 .unwrap_or_else(|_| TofOperationMode::Unknown);
1186 pars.trigger_poisson_rate = parse_u32 (bytestream, pos);
1187 pars.trigger_fixed_rate = parse_u32 (bytestream, pos);
1188 pars.data_type
1189 = DataType::try_from(parse_u8(bytestream, pos))
1190 .unwrap_or_else(|_| DataType::Unknown);
1191 pars.rb_buff_size = parse_u16(bytestream, pos);
1192 *pos += 2; Ok(pars)
1195 }
1196
1197 fn to_bytestream(&self) -> Vec<u8> {
1198 let mut stream = Vec::<u8>::with_capacity(Self::SIZE);
1199 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
1200 stream.extend_from_slice(&self. nseconds.to_le_bytes());
1201 stream.extend_from_slice(&(self.tof_op_mode as u8).to_le_bytes());
1202 stream.extend_from_slice(&self.trigger_poisson_rate.to_le_bytes());
1203 stream.extend_from_slice(&self.trigger_fixed_rate.to_le_bytes());
1204 stream.extend_from_slice(&(self.data_type as u8).to_le_bytes());
1205 stream.extend_from_slice(&self.rb_buff_size.to_le_bytes());
1206 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
1207 stream
1208 }
1209}
1210
1211impl Default for LiftofRBConfig {
1212 fn default() -> Self {
1213 Self::new()
1214 }
1215}
1216
1217impl fmt::Display for LiftofRBConfig {
1218 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1219 write!(f,
1220"<LiftofRBConfig -- is_active : true
1221 nseconds : {}
1222 TOF op. mode : {}
1223 data type : {}
1224 tr_poi_rate : {}
1225 tr_fix_rate : {}
1226 buff size : {} [events]>",
1227 self.nseconds,
1228 self.tof_op_mode,
1229 self.data_type,
1230 self.trigger_poisson_rate,
1231 self.trigger_fixed_rate,
1232 self.rb_buff_size)
1233 }
1234}
1235
1236#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
1285pub struct ChannelMaskSettings {
1286 pub set_channel_mask : bool,
1288 pub set_strategy : ParameterSetStrategy,
1294 pub rb_channel_mask : HashMap<String, [bool;9]>
1298}
1299
1300impl ChannelMaskSettings {
1301 pub fn new() -> Self {
1302 let mut default_thresholds = HashMap::<String, [bool; 9]>::new();
1303 for k in 1..51 {
1304 let key = format!("RB{k:02}");
1305 default_thresholds.insert(key, [true;9]);
1306 }
1307Self {
1330 set_channel_mask : false,
1331 set_strategy : ParameterSetStrategy::ControlServer,
1332 rb_channel_mask : default_thresholds,
1333 }
1334 }
1335
1336 #[cfg(feature="database")]
1337 pub fn emit_ch_mask_packets(&self, rbs : &HashMap<u8,RAT>) -> Vec<TofPacket> {
1338 let mut packets = Vec::<TofPacket>::new();
1339 for k in rbs.keys() {
1340 let rb = &rbs[&k];
1341 let rb_key = format!("RB{:2}", rb);
1342 let mut cmd = TofCommandV2::new();
1343 cmd.command_code = TofCommandCode::SetRBChannelMask;
1344 let mut payload = RBChannelMaskConfig::new();
1345 payload.rb_id = rb.rb2_id as u8;
1346 if *k as usize >= self.rb_channel_mask.len() {
1347 error!("RB ID {k} larger than 46!");
1348 continue;
1349 }
1350 payload.channels = self.rb_channel_mask[&rb_key];
1351 cmd.payload = payload.to_bytestream();
1352 let tp = cmd.pack();
1353 packets.push(tp);
1354 }
1355 packets
1356 }
1357}
1358impl fmt::Display for ChannelMaskSettings {
1359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1360 let disp : String;
1361 match toml::to_string(self) {
1362 Err(err) => {
1363 error!("Deserialization error! {err}");
1364 disp = String::from("-- DESERIALIZATION ERROR! --");
1365 }
1366 Ok(_disp) => {
1367 disp = _disp;
1368 }
1369 }
1370 write!(f, "<RBChannelMaskConfig :\n{}>", disp)
1371 }
1372}
1373
1374impl Default for ChannelMaskSettings {
1375 fn default() -> Self {
1376 Self::new()
1377 }
1378}
1379
1380#[cfg(feature="random")]
1381#[test]
1382fn mtb_config() {
1383
1384 use tof_dataclasses::FromRandom;
1385 for _ in 0..100 {
1386 let cfg = TriggerConfig::from_random();
1387 let mut settings = MTBSettings::new();
1388 settings.from_triggerconfig(&cfg);
1389 let test = settings.emit_triggerconfig();
1390 if cfg.gaps_trigger_use_beta.is_some() {
1391 assert_eq!(cfg.gaps_trigger_use_beta, test.gaps_trigger_use_beta);
1392 }
1393 if cfg.prescale.is_some() {
1394 assert_eq!(cfg.prescale, test.prescale);
1395 }
1396 if cfg.trigger_type.is_some() {
1397 assert_eq!(cfg.trigger_type, test.trigger_type);
1398 }
1399 if cfg.use_combo_trigger.is_some() {
1400 assert_eq!(cfg.use_combo_trigger, test.use_combo_trigger);
1401 }
1402 if cfg.combo_trigger_type.is_some() {
1403 assert_eq!(cfg.combo_trigger_type, test.combo_trigger_type);
1404 }
1405 if cfg.combo_trigger_prescale.is_some() {
1406 assert_eq!(cfg.combo_trigger_prescale, test.combo_trigger_prescale);
1407 }
1408 if cfg.trace_suppression.is_some() {
1409 assert_eq!(cfg.trace_suppression, test.trace_suppression);
1410 }
1411 if cfg.mtb_moni_interval.is_some() {
1412 assert_eq!(cfg.mtb_moni_interval, test.mtb_moni_interval);
1413 }
1414 if cfg.tiu_ignore_busy.is_some() {
1415 assert_eq!(cfg.tiu_ignore_busy, test.tiu_ignore_busy);
1416 }
1417 if cfg.hb_send_interval.is_some() {
1418 assert_eq!(cfg.hb_send_interval, test.hb_send_interval);
1419 }
1420 }
1421}
1422
1423#[test]
1424fn write_config_file() {
1425 let settings = LiftofSettings::new();
1426 settings.to_toml(String::from("liftof-config-test.toml"));
1428}
1429
1430#[test]
1431fn read_config_file() {
1432 let _settings = LiftofSettings::from_toml("liftof-config-test.toml");
1433}
1434
1435