1pub mod control;
20pub mod registers;
21
22use std::sync::{
24 Arc,
25 Mutex,
26};
27
28use std::time::{
29 Duration,
30 Instant
31};
32
33use std::thread;
34use crossbeam_channel::Sender;
35use serde_json::json;
36
37use crate::prelude::*;
41use crate::io::ipbus::IPBus;
42
43use control::*;
44use registers::*;
45
46#[cfg(feature="pybindings")]
47use comfy_table::modifiers::UTF8_ROUND_CORNERS;
48#[cfg(feature="pybindings")]
49use comfy_table::presets::UTF8_FULL;
50#[cfg(feature="pybindings")]
51use comfy_table::*;
52
53fn remove_from_word(s: String, word: &str) -> String {
55 if let Some(index) = s.find(word) {
56 s[..index].to_string()
58 } else {
59 s
61 }
62}
63
64fn read_until_footer(bus : &mut IPBus)
68 -> Result<Vec<u32>, MasterTriggerError> {
69 let mut data = Vec::<u32>::new();
70 loop {
71 let val = bus.read(0x11)?;
72 if val != 0xAAAAAAAA {
73 data.push(val);
74 }
75 if (val == 0x55555555) || (val == 0xAAAAAAAA) {
76 break;
77 }
78 }
79 Ok(data)
80}
81
82
83pub fn get_event(bus : &mut IPBus)
96 -> Option<Result<TofEvent, MasterTriggerError>> {
97 let mut mte = TofEvent::new();
99 let n_daq_words_fixed = 9u32;
100 let mut data : Vec<u32>;
101 loop {
102 if EVQ_SIZE.get(bus).ok()? < 12 {
113 return None;
114 } else {
115 break;
116 }
117 }
118 match bus.read_multiple(0x11, n_daq_words_fixed as usize, false) {
120 Ok(_data) => {
121 data = _data;
122 }
123 Err(err) => {
124 return Some(Err(err.into()));
125 }
126 }
127 if data.len() < 9 {
128 error!("Got MTB data, but the package ends before we get LTB information!");
131 warn!("Resetting master trigger DAQ");
132 match reset_daq(bus) {Err(err) => error!("Can not reset DAQ, error {err}"),
134 Ok(_) => ()
135 }
136 return Some(Err(MasterTriggerError::DataTooShort));
137 }
138 let n_ltb = data[8].count_ones();
139 let odd = n_ltb % 2 != 0;
142 let n_daq_words_flex : usize;
143 let n_hit_words : usize;
144 if odd {
146 n_hit_words = (n_ltb as usize + 1)/2;
147 } else {
148 n_hit_words = n_ltb as usize/2;
149 }
150 n_daq_words_flex = n_hit_words + 2; let mut data_flex : Vec<u32>;
153 match bus.read_multiple(0x11, n_daq_words_flex, false) {
154 Ok(_data) => {
155 data_flex = _data;
156 }
157 Err(err) => {
158 return Some(Err(err.into()));
159 }
160 }
161 data.append(&mut data_flex);
162 if data[0] != 0xAAAAAAAA {
163 error!("Got MTB data, but the header is incorrect {:x}", data[0]);
164 return Some(Err(MasterTriggerError::PackageHeaderIncorrect));
165 }
166
167 let n_daq_words = n_daq_words_fixed as usize + n_daq_words_flex;
168 let foot_pos = n_daq_words_fixed as usize + n_daq_words_flex - 1;
169 if data.len() != foot_pos + 1{
170 error!("Somehow the MTB DATA are misaligned! {}, {}", data.len(), foot_pos);
171 return Some(Err(MasterTriggerError::DataTooShort));
172 }
173 if data[foot_pos] != 0x55555555 {
174 error!("Got MTB data, but the footer is incorrect {:x}", data[foot_pos]);
175 if data[foot_pos] == 0xAAAAAAAA {
176 error!("Found next header, the package is TOO LONG! Attempt to fix for this event, but the next is LOST!");
177 info!("If we want to fix this, this whole mechanism needs a refactor and needs to fetch more thatn a single event at a time!");
178 read_until_footer(bus).ok()?;
180 data.pop();
182 } else {
183 let mut rest = read_until_footer(bus).ok()?;
185 data.append(&mut rest);
186 if data.len() != n_daq_words as usize + 1 {
187 error!("We tried to recover the event, however, that failed! Expected size of the packet {}, actual size {}", n_daq_words, data.len());
188 println!("-------------- DEBUG -------------------");
191 println!("N LTBs {} ({})", data[8].count_ones(), data[8]);
192 for k in data {
193 println!("-- {:x} ({})", k,k);
194 }
195 println!("--------------------");
196 return Some(Err(MasterTriggerError::PackageFooterIncorrect));
197 } else {
198 info!("Event recoveered!");
199 }
200 }
201 }
202 mte.event_id = data[1];
205 mte.mt_timestamp = data[2];
206 mte.mt_tiu_timestamp = data[3];
207 mte.mt_tiu_gps32 = data[4];
208 mte.mt_tiu_gps16 = (data[5] & 0x0000ffff) as u16;
209 mte.mt_trigger_sources = ((data[5] & 0xffff0000) >> 16) as u16;
210 let rbmask = (data[7] as u64) << 32 | data[6] as u64;
212 mte.mtb_link_mask = rbmask;
213 mte.dsi_j_mask = data[8];
214 for k in 9..9 + n_hit_words {
215 let ltb_hits = data[k as usize];
216 let first = (ltb_hits & 0x0000ffff) as u16;
218 let second = ((ltb_hits & 0xffff0000) >> 16) as u16;
219 mte.channel_mask.push(first);
220 if k == ( 9 + n_hit_words) {
223 if !odd {
224 mte.channel_mask.push(second);
225 }
226 } else {
227 mte.channel_mask.push(second);
228 }
229 }
230 Some(Ok(mte))
233}
234
235pub fn get_mtbmonidata(bus : &mut IPBus)
239 -> Result<MtbMoniData, MasterTriggerError> {
240 let mut moni = MtbMoniData::new();
241 let data = bus.read_multiple(0x120, 4, true)?;
242 if data.len() < 4 {
243 return Err(MasterTriggerError::BrokenPackage);
244 }
245 let tiu_busy_len = TIU_BUSY_LENGTH.get(bus)?;
246 let tiu_aux_link = (TIU_USE_AUX_LINK.get(bus)? != 0) as u8;
247 let tiu_emu_mode = (TIU_EMULATION_MODE.get(bus)? != 0) as u8;
248 let aggr_tiu = TIU_LT_AND_RB_MULT.get(bus)?;
249 let tiu_link_bad = (aggr_tiu & 0x1) as u8;
250 let tiu_busy_stuck = ((aggr_tiu & 0x2) >> 1) as u8;
251 let tiu_busy_ign = ((aggr_tiu & 0x4) >> 2) as u8;
252 let mut tiu_status = 0u8;
253 tiu_status = tiu_status | (tiu_emu_mode);
254 tiu_status = tiu_status | (tiu_aux_link << 1);
255 tiu_status = tiu_status | ((tiu_link_bad as u8) << 2);
256 tiu_status = tiu_status | (tiu_busy_stuck << 3);
257 tiu_status = tiu_status | (tiu_busy_ign << 4);
258 let daq_queue_len = EVQ_NUM_EVENTS.get(bus)? as u16;
259 moni.tiu_status = tiu_status;
260 moni.tiu_busy_len = tiu_busy_len;
261 moni.daq_queue_len = daq_queue_len;
262 let first_word = 0x00000fff;
264 let second_word = 0x0fff0000;
265 moni.temp = ( data[2] & first_word ) as u16;
266 moni.vccint = ((data[2] & second_word ) >> 16) as u16;
267 moni.vccaux = ( data[3] & first_word ) as u16;
268 moni.vccbram = ((data[3] & second_word ) >> 16) as u16;
269
270 let rate = bus.read_multiple(0x17, 2, true)?;
271 let mask = 0x0000ffff;
275 moni.rate = (rate[0] & mask) as u16;
276 moni.lost_rate = (rate[1] & mask) as u16;
277 let rb_lost_rate = RB_LOST_TRIGGER_RATE.get(bus)?;
278 if rb_lost_rate > 255 {
279 moni.rb_lost_rate = 255;
280 } else {
281 moni.rb_lost_rate = rb_lost_rate as u8;
282 }
283 Ok(moni)
284}
285
286pub fn configure_mtb(bus : &mut IPBus,
303 settings : &MTBSettings) -> Result<(), MasterTriggerError> {
304 let trace_suppression = settings.trace_suppression;
305 match set_trace_suppression(bus, trace_suppression) {
306 Err(err) => error!("Unable to set trace suppression mode! {err}"),
307 Ok(_) => {
308 if trace_suppression {
309 println!("==> Setting MTB to trace suppression mode!");
310 } else {
311 println!("==> Setting MTB to ALL_RB_READOUT mode!");
312 warn!("Reading out all events from all RBs! Data might be very large!");
313 }
314 }
315 }
316
317 let tiu_ignore_busy = settings.tiu_ignore_busy;
318 match TIU_BUSY_IGNORE.set(bus, tiu_ignore_busy as u32) {
319 Err(err) => error!("Unable to change tiu busy ignore settint! {err}"),
320 Ok(_) => {
321 if tiu_ignore_busy {
322 warn!("Ignoring TIU since tiu_busy_ignore is set in the config file!");
323 println!("==> Ignoring TIU since tiu_busy_ignore is set in the config file!");
324 }
325 }
326 }
327
328 let use_fixed_deadtime = settings.use_fixed_deadtime.unwrap_or(false);
331 if use_fixed_deadtime {
332 match MIN_DEADTIME_MODE.set(bus, true as u32) {
333 Err(err) => {
334 error!("Unable to set MTB in fixed deadtime mode {err}!");
335 }
336 Ok(_) => {
337 warn!("Ignoring the busy part of the TIU signal from the TIU due to min deadtime setting!");
338 println!("==> MTB in 'Min/fixed deadtime mode'. This will ignore the BUSY part of the TIU signal");
339 }
340 }
341 } else {
342 match MIN_DEADTIME_MODE.set(bus, false as u32) {
343 Err(err) => {
344 error!("Unable to set MTB in fixed deadtime mode {err}!");
345 }
346 Ok(_) => {
347 warn!("Ignoring the busy part of the TIU signal from the TIU due to min deadtime setting!");
348 println!("==> MTB in 'Min/fixed deadtime mode'. This will ignore the BUSY part of the TIU signal");
349 }
350 }
351 }
352 info!("Settting rb integration window!");
353 let int_wind = settings.rb_int_window;
354 match set_rb_int_window(bus, int_wind) {
355 Err(err) => error!("Unable to set rb integration window! {err}"),
356 Ok(_) => {
357 info!("rb integration window set to {}", int_wind);
358 }
359 }
360
361 match unset_all_triggers(bus) {
362 Err(err) => error!("Unable to undo previous trigger settings! {err}"),
363 Ok(_) => ()
364 }
365 match settings.trigger_type {
366 TriggerType::Poisson => {
367 match set_poisson_trigger(bus,settings.poisson_trigger_rate) {
368 Err(err) => error!("Unable to set the POISSON trigger! {err}"),
369 Ok(_) => ()
370 }
371 }
372 TriggerType::Any => {
373 match set_any_trigger(bus,settings.trigger_prescale) {
374 Err(err) => error!("Unable to set the ANY trigger! {err}"),
375 Ok(_) => ()
376 }
377 }
378 TriggerType::Track => {
379 match set_track_trigger(bus, settings.trigger_prescale) {
380 Err(err) => error!("Unable to set the TRACK trigger! {err}"),
381 Ok(_) => ()
382 }
383 }
384 TriggerType::TrackCentral => {
385 match set_central_track_trigger(bus, settings.trigger_prescale) {
386 Err(err) => error!("Unable to set the CENTRAL TRACK trigger! {err}"),
387 Ok(_) => ()
388 }
389 }
390 TriggerType::TrackUmbCentral => {
391 match set_track_umb_central_trigger(bus, settings.trigger_prescale) {
392 Err(err) => error!("Unable to set the TRACK UMB CENTRAL trigger! {err}"),
393 Ok(_) => ()
394 }
395 }
396 TriggerType::Gaps => {
397 match set_gaps_trigger(bus, settings.gaps_trigger_use_beta) {
398 Err(err) => error!("Unable to set the GAPS trigger! {err}"),
399 Ok(_) => ()
400 }
401 }
402 TriggerType::Gaps633 => {
403 match set_gaps633_trigger(bus, settings.gaps_trigger_use_beta) {
404 Err(err) => error!("Unable to set the GAPS trigger! {err}"),
405 Ok(_) => ()
406 }
407 }
408 TriggerType::Gaps422 => {
409 match set_gaps422_trigger(bus, settings.gaps_trigger_use_beta) {
410 Err(err) => error!("Unable to set the GAPS trigger! {err}"),
411 Ok(_) => ()
412 }
413 }
414 TriggerType::Gaps211 => {
415 match set_gaps211_trigger(bus, settings.gaps_trigger_use_beta) {
416 Err(err) => error!("Unable to set the GAPS trigger! {err}"),
417 Ok(_) => ()
418 }
419 }
420 TriggerType::Gaps1044 => {
421 match set_gaps1044_trigger(bus, settings.gaps_trigger_use_beta) {
422 Err(err) => error!("Unable to set the GAPS trigger! {err}"),
423 Ok(_) => ()
424 }
425 }
426 TriggerType::UmbCube => {
427 match set_umbcube_trigger(bus) {
428 Err(err) => error!("Unable to set UmbCube trigger! {err}"),
429 Ok(_) => ()
430 }
431 }
432 TriggerType::UmbCubeZ => {
433 match set_umbcubez_trigger(bus) {
434 Err(err) => error!("Unable to set UmbCubeZ trigger! {err}"),
435 Ok(_) => ()
436 }
437 }
438 TriggerType::UmbCorCube => {
439 match set_umbcorcube_trigger(bus) {
440 Err(err) => error!("Unable to set UmbCorCube trigger! {err}"),
441 Ok(_) => ()
442 }
443 }
444 TriggerType::CorCubeSide => {
445 match set_corcubeside_trigger(bus) {
446 Err(err) => error!("Unable to set CorCubeSide trigger! {err}"),
447 Ok(_) => ()
448 }
449 }
450 TriggerType::Umb3Cube => {
451 match set_umb3cube_trigger(bus) {
452 Err(err) => error!("Unable to set Umb3Cube trigger! {err}"),
453 Ok(_) => ()
454 }
455 }
456 TriggerType::Unknown => {
457 println!("== ==> Not setting any trigger condition. You can set it through pico_hal.py");
458 warn!("Trigger condition undefined! Not setting anything!");
459 error!("Trigger conditions unknown!");
460 }
461 _ => {
462 error!("Trigger type {} not covered!", settings.trigger_type);
463 println!("= => Not setting any trigger condition. You can set it through pico_hal.py");
464 warn!("Trigger condition undefined! Not setting anything!");
465 error!("Trigger conditions unknown!");
466 }
467 }
468
469 if settings.use_combo_trigger {
473 let global_prescale = settings.global_trigger_prescale;
474 let prescale_val = (u32::MAX as f32 * global_prescale as f32).floor() as u32;
475 println!("=> Setting an additonal trigger - using combo mode. Using prescale of {}", prescale_val as f32 / u32::MAX as f32);
476 match settings.global_trigger_type {
478 TriggerType::Any => {
479 match ANY_TRIG_PRESCALE.set(bus, prescale_val) {
480 Ok(_) => (),
481 Err(err) => error!("Settting the prescale {} for the any trigger failed! {err}", prescale_val)
482 }
483 }
484 TriggerType::Track => {
485 match TRACK_TRIG_PRESCALE.set(bus, prescale_val) {
486 Ok(_) => (),
487 Err(err) => error!("Settting the prescale {} for the any trigger failed! {err}", prescale_val)
488 }
489 }
490 TriggerType::TrackCentral => {
491 match TRACK_CENTRAL_PRESCALE.set(bus, prescale_val) {
492 Ok(_) => (),
493 Err(err) => error!("Settting the prescale {} for the track central trigger failed! {err}", prescale_val)
494 }
495 }
496 TriggerType::TrackUmbCentral => {
497 match TRACK_UMB_CENTRAL_PRESCALE.set(bus, prescale_val) {
498 Ok(_) => (),
499 Err(err) => error!("Settting the prescale {} for the track umb central trigger failed! {err}", prescale_val)
500 }
501 }
502 _ => {
503 error!("Unable to set {} as a global trigger type!", settings.global_trigger_type);
504 }
505 }
506 }
507
508 Ok(())
513}
514
515pub fn master_trigger(mt_address : &str,
536 mt_sender : &Sender<TofEvent>,
537 moni_sender : &Sender<TofPacket>,
538 thread_control : Arc<Mutex<ThreadControl>>,
539 verbose : bool) {
540 let mut bus : IPBus;
541 let mut heartbeat = MasterTriggerHB::new();
542 let mut mtb_timeout = Instant::now();
543 let mut moni_interval = Instant::now();
544 let mut tc_timer = Instant::now();
545
546 let mut settings : MTBSettings;
547 let mut cali_active : bool;
548 let mut holdoff : bool;
549 let mut veri_active : bool;
550 loop {
551 match thread_control.lock() {
552 Ok(tc) => {
553 settings = tc.liftof_settings.mtb_settings.clone();
554 cali_active = tc.calibration_active;
555 holdoff = tc.holdoff_mtb_thread;
556 veri_active = tc.verification_active;
557 }
558 Err(err) => {
559 error!("Can't acquire lock for ThreadControl! Unable to set calibration mode! {err}");
560 return;
561 }
562 }
563
564 if holdoff || cali_active {
565 thread::sleep(Duration::from_secs(5));
566 } else {
567 if !holdoff {
568 println!("=> Docking clamp released!");
569 }
570 break;
571 }
572 if moni_interval.elapsed().as_secs() > settings.mtb_moni_interval {
573 match IPBus::new(mt_address) {
574 Err(err) => {
575 debug!("Can't connect to MTB, will try again in 10 ms! {err}");
576 continue;
577 }
578 Ok(mut moni_bus) => {
579 match get_mtbmonidata(&mut moni_bus) {
580 Err(err) => {
581 error!("Can not get MtbMoniData! {err}");
582 },
583 Ok(moni) => {
584 let tp = moni.pack();
585 match moni_sender.send(tp) {
586 Err(err) => {
587 error!("Can not send MtbMoniData over channel! {err}");
588 },
589 Ok(_) => ()
590 }
591 }
592 }
593 }
594 }
595 moni_interval = Instant::now();
596 }
597 }
598 let mtb_timeout_sec = settings.mtb_timeout_sec;
599 let mtb_moni_interval = settings.mtb_moni_interval;
600
601 let mut last_event_id = 0u32;
603 let mut first = true;
604 let mut slack_cadence = 5; let mut evq_num_events = 0u64;
607 let mut n_iter_loop = 0u64;
608 let mut hb_timer = Instant::now();
609 let hb_interval = Duration::from_secs(settings.hb_send_interval as u64);
610 let mut n_non_recoverable = 0usize; let connection_timeout = Instant::now();
614 loop {
615 match IPBus::new(mt_address) {
616 Err(err) => {
617 debug!("Can't connect to MTB, will try again in 10 ms! {err}");
618 thread::sleep(Duration::from_millis(10));
619 }
620 Ok(_bus) => {
621 bus = _bus;
622 break
623 }
624 }
625 if connection_timeout.elapsed().as_secs() > 10 {
626 error!("Unable to connect to MTB after 10 seconds!");
627 match thread_control.lock() {
628 Ok(mut tc) => {
629 tc.thread_master_trg_active = false;
630 }
631 Err(err) => {
632 error!("Can't acquire lock for ThreadControl! Unable to set calibration mode! {err}");
633 },
634 }
635 return;
636 }
637 }
638
639 debug!("Resetting master trigger DAQ");
640 bus.pid = 0;
642 match bus.realign_packet_id() {
643 Err(err) => error!("Can not realign packet ID! {err}"),
644 Ok(_) => ()
645 }
646
647 match reset_daq(&mut bus) {Err(err) => error!("Can not reset DAQ! {err}"),
649 Ok(_) => ()
650 }
651
652 match RESYNC.pulse_it(&mut bus) {
653 Err(err) => error!("Unable to resycn MTB and RB clocks! {err}"),
654 Ok(_) => println!("=> RB and MTB clocks synchronized!")
655 }
656
657 match EVENT_CNT_RESET.set(&mut bus, 1) {
658 Err(err) => error!("Unable to reset event counter! {err}"),
659 Ok(_) => println!("=> Event counter reset!")
660 }
661
662 match configure_mtb(&mut bus, &settings) {
663 Err(err) => error!("Configuring the MTB failed! {err}"),
664 Ok(()) => ()
665 }
666
667 let mut preload_cache = 1000; loop {
669 if tc_timer.elapsed().as_secs_f32() > 2.5 {
672 match thread_control.try_lock() {
673 Ok(mut tc) => {
674 if tc.stop_flag || tc.sigint_recvd {
675 tc.end_all_rb_threads = true;
676 break;
677 }
678
679 },
680 Err(err) => {
681 error!("Can't acquire lock for ThreadControl! Unable to set calibration mode! {err}");
682 },
683 }
684 tc_timer = Instant::now();
685 }
686 if mtb_timeout.elapsed().as_secs() > mtb_timeout_sec {
689 if mtb_timeout.elapsed().as_secs() > mtb_timeout_sec {
690 info!("reconnection timer elapsed");
691 } else {
692 info!("reconnection requested");
693 }
694 match IPBus::new(mt_address) {
695 Err(err) => {
696 error!("Can't connect to MTB! {err}");
697 continue; }
699 Ok(_bus) => {
700 bus = _bus;
701 debug!("Resetting master trigger DAQ");
703 bus.pid = 0;
705 match bus.realign_packet_id() {
706 Err(err) => error!("Can not realign packet ID! {err}"),
707 Ok(_) => ()
708 }
709 match reset_daq(&mut bus) {Err(err) => error!("Can not reset DAQ! {err}"),
711 Ok(_) => ()
712 }
713 }
714 }
715 mtb_timeout = Instant::now();
716 }
717 if moni_interval.elapsed().as_secs() > mtb_moni_interval || first {
718 if first {
719 first = false;
720 }
721 match get_mtbmonidata(&mut bus) {
722 Err(err) => {
723 error!("Can not get MtbMoniData! {err}");
724 },
725 Ok(_moni) => {
726 if settings.tofbot_webhook != String::from("") {
727 let url = &settings.tofbot_webhook;
728 let message = format!("\u{1F916}\u{1F680}\u{1F388} [LIFTOF (Bot)]\n rate - {}[Hz]\n {}", _moni.rate, settings);
729 let clean_message = remove_from_word(message, "tofbot_webhook");
730 let data = json!({
731 "text" : clean_message
732 });
733 match serde_json::to_string(&data) {
734 Ok(data_string) => {
735 if slack_cadence == 0 {
736 match ureq::post(url)
737 .set("Content-Type", "application/json")
738 .send_string(&data_string) {
739 Err(err) => {
740 error!("Unable to send {} to TofBot! {err}", data_string);
741 }
742 Ok(response) => {
743 match response.into_string() {
744 Err(err) => {
745 error!("Not able to read response! {err}");
746 }
747 Ok(body) => {
748 if verbose {
749 println!("[master_trigger] - TofBot responded with {}", body);
750 }
751 }
752 }
753 }
754 }
755 } else {
756 slack_cadence -= 1;
757 }
758 if slack_cadence == 0 {
759 slack_cadence = 5;
760 }
761 }
762 Err(err) => {
763 error!("Can not convert .json to string! {err}");
764 }
765 }
766 }
767 let tp = _moni.pack();
769 match moni_sender.send(tp) {
770 Err(err) => {
771 error!("Can not send MtbMoniData over channel! {err}");
772 },
773 Ok(_) => ()
774 }
775 }
776 }
777 moni_interval = Instant::now();
778 }
779
780 match get_event(&mut bus){ None => {
782 }
783 Some(Err(err)) => {
784 match err {
785 MasterTriggerError::PackageFooterIncorrect
786 | MasterTriggerError::PackageHeaderIncorrect
787 | MasterTriggerError::DataTooShort
788 | MasterTriggerError::BrokenPackage => {
789 if n_non_recoverable == 100 {
792 error!("We have seen {} non-recoverable events, let's reset the DAQ!", n_non_recoverable);
793 match reset_daq(&mut bus) {Err(err) => error!("Can not reset DAQ, error {err}"),
795 Ok(_) => ()
796 }
797 n_non_recoverable = 0;
798 }
799 n_non_recoverable += 1;
800 }
801 _ => ()
802 }
803 },
804 Some(Ok(mut _ev)) => {
805 if _ev.event_id == last_event_id {
806 error!("We got a duplicate event from the MTB!");
807 continue;
808 }
809 if _ev.event_id > last_event_id + 1 {
810 if last_event_id != 0 {
811 error!("We skipped {} events!", _ev.event_id - last_event_id);
812 heartbeat.n_ev_missed += (_ev.event_id - last_event_id) as u64;
813 }
814 }
815 last_event_id = _ev.event_id;
816 heartbeat.n_events += 1;
817 let mt_timestamp = _ev.get_mt_timestamp_abs();
820 _ev.timestamp32 = (mt_timestamp & 0x00000000ffffffff ) as u32;
821 _ev.timestamp16 = ((mt_timestamp & 0x0000ffff00000000 ) >> 32) as u16;
822 _ev.trigger_sources = _ev.mt_trigger_sources; _ev.n_trigger_paddles = _ev.get_trigger_hits().len() as u8;
824 let triggers = TriggerType::transcode_trigger_sources(_ev.mt_trigger_sources);
825 if triggers.len() == 2 {
826 heartbeat.trigger_type = triggers[0];
827 heartbeat.combo_trig_type = triggers[1];
828 }
829 if triggers.len() == 1 {
830 heartbeat.trigger_type = triggers[0];
831 }
832 if !veri_active {
833 match mt_sender.send(_ev) {
834 Err(err) => {
835 error!("Can not send TofEvent over channel! {err}");
836 heartbeat.n_ev_unsent += 1;
837 },
838 Ok(_) => ()
839 }
840 }
841 }
842 }
843
844 if preload_cache > 0 {
845 preload_cache -= 1;
846 continue;
847 }
848 if hb_timer.elapsed() >= hb_interval {
849 match EVQ_NUM_EVENTS.get(&mut bus) {
850 Err(err) => {
851 error!("Unable to query {}! {err}", EVQ_NUM_EVENTS);
852 }
853 Ok(num_ev) => {
854 evq_num_events += num_ev as u64;
855 heartbeat.evq_num_events_last = num_ev as u64;
856 n_iter_loop += 1;
857 heartbeat.evq_num_events_avg = (evq_num_events as u64)/(n_iter_loop as u64);
858 }
859 }
860 heartbeat.total_elapsed += hb_timer.elapsed().as_secs() as u64;
861 match TRIGGER_RATE.get(&mut bus) {
862 Ok(trate) => {
863 heartbeat.trate = trate as u64;
864 }
865 Err(err) => {
866 error!("Unable to query {}! {err}", TRIGGER_RATE);
867 }
868 }
869 match LOST_TRIGGER_RATE.get(&mut bus) {
870 Ok(lost_trate) => {
871 heartbeat.lost_trate = lost_trate as u64;
872 }
873 Err(err) => {
874 error!("Unable to query {}! {err}", LOST_TRIGGER_RATE);
875 }
876 }
877
878 match RB_LOST_TRIGGER_RATE.get(&mut bus) {
879 Err(err) => {
880 error!("Unable to query {}! {err}", RB_LOST_TRIGGER_RATE);
881 }
882 Ok(rb_lost_rate) => {
883 heartbeat.rb_lost_rate = rb_lost_rate as u64;
884 }
885 }
886
887 match CLOCK_RATE.get(&mut bus) {
888 Err(err) => {
889 error!("Unable to query {}! {err}", CLOCK_RATE);
890 }
891 Ok(clock_rate) => {
892 heartbeat.clock_rate = clock_rate as u64;
893 }
894 }
895 match MIN_DEADTIME_MODE.get(&mut bus) {
896 Err(err) => {
897 error!("Unable to query {}! {err}", MIN_DEADTIME_MODE);
898 }
899 Ok(tiu_ignore_deadtime) => {
900 heartbeat.tiu_ignore_deadtime = tiu_ignore_deadtime != 0;
901 }
902 }
903
904 match TIU_TIMEOUT_CONST.get(&mut bus) {
905 Err(err) => {
906 error!("Unable to query {}! {err}", TIU_TIMEOUT_CONST);
907 }
908 Ok(tiu_timeout_cnt) => {
909 heartbeat.tiu_timeout_cnt = tiu_timeout_cnt as u64;
910 }
911 }
912
913 match TIU_BUSY_RATE.get(&mut bus) {
914 Err(err) => {
915 error!("Unable to query {} {err}!", TIU_BUSY_RATE);
916 }
917 Ok(tiu_busy_rate) => {
918 heartbeat.tiu_busy_rate = tiu_busy_rate as u16;
919 }
920 }
921
922 match TRG_LOST_TRIGGER_RATE.get(&mut bus) {
923 Err(err) => {
924 error!("Unable to query {} {err}!", TRG_LOST_TRIGGER_RATE);
925 }
926 Ok(trg_lost_trg_rate) => {
927 heartbeat.trg_lost_trg_rate = trg_lost_trg_rate as u16;
928 }
929 }
930
931 match GAPS_TRIGGER_BLOCKED_RATE.get(&mut bus) {
932 Err(err) => {
933 error!("Unable to query {} {err}!", GAPS_TRIGGER_BLOCKED_RATE);
934 }
935 Ok(gaps_blocked_rate) => {
936 heartbeat.gaps_blocked_rate = gaps_blocked_rate as u16;
937 }
938 }
939 match TRACK_TRIGGER_BLOCKED_RATE.get(&mut bus) {
940 Err(err) => {
941 error!("Unable to query {} {err}!", TRACK_TRIGGER_BLOCKED_RATE);
942 }
943 Ok(track_blocked_rate) => {
944 heartbeat.track_blocked_rate = track_blocked_rate as u16;
945 }
946 }
947 match ANY_TRIGGER_BLOCKED_RATE.get(&mut bus) {
948 Err(err) => {
949 error!("Unable to query {} {err}!", ANY_TRIGGER_BLOCKED_RATE);
950 }
951 Ok(any_blocked_rate) => {
952 heartbeat.any_blocked_rate = any_blocked_rate as u16;
953 }
954 }
955
956 match TRACK_CENTRAL_BLOCKED_RATE.get(&mut bus) {
957 Err(err) => {
958 error!("Unable to query {} {err}!", TRACK_CENTRAL_BLOCKED_RATE);
959 }
960 Ok(trkctrl_blocked_rate) => {
961 heartbeat.trkctrl_blocked_rate = trkctrl_blocked_rate as u16;
962 }
963 }
964
965 match TRACK_UMB_CENTRAL_BLOCKED_RATE.get(&mut bus) {
966 Err(err) => {
967 error!("Unable to query {} {err}!", TRACK_UMB_CENTRAL_BLOCKED_RATE);
968 }
969 Ok(trkumbctrl_blocked) => {
970 heartbeat.trkumbctrl_blocked = trkumbctrl_blocked as u16;
971 }
972 }
973
974 match PRESCALE_BYPASS.get(&mut bus) {
975 Err(err) => {
976 error!("Unable to query {} {err}!", PRESCALE_BYPASS);
977 }
978 Ok(prescale_bypass) => {
979 heartbeat.prescale_bypass = prescale_bypass != 0;
980 }
981 }
982
983 match TRACK_TRIG_PRESCALE.get(&mut bus) {
984 Ok(ps) => {
985 heartbeat.prescale_track = (ps as f32) / (u32::MAX as f32) ;
986 }
987 Err(err) => {
988 error!("Unable to query {}! {err}", TRACK_TRIG_PRESCALE);
989 }
990 }
991 match GAPS_TRIG_PRESCALE.get(&mut bus) {
992 Ok(ps) => {
993 heartbeat.prescale_gaps = (ps as f32) / (u32::MAX as f32) ;
994 }
995 Err(err) => {
996 error!("Unable to query {}! {err}", GAPS_TRIG_PRESCALE);
997 }
998 }
999 heartbeat.version = ProtocolVersion::V1;
1000 if verbose {
1001 println!("{}", heartbeat);
1002 }
1003
1004 let pack = heartbeat.pack();
1005 match moni_sender.send(pack) {
1006 Err(err) => {
1007 error!("Can not send MTB Heartbeat over channel! {err}");
1008 },
1009 Ok(_) => ()
1010 }
1011 hb_timer = Instant::now();
1012 }
1013 }
1014}
1015
1016#[cfg(feature = "pybindings")]
1017#[pyfunction]
1018#[pyo3(name="prescale_to_u32")]
1019pub fn wrap_prescale_to_u32(prescale : f32) -> u32 {
1023 let mut _prescale = prescale;
1024 prescale_to_u32(prescale)
1025}
1026
1027#[cfg(feature="pybindings")]
1031#[pyclass]
1032#[pyo3(name = "MasterTrigger")]
1033pub struct PyMasterTrigger {
1034 ipbus : IPBus,
1035}
1036
1037#[cfg(feature="pybindings")]
1038#[pymethods]
1039impl PyMasterTrigger {
1040 #[new]
1041 fn new(target_address : &str) -> Self {
1042 let ipbus = IPBus::new(target_address).expect("Unable to connect to {target_address}");
1043 Self {
1044 ipbus : ipbus,
1045 }
1046 }
1047
1048 fn reset_daq(&mut self) -> PyResult<()>{
1049 match self.ipbus.write(0x10,1) {
1050 Ok(result) => {
1051 return Ok(result);
1052 }
1053 Err(err) => {
1054 return Err(PyValueError::new_err(err.to_string()));
1055 }
1056 }
1057 }
1058
1059 fn get_expected_pid(&mut self) -> PyResult<u16> {
1060 match self.ipbus.get_target_next_expected_packet_id(){
1061 Ok(result) => {
1062 return Ok(result);
1063 }
1064 Err(err) => {
1065 return Err(PyValueError::new_err(err.to_string()));
1066 }
1067 }
1068 }
1069
1070 fn realign_packet_id(&mut self) -> PyResult<()> {
1071 match self.ipbus.realign_packet_id() {
1072 Ok(_) => {
1073 return Ok(());
1074 }
1075 Err(err) => {
1076 return Err(PyValueError::new_err(err.to_string()));
1077 }
1078 }
1079 }
1080
1081 fn set_packet_id(&mut self, pid : u16) {
1082 self.ipbus.pid = pid;
1083 }
1084
1085 fn get_packet_id(&mut self) -> u16 {
1086 self.ipbus.pid
1087 }
1088
1089 #[getter]
1090 fn rate(&mut self) -> PyResult<u32> {
1092 match TRIGGER_RATE.get(&mut self.ipbus) {
1093 Ok(rate) => {
1094 return Ok(rate);
1095 }
1096 Err(err) => {
1097 return Err(PyValueError::new_err(err.to_string()));
1098 }
1099 }
1100 }
1101
1102 #[getter]
1103 fn get_swap_rb_link_ids(&mut self) -> PyResult<bool> {
1104 match SWAP_RB_LINK_IDS.get(&mut self.ipbus) {
1105 Ok(swap) => {
1106 return Ok(swap > 0);
1107 }
1108 Err(err) => {
1109 return Err(PyValueError::new_err(err.to_string()));
1110 }
1111 }
1112 }
1113
1114 #[setter]
1115 fn set_swap_rb_link_ids(&mut self, swap : u32) -> PyResult<()> {
1116 match SWAP_RB_LINK_IDS.set(&mut self.ipbus, swap) {
1117 Ok(_) => {
1118 return Ok(());
1119 }
1120 Err(err) => {
1121 return Err(PyValueError::new_err(err.to_string()));
1122 }
1123 }
1124 }
1125
1126 #[getter]
1127 fn lost_rate(&mut self) -> PyResult<u32> {
1133 match LOST_TRIGGER_RATE.get(&mut self.ipbus) {
1134 Ok(rate) => {
1135 return Ok(rate);
1136 }
1137 Err(err) => {
1138 return Err(PyValueError::new_err(err.to_string()));
1139 }
1140 }
1141 }
1142 #[getter]
1143 fn get_prescale_bypass(&mut self) -> PyResult<u32> {
1144 match PRESCALE_BYPASS.get(&mut self.ipbus) {
1145 Ok(rate) => {
1146 return Ok(rate);
1147 }
1148 Err(err) => {
1149 return Err(PyValueError::new_err(err.to_string()));
1150 }
1151 }
1152 }
1153 #[getter]
1154 fn clock_rate(&mut self) -> PyResult<u32> {
1155 match CLOCK_RATE.get(&mut self.ipbus) {
1156 Ok(rate) => {
1157 return Ok(rate);
1158 }
1159 Err(err) => {
1160 return Err(PyValueError::new_err(err.to_string()));
1161 }
1162 }
1163 }
1164
1165 #[getter]
1166 fn rb_lost_rate(&mut self) -> PyResult<u32> {
1168 match RB_LOST_TRIGGER_RATE.get(&mut self.ipbus) {
1169 Ok(rate) => {
1170 return Ok(rate);
1171 }
1172 Err(err) => {
1173 return Err(PyValueError::new_err(err.to_string()));
1174 }
1175 }
1176 }
1177
1178 #[getter]
1180 fn tiu_lost_rate(&mut self) -> PyResult<u32> {
1181 match TIU_LOST_TRIGGER_RATE.get(&mut self.ipbus) {
1182 Ok(rate) => {
1183 return Ok(rate);
1184 }
1185 Err(err) => {
1186 return Err(PyValueError::new_err(err.to_string()));
1187 }
1188 }
1189 }
1190
1191 #[getter]
1193 fn trg_lost_trg_rate(&mut self) -> PyResult<u32> {
1194 match TRG_LOST_TRIGGER_RATE.get(&mut self.ipbus) {
1195 Ok(rate) => {
1196 return Ok(rate);
1197 }
1198 Err(err) => {
1199 return Err(PyValueError::new_err(err.to_string()));
1200 }
1201 }
1202 }
1203
1204 #[getter]
1206 fn get_tiu_timeout_cnt(&mut self) -> PyResult<u32> {
1207 match TIU_TIMEOUT_CONST.get(&mut self.ipbus) {
1208 Ok(rate) => {
1209 return Ok(rate);
1210 }
1211 Err(err) => {
1212 return Err(PyValueError::new_err(err.to_string()));
1213 }
1214 }
1215 }
1216 #[getter]
1218 fn tiu_busy_rate(&mut self) -> PyResult<u32> {
1219 match TIU_BUSY_RATE.get(&mut self.ipbus) {
1220 Ok(rate) => {
1221 return Ok(rate);
1222 }
1223 Err(err) => {
1224 return Err(PyValueError::new_err(err.to_string()));
1225 }
1226 }
1227 }
1228 fn get_tiu_emulation_mode(&mut self) -> PyResult<u32> {
1231 match TIU_EMULATION_MODE.get(&mut self.ipbus) {
1232 Ok(mode) => {
1233 return Ok(mode);
1234 }
1235 Err(err) => {
1236 return Err(PyValueError::new_err(err.to_string()));
1237 }
1238 }
1239 }
1240 #[getter]
1242 fn get_ignore_tiu_busy(&mut self) -> PyResult<u32> {
1243 match MIN_DEADTIME_MODE.get(&mut self.ipbus) {
1244 Ok(mode) => {
1245 return Ok(mode);
1246 }
1247 Err(err) => {
1248 return Err(PyValueError::new_err(err.to_string()));
1249 }
1250 }
1251 }
1252
1253 #[setter]
1254 fn set_tiu_emulation_mode(&mut self, value : u32) -> PyResult<()> {
1255 match TIU_EMULATION_MODE.set(&mut self.ipbus, value) {
1256 Ok(_) => {
1257 return Ok(());
1258 }
1259 Err(err) => {
1260 return Err(PyValueError::new_err(err.to_string()));
1261 }
1262 }
1263 }
1264
1265 #[setter]
1266 fn set_tiu_timeout_cnt(&mut self, value : u32) -> PyResult<()> {
1267 match TIU_TIMEOUT_CONST.set(&mut self.ipbus, value) {
1268 Ok(_) => {
1269 return Ok(());
1270 }
1271 Err(err) => {
1272 return Err(PyValueError::new_err(err.to_string()));
1273 }
1274 }
1275 }
1276 #[setter]
1277 fn set_ignore_tiu_busy(&mut self, value : u32) -> PyResult<()> {
1278 match MIN_DEADTIME_MODE.set(&mut self.ipbus, value) {
1279 Ok(_) => {
1280 return Ok(());
1281 }
1282 Err(err) => {
1283 return Err(PyValueError::new_err(err.to_string()));
1284 }
1285 }
1286 }
1287
1288 #[setter]
1289 fn set_tiu_emulation_mode_bsy_cnt(&mut self, cycles : u32) -> PyResult<()> {
1290 match TIU_EMU_BUSY_CNT.set(&mut self.ipbus, cycles) {
1291 Ok(_) => {
1292 return Ok(());
1293 }
1294 Err(err) => {
1295 return Err(PyValueError::new_err(err.to_string()));
1296 }
1297 }
1298 }
1299
1300 #[getter]
1301 fn get_tiu_emulation_mode_bsy_cnt(&mut self) -> PyResult<u32> {
1302 match TIU_EMU_BUSY_CNT.get(&mut self.ipbus) {
1303 Ok(value) => {
1304 return Ok(value);
1305 }
1306 Err(err) => {
1307 return Err(PyValueError::new_err(err.to_string()));
1308 }
1309 }
1310 }
1311
1312 fn get_enable_cyclic_trig(&mut self) -> PyResult<bool> {
1313 match TRIG_CYCLIC_EN.get(&mut self.ipbus) {
1314 Ok(value) => {
1315 return Ok(value > 0);
1316 }
1317 Err(err) => {
1318 return Err(PyValueError::new_err(err.to_string()));
1319 }
1320 }
1321 }
1322
1323 fn disable_cyclic_trig(&mut self) -> PyResult<()> {
1324 match TRIG_CYCLIC_EN.set(&mut self.ipbus, 0x0) {
1325 Ok(_) => {
1326 return Ok(());
1327 }
1328 Err(err) => {
1329 return Err(PyValueError::new_err(err.to_string()));
1330 }
1331 }
1332 }
1333
1334 fn enable_cyclic_trig(&mut self) -> PyResult<()> {
1335 match TRIG_CYCLIC_EN.set(&mut self.ipbus, 0x1) {
1336 Ok(_) => {
1337 return Ok(());
1338 }
1339 Err(err) => {
1340 return Err(PyValueError::new_err(err.to_string()));
1341 }
1342 }
1343 }
1344
1345 fn get_cyclic_trigger_interval(&mut self) -> PyResult<u32> {
1346 match TRIG_CYCLIC_INTERVAL.get(&mut self.ipbus) {
1347 Ok(interval) => {
1348 return Ok(interval);
1349 }
1350 Err(err) => {
1351 return Err(PyValueError::new_err(err.to_string()));
1352 }
1353 }
1354 }
1355
1356 fn set_cyclic_trigger_interval(&mut self, interval : u32) -> PyResult<()> {
1357 match TRIG_CYCLIC_INTERVAL.set(&mut self.ipbus, interval) {
1358 Ok(_) => {
1359 return Ok(());
1360 }
1361 Err(err) => {
1362 return Err(PyValueError::new_err(err.to_string()));
1363 }
1364 }
1365 }
1366
1367 fn trigger(&mut self) -> PyResult<()> {
1369 match FORCE_TRIGGER.set(&mut self.ipbus, 1) {
1370 Ok(_) => {
1371 return Ok(());
1372 }
1373 Err(err) => {
1374 return Err(PyValueError::new_err(err.to_string()));
1375 }
1376 }
1377 }
1378
1379 fn set_poisson_trigger(&mut self, rate : u32) -> PyResult<()> {
1380 let clk_period = 100000000;
1381 let rate_val = (u32::MAX*rate)/clk_period;match TRIG_GEN_RATE.set(&mut self.ipbus, rate_val) {
1383 Ok(_) => {
1384 return Ok(());
1385 }
1386 Err(err) => {
1387 return Err(PyValueError::new_err(err.to_string()));
1388 }
1389 }
1390 }
1391
1392 fn set_gaps_track_trigger(&mut self, prescale : f32, use_beta : bool) -> PyResult<()> {
1393 match control::set_gaps_track_trigger(&mut self.ipbus, prescale, use_beta) {
1394 Ok(_) => {
1395 return Ok(());
1396 }
1397 Err(err) => {
1398 return Err(PyValueError::new_err(err.to_string()));
1399 }
1400 }
1401 }
1402
1403 fn set_gaps_any_trigger(&mut self, prescale : f32, use_beta : bool) -> PyResult<()> {
1404 match control::set_gaps_any_trigger(&mut self.ipbus, prescale, use_beta) {
1405 Ok(_) => {
1406 return Ok(());
1407 }
1408 Err(err) => {
1409 return Err(PyValueError::new_err(err.to_string()));
1410 }
1411 }
1412 }
1413
1414 fn set_gaps_central_track_trigger(&mut self, prescale : f32, use_beta : bool) -> PyResult<()> {
1415 match control::set_gaps_central_track_trigger(&mut self.ipbus, prescale, use_beta) {
1416 Ok(_) => {
1417 return Ok(());
1418 }
1419 Err(err) => {
1420 return Err(PyValueError::new_err(err.to_string()));
1421 }
1422 }
1423 }
1424
1425 fn set_gaps422_central_track_trigger(&mut self, prescale : f32, use_beta : bool) -> PyResult<()> {
1426 match control::set_gaps422_central_track_trigger(&mut self.ipbus, prescale, use_beta) {
1427 Ok(_) => {
1428 return Ok(());
1429 }
1430 Err(err) => {
1431 return Err(PyValueError::new_err(err.to_string()));
1432 }
1433 }
1434 }
1435
1436 fn get_lt_link_en0(&mut self) -> PyResult<u32> {
1438 match LT_LINK_EN0.get(&mut self.ipbus) {
1439 Ok(value) => {
1440 return Ok(value);
1441 }
1442 Err(err) => {
1443 return Err(PyValueError::new_err(err.to_string()));
1444 }
1445 }
1446 }
1447 fn get_lt_link_en1(&mut self) -> PyResult<u32> {
1449 match LT_LINK_EN1.get(&mut self.ipbus) {
1450 Ok(value) => {
1451 return Ok(value);
1452 }
1453 Err(err) => {
1454 return Err(PyValueError::new_err(err.to_string()));
1455 }
1456 }
1457 }
1458 fn get_lt_link_en02(&mut self) -> PyResult<u32> {
1460 match LT_LINK_EN2.get(&mut self.ipbus) {
1461 Ok(value) => {
1462 return Ok(value);
1463 }
1464 Err(err) => {
1465 return Err(PyValueError::new_err(err.to_string()));
1466 }
1467 }
1468 }
1469 fn get_lt_link_en3(&mut self) -> PyResult<u32> {
1471 match LT_LINK_EN3.get(&mut self.ipbus) {
1472 Ok(value) => {
1473 return Ok(value);
1474 }
1475 Err(err) => {
1476 return Err(PyValueError::new_err(err.to_string()));
1477 }
1478 }
1479 }
1480 fn get_lt_link_en4(&mut self) -> PyResult<u32> {
1482 match LT_LINK_EN4.get(&mut self.ipbus) {
1483 Ok(value) => {
1484 return Ok(value);
1485 }
1486 Err(err) => {
1487 return Err(PyValueError::new_err(err.to_string()));
1488 }
1489 }
1490 }
1491 fn set_lt_link_en0(&mut self, value : u32) -> PyResult<u32> {
1493 match LT_LINK_EN0.set(&mut self.ipbus, value) {
1494 Ok(_) => {
1495 return Ok(value);
1496 }
1497 Err(err) => {
1498 return Err(PyValueError::new_err(err.to_string()));
1499 }
1500 }
1501 }
1502 fn set_lt_link_en1(&mut self, value : u32) -> PyResult<u32> {
1504 match LT_LINK_EN1.set(&mut self.ipbus, value) {
1505 Ok(_) => {
1506 return Ok(value);
1507 }
1508 Err(err) => {
1509 return Err(PyValueError::new_err(err.to_string()));
1510 }
1511 }
1512 }
1513 fn set_lt_link_en2(&mut self, value : u32) -> PyResult<u32> {
1515 match LT_LINK_EN2.set(&mut self.ipbus, value) {
1516 Ok(_) => {
1517 return Ok(value);
1518 }
1519 Err(err) => {
1520 return Err(PyValueError::new_err(err.to_string()));
1521 }
1522 }
1523 }
1524 fn set_lt_link_en3(&mut self, value : u32) -> PyResult<u32> {
1526 match LT_LINK_EN3.set(&mut self.ipbus, value) {
1527 Ok(_) => {
1528 return Ok(value);
1529 }
1530 Err(err) => {
1531 return Err(PyValueError::new_err(err.to_string()));
1532 }
1533 }
1534 }
1535 fn set_lt_link_en4(&mut self, value : u32) -> PyResult<u32> {
1537 match LT_LINK_EN4.set(&mut self.ipbus, value) {
1538 Ok(_) => {
1539 return Ok(value);
1540 }
1541 Err(err) => {
1542 return Err(PyValueError::new_err(err.to_string()));
1543 }
1544 }
1545 }
1546 fn get_lt_link_automask(&mut self) -> PyResult<bool> {
1548 match LT_LINK_AUTOMASK.get(&mut self.ipbus) {
1549 Ok(value) => {
1550 return Ok(value != 0);
1551 }
1552 Err(err) => {
1553 return Err(PyValueError::new_err(err.to_string()));
1554 }
1555 }
1556 }
1557 fn set_lt_link_automask(&mut self, toggle : bool) -> PyResult<bool> {
1559 match LT_LINK_AUTOMASK.set(&mut self.ipbus, toggle as u32) {
1560 Ok(_) => {
1561 return Ok(true);
1562 }
1563 Err(err) => {
1564 return Err(PyValueError::new_err(err.to_string()));
1565 }
1566 }
1567 }
1568fn get_gaps_trigger_prescale(&mut self) -> PyResult<f32> {
1569 match GAPS_TRIG_PRESCALE.get(&mut self.ipbus) {
1570 Ok (prescale_bus) => {
1571 let prescale_val = (u32::MAX as f32 * prescale_bus as f32).floor() as f32;
1572 return Ok(prescale_val)
1573 }
1574 Err(err) => {
1575 return Err(PyValueError::new_err(err.to_string()));
1576 }
1577 }
1578}
1579
1580fn set_gaps_trigger_prescale(&mut self, prescale : f32) -> PyResult<f32> {
1581 let prescale_val = (f32::MAX * prescale as f32).floor() as u32;
1582 match GAPS_TRIG_PRESCALE.set(&mut self.ipbus, prescale_val) {
1583 Ok(_) => {
1584 return Ok(prescale)
1585 }
1586 Err(err) => {
1587 return Err(PyValueError::new_err(err.to_string()));
1588 }
1589 }
1590}
1591
1592fn set_track_trigger_is_global(&mut self) -> PyResult<()> {
1593 match TRACK_CENTRAL_IS_GLOBAL.set(&mut self.ipbus, 1) {
1594 Ok(_) => {
1595 return Ok(());
1596 }
1597 Err(err) => {
1598 return Err(PyValueError::new_err(err.to_string()));
1599 }
1600 }
1601 }
1602
1603
1604fn get_ltb_links_ready(&mut self) -> PyResult<HashMap<u8, u32>> {
1605 let registers = [LT_LINK_READY0, LT_LINK_READY1,
1606 LT_LINK_READY2, LT_LINK_READY3,
1607 LT_LINK_READY4];
1608 let mut ready = HashMap::<u8, u32>::new();
1609 for (k,reg) in registers.iter().enumerate() {
1610 match reg.get(&mut self.ipbus) {
1611 Err(err) => {
1612 return Err(PyValueError::new_err(err.to_string()));
1613 }
1614 Ok(cnt) => {
1615 ready.insert(k as u8, cnt);
1616 }
1617 }
1618 }
1619 Ok(ready)
1620 }
1621
1622 fn get_ltb_event_cnts(&mut self) -> PyResult<HashMap<u8, u32>> {
1623 let registers = [LT0, LT1, LT2, LT3, LT4, LT5, LT6, LT7, LT8, LT9,
1624 LT10, LT11, LT12, LT13, LT14, LT15, LT16, LT17, LT18, LT19,
1625 LT20, LT21, LT22, LT23, LT24];
1626 let mut counters = HashMap::<u8, u32>::new();
1627 for (k,reg) in registers.iter().enumerate() {
1628 match reg.get(&mut self.ipbus) {
1629 Err(err) => {
1630 return Err(PyValueError::new_err(err.to_string()));
1631 }
1632 Ok(cnt) => {
1633 counters.insert(k as u8, cnt);
1634 }
1635 }
1636 }
1637 let mut table = Table::new();
1639 table
1640 .load_preset(UTF8_FULL)
1641 .apply_modifier(UTF8_ROUND_CORNERS)
1642 .set_content_arrangement(ContentArrangement::Dynamic)
1643 .set_width(80)
1644 .set_header(vec!["LT 0", "LT 1", "LT 2", "LT 3", "LT 4"])
1645 .add_row(vec![
1646 Cell::new(&(format!("{}", counters[&0]))),
1647 Cell::new(&(format!("{}", counters[&1]))),
1648 Cell::new(&(format!("{}", counters[&2]))),
1649 Cell::new(&(format!("{}", counters[&3]))),
1650 Cell::new(&(format!("{}", counters[&4]))),
1651 ])
1653 .add_row(vec![
1654 Cell::new(String::from("LT 5")),
1655 Cell::new(String::from("LT 6")),
1656 Cell::new(String::from("LT 7")),
1657 Cell::new(String::from("LT 8")),
1658 Cell::new(String::from("LT 9")),
1659 ])
1660 .add_row(vec![
1661 Cell::new(&(format!("{}", counters[&5]))),
1662 Cell::new(&(format!("{}", counters[&6]))),
1663 Cell::new(&(format!("{}", counters[&7]))),
1664 Cell::new(&(format!("{}", counters[&8]))),
1665 Cell::new(&(format!("{}", counters[&9]))),
1666 ])
1667 .add_row(vec![
1668 Cell::new(String::from("LT 10")),
1669 Cell::new(String::from("LT 11")),
1670 Cell::new(String::from("LT 12")),
1671 Cell::new(String::from("LT 13")),
1672 Cell::new(String::from("LT 14")),
1673 ])
1674 .add_row(vec![
1675 Cell::new(&(format!("{}", counters[&10]))),
1676 Cell::new(&(format!("{}", counters[&11]))),
1677 Cell::new(&(format!("{}", counters[&12]))),
1678 Cell::new(&(format!("{}", counters[&13]))),
1679 Cell::new(&(format!("{}", counters[&14]))),
1680 ])
1681 .add_row(vec![
1682 Cell::new(String::from("LT 15")),
1683 Cell::new(String::from("LT 16")),
1684 Cell::new(String::from("LT 17")),
1685 Cell::new(String::from("LT 18")),
1686 Cell::new(String::from("LT 19")),
1687 ])
1688 .add_row(vec![
1689 Cell::new(&(format!("{}", counters[&15]))),
1690 Cell::new(&(format!("{}", counters[&16]))),
1691 Cell::new(&(format!("{}", counters[&17]))),
1692 Cell::new(&(format!("{}", counters[&18]))),
1693 Cell::new(&(format!("{}", counters[&19]))),
1694 ])
1695 .add_row(vec![
1696 Cell::new(String::from("LT 20")),
1697 Cell::new(String::from("LT 21")),
1698 Cell::new(String::from("LT 22")),
1699 Cell::new(String::from("LT 23")),
1700 Cell::new(String::from("LT 24")),
1701 ])
1702 .add_row(vec![
1703 Cell::new(&(format!("{}", counters[&20]))),
1704 Cell::new(&(format!("{}", counters[&21]))),
1705 Cell::new(&(format!("{}", counters[&22]))),
1706 Cell::new(&(format!("{}", counters[&23]))),
1707 Cell::new(&(format!("{}", counters[&24]))),
1708 ]);
1709
1710 let column = table.column_mut(2).expect("Our table has three columns");
1712 column.set_cell_alignment(CellAlignment::Right);
1713 println!("{table}");
1714 Ok(counters)
1715 }
1716
1717 fn get_rb_event_cnts(&mut self) -> PyResult<HashMap<u8, u8>> {
1719 let registers = [RB0_CNTS, RB1_CNTS, RB2_CNTS, RB3_CNTS, RB4_CNTS,
1720 RB5_CNTS, RB6_CNTS, RB7_CNTS, RB8_CNTS, RB9_CNTS,
1721 RB10_CNTS, RB11_CNTS, RB12_CNTS, RB13_CNTS, RB14_CNTS,
1722 RB15_CNTS, RB16_CNTS, RB17_CNTS, RB18_CNTS, RB19_CNTS,
1723 RB20_CNTS, RB21_CNTS, RB22_CNTS, RB23_CNTS, RB24_CNTS,
1724 RB25_CNTS, RB26_CNTS, RB27_CNTS, RB28_CNTS, RB29_CNTS,
1725 RB30_CNTS, RB31_CNTS, RB32_CNTS, RB33_CNTS, RB34_CNTS,
1726 RB35_CNTS, RB36_CNTS, RB37_CNTS, RB38_CNTS, RB39_CNTS,
1727 RB40_CNTS, RB41_CNTS, RB42_CNTS, RB43_CNTS, RB44_CNTS,
1728 RB45_CNTS, RB46_CNTS, RB47_CNTS, RB48_CNTS, RB49_CNTS];
1729 let mut counters = HashMap::<u8, u8>::new();
1730 for (k,reg) in registers.iter().enumerate() {
1731 match reg.get(&mut self.ipbus) {
1732 Err(err) => {
1733 return Err(PyValueError::new_err(err.to_string()));
1734 }
1735 Ok(cnt) => {
1736 counters.insert(k as u8, cnt as u8);
1737 }
1738 }
1739 }
1740 let mut table = Table::new();
1741 table
1742 .load_preset(UTF8_FULL)
1743 .apply_modifier(UTF8_ROUND_CORNERS)
1744 .set_content_arrangement(ContentArrangement::Dynamic)
1745 .set_width(60)
1746 .set_header(vec!["RB 0", "RB 1", "RB 2", "RB 3", "RB 4"])
1747 .add_row(vec![
1748 Cell::new(&(format!("{}", counters[&0]))),
1749 Cell::new(&(format!("{}", counters[&1]))),
1750 Cell::new(&(format!("{}", counters[&2]))),
1751 Cell::new(&(format!("{}", counters[&3]))),
1752 Cell::new(&(format!("{}", counters[&4]))),
1753 ])
1755 .add_row(vec![
1756 Cell::new(String::from("RB 5")),
1757 Cell::new(String::from("RB 6")),
1758 Cell::new(String::from("RB 7")),
1759 Cell::new(String::from("RB 8")),
1760 Cell::new(String::from("RB 9")),
1761 ])
1762 .add_row(vec![
1763 Cell::new(&(format!("{}", counters[&5]))),
1764 Cell::new(&(format!("{}", counters[&6]))),
1765 Cell::new(&(format!("{}", counters[&7]))),
1766 Cell::new(&(format!("{}", counters[&8]))),
1767 Cell::new(&(format!("{}", counters[&9]))),
1768 ])
1769 .add_row(vec![
1770 Cell::new(String::from("RB 10")),
1771 Cell::new(String::from("RB 11")),
1772 Cell::new(String::from("RB 12")),
1773 Cell::new(String::from("RB 13")),
1774 Cell::new(String::from("RB 14")),
1775 ])
1776 .add_row(vec![
1777 Cell::new(&(format!("{}", counters[&10]))),
1778 Cell::new(&(format!("{}", counters[&11]))),
1779 Cell::new(&(format!("{}", counters[&12]))),
1780 Cell::new(&(format!("{}", counters[&13]))),
1781 Cell::new(&(format!("{}", counters[&14]))),
1782 ])
1783 .add_row(vec![
1784 Cell::new(String::from("RB 15")),
1785 Cell::new(String::from("RB 16")),
1786 Cell::new(String::from("RB 17")),
1787 Cell::new(String::from("RB 18")),
1788 Cell::new(String::from("RB 19")),
1789 ])
1790 .add_row(vec![
1791 Cell::new(&(format!("{}", counters[&15]))),
1792 Cell::new(&(format!("{}", counters[&16]))),
1793 Cell::new(&(format!("{}", counters[&17]))),
1794 Cell::new(&(format!("{}", counters[&18]))),
1795 Cell::new(&(format!("{}", counters[&19]))),
1796 ])
1797 .add_row(vec![
1798 Cell::new(String::from("RB 20")),
1799 Cell::new(String::from("RB 21")),
1800 Cell::new(String::from("RB 22")),
1801 Cell::new(String::from("RB 23")),
1802 Cell::new(String::from("RB 24")),
1803 ])
1804 .add_row(vec![
1805 Cell::new(&(format!("{}", counters[&20]))),
1806 Cell::new(&(format!("{}", counters[&21]))),
1807 Cell::new(&(format!("{}", counters[&22]))),
1808 Cell::new(&(format!("{}", counters[&23]))),
1809 Cell::new(&(format!("{}", counters[&24]))),
1810 ])
1811 .add_row(vec![
1812 Cell::new(String::from("RB 25")),
1813 Cell::new(String::from("RB 26")),
1814 Cell::new(String::from("RB 27")),
1815 Cell::new(String::from("RB 28")),
1816 Cell::new(String::from("RB 29")),
1817 ])
1818 .add_row(vec![
1819 Cell::new(&(format!("{}", counters[&25]))),
1820 Cell::new(&(format!("{}", counters[&26]))),
1821 Cell::new(&(format!("{}", counters[&27]))),
1822 Cell::new(&(format!("{}", counters[&28]))),
1823 Cell::new(&(format!("{}", counters[&29]))),
1824 ])
1825 .add_row(vec![
1826 Cell::new(String::from("RB 30")),
1827 Cell::new(String::from("RB 31")),
1828 Cell::new(String::from("RB 32")),
1829 Cell::new(String::from("RB 33")),
1830 Cell::new(String::from("RB 34")),
1831 ])
1832 .add_row(vec![
1833 Cell::new(&(format!("{}", counters[&30]))),
1834 Cell::new(&(format!("{}", counters[&31]))),
1835 Cell::new(&(format!("{}", counters[&32]))),
1836 Cell::new(&(format!("{}", counters[&33]))),
1837 Cell::new(&(format!("{}", counters[&34]))),
1838 ])
1839 .add_row(vec![
1840 Cell::new(String::from("RB 35")),
1841 Cell::new(String::from("RB 36")),
1842 Cell::new(String::from("RB 37")),
1843 Cell::new(String::from("RB 38")),
1844 Cell::new(String::from("RB 39")),
1845 ])
1846 .add_row(vec![
1847 Cell::new(&(format!("{}", counters[&35]))),
1848 Cell::new(&(format!("{}", counters[&36]))),
1849 Cell::new(&(format!("{}", counters[&37]))),
1850 Cell::new(&(format!("{}", counters[&38]))),
1851 Cell::new(&(format!("{}", counters[&39]))),
1852 ])
1853 .add_row(vec![
1854 Cell::new(String::from("RB 40")),
1855 Cell::new(String::from("RB 41")),
1856 Cell::new(String::from("RB 42")),
1857 Cell::new(String::from("RB 43")),
1858 Cell::new(String::from("RB 44")),
1859 ])
1860 .add_row(vec![
1861 Cell::new(&(format!("{}", counters[&40]))),
1862 Cell::new(&(format!("{}", counters[&41]))),
1863 Cell::new(&(format!("{}", counters[&42]))),
1864 Cell::new(&(format!("{}", counters[&43]))),
1865 Cell::new(&(format!("{}", counters[&44]))),
1866 ])
1867 .add_row(vec![
1868 Cell::new(String::from("RB 45")),
1869 Cell::new(String::from("RB 46")),
1870 Cell::new(String::from("RB 47")),
1871 Cell::new(String::from("RB 48")),
1872 Cell::new(String::from("RB 49")),
1873 ])
1874 .add_row(vec![
1875 Cell::new(&(format!("{}", counters[&45]))),
1876 Cell::new(&(format!("{}", counters[&46]))),
1877 Cell::new(&(format!("{}", counters[&47]))),
1878 Cell::new(&(format!("{}", counters[&48]))),
1879 Cell::new(&(format!("{}", counters[&49]))),
1880 ]);
1881
1882 let column = table.column_mut(2).expect("Our table has three columns");
1884 column.set_cell_alignment(CellAlignment::Right);
1885 println!("{table}");
1886 Ok(counters)
1887 }
1888
1889 fn reset_rb_counters(&mut self) -> PyResult<()> {
1891 println!("{}", RB_CNTS_RESET);
1892 match RB_CNTS_RESET.set(&mut self.ipbus, 1) {
1893 Ok(_) => {
1894 return Ok(());
1895 }
1896 Err(err) => {
1897 return Err(PyValueError::new_err(err.to_string()));
1898 }
1899 }
1900 }
1901
1902 fn reset_ltb_counters(&mut self) -> PyResult<()> {
1904 match LT_HIT_CNT_RESET.set(&mut self.ipbus, 1) {
1905 Ok(_) => {
1906 return Ok(());
1907 }
1908 Err(err) => {
1909 return Err(PyValueError::new_err(err.to_string()));
1910 }
1911 }
1912 }
1913
1914 fn set_ltb_ch_mask(&mut self, lt_link : u8, mask : u8) -> PyResult<()> {
1921 let registers = [LT0_CHMASK, LT1_CHMASK, LT2_CHMASK, LT3_CHMASK, LT4_CHMASK,
1922 LT5_CHMASK, LT6_CHMASK, LT7_CHMASK, LT8_CHMASK, LT9_CHMASK,
1923 LT10_CHMASK, LT11_CHMASK, LT12_CHMASK, LT13_CHMASK, LT14_CHMASK,
1924 LT15_CHMASK, LT16_CHMASK, LT17_CHMASK, LT18_CHMASK, LT19_CHMASK,
1925 LT20_CHMASK, LT21_CHMASK, LT22_CHMASK, LT23_CHMASK, LT24_CHMASK];
1926 if lt_link as usize > registers.len() {
1927 return Err(PyValueError::new_err(String::from("Mask has to be in range 0-24!")));
1928 }
1929
1930 match registers[lt_link as usize].set(&mut self.ipbus, mask as u32) {
1931 Ok(_) => {
1932 return Ok(());
1933 }
1934 Err(err) => {
1935 return Err(PyValueError::new_err(err.to_string()));
1936 }
1937 }
1938 }
1939
1940
1941 fn set_trace_suppression(&mut self, trace_sup : bool) -> PyResult<()> {
1942 let read_all_rb : u32;
1943 if trace_sup {
1944 read_all_rb = 0;
1945 } else {
1946 read_all_rb = 1;
1947 }
1948 match RB_READ_ALL_CHANNELS.set(&mut self.ipbus, read_all_rb) {
1949 Ok(_) => {
1950 Ok(())
1951 }
1952 Err(err) => {
1953 return Err(PyValueError::new_err(err.to_string()));
1954 }
1955 }
1956 }
1957
1958 fn get_trace_suppression(&mut self) -> PyResult<u32> {
1959 match RB_READ_ALL_CHANNELS.get(&mut self.ipbus) {
1960 Ok(cnt) => {
1961 return Ok(cnt);
1962 }
1963 Err(err) => {
1964 return Err(PyValueError::new_err(err.to_string()));
1965 }
1966 }
1967 }
1968
1969 fn set_total_tof_thresh(&mut self, value : u32) -> PyResult<()> {
1970 match TOTAL_TOF_THRESH.set(&mut self.ipbus, value) {
1971 Ok(_) => {
1972 Ok(())
1973 }
1974 Err(err) => {
1975 return Err(PyValueError::new_err(err.to_string()));
1976 }
1977 }
1978 }
1979
1980 fn get_total_tof_thresh(&mut self) -> PyResult<u32> {
1981 match TOTAL_TOF_THRESH.get(&mut self.ipbus) {
1982 Ok(cnt) => {
1983 return Ok(cnt);
1984 }
1985 Err(err) => {
1986 return Err(PyValueError::new_err(err.to_string()));
1987 }
1988 }
1989 }
1990
1991 fn set_inner_tof_thresh(&mut self, value : u32) -> PyResult<()> {
1992 match INNER_TOF_THRESH.set(&mut self.ipbus, value) {
1993 Ok(_) => {
1994 return Ok(());
1995 }
1996 Err(err) => {
1997 return Err(PyValueError::new_err(err.to_string()));
1998 }
1999 }
2000 }
2001
2002 fn get_inner_tof_thresh(&mut self) -> PyResult<u32> {
2003 match INNER_TOF_THRESH.get(&mut self.ipbus) {
2004 Ok(cnt) => {
2005 return Ok(cnt);
2006 }
2007 Err(err) => {
2008 return Err(PyValueError::new_err(err.to_string()));
2009 }
2010 }
2011 }
2012
2013 fn set_outer_tof_thresh(&mut self, value : u32) -> PyResult<()> {
2014 match OUTER_TOF_THRESH.set(&mut self.ipbus, value) {
2015 Ok(_) => {
2016 return Ok(());
2017 }
2018 Err(err) => {
2019 return Err(PyValueError::new_err(err.to_string()));
2020 }
2021 }
2022 }
2023
2024 fn get_outer_tof_thresh(&mut self) -> PyResult<u32> {
2025 match OUTER_TOF_THRESH.get(&mut self.ipbus) {
2026 Ok(cnt) => {
2027 return Ok(cnt);
2028 }
2029 Err(err) => {
2030 return Err(PyValueError::new_err(err.to_string()));
2031 }
2032 }
2033 }
2034
2035 fn set_cube_side_thresh(&mut self, value : u32) -> PyResult<()> {
2036 match CUBE_SIDE_THRESH.set(&mut self.ipbus, value) {
2037 Ok(_) => {
2038 return Ok(());
2039 }
2040 Err(err) => {
2041 return Err(PyValueError::new_err(err.to_string()));
2042 }
2043 }
2044 }
2045
2046 fn get_cube_side_thresh(&mut self) -> PyResult<u32> {
2047 match CUBE_SIDE_THRESH.get(&mut self.ipbus) {
2048 Ok(cnt) => {
2049 return Ok(cnt);
2050 }
2051 Err(err) => {
2052 return Err(PyValueError::new_err(err.to_string()));
2053 }
2054 }
2055 }
2056
2057 fn set_cube_top_thresh(&mut self, value : u32) -> PyResult<()> {
2058 match CUBE_TOP_THRESH.set(&mut self.ipbus, value) {
2059 Ok(_) => {
2060 return Ok(());
2061 }
2062 Err(err) => {
2063 return Err(PyValueError::new_err(err.to_string()));
2064 }
2065 }
2066 }
2067
2068 fn get_cube_top_thresh(&mut self) -> PyResult<u32> {
2069 match CUBE_TOP_THRESH.get(&mut self.ipbus) {
2070 Ok(cnt) => {
2071 return Ok(cnt);
2072 }
2073 Err(err) => {
2074 return Err(PyValueError::new_err(err.to_string()));
2075 }
2076 }
2077 }
2078
2079 fn set_cube_bot_thresh(&mut self, value : u32) -> PyResult<()> {
2080 match CUBE_BOT_THRESH.set(&mut self.ipbus, value) {
2081 Ok(_) => {
2082 return Ok(());
2083 }
2084 Err(err) => {
2085 return Err(PyValueError::new_err(err.to_string()));
2086 }
2087 }
2088 }
2089
2090 fn get_cube_bot_thresh(&mut self) -> PyResult<u32> {
2091 match CUBE_BOT_THRESH.get(&mut self.ipbus) {
2092 Ok(cnt) => {
2093 return Ok(cnt);
2094 }
2095 Err(err) => {
2096 return Err(PyValueError::new_err(err.to_string()));
2097 }
2098 }
2099 }
2100
2101 fn set_cube_corner_thresh(&mut self, value : u32) -> PyResult<()> {
2102 match CUBE_CORNER_THRESH.set(&mut self.ipbus, value) {
2103 Ok(_) => {
2104 return Ok(());
2105 }
2106 Err(err) => {
2107 return Err(PyValueError::new_err(err.to_string()));
2108 }
2109 }
2110 }
2111
2112 fn get_cube_corner_thresh(&mut self) -> PyResult<u32> {
2113 match CUBE_CORNER_THRESH.get(&mut self.ipbus) {
2114 Ok(cnt) => {
2115 return Ok(cnt);
2116 }
2117 Err(err) => {
2118 return Err(PyValueError::new_err(err.to_string()));
2119 }
2120 }
2121 }
2122
2123 fn set_umbrella_thresh(&mut self, value : u32) -> PyResult<()> {
2124 match UMBRELLA_THRESH.set(&mut self.ipbus, value) {
2125 Ok(_) => {
2126 return Ok(());
2127 }
2128 Err(err) => {
2129 return Err(PyValueError::new_err(err.to_string()));
2130 }
2131 }
2132 }
2133
2134 fn get_umbrella_thresh(&mut self) -> PyResult<u32> {
2135 match UMBRELLA_THRESH.get(&mut self.ipbus) {
2136 Ok(cnt) => {
2137 return Ok(cnt);
2138 }
2139 Err(err) => {
2140 return Err(PyValueError::new_err(err.to_string()));
2141 }
2142 }
2143 }
2144
2145 fn set_umbrella_center_thresh(&mut self, value : u32) -> PyResult<()> {
2146 match UMBRELLA_CENTER_THRESH.set(&mut self.ipbus, value) {
2147 Ok(_) => {
2148 return Ok(());
2149 }
2150 Err(err) => {
2151 return Err(PyValueError::new_err(err.to_string()));
2152 }
2153 }
2154 }
2155
2156 fn get_umbrella_center_thresh(&mut self) -> PyResult<u32> {
2157 match UMBRELLA_CENTER_THRESH.get(&mut self.ipbus) {
2158 Ok(cnt) => {
2159 return Ok(cnt);
2160 }
2161 Err(err) => {
2162 return Err(PyValueError::new_err(err.to_string()));
2163 }
2164 }
2165 }
2166
2167 fn set_cortina_thresh(&mut self, value : u32) -> PyResult<()> {
2168 match CORTINA_THRESH.set(&mut self.ipbus, value) {
2169 Ok(_) => {
2170 return Ok(());
2171 }
2172 Err(err) => {
2173 return Err(PyValueError::new_err(err.to_string()));
2174 }
2175 }
2176 }
2177
2178 fn get_cortina_thresh(&mut self) -> PyResult<u32> {
2179 match CORTINA_THRESH.get(&mut self.ipbus) {
2180 Ok(cnt) => {
2181 return Ok(cnt);
2182 }
2183 Err(err) => {
2184 return Err(PyValueError::new_err(err.to_string()));
2185 }
2186 }
2187 }
2188
2189 fn set_configurable_trigger(&mut self, value : u32) -> PyResult<()> {
2190 match CONFIGURABLE_TRIGGER_EN.set(&mut self.ipbus, value) {
2191 Ok(_) => {
2192 return Ok(());
2193 }
2194 Err(err) => {
2195 return Err(PyValueError::new_err(err.to_string()));
2196 }
2197 }
2198 }
2199
2200 fn get_configurable_trigger(&mut self) -> PyResult<u32> {
2201 match CONFIGURABLE_TRIGGER_EN.get(&mut self.ipbus) {
2202 Ok(cnt) => {
2203 return Ok(cnt);
2204 }
2205 Err(err) => {
2206 return Err(PyValueError::new_err(err.to_string()));
2207 }
2208 }
2209 }
2210
2211 fn set_any_trigger(&mut self, prescale : u32) -> PyResult<()> {
2212 match ANY_TRIG_PRESCALE.set(&mut self.ipbus, prescale) {
2213 Ok(_) => {
2214 return Ok(());
2215 }
2216 Err(err) => {
2217 return Err(PyValueError::new_err(err.to_string()));
2218 }
2219 }
2220 }
2221
2222 fn set_track_trigger(&mut self, prescale : u32) -> PyResult<()> {
2223 match TRACK_TRIG_PRESCALE.set(&mut self.ipbus, prescale) {
2224 Ok(_) => {
2225 return Ok(());
2226 }
2227 Err(err) => {
2228 return Err(PyValueError::new_err(err.to_string()));
2229 }
2230 }
2231 }
2232
2233 fn set_central_track_trigger(&mut self, prescale : u32) -> PyResult<()> {
2234 match TRACK_CENTRAL_PRESCALE.set(&mut self.ipbus, prescale) {
2235 Ok(_) => {
2236 return Ok(());
2237 }
2238 Err(err) => {
2239 return Err(PyValueError::new_err(err.to_string()));
2240 }
2241 }
2242 }
2243
2244 fn use_tiu_aux_link(&mut self, use_it : bool) -> PyResult<()> {
2245 match control::use_tiu_aux_link(&mut self.ipbus, use_it) {
2246 Ok(_) => {
2247 return Ok(());
2248 }
2249 Err(err) => {
2250 return Err(PyValueError::new_err(err.to_string()));
2251 }
2252 }
2253 }
2254
2255 fn stop_all_triggers(&mut self) -> PyResult<()> {
2256 match control::unset_all_triggers(&mut self.ipbus) {
2257 Ok(_) => {
2258 return Ok(());
2259 }
2260 Err(err) => {
2261 return Err(PyValueError::new_err(err.to_string()));
2262 }
2263 }
2264 }
2265
2266 fn set_umbcube_trigger(&mut self) -> PyResult<()> {
2267 match control::set_umbcube_trigger(&mut self.ipbus) {
2268 Ok(_) => {
2269 return Ok(());
2270 }
2271 Err(err) => {
2272 return Err(PyValueError::new_err(err.to_string()));
2273 }
2274 }
2275 }
2276
2277 fn set_umbcubez_trigger(&mut self) -> PyResult<()> {
2278 match control::set_umbcubez_trigger(&mut self.ipbus) {
2279 Ok(_) => {
2280 return Ok(());
2281 }
2282 Err(err) => {
2283 return Err(PyValueError::new_err(err.to_string()));
2284 }
2285 }
2286 }
2287
2288 fn set_umbcorcube_trigger(&mut self) -> PyResult<()> {
2289 match control::set_umbcorcube_trigger(&mut self.ipbus) {
2290 Ok(_) => {
2291 return Ok(());
2292 }
2293 Err(err) => {
2294 return Err(PyValueError::new_err(err.to_string()));
2295 }
2296 }
2297 }
2298
2299 fn set_corcubeside_trigger(&mut self) -> PyResult<()> {
2300 match control::set_corcubeside_trigger(&mut self.ipbus) {
2301 Ok(_) => {
2302 return Ok(());
2303 }
2304 Err(err) => {
2305 return Err(PyValueError::new_err(err.to_string()));
2306 }
2307 }
2308 }
2309
2310 fn set_umb3cube_trigger(&mut self) -> PyResult<()> {
2311 match control::set_umb3cube_trigger(&mut self.ipbus) {
2312 Ok(_) => {
2313 return Ok(());
2314 }
2315 Err(err) => {
2316 return Err(PyValueError::new_err(err.to_string()));
2317 }
2318 }
2319 }
2320
2321 #[getter]
2322 fn get_tiu_busy_ignore(&mut self) -> PyResult<bool> {
2323 match TIU_BUSY_IGNORE.get(&mut self.ipbus) {
2324 Ok(bsy) => {
2325 let res = bsy != 0;
2326 return Ok(res);
2327 }
2328 Err(err) => {
2329 return Err(PyValueError::new_err(err.to_string()));
2330 }
2331 }
2332 }
2333
2334 #[setter]
2335 fn set_tiu_busy_ignore(&mut self, bsy : bool) -> PyResult<()> {
2336 match TIU_BUSY_IGNORE.set(&mut self.ipbus, bsy as u32) {
2337 Ok(_) => {
2338 return Ok(());
2339 }
2340 Err(err) => {
2341 return Err(PyValueError::new_err(err.to_string()));
2342 }
2343 }
2344 }
2345
2346 #[getter]
2347 fn get_tiu_busy_stuck(&mut self) -> PyResult<bool> {
2348 match TIU_BUSY_STUCK.get(&mut self.ipbus) {
2349 Ok(value) => {
2350 return Ok(value > 0);
2351 }
2352 Err(err) => {
2353 return Err(PyValueError::new_err(err.to_string()));
2354 }
2355 }
2356 }
2357
2358 #[getter]
2359 fn get_tiu_bad(&mut self) -> PyResult<bool> {
2360 match TIU_BAD.get(&mut self.ipbus) {
2361 Ok(value) => {
2362 return Ok(value > 0);
2363 }
2364 Err(err) => {
2365 return Err(PyValueError::new_err(err.to_string()));
2366 }
2367 }
2368 }
2369
2370 fn get_event_cnt(&mut self) -> PyResult<u32> {
2371 match EVENT_CNT.get(&mut self.ipbus) {
2372 Ok(cnt) => {
2373 return Ok(cnt);
2374 }
2375 Err(err) => {
2376 return Err(PyValueError::new_err(err.to_string()));
2377 }
2378 }
2379 }
2380
2381 fn get_event_queue_size(&mut self)
2382 -> PyResult<u32> {
2383 match EVQ_SIZE.get(&mut self.ipbus) {
2384 Ok(cnt) => {
2385 return Ok(cnt);
2386 }
2387 Err(err) => {
2388 return Err(PyValueError::new_err(err.to_string()));
2389 }
2390 }
2391 }
2392
2393 fn get_event_queue_full(&mut self)
2394 -> PyResult<u32> {
2395 match EVQ_FULL.get(&mut self.ipbus) {
2396 Ok(cnt) => {
2397 return Ok(cnt);
2398 }
2399 Err(err) => {
2400 return Err(PyValueError::new_err(err.to_string()));
2401 }
2402 }
2403 }
2404
2405 fn get_nevents_in_queue(&mut self)
2406 -> PyResult<u32> {
2407 match EVQ_NUM_EVENTS.get(&mut self.ipbus) {
2408 Ok(cnt) => {
2409 return Ok(cnt);
2410 }
2411 Err(err) => {
2412 return Err(PyValueError::new_err(err.to_string()));
2413 }
2414 }
2415 }
2416
2417
2418 #[pyo3(name="get_event")]
2419 fn get_event_py(&mut self, read_until_footer : bool, verbose : bool, debug : bool)
2420 -> PyResult<TofEvent> {
2421 let use_dbg_version = debug;
2422 if !use_dbg_version {
2423 match get_event(&mut self.ipbus) {
2425 None => {
2426 warn!("Did not get an event, returning empty event!");
2428 let event = TofEvent::new();
2429 Ok(event)
2430 }
2431 Some(Err(err)) => {
2432 return Err(PyValueError::new_err(err.to_string()));
2434 }
2435 Some(Ok(mte)) => {
2436 Ok(mte)
2437 }
2438 }
2439 } else {
2440 let mut n_daq_words : u16;
2444 let mut n_daq_words_actual : u16;
2445 loop {
2446 match EVQ_NUM_EVENTS.get(&mut self.ipbus) {
2447 Err(_err) => {
2448 continue;
2449 }
2450 Ok(nevents_in_q) => {
2451 if nevents_in_q == 0 {
2452 if verbose {
2453 println!("[MasterTrigger::get_event] => EventQueue empty!!");
2454 }
2455 return Err(PyValueError::new_err(String::from("<MasterTriggerError: EventQueueEmpty>")));
2456 }
2457 }
2458 }
2459 match self.ipbus.read(0x13) {
2460 Err(_err) => {
2461 continue;
2466 },
2467 Ok(_n_words) => {
2468 n_daq_words = (_n_words >> 16) as u16;
2469 if _n_words == 0 {
2470 continue;
2471 }
2472 let rest = n_daq_words % 2;
2474 n_daq_words /= 2 + rest; break;
2478 }
2479 }
2480 }
2481 let mut data : Vec<u32>;
2482 if verbose {
2483 println!("[MasterTrigger::get_event] => Will query DAQ for {n_daq_words} words!");
2484 }
2485 n_daq_words_actual = n_daq_words;
2486 match self.ipbus.read_multiple(
2487 0x11,
2488 n_daq_words as usize,
2489 false) {
2490 Err(err) => {
2491 if verbose {
2492 println!("[MasterTrigger::get_event] => failed! {err}");
2493 }
2494 return Err(PyValueError::new_err(err.to_string()));
2495 }
2496 Ok(_data) => {
2497 data = _data;
2498 for (i,word) in data.iter().enumerate() {
2499 let desc : &str;
2500 let desc_str : String;
2501 match i {
2503 0 => desc = "HEADER",
2504 1 => desc = "EVENTID",
2505 2 => desc = "TIMESTAMP",
2506 3 => desc = "TIU_TIMESTAMP",
2507 4 => desc = "TIU_GPS32",
2508 5 => desc = "TIU_GPS16 + TRIG_SOURCE",
2509 6 => desc = "RB MASK 0",
2510 7 => desc = "RB MASK 1",
2511 8 => {
2512 desc_str = format!("BOARD MASK ({} ltbs)", word.count_ones());
2514 desc = &desc_str;
2515 },
2516 _ => desc = "?"
2517 }
2518 if verbose {
2519 println!("[MasterTrigger::get_event] => DAQ word {} \t({:x}) \t[{}]", word, word, desc);
2520 }
2521 }
2522 }
2523 }
2524 if data[0] != 0xAAAAAAAA {
2525 if verbose {
2526 println!("[MasterTrigger::get_event] => Got MTB data, but the header is incorrect {}", data[0]);
2527 }
2528 return Err(PyValueError::new_err(String::from("Incorrect header value!")));
2529 }
2530 let foot_pos = (n_daq_words - 1) as usize;
2531 if data.len() <= foot_pos {
2532 if verbose {
2533 println!("[MasterTrigger::get_event] => Got MTB data, but the format is not correct");
2534 }
2535 return Err(PyValueError::new_err(String::from("Empty data!")));
2536 }
2537 if data[foot_pos] != 0x55555555 {
2538 if verbose {
2539 println!("[MasterTrigger::get_event] => Did not read unti footer!");
2540 }
2541 if read_until_footer {
2542 if verbose {
2543 println!("[MasterTrigger::get_event] => .. will read additional words!");
2544 }
2545 loop {
2546 match self.ipbus.read(0x11) {
2547 Err(err) => {
2548 if verbose {
2549 println!("[MasterTrigger::get_event] => Issues reading from 0x11");
2550 }
2551 return Err(PyValueError::new_err(err.to_string()));
2552 },
2553 Ok(next_word) => {
2554 n_daq_words_actual += 1;
2555 data.push(next_word);
2556 if next_word == 0x55555555 {
2557 break;
2558 }
2559 }
2560 }
2561 }
2562 if verbose {
2563 println!("[MasterTrigger::get_event] => We read {} additional words!", n_daq_words_actual - n_daq_words);
2564 }
2565 } else {
2566 if verbose {
2567 println!("[MasterTrigger::get_event] => Got MTB data, but the footer is incorrect {}", data[foot_pos]);
2568 }
2569 return Err(PyValueError::new_err(String::from("Footer incorrect!")));
2570 }
2571 }
2572
2573 let mut mte = TofEvent::new();
2579 mte.event_id = data[1];
2580 mte.mt_timestamp = data[2];
2581 mte.mt_tiu_timestamp = data[3];
2582 mte.mt_tiu_gps32 = data[4];
2583 mte.mt_tiu_gps16 = (data[5] & 0x0000ffff) as u16;
2584 mte.trigger_sources = ((data[5] & 0xffff0000) >> 16) as u16;
2585 let rbmask = (data[7] as u64) << 31 | data[6] as u64;
2587 mte.mtb_link_mask = rbmask;
2588 mte.dsi_j_mask = data[8];
2589 let mut n_hit_words = n_daq_words_actual - 9 - 2; if n_hit_words > n_daq_words_actual {
2591 n_hit_words = 0;
2592 println!("[MasterTrigger::get_event] N hit word calculation failed! fixing... {}", n_hit_words);
2593 }
2594 if verbose {
2595 println!("[MasterTrigger::get_event] => Will read {} hit word", n_hit_words);
2596 }
2597 for k in 1..n_hit_words+1 {
2598 if verbose {
2599 println!("[MasterTrigger::get_event] => Getting word {}", k);
2600 }
2601 let first = (data[8 + k as usize] & 0x0000ffff) as u16;
2602 let second = ((data[8 + k as usize] & 0xffff0000) >> 16) as u16;
2603 mte.channel_mask.push(first);
2604 if second != 0 {
2605 mte.channel_mask.push(second);
2606 }
2607 }
2608 if verbose {
2609 println!("[MasterTrigger::get_event] => Got MTE \n{}", mte);
2610 }
2611 let event = TofEvent::new();
2612 Ok(event)
2613 }
2614 }
2615}
2616
2617