liftof_rb/
control.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
//! Convenience functions to read/write
//!  the various control registers
//!
//!  
//!  For the mapping of registers/addresses, 
//!  see `registers.rs`
//!

use crate::registers::*;
use crate::memory::*;

use std::time::Duration;
use std::thread;

extern crate liftof_lib;

/// Read the link ID from the MTB 
///
/// THe link ID comes from the MTB
pub fn get_mtb_link_id() -> Result<u32, RegisterError> {
  trace!("Getting MTB Link ID!");
  let mut val = read_control_reg(MT_LINK_ID)?;
  val = val & 0x01F8;
  val = val >> 3;
  Ok(val) 
}


/// write header only packets when the drs is busy
pub fn enable_evt_fragments() -> Result<(), RegisterError> {
  trace!("Enable event fragment writing!");
  write_control_reg(WRITE_EVENTFRAGMENT, 1)?;
  Ok(())
}

/// use the random self trigger
pub fn set_self_trig_rate(rate : u32) -> Result<(), RegisterError> {
  warn!("Setting self trigger rate, writing register {}", TRIG_GEN_RATE);
  write_control_reg(TRIG_GEN_RATE, rate)?;
  Ok(())
}

/// do not write header only packets when the drs is busyu
pub fn disable_evt_fragments() -> Result<(), RegisterError> {
  trace!("Disable event fragment writing!");
  write_control_reg(WRITE_EVENTFRAGMENT, 0)?;
  Ok(())
}

/// enable triggering
pub fn enable_trigger() -> Result<(), RegisterError> {
  trace!("Enable triggers!");
  write_control_reg(TRIGGER_ENABLE, 1)?;
  Ok(())
}

/// stop all triggers
pub fn disable_trigger() -> Result<(), RegisterError> {
  trace!("Enable triggers!");
  write_control_reg(TRIGGER_ENABLE, 0)?;
  Ok(())
}

pub fn daq_is_busy() -> Result<bool, RegisterError> {
  let busy = (read_control_reg(DAQ_BUSY)? & 0x2) > 0;
  Ok(busy)
}

/// Reset the board and prepare for a new run
///
/// Procedure as discussed in 12/2023
/// Trigger disable (0 to 0x11C\[0\])
/// Set desired trigger mode  (1 to 0x114\[0\] for MTB trigger or 0 to 0x114\[0\] for software trigger)
/// Soft reset (1 to 0x70\[0\])
/// Check for soft reset done (read 0x74\[15\])
/// Trigger enable (1 to 0x11C\[0\])
pub fn soft_reset_board() -> Result<(), RegisterError> {
  trace!("Initialize soft reset procedure!");
  let eight_cycles = Duration::from_micros(4);
  write_control_reg(SOFT_RESET, 0x1)?;
  thread::sleep(eight_cycles);
  let mut ncycles = 0;
  while !soft_reset_done()? {
    thread::sleep(eight_cycles);
    ncycles += 1;
    if ncycles % 10 == 0 {
      error!("Not getting SOFT_RESET_DONE acknowledged. Will try DMA reset");
      match reset_dma() {
        Err(err) => error!("Unable to reset DMA! {err}"),
        Ok(_)    => ()
      }
    }
    if ncycles == 29 {
      return Err(RegisterError::RegisterTimeOut);     
    }
  }
  Ok(())
}

/// Check if the soft reset procedure has finished
pub fn soft_reset_done() -> Result<bool, RegisterError> {
  let mask : u32 = 1 << 15;
  let value = read_control_reg(SOFT_RESET_DONE)?;
  return Ok((value & mask) > 0)
}


/// Start DRS4 data acquistion
pub fn start_drs4_daq() -> Result<(), RegisterError> {
  trace!("SET DRS4 START");
  write_control_reg(DRS_START, 1)?;
  Ok(())
}


/// Put the daq in idle state, that is stop data taking
pub fn idle_drs4_daq() -> Result<(), RegisterError> {
  trace!("SET DRS4 IDLE");
  write_control_reg(DRS_REINIT, 1)?;
  Ok(())
}

