nscope/scope/
analog_output.rs1use std::error::Error;
12use std::str::FromStr;
13use std::sync::{mpsc, RwLock};
14use std::sync::mpsc::Sender;
15
16use crate::scope::commands::ScopeCommand;
17
18use super::commands::Command;
19
20#[derive(Debug, PartialEq, Copy, Clone)]
22pub enum AnalogWaveType {
23 Sine = 0,
24 Triangle = 1,
25}
26
27impl FromStr for AnalogWaveType {
28 type Err = ();
29 fn from_str(input: &str) -> Result<AnalogWaveType, Self::Err> {
30 match input {
31 "Sine" => Ok(AnalogWaveType::Sine),
32 "Triangle" => Ok(AnalogWaveType::Triangle),
33 _ => Err(()),
34 }
35 }
36}
37
38#[derive(Debug, PartialEq, Copy, Clone)]
40pub enum AnalogSignalPolarity {
41 Unipolar,
42 Bipolar,
43}
44
45impl FromStr for AnalogSignalPolarity {
46 type Err = ();
47 fn from_str(input: &str) -> Result<AnalogSignalPolarity, Self::Err> {
48 match input {
49 "Unipolar" => Ok(AnalogSignalPolarity::Unipolar),
50 "Bipolar" => Ok(AnalogSignalPolarity::Bipolar),
51 _ => Err(()),
52 }
53 }
54}
55
56#[derive(Clone, Copy, Debug)]
58struct AnalogOutputState {
59 is_on: bool,
60 frequency: f64,
61 amplitude: f64,
62 wave_type: AnalogWaveType,
63 polarity: AnalogSignalPolarity,
64}
65
66#[derive(Debug)]
68pub struct AnalogOutput {
69 pub channel: usize,
70 command_tx: Sender<Command>,
71 state: RwLock<AnalogOutputState>,
72}
73
74impl AnalogOutput {
75 pub(super) fn create(cmd_tx: Sender<Command>, ax_channel: usize) -> Self {
76
77 let default_state = AnalogOutputState {
78 is_on: false,
79 frequency: 1.0,
80 amplitude: 1.0,
81 wave_type: AnalogWaveType::Sine,
82 polarity: AnalogSignalPolarity::Unipolar,
83 };
84
85 let ax = AnalogOutput {
86 command_tx: cmd_tx,
87 channel: ax_channel,
88 state: RwLock::new(default_state),
89 };
90
91 ax.set(default_state);
92 ax
93 }
94
95 fn set(&self, ax_state: AnalogOutputState) {
96 let (tx, rx) = mpsc::channel::<AnalogOutputState>();
98
99 let command = Command::SetAnalogOutput(AxRequest {
101 channel: self.channel,
102 ax_state,
103 sender: tx,
104
105 });
106
107 self.command_tx.send(command).unwrap();
109
110 let response_state = rx.recv().unwrap();
112 *self.state.write().unwrap() = response_state;
114 }
115
116 pub fn is_on(&self) -> bool {
117 self.state.read().unwrap().is_on
118 }
119 pub fn frequency(&self) -> f64 {
120 self.state.read().unwrap().frequency
121 }
122 pub fn amplitude(&self) -> f64 {
123 self.state.read().unwrap().amplitude
124 }
125 pub fn wave_type(&self) -> AnalogWaveType {
126 self.state.read().unwrap().wave_type
127 }
128 pub fn polarity(&self) -> AnalogSignalPolarity {
129 self.state.read().unwrap().polarity
130 }
131
132
133 pub fn turn_on(&self) {
134 let mut state = *self.state.read().unwrap();
135 state.is_on = true;
136 self.set(state)
137 }
138 pub fn turn_off(&self) {
139 let mut state = *self.state.read().unwrap();
140 state.is_on = false;
141 self.set(state)
142 }
143
144 pub fn set_frequency(&self, desired_hz: f64) {
145 let mut state = *self.state.read().unwrap();
146 state.frequency = desired_hz;
147 self.set(state)
148 }
149
150 pub fn set_amplitude(&self, desired_volts: f64) {
151 let mut state = *self.state.read().unwrap();
152 state.amplitude = desired_volts;
153 self.set(state)
154 }
155
156 pub fn set_wave_type(&self, wave_type: AnalogWaveType) {
157 let mut state = *self.state.read().unwrap();
158 state.wave_type = wave_type;
159 self.set(state)
160 }
161
162 pub fn set_polarity(&self, polarity: AnalogSignalPolarity) {
163 let mut state = *self.state.read().unwrap();
164 state.polarity = polarity;
165 self.set(state)
166 }
167}
168
169
170#[derive(Debug)]
171pub(super) struct AxRequest {
172 channel: usize,
173 ax_state: AnalogOutputState,
174 sender: Sender<AnalogOutputState>,
175}
176
177impl ScopeCommand for AxRequest {
178 fn fill_tx_buffer(&self, usb_buf: &mut [u8; 65]) -> Result<(), Box<dyn Error>> {
179 usb_buf[1] = 0x02;
180
181 let i_ch = 3 + 10 * self.channel;
182 if self.ax_state.is_on {
183 usb_buf[i_ch] = self.ax_state.wave_type as u8;
184 usb_buf[i_ch] |= 0x80;
185
186 let scaled_frequency = self.ax_state.frequency * 2.0_f64.powi(28) / 4000000.0;
187 let freq_register: u32 = scaled_frequency as u32;
188
189 usb_buf[i_ch + 1] = (freq_register & 0x00FF) as u8;
190 usb_buf[i_ch + 2] = ((freq_register & 0x3F00) >> 8) as u8;
191 usb_buf[i_ch + 3] = (freq_register >> 14 & 0x00FF) as u8;
192 usb_buf[i_ch + 4] = ((freq_register >> 14 & 0x3F00) >> 8) as u8;
193
194 if self.ax_state.amplitude < 0.0 {
195 usb_buf[i_ch] |= 0x2;
196 }
197 let rf = 49900.0;
198 let vin = 0.6;
199 let rm = 75.0;
200 let rv = 100000.0 / 257.0;
201
202 let gain: u8 = match self.ax_state.polarity {
203 AnalogSignalPolarity::Unipolar => ((vin * rf / self.ax_state.amplitude.abs() - rm) / rv) as u8,
204 AnalogSignalPolarity::Bipolar => {
205 ((vin * rf / 2.0 / self.ax_state.amplitude.abs() - rm) / rv) as u8
206 }
207 };
208
209 let offset: u8 = ((rm + rv * (gain as f64)) / (rm + rv * (gain as f64) + rf)
210 * self.ax_state.amplitude.abs()
211 * 255.0
212 / 3.05) as u8;
213
214 usb_buf[i_ch + 5] = gain;
215 usb_buf[i_ch + 6] = offset;
216 } else {
217 usb_buf[i_ch] = 0xFF;
218 }
219 Ok(())
220 }
221
222 fn handle_rx(&self, _usb_buf: &[u8; 64]) {
223 self.sender.send(self.ax_state).unwrap();
224 }
225
226 fn is_finished(&self) -> bool {
227 true
228 }
229}