Updating after review
This commit is contained in:
parent
89eaefd8d5
commit
7b76b1f14c
@ -26,7 +26,9 @@ pub struct Settings {
|
||||
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
||||
allow_hold: bool,
|
||||
force_hold: bool,
|
||||
telemetry_period_secs: u16,
|
||||
|
||||
// The telemetry period in seconds.
|
||||
telemetry_period: u16,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@ -44,7 +46,7 @@ impl Default for Settings {
|
||||
allow_hold: false,
|
||||
// Force suppress filter output updates.
|
||||
force_hold: false,
|
||||
telemetry_period_secs: 10,
|
||||
telemetry_period: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,9 +132,13 @@ const APP: () = {
|
||||
c.resources.dacs.1.acquire_buffer(),
|
||||
];
|
||||
|
||||
let digital_inputs = [
|
||||
c.resources.digital_inputs.0.is_high().unwrap(),
|
||||
c.resources.digital_inputs.1.is_high().unwrap(),
|
||||
];
|
||||
|
||||
let hold = c.resources.settings.force_hold
|
||||
|| (c.resources.digital_inputs.1.is_high().unwrap()
|
||||
&& c.resources.settings.allow_hold);
|
||||
|| (digital_inputs[1] && c.resources.settings.allow_hold);
|
||||
|
||||
for channel in 0..adc_samples.len() {
|
||||
for sample in 0..adc_samples[0].len() {
|
||||
@ -153,16 +159,12 @@ const APP: () = {
|
||||
}
|
||||
|
||||
// Update telemetry measurements.
|
||||
c.resources.telemetry.latest_samples =
|
||||
c.resources.telemetry.adcs =
|
||||
[adc_samples[0][0] as i16, adc_samples[1][0] as i16];
|
||||
|
||||
c.resources.telemetry.latest_outputs =
|
||||
[dac_samples[0][0], dac_samples[1][0]];
|
||||
c.resources.telemetry.dacs = [dac_samples[0][0], dac_samples[1][0]];
|
||||
|
||||
c.resources.telemetry.digital_inputs = [
|
||||
c.resources.digital_inputs.0.is_high().unwrap(),
|
||||
c.resources.digital_inputs.1.is_high().unwrap(),
|
||||
];
|
||||
c.resources.telemetry.digital_inputs = digital_inputs;
|
||||
}
|
||||
|
||||
#[idle(resources=[network], spawn=[settings_update])]
|
||||
@ -202,7 +204,7 @@ const APP: () = {
|
||||
let telemetry_period = c
|
||||
.resources
|
||||
.settings
|
||||
.lock(|settings| settings.telemetry_period_secs);
|
||||
.lock(|settings| settings.telemetry_period);
|
||||
|
||||
// Schedule the telemetry task in the future.
|
||||
c.schedule
|
||||
|
@ -56,7 +56,9 @@ pub struct Settings {
|
||||
lockin_phase: i32,
|
||||
|
||||
output_conf: [Conf; 2],
|
||||
telemetry_period_secs: u16,
|
||||
|
||||
// The telemetry period in seconds.
|
||||
telemetry_period: u16,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@ -73,7 +75,7 @@ impl Default for Settings {
|
||||
lockin_phase: 0, // Demodulation LO phase offset
|
||||
|
||||
output_conf: [Conf::InPhase, Conf::Quadrature],
|
||||
telemetry_period_secs: 10,
|
||||
telemetry_period: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,11 +239,10 @@ const APP: () = {
|
||||
}
|
||||
|
||||
// Update telemetry measurements.
|
||||
c.resources.telemetry.latest_samples =
|
||||
c.resources.telemetry.adcs =
|
||||
[adc_samples[0][0] as i16, adc_samples[1][0] as i16];
|
||||
|
||||
c.resources.telemetry.latest_outputs =
|
||||
[dac_samples[0][0], dac_samples[1][0]];
|
||||
c.resources.telemetry.dacs = [dac_samples[0][0], dac_samples[1][0]];
|
||||
}
|
||||
|
||||
#[idle(resources=[network], spawn=[settings_update])]
|
||||
@ -285,7 +286,7 @@ const APP: () = {
|
||||
let telemetry_period = c
|
||||
.resources
|
||||
.settings
|
||||
.lock(|settings| settings.telemetry_period_secs);
|
||||
.lock(|settings| settings.telemetry_period);
|
||||
|
||||
// Schedule the telemetry task in the future.
|
||||
c.schedule
|
||||
|
@ -69,12 +69,12 @@ impl rtic::Monotonic for SystemTimer {
|
||||
// is taken when reading and modifying register values.
|
||||
let regs = unsafe { &*hal::device::TIM15::ptr() };
|
||||
|
||||
cortex_m::interrupt::free(|_cs| {
|
||||
loop {
|
||||
// Checking for overflows of the current counter must be performed atomically. Any
|
||||
// other task that is accessing the current time could potentially race for the
|
||||
// registers. Note that this is only required for writing to global state (e.g. timer
|
||||
// registers and overflow counter)
|
||||
if let Some(time) = cortex_m::interrupt::free(|_cs| {
|
||||
// Check for overflows and clear the overflow bit atomically. This must be done in
|
||||
// a critical section to prevent race conditions on the status register.
|
||||
if regs.sr.read().uif().bit_is_set() {
|
||||
@ -91,14 +91,12 @@ impl rtic::Monotonic for SystemTimer {
|
||||
if regs.sr.read().uif().bit_is_clear() {
|
||||
// Note(unsafe): We are in a critical section, so it is safe to read the
|
||||
// global variable.
|
||||
unsafe { Some((OVERFLOWS * 65535 + current_value) as i32) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
return time;
|
||||
return unsafe {
|
||||
((OVERFLOWS << 16) + current_value) as i32
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Reset the timer count.
|
||||
|
@ -33,9 +33,9 @@ pub struct TelemetryClient<T: Serialize> {
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TelemetryBuffer {
|
||||
/// The latest input sample on ADC0/ADC1.
|
||||
pub latest_samples: [i16; 2],
|
||||
pub adcs: [i16; 2],
|
||||
/// The latest output code on DAC0/DAC1.
|
||||
pub latest_outputs: [u16; 2],
|
||||
pub dacs: [u16; 2],
|
||||
/// The latest digital input states during processing.
|
||||
pub digital_inputs: [bool; 2],
|
||||
}
|
||||
@ -47,16 +47,16 @@ pub struct TelemetryBuffer {
|
||||
/// overhead.
|
||||
#[derive(Serialize)]
|
||||
pub struct Telemetry {
|
||||
input_levels: [f32; 2],
|
||||
output_levels: [f32; 2],
|
||||
adcs: [f32; 2],
|
||||
dacs: [f32; 2],
|
||||
digital_inputs: [bool; 2],
|
||||
}
|
||||
|
||||
impl Default for TelemetryBuffer {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
latest_samples: [0, 0],
|
||||
latest_outputs: [0, 0],
|
||||
adcs: [0, 0],
|
||||
dacs: [0, 0],
|
||||
digital_inputs: [false, false],
|
||||
}
|
||||
}
|
||||
@ -79,30 +79,29 @@ impl TelemetryBuffer {
|
||||
// input signal has a fixed gain of 1/5 through a static input active filter. Finally, at
|
||||
// the very front-end of the signal, there's an analog input multiplier that is
|
||||
// configurable by the user.
|
||||
let adc_volts_per_lsb = 5.0 * 4.096 / 2.0 / i16::MAX as f32;
|
||||
let in0_volts =
|
||||
(self.latest_samples[0] as f32 / i16::MAX as f32) * 4.096 / 2.0
|
||||
* 5.0
|
||||
/ afe0.as_multiplier();
|
||||
(adc_volts_per_lsb * self.adcs[0] as f32) / afe0.as_multiplier();
|
||||
let in1_volts =
|
||||
(self.latest_samples[1] as f32 / i16::MAX as f32) * 4.096 / 2.0
|
||||
* 5.0
|
||||
/ afe1.as_multiplier();
|
||||
(adc_volts_per_lsb * self.adcs[1] as f32) / afe1.as_multiplier();
|
||||
|
||||
// The output voltage is generated by the DAC with an output range of +/- 4.096 V. This
|
||||
// signal then passes through a 2.5x gain stage. Note that the DAC operates using unsigned
|
||||
// integers, and u16::MAX / 2 is considered zero voltage output. Thus, the dynamic range of
|
||||
// the output stage is +/- 10.24 V. At a DAC code of zero, there is an output of -10.24 V,
|
||||
// and at a max DAC code, there is an output of 10.24 V.
|
||||
let out0_volts = (10.24 * 2.0)
|
||||
* (self.latest_outputs[0] as f32 / (u16::MAX as f32))
|
||||
- 10.24;
|
||||
let out1_volts = (10.24 * 2.0)
|
||||
* (self.latest_outputs[1] as f32 / (u16::MAX as f32))
|
||||
- 10.24;
|
||||
//
|
||||
// Note: The MAX code corresponding to +VREF is not programmable, as it is 1 bit larger
|
||||
// than full-scale.
|
||||
let dac_volts_per_lsb = 10.24 * 2.0 / (u16::MAX as u32 + 1) as f32;
|
||||
let dac_offset = -10.24;
|
||||
|
||||
let out0_volts = dac_volts_per_lsb * self.dacs[0] as f32 + dac_offset;
|
||||
let out1_volts = dac_volts_per_lsb * self.dacs[1] as f32 + dac_offset;
|
||||
|
||||
Telemetry {
|
||||
input_levels: [in0_volts, in1_volts],
|
||||
output_levels: [out0_volts, out1_volts],
|
||||
adcs: [in0_volts, in1_volts],
|
||||
dacs: [out0_volts, out1_volts],
|
||||
digital_inputs: self.digital_inputs,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user