/// Get the blob buffer occupancy for one of the two buffers
///  
/// This is a bit tricky. This will continuously change, as 
/// the DRS4 is writing into the memory. At some point, it 
/// will be full, not changing it's value anymore. At that 
/// point, if set, the firmware has switched automatically 
/// to the other buffer. 
///
/// Also, it will only read something like zero if the 
/// DMA has completly been reset (calling dma_reset).
/// 
/// # Arguments
///
/// * which : select the blob buffer to query
///
///
pub fn get_blob_buffer_occ(which : &RamBuffer) -> Result<u32, RegisterError> {
  let address = match which {
    RamBuffer::A => RAM_A_OCCUPANCY,
    RamBuffer::B => RAM_B_OCCUPANCY,
  };

  let value = read_control_reg(address)?;
  Ok(value)
}


/// Check if teh TRIGGER_ENABLE register is set
pub fn get_triggers_enabled() -> Result<bool, RegisterError> {
  let value = read_control_reg(TRIGGER_ENABLE)?;
  Ok(value > 0)
}

/// FIXME
pub fn get_dma_pointer() -> Result<u32, RegisterError> {
  let value = read_control_reg(DMA_POINTER)?;
  Ok(value)
}

/// Reset the DMA memory (blob data) and write 0s
pub fn clear_dma_memory() -> Result<(), RegisterError> {
  trace!("SET DMA CLEAR");
  write_control_reg(DMA_CLEAR, 1)?;  
  // the reset takes 8 clock cycles at 33 MHz (about 3.4 micro)
  let eight_cycles = Duration::from_micros(4);
  thread::sleep(eight_cycles);
  Ok(())
}


/// Reset means, the memory can be used again, but it does not mean it 
/// clears the memory.
///
/// The writing into the memory thus can start anywhere in memory (does 
/// not have to be from 0)
pub fn reset_ram_buffer_occ(which : &RamBuffer) -> Result<(), RegisterError> {
  match which { 
    RamBuffer::A => write_control_reg(RAM_A_OCC_RST, 0x1)?,
    RamBuffer::B => write_control_reg(RAM_B_OCC_RST, 0x1)?
  };
  // the reset takes 8 clock cycles at 33 MHz (about 3.4 micro)
  let eight_cycles = Duration::from_micros(4);
  thread::sleep(eight_cycles);
  Ok(())
}

/// Get the recorded triggers by the DRS4
pub fn get_trigger_rate() -> Result<u32, RegisterError> {
  let value = read_control_reg(TRIGGER_RATE)?;
  Ok(value)
}

/// Get the rate of the lost triggers by the DRS4
pub fn get_lost_trigger_rate() -> Result<u32, RegisterError> {
  let value = read_control_reg(LOST_TRIGGER_RATE)?;
  Ok(value)
}

/// Get the event counter from the DRS4
///
/// The event counter is NOT the event id comming from 
/// the master trigger. It is simply the number of 
/// events observed since the last reset.
///
pub fn get_event_count() -> Result<u32, RegisterError> {
  let value = read_control_reg(CNT_EVENT)?;
  Ok(value)
}

/// Get the event counter as sent from the MTB
pub fn get_event_count_mt() -> Result<u32, RegisterError> {
  let value = read_control_reg(MT_EVENT_CNT)?;
  Ok(value)
}

/// Get the rate as sent from the MTB
pub fn get_event_rate_mt() -> Result<u32, RegisterError> {
  let value = read_control_reg(MT_TRIG_RATE)?;
  Ok(value)
}

/// Get the lost events event counter from the DRS4
pub fn get_lost_event_count() -> Result<u32, RegisterError> {
  let value = read_control_reg(CNT_LOST_EVENT)?;
  Ok(value)
}

/// This simply sets the configure bit.
///
/// Unclear what it actually does.
/// FIXME
pub fn set_drs4_configure() -> Result<(), RegisterError> {
  trace!("SET DRS4 CONFIGURE");
  write_control_reg(DRS_CONFIGURE, 1)?;
  Ok(())
}

/// Force a trigger
///
/// _If I understand it correctly, this is a single trigger_
///
pub fn trigger() -> Result<(), RegisterError> {
  //warn!("Setting force trigger mode!");
  write_control_reg(FORCE_TRIG, 1)?;
  Ok(())
}

