liftof_lib/master_trigger/
control.rs

1//! Master trigger board control
2//!
3//! Set registers and enable/disable features,
4//! readout event and monitoring data
5//!
6//! Many control functions in this module can go
7//! away, since they can be replaced by the 
8//! calls on the register implementation directly.
9
10use std::error::Error;
11use tof_dataclasses::ipbus::{
12  IPBus,
13};
14
15use crate::master_trigger::registers::*;
16
17/// Read event counter register of MTB
18///
19/// This gives the number of events read 
20/// since the last counter reset
21pub fn read_event_cnt(bus : &mut IPBus) //,
22                      //buffer : &mut [u8;MT_MAX_PACKSIZE])
23  -> Result<u32, Box<dyn Error>> {
24  let event_count = bus.read(0xd)?;
25  trace!("Got event count! {} ", event_count);
26  Ok(event_count)
27}
28
29/// Set the RB readout mode - either 
30/// read out all channels all the time
31/// or use the MTB to indicate to the RBs
32/// which channels to read out 
33pub fn set_trace_suppression(bus : &mut IPBus,
34                             sup : bool) 
35  -> Result<(), Box<dyn Error>> {
36  info!("Setting MTB trace suppression {}!", sup);
37  let mut value = bus.read(0xf)?;
38  // bit 13 has to be 1 for read all channels
39  let read_all_ch = u32::pow(2, 13);
40  if sup { // sup means !read_all_ch
41    value = value & !read_all_ch;
42  }
43  else {
44    value = value | read_all_ch; 
45  }
46  bus.write(0xf, value)?;
47  Ok(())
48}
49
50/// Reset the state of the MTB DAQ buffer
51/// This can be safely issued without 
52/// resetting the event id
53pub fn reset_daq(bus : &mut IPBus) 
54  -> Result<(), Box<dyn Error>> {
55  info!("Resetting DAQ!");
56  bus.write(0x10, 1)?;
57  Ok(())
58}
59
60
61/// Retrieve the status of the TIU link
62///
63/// The TIU is the trigger interface unit
64/// and connects TOF and Tracker
65///
66/// # Returns:
67///
68///   bool : true if the link status is "good"
69///          which means TIU is connected and 
70///          link is ok
71pub fn tiu_link_is_good(bus : &mut IPBus)
72  -> Result<bool, Box<dyn Error>> {
73  let mut tiu_good = 0x1u32;
74  let value        = bus.read(0xf)?;
75  tiu_good         = tiu_good & ( value & 0x1);
76  Ok(tiu_good > 0)
77}
78
79/// The TIU emulation mode literally allows to emulate a TIU even if it 
80/// is not connected.
81///
82/// This will inject a certain deadtime into the MasterTrigger triggering
83/// system, as if a BUSY signal was received from an actual TIU
84pub fn set_tiu_emulation_mode(bus : &mut IPBus, set_emulation_mode : bool) 
85  -> Result<(), Box<dyn Error>> {
86    info!("Setting TIU Emulation mode {}", set_emulation_mode);
87    let mut value = bus.read(0xe)?;
88    let bitset : u32;
89    if set_emulation_mode {
90      bitset = 0x1;
91    } else {
92      bitset = 0x0;
93    }
94    value = value & 0xfffffffe;
95    value = value | bitset;
96    bus.write(0xe, value)?;
97    Ok(())
98}
99
100/// Set the busy count for the tiu emulation mode in 10ns clockcycles
101pub fn set_tiu_emulation_mode_bsy_cnt(bus : &mut IPBus, cycles : u32)
102  -> Result<(), Box<dyn Error>> {
103  info!("Setting TIU Emulation mode bsy cnt to {} clock cycles (10ns each)", cycles);
104  TIU_EMU_BUSY_CNT.set(bus, cycles)?;
105  Ok(()) 
106}
107
108/// Get the number of clock cycles (1=10ns) that the emulator will remain busy
109pub fn get_tiu_emu_busy_cnt(bus : &mut IPBus) 
110  -> Result<u32, Box<dyn Error>> {
111  TIU_EMU_BUSY_CNT.get(bus)
112}
113
114pub fn get_gaps_trigger_prescale(bus : &mut IPBus)
115  -> Result<f32, Box<dyn Error>> {
116    let prescale_bus = GAPS_TRIG_PRESCALE.get(bus)?;
117    let prescale_val = (prescale_bus as f32)/f32::MAX;
118    return Ok(prescale_val)
119  }
120
121pub fn set_gaps_trigger_prescale(bus : &mut IPBus, prescale : f32)
122  -> Result<(), Box<dyn Error>> {
123    let prescale_val = (u32::MAX as f32 * prescale).floor() as u32;
124    info!("Setting gaps trigger with prescale {};)", prescale);
125    bus.write(0x248, prescale_val)?;
126  Ok(())
127  }
128/// The readoutboard integration window
129///
130/// The default setting is "1" and currently 
131/// it should only be changed by experts for 
132/// a good reason.
133///
134/// The RB integration window affects the readout
135/// of RB pulses which are not part of the initial
136/// Trigger, but come later instead.
137/// This is reflected in the BOARD_MASKs/mtb_link_id
138/// mas of the MasterTriggerEvent. The larger the 
139/// number, the more boards we might expect. (?)
140pub fn set_rb_int_window(bus : &mut IPBus, wind : u8)
141  -> Result<(), Box<dyn Error>> {
142  info!("Setting RB_INT_WINDOW to {}!", wind);
143  let mut value  =  bus.read(0xf)?;
144  //println!("==> Retrieved {value} from register 0xf on MTB");
145  let mask   = 0xffffe0ff;
146  // switch the bins off
147  value          = value & mask;
148  let wind_bits  = (wind as u32) << 8;
149  value = value | wind_bits;
150  bus.write(0xf, value)?;
151  trace!("++ Writing to register ++");
152  value = bus.read(0xf)?;
153  trace!("==> Reading back value {value} from register 0xf on MTB after writing to it!");
154  Ok(())
155}
156
157/// Set the poisson trigger with a prescale
158pub fn set_poisson_trigger(bus : &mut IPBus, rate : u32) 
159  -> Result<(), Box<dyn Error>> {
160  //let clk_period = 1e8u32; 
161  let clk_period = 100000000;
162  let rate_val = (u32::MAX*rate)/clk_period;//(1.0/ clk_period)).floor() as u32;
163  
164  //let rate_val   = (rate as f32 * u32::MAX as f32/1.0e8) as u32; 
165  info!("Setting poisson trigger with rate {}!", rate);
166  bus.write(0x9, rate_val)?;
167  Ok(())
168}
169
170/// Set the any trigger with a prescale
171pub fn set_any_trigger(bus : &mut IPBus, prescale : f32) 
172  -> Result<(), Box<dyn Error>> {
173  let prescale_val = (u32::MAX as f32 * prescale).floor() as u32;
174  info!("Setting any trigger with prescale {}!", prescale);
175  bus.write(0x40, prescale_val)?;
176  Ok(())
177}
178
179/// Set the track trigger with a prescale
180pub fn set_track_trigger(bus : &mut IPBus, prescale : f32) 
181  -> Result<(), Box<dyn Error>> {
182  let prescale_val = (u32::MAX as f32 * prescale).floor() as u32;
183  info!("Setting track trigger with prescale {}!", prescale);
184  bus.write(0x41, prescale_val)?;
185  Ok(())
186}
187
188/// Set the CENTRAL track trigger with a prescale
189pub fn set_central_track_trigger(bus : &mut IPBus, prescale : f32) 
190  -> Result<(), Box<dyn Error>> {
191  let prescale_val = (u32::MAX as f32 * prescale).floor() as u32;
192  info!("Setting CENTRAL TRACK trigger with prescale {}!", prescale);
193  bus.write(0x42, prescale_val)?;
194  Ok(())
195}
196
197pub fn set_track_umb_central_trigger(bus : &mut IPBus, prescale : f32)
198    -> Result<(), Box<dyn Error>> {
199    let prescale_val = (u32::MAX as f32 * prescale).floor() as u32;
200    info!("Setting TRACK UMB CENTRAL trigger with prescale {}!", prescale);
201    bus.write(0x249, prescale_val)?;
202    Ok(())
203  }
204
205
206/// Disable all triggers
207pub fn unset_all_triggers(bus : &mut IPBus) 
208  -> Result<(), Box<dyn Error>> {
209  // first the GAPS trigger, whcih is a more 
210  // complicated register, where we only have
211  // to flip 1 bit
212  //zero_all_trigger_thresholds(bus)?;
213  let mut trig_settings = bus.read(0x14)?;
214  trig_settings         = trig_settings & !u32::pow(2,24);
215  bus.write(0x14, trig_settings)?;
216  set_poisson_trigger(bus, 0)?;
217  set_any_trigger    (bus, 0.0)?;
218  set_track_trigger  (bus, 0.0)?;
219  set_central_track_trigger(bus, 0.0)?;
220  set_configurable_trigger(bus, false)?;
221  TRACK_TRIG_IS_GLOBAL.set(bus, 0)?; 
222  ANY_TRIG_IS_GLOBAL.set(bus, 0)?;
223  TRACK_CENTRAL_IS_GLOBAL.set(bus, 0)?;
224  set_track_umb_central_trigger(bus, 0.0)?;
225  Ok(())
226}
227
228/// Set the gaps trigger with a prescale
229pub fn set_gaps_trigger(bus : &mut IPBus, use_beta : bool) 
230  -> Result<(), Box<dyn Error>> {
231  info!("Setting GAPS Antiparticle trigger, use beta {}!", use_beta);
232  set_inner_tof_threshold(bus,0x3)?;
233  set_outer_tof_threshold(bus,0x3)?;
234  set_total_tof_threshold(bus,0x8)?;
235  let mut trig_settings = bus.read(0x14)?;
236  trig_settings = trig_settings | u32::pow(2,24);
237  if use_beta {
238    trig_settings = trig_settings | u32::pow(2,25);
239  }
240  bus.write(0x14, trig_settings)?;
241  Ok(())
242}
243
244pub fn set_gaps_track_trigger(bus : &mut IPBus, prescale : f32, use_beta : bool) 
245  -> Result<(), Box<dyn Error>> {
246  info!("Setting GAPS + Track trigger combo");
247  TRACK_TRIG_IS_GLOBAL.set(bus, 1)?;
248  set_gaps_trigger(bus, use_beta)?;
249  set_track_trigger(bus, prescale)?;
250  Ok(())
251}
252
253pub fn set_gaps_any_trigger(bus : &mut IPBus, prescale : f32, use_beta : bool)
254  -> Result<(), Box<dyn Error>> {
255    info!("Setting GAPS + Any trigger combo");
256    ANY_TRIG_IS_GLOBAL.set(bus, 1)?;
257    set_gaps_trigger(bus, use_beta)?;
258    set_any_trigger(bus, prescale)?;
259    Ok(())
260  }
261
262pub fn set_gaps_central_track_trigger(bus : &mut IPBus, prescale : f32, use_beta : bool)
263  -> Result<(), Box<dyn Error>> {
264    info!("Setting GAPS + Central Track trigger combo");
265    TRACK_CENTRAL_IS_GLOBAL.set(bus, 1)?;
266    set_gaps_trigger(bus, use_beta)?;
267    set_central_track_trigger(bus, prescale)?;
268    Ok(())
269  }
270
271pub fn set_gaps422_central_track_trigger(bus : &mut IPBus, prescale : f32, use_beta : bool)
272  -> Result<(), Box<dyn Error>> {
273    info!("Setting GAPS + Central Track trigger combo");
274    TRACK_CENTRAL_IS_GLOBAL.set(bus, 1)?;
275    set_gaps422_trigger(bus, use_beta)?;
276    set_central_track_trigger(bus, prescale)?;
277    Ok(())
278  }
279
280pub fn set_gaps633_trigger(bus : &mut IPBus, use_beta : bool) 
281  -> Result<(), Box<dyn Error>> {
282  info!("Setting GAPS Antiparticle trigger, use beta {}!", use_beta);
283  set_inner_tof_threshold(bus,0x3)?;
284  set_outer_tof_threshold(bus,0x3)?;
285  set_total_tof_threshold(bus,0x6)?;
286  let mut trig_settings = bus.read(0x14)?;
287  trig_settings = trig_settings | u32::pow(2,24);
288  if use_beta {
289    trig_settings = trig_settings | u32::pow(2,25);
290  }
291  bus.write(0x14, trig_settings)?;
292  Ok(())
293}
294
295pub fn set_gaps422_trigger(bus : &mut IPBus, use_beta : bool) 
296  -> Result<(), Box<dyn Error>> {
297  info!("Setting GAPS Antiparticle trigger, use beta {}!", use_beta);
298  set_inner_tof_threshold(bus,0x2)?;
299  set_outer_tof_threshold(bus,0x2)?;
300  set_total_tof_threshold(bus,0x4)?;
301  let mut trig_settings = bus.read(0x14)?;
302  trig_settings = trig_settings | u32::pow(2,24);
303  if use_beta {
304    trig_settings = trig_settings | u32::pow(2,25);
305  }
306  bus.write(0x14, trig_settings)?;
307  Ok(())
308}
309
310pub fn set_gaps211_trigger(bus : &mut IPBus, use_beta : bool) 
311  -> Result<(), Box<dyn Error>> {
312  info!("Setting GAPS Antiparticle trigger, use beta {}!", use_beta);
313  set_inner_tof_threshold(bus,0x1)?;
314  set_outer_tof_threshold(bus,0x1)?;
315  set_total_tof_threshold(bus,0x2)?;
316  let mut trig_settings = bus.read(0x14)?;
317  trig_settings = trig_settings | u32::pow(2,24);
318  if use_beta {
319    trig_settings = trig_settings | u32::pow(2,25);
320  }
321  bus.write(0x14, trig_settings)?;
322  Ok(())
323}
324
325pub fn set_configurable_trigger(bus : &mut IPBus, enable : bool) 
326  -> Result<(), Box<dyn Error>> {
327  if enable {
328    info!("Enabling configurable trigger!");
329  } else {
330    info!("Disabling configurable trigger!");
331  }
332  let mut trig_settings = bus.read(0x14)?;
333  //println!("Got {} trig settings", trig_settings);
334  if enable {
335    trig_settings = trig_settings | u32::pow(2,31);
336  } else {
337    trig_settings = trig_settings & !(u32::pow(2,31));
338  }
339  //println!("Will write {} trig settings", trig_settings);
340  bus.write(0x14, trig_settings)?;
341  Ok(())
342}
343
344pub fn set_inner_tof_threshold(bus : &mut IPBus, thresh : u8)
345  -> Result<(), Box<dyn Error>> {
346  info!("Setting inner TOF threshold {}!", thresh);
347  let mut trig_settings = bus.read(0x14)?;
348  trig_settings = trig_settings & 0xffffff00;
349  trig_settings = trig_settings | thresh as u32;
350  bus.write(0x14, trig_settings)?;
351  Ok(())
352}
353
354pub fn set_outer_tof_threshold(bus : &mut IPBus, thresh : u8)
355  -> Result<(), Box<dyn Error>> {
356  info!("Setting outer TOF threshold {}!", thresh);
357  let mut trig_settings = bus.read(0x14)?;
358  trig_settings = trig_settings & 0xffff00ff;
359  trig_settings = trig_settings | ((thresh as u32) << 8);
360  bus.write(0x14, trig_settings)?;
361  Ok(())
362}
363
364pub fn set_total_tof_threshold(bus : &mut IPBus, thresh : u8)
365  -> Result<(), Box<dyn Error>> {
366  info!("Setting total TOF threshold {}!", thresh);
367  let mut trig_settings = bus.read(0x14)?;
368  trig_settings = trig_settings & 0xff00ffff;
369  trig_settings = trig_settings | ((thresh as u32) << 16);
370  bus.write(0x14, trig_settings)?;
371  Ok(())
372}
373
374pub fn set_cube_side_threshold(bus : &mut IPBus, thresh : u8)
375  -> Result<(), Box<dyn Error>> {
376  info!("Setting cube side threshold {}!", thresh);
377  let mut trig_settings = bus.read(0x15)?;
378  trig_settings = trig_settings & 0xffffff00;
379  trig_settings = trig_settings | thresh as u32;
380  bus.write(0x15, trig_settings)?;
381  Ok(())
382}
383
384pub fn set_cube_top_threshold(bus : &mut IPBus, thresh : u8)
385  -> Result<(), Box<dyn Error>> {
386  info!("Setting cube top threshold {}!", thresh);
387  let mut trig_settings = bus.read(0x15)?;
388  trig_settings = trig_settings & 0xffff00ff;
389  trig_settings = trig_settings | ((thresh as u32) << 8);
390  bus.write(0x15, trig_settings)?;
391  Ok(())
392}
393
394pub fn set_cube_bottom_threshold(bus : &mut IPBus, thresh : u8)
395  -> Result<(), Box<dyn Error>> {
396  info!("Setting cube bottom threshold {}!", thresh);
397  let mut trig_settings = bus.read(0x15)?;
398  trig_settings = trig_settings & 0xff00ffff;
399  trig_settings = trig_settings | ((thresh as u32) << 16);
400  bus.write(0x15, trig_settings)?;
401  Ok(())
402}
403
404pub fn set_cube_corner_threshold(bus : &mut IPBus, thresh : u8)
405  -> Result<(), Box<dyn Error>> {
406  info!("Setting cube corner threshold {}!", thresh);
407  let mut trig_settings = bus.read(0x15)?;
408  trig_settings = trig_settings & 0x00ffffff;
409  trig_settings = trig_settings | ((thresh as u32) << 24);
410  bus.write(0x15, trig_settings)?;
411  Ok(())
412}
413
414pub fn set_umbrella_threshold(bus : &mut IPBus, thresh : u8)
415  -> Result<(), Box<dyn Error>> {
416  info!("Setting umbrella threshold {}!", thresh);
417  let mut trig_settings = bus.read(0x16)?;
418  // first zero out all the bits
419  println!("Got trig settings {}", trig_settings);
420  trig_settings = trig_settings & 0xffffff00;
421  println!("Got trig settings {}", trig_settings);
422  trig_settings = trig_settings | thresh as u32;
423  println!("Got trig settings {}", trig_settings);
424  let dbg = trig_settings & 0x000000ff;
425  println!("The threshold is set to {}", dbg);
426  bus.write(0x16, trig_settings)?;
427  Ok(())
428}
429
430pub fn set_cortina_threshold(bus : &mut IPBus, thresh : u8)
431  -> Result<(), Box<dyn Error>> {
432  info!("Setting cortina threshold {}!", thresh);
433  let mut trig_settings = bus.read(0x16)?;
434  trig_settings = trig_settings & 0xff00ffff;
435  trig_settings = trig_settings | ((thresh as u32) << 16);
436  bus.write(0x16, trig_settings)?;
437  Ok(())
438}
439
440pub fn set_umbcenter_threshold(bus : &mut IPBus, thresh : u8)
441  -> Result<(), Box<dyn Error>> {
442  info!("Setting Umbrella center threshold {}!", thresh);
443  let mut trig_settings = bus.read(0x16)?;
444  trig_settings = trig_settings & 0xffff00ff;
445  trig_settings = trig_settings | ((thresh as u32) << 8);
446  bus.write(0x16, trig_settings)?;
447  Ok(())
448}
449
450
451/// 1 Hit on Umbrella && 1 Hit on Cube
452pub fn set_umbcube_trigger(bus : &mut IPBus) 
453  ->Result<(), Box<dyn Error>> {
454  zero_config_trigger_thresholds(bus)?;
455  // now set the deired thresholds,
456  // because we zero'd out everything, 
457  // we just need to enable here.
458  set_configurable_trigger(bus,true)?;
459  set_umbrella_threshold(bus,1)?;
460  set_inner_tof_threshold(bus,1)?;
461  Ok(())
462}
463
464/// 1 Hit on Umbrella + 1 Hit on cube top
465pub fn set_umbcubez_trigger(bus : &mut IPBus) 
466  ->Result<(), Box<dyn Error>> {
467  zero_config_trigger_thresholds(bus)?;
468  set_configurable_trigger(bus,true)?;
469  set_umbrella_threshold(bus,1)?;
470  set_cube_top_threshold(bus,1)?;
471  Ok(())
472}
473
474/// 1 Hit on Umbrella && 1 Hit on Cortina && 1 Hit on Cube
475pub fn set_umbcorcube_trigger(bus : &mut IPBus) 
476  ->Result<(), Box<dyn Error>> {
477  zero_config_trigger_thresholds(bus)?;
478  set_configurable_trigger(bus,true)?;
479  set_umbrella_threshold(bus,1)?;
480  set_cortina_threshold(bus, 1)?;
481  set_inner_tof_threshold(bus, 1)?;
482  Ok(())
483}
484
485/// 1 Hit in Cortina && 1 Hit in Cube side
486pub fn set_corcubeside_trigger(bus : &mut IPBus) 
487  ->Result<(), Box<dyn Error>> {
488  zero_config_trigger_thresholds(bus)?;
489  set_configurable_trigger(bus,true)?;
490  set_cortina_threshold(bus,1)?;
491  set_cube_side_threshold(bus,1)?;
492  Ok(())
493}
494
495/// 1 Hit in Umbrella && 3 Hits in Cube
496pub fn set_umb3cube_trigger(bus : &mut IPBus) 
497  ->Result<(), Box<dyn Error>> {
498  set_configurable_trigger(bus,true)?;
499  zero_config_trigger_thresholds(bus)?;
500  set_umbrella_threshold(bus,1)?;
501  set_inner_tof_threshold(bus,3)?;
502  Ok(())
503}
504
505/// Zero out the configurable trigger thresholds
506pub fn zero_config_trigger_thresholds(bus : &mut IPBus)
507  ->Result<() ,Box<dyn Error>> {
508  INNER_TOF_THRESH.set(bus,0)?;
509  OUTER_TOF_THRESH.set(bus,0)?;
510  TOTAL_TOF_THRESH.set(bus,0)?;
511  CUBE_SIDE_THRESH.set(bus,0)?; 	
512  CUBE_TOP_THRESH.set(bus, 0)?; 	
513  CUBE_BOT_THRESH.set(bus, 0)?; 	
514  CUBE_CORNER_THRESH.set(bus, 0)?; 	
515  UMBRELLA_THRESH.set(bus, 0)?; 	
516  UMBRELLA_CENTER_THRESH.set(bus, 0)?;
517  Ok(())
518}
519
520/// Force a single trigger (just once)
521pub fn force_trigger(bus : &mut IPBus)
522  -> Result<(), Box<dyn Error>> {
523  //println!("==> Generating trigger!");
524  bus.write(0x8, 0x1)?;
525  Ok(())
526}
527
528pub fn use_tiu_aux_link(bus :&mut IPBus, use_it : bool) 
529  -> Result<(), Box<dyn Error>> {
530  if use_it {
531    TIU_USE_AUX_LINK.set(bus, 1)?;
532  } else {
533    TIU_USE_AUX_LINK.set(bus, 0)?;
534  }
535  Ok(())
536}
537
538
539pub fn set_fire_bits(bus : &mut IPBus, channel : u8)
540  -> Result<(), Box<dyn Error>> {
541  if channel < 25 {
542    let mut ch = channel as u32;
543    ch = ch << channel;
544    bus.write(0x101,ch)?;
545  } else if channel < 50 {
546    let mut ch = channel as u32 - 25;
547    ch = ch << channel;
548    bus.write(0x102,ch)?;
549  } else if channel < 75 {
550    let mut ch = channel as u32 - 50;
551    ch = ch << channel;
552    bus.write(0x103,ch)?;
553  } else if channel < 100 {
554    let mut ch = channel as u32 - 75;
555    ch = ch << channel;
556    bus.write(0x104,ch)?;
557  } else if channel < 125 {
558    let mut ch = channel as u32 - 100;
559    ch = ch << channel;
560    bus.write(0x105,ch)?;
561  } else if channel < 150 {
562    let mut ch = channel as u32 - 125;
563    ch = ch << channel;
564    bus.write(0x106,ch)?;
565  } else if channel < 175 {
566    let mut ch = channel as u32 - 150;
567    ch = ch << channel;
568    bus.write(0x107,ch)?;
569  } else if channel < 200 {
570    let mut ch = channel as u32 - 175;
571    ch = ch << channel;
572    bus.write(0x107,ch)?;
573  }
574  Ok(())
575}
576
577pub fn fire_ltb(bus : &mut IPBus)
578  -> Result<(), Box<dyn Error>> {
579  bus.write(0x100,0x1)?;
580  Ok(())
581}
582