1use crate::{flea_scope::CaptureConfigError, FleaProbe};
2
3pub trait TriggerConfig {
4 fn into_trigger_fields(self) -> StringifiedTriggerConfig;
5}
6
7pub struct StringifiedTriggerConfig {
8 trigger_fields: String,
9}
10
11impl StringifiedTriggerConfig {
12 pub fn into_string(self) -> String {
13 self.trigger_fields
14 }
15}
16
17#[derive(Debug, Clone, Copy, PartialEq)]
18pub enum BitState {
19 High,
20 Low,
21 DontCare,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq)]
25pub enum DigitalTriggerBehavior {
26 Auto,
27 While,
28 Start,
29 Stop,
30}
31
32impl DigitalTriggerBehavior {
33 pub fn as_str(&self) -> &'static str {
34 match self {
35 DigitalTriggerBehavior::Auto => "~",
36 DigitalTriggerBehavior::While => "",
37 DigitalTriggerBehavior::Start => "+",
38 DigitalTriggerBehavior::Stop => "-",
39 }
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq)]
44pub enum AnalogTriggerBehavior {
45 Auto,
46 Level,
47 Rising,
48 Falling,
49}
50
51impl AnalogTriggerBehavior {
52 pub fn as_str(&self) -> &'static str {
53 match self {
54 AnalogTriggerBehavior::Auto => "~",
55 AnalogTriggerBehavior::Level => "",
56 AnalogTriggerBehavior::Rising => "+",
57 AnalogTriggerBehavior::Falling => "-",
58 }
59 }
60}
61
62#[derive(Debug)]
63pub struct BitTriggerBuilder {
64 bit_states: [BitState; 9],
65}
66
67impl BitTriggerBuilder {
68 pub fn new() -> Self {
69 Self {
70 bit_states: [BitState::DontCare; 9],
71 }
72 }
73
74 pub fn set_bit(mut self, bit: usize, state: BitState) -> Self {
75 if bit >= self.bit_states.len() {
76 panic!(
77 "Bit index {} out of range, must be between 0 and {}",
78 bit,
79 self.bit_states.len() - 1
80 );
81 }
82 self.bit_states[bit] = state;
83 self
84 }
85
86 pub fn bit0(self, state: BitState) -> Self {
87 self.set_bit(0, state)
88 }
89
90 pub fn bit1(self, state: BitState) -> Self {
91 self.set_bit(1, state)
92 }
93
94 pub fn bit2(self, state: BitState) -> Self {
95 self.set_bit(2, state)
96 }
97
98 pub fn bit3(self, state: BitState) -> Self {
99 self.set_bit(3, state)
100 }
101
102 pub fn bit4(self, state: BitState) -> Self {
103 self.set_bit(4, state)
104 }
105
106 pub fn bit5(self, state: BitState) -> Self {
107 self.set_bit(5, state)
108 }
109
110 pub fn bit6(self, state: BitState) -> Self {
111 self.set_bit(6, state)
112 }
113
114 pub fn bit7(self, state: BitState) -> Self {
115 self.set_bit(7, state)
116 }
117
118 pub fn bit8(self, state: BitState) -> Self {
119 self.set_bit(8, state)
120 }
121
122 pub fn is_matching(self) -> DigitalTrigger {
123 DigitalTrigger::new(self.bit_states, DigitalTriggerBehavior::While)
124 }
125
126 pub fn starts_matching(self) -> DigitalTrigger {
127 DigitalTrigger::new(self.bit_states, DigitalTriggerBehavior::Start)
128 }
129
130 pub fn stops_matching(self) -> DigitalTrigger {
131 DigitalTrigger::new(self.bit_states, DigitalTriggerBehavior::Stop)
132 }
133
134 pub fn auto(self) -> DigitalTrigger {
136 DigitalTrigger::new(self.bit_states, DigitalTriggerBehavior::Auto)
137 }
138}
139
140impl Default for BitTriggerBuilder {
141 fn default() -> Self {
142 Self::new()
143 }
144}
145
146#[derive(Debug, Clone)]
147pub struct DigitalTrigger {
148 pub bit_states: [BitState; 9],
149 pub behavior: DigitalTriggerBehavior,
150}
151
152impl DigitalTrigger {
153 pub fn new(bit_states: [BitState; 9], behavior: DigitalTriggerBehavior) -> Self {
154 Self {
155 bit_states,
156 behavior,
157 }
158 }
159
160 pub fn start_capturing_when() -> BitTriggerBuilder {
161 BitTriggerBuilder::new()
162 }
163}
164
165impl TriggerConfig for DigitalTrigger {
166 fn into_trigger_fields(self) -> StringifiedTriggerConfig {
167 let mut relevant_bits = 0u32;
168 for (i, state) in self.bit_states.iter().enumerate() {
169 if *state != BitState::DontCare {
170 relevant_bits |= 1 << i;
171 }
172 }
173
174 let mut active_bits = 0u32;
175 for (i, state) in self.bit_states.iter().enumerate() {
176 if *state == BitState::High {
177 active_bits |= 1 << i;
178 }
179 }
180
181 let trigger_behavior_flag = self.behavior.as_str();
182 StringifiedTriggerConfig {
183 trigger_fields: format!(
184 "{}0x{:02x} 0x{:02x}",
185 trigger_behavior_flag, active_bits, relevant_bits
186 ),
187 }
188 }
189}
190
191#[derive(Debug, Clone)]
192pub struct AnalogTriggerBuilder {
193 pub volts: f64,
194 pub behavior: AnalogTriggerBehavior,
195}
196
197impl AnalogTriggerBuilder {
198 pub fn rising_edge(mut self) -> AnalogTriggerBuilder {
199 self.behavior = AnalogTriggerBehavior::Rising;
200 self
201 }
202
203 pub fn falling_edge(mut self) -> AnalogTriggerBuilder {
204 self.behavior = AnalogTriggerBehavior::Falling;
205 self
206 }
207
208 pub fn level(mut self) -> AnalogTriggerBuilder {
209 self.behavior = AnalogTriggerBehavior::Level;
210 self
211 }
212
213 pub fn auto(mut self) -> AnalogTriggerBuilder {
215 self.behavior = AnalogTriggerBehavior::Auto;
216 self
217 }
218
219 pub fn into_trigger(self, flea_probe: &FleaProbe) -> Result<AnalogTrigger, CaptureConfigError> {
220 let raw_level = (flea_probe.voltage_to_raw(self.volts) / 4.0 + 0.5) as i16;
221
222 if !(-1023..=1023).contains(&raw_level) {
223 return Err(CaptureConfigError::VoltageOutOfRange);
224 }
225 Ok(AnalogTrigger::new(raw_level, self.behavior))
226 }
227}
228
229#[derive(Debug, Clone)]
230pub struct AnalogTrigger {
231 pub level: i16,
232 pub behavior: AnalogTriggerBehavior,
233}
234
235impl AnalogTrigger {
236 pub fn new(raw_value: i16, behavior: AnalogTriggerBehavior) -> Self {
237 Self {
238 level: raw_value,
239 behavior,
240 }
241 }
242
243 pub fn start_capturing_when(volts: f64) -> AnalogTriggerBuilder {
244 AnalogTriggerBuilder {
245 volts,
246 behavior: AnalogTriggerBehavior::Auto,
247 }
248 }
249}
250
251impl TriggerConfig for AnalogTrigger {
252 fn into_trigger_fields(self) -> StringifiedTriggerConfig {
253 let trigger_behavior_flag = self.behavior.as_str();
254
255 StringifiedTriggerConfig {
256 trigger_fields: format!("{}{} 0", trigger_behavior_flag, self.level),
257 }
258 }
259}
260
261#[derive(Debug, Clone)]
264pub enum Trigger {
265 Analog(AnalogTrigger),
266 Digital(DigitalTrigger),
267}
268
269impl From<AnalogTrigger> for Trigger {
270 fn from(trigger: AnalogTrigger) -> Self {
271 Self::Analog(trigger)
272 }
273}
274
275impl From<DigitalTrigger> for Trigger {
276 fn from(trigger: DigitalTrigger) -> Self {
277 Self::Digital(trigger)
278 }
279}