/// Reset of the internal event counter
///
///  This is NOT the event id.
pub fn reset_drs_event_ctr() -> Result<(), RegisterError> {
  trace!("SET DRS4 EV CNT RESET");
  write_control_reg(CNT_RESET, 1)?;
  Ok(())
}

pub fn reset_daq() -> Result<(), RegisterError> {
  trace!("SET DAQ RESET");
  write_control_reg(DAQ_RESET, 1)?;
  Ok(())
}

pub fn reset_drs() -> Result<(), RegisterError> {
  trace!("SET DRS RESET");
  write_control_reg(DRS_REINIT, 1)?;
  Ok(())
}

///! Resets the DMA state machine.
pub fn reset_dma() -> Result<(), RegisterError> {
  trace!("SET DMA RESET");
  write_control_reg(DMA_RESET, 1)?;
  // the reset takes 8 clock cycles at 33 MHz (about 3.4 micro)
  let eight_cycles = Duration::from_micros(4);
  thread::sleep(eight_cycles);
  Ok(())
}


///! Toggle between the data buffers A and B
pub fn switch_ram_buffer() -> Result<(), RegisterError> {
  trace!("SET DMA DATA BUFF TOGGLE");
  write_control_reg(TOGGLE_RAM, 1)?;
  Ok(())
}

///! The device DNA is a unique identifier
pub fn get_device_dna() -> Result<u64, RegisterError> {
  let lsb = read_control_reg(DNA_LSBS)?;
  let msb = read_control_reg(DNA_MSBS)?;
  let mut value : u64 = 0;
  value = value | (msb as u64) << 32;
  value = value | lsb as u64;
  Ok(value)
}


/// Enable the readout of all channels + the 9th channel
pub fn set_readout_all_channels_and_ch9() -> Result<(), RegisterError> {
  warn!("This might be buggy!");
  let all_channels : u32 = 511;
  let ch_9         : u32 = 512;
  let value = all_channels | ch_9;
  trace!("SET DRS4 READOUT MASK");
  write_control_reg(READOUT_MASK, value)?;
  Ok(())
}

/// Enable active channels by not touching the ch9 bits
pub fn set_active_channel_mask(ch_mask : u8) -> Result<(), RegisterError> {
  let mut value   = read_control_reg(READOUT_MASK)?;
  // FIXME - do debug! instead.
  println!("==> Got current channel mask! {value}");
  let ch9_part     = value & 0xFF00; // set all ch to 0;
  value            = ch9_part | ch_mask as u32;
  write_control_reg(READOUT_MASK, value)?;
  println!("==> Wrote {value} to channel mask register!");
  Ok(())
}

pub fn set_active_channel_mask_with_ch9(ch_mask : u32) -> Result<(), RegisterError> {
  let ch_9  : u32 = 256;
  let value = ch_mask | ch_9;
  write_control_reg(READOUT_MASK, value)?;
  Ok(())
}

/// Enable the master trigger mode
pub fn set_master_trigger_mode() -> Result<(), RegisterError> {
  trace!("SET DRS4 MT MODE");
  write_control_reg(MT_TRIGGER_MODE, 1)?;
  Ok(())
}

/// Disable the master trigger
pub fn disable_master_trigger_mode() -> Result<(), RegisterError> {
  warn!("Disabeling master trigger mode");
  write_control_reg(MT_TRIGGER_MODE, 0)?;
  Ok(())
}


///! Get the board ID from the control registers.
pub fn get_board_id() -> Result<u32, RegisterError> { 
  let board_id = read_control_reg(BOARD_ID)?;
  Ok(board_id)
}

///! Get the board ID from the control registers.
pub fn get_board_id_string() -> Result<String, RegisterError> { 
  let board_id = get_board_id()?;
  let board_id_string = liftof_lib::to_board_id_string(board_id);
  Ok(board_id_string)
}

/// Read te last DRS4 Deadtime
pub fn get_deadtime() -> Result<u32, RegisterError> {
  let deadtime = read_control_reg(DRS_DEADTIME)?;
  Ok(deadtime & 0xffff)
}