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