Updating after review

This commit is contained in:
Ryan Summers 2021-05-07 13:02:14 +02:00
parent 89eaefd8d5
commit 7b76b1f14c
4 changed files with 50 additions and 50 deletions

View File

@ -26,7 +26,9 @@ pub struct Settings {
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2], iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
allow_hold: bool, allow_hold: bool,
force_hold: bool, force_hold: bool,
telemetry_period_secs: u16,
// The telemetry period in seconds.
telemetry_period: u16,
} }
impl Default for Settings { impl Default for Settings {
@ -44,7 +46,7 @@ impl Default for Settings {
allow_hold: false, allow_hold: false,
// Force suppress filter output updates. // Force suppress filter output updates.
force_hold: false, force_hold: false,
telemetry_period_secs: 10, telemetry_period: 10,
} }
} }
} }
@ -130,9 +132,13 @@ const APP: () = {
c.resources.dacs.1.acquire_buffer(), 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 let hold = c.resources.settings.force_hold
|| (c.resources.digital_inputs.1.is_high().unwrap() || (digital_inputs[1] && c.resources.settings.allow_hold);
&& c.resources.settings.allow_hold);
for channel in 0..adc_samples.len() { for channel in 0..adc_samples.len() {
for sample in 0..adc_samples[0].len() { for sample in 0..adc_samples[0].len() {
@ -153,16 +159,12 @@ const APP: () = {
} }
// Update telemetry measurements. // Update telemetry measurements.
c.resources.telemetry.latest_samples = c.resources.telemetry.adcs =
[adc_samples[0][0] as i16, adc_samples[1][0] as i16]; [adc_samples[0][0] as i16, adc_samples[1][0] as i16];
c.resources.telemetry.latest_outputs = c.resources.telemetry.dacs = [dac_samples[0][0], dac_samples[1][0]];
[dac_samples[0][0], dac_samples[1][0]];
c.resources.telemetry.digital_inputs = [ c.resources.telemetry.digital_inputs = digital_inputs;
c.resources.digital_inputs.0.is_high().unwrap(),
c.resources.digital_inputs.1.is_high().unwrap(),
];
} }
#[idle(resources=[network], spawn=[settings_update])] #[idle(resources=[network], spawn=[settings_update])]
@ -202,7 +204,7 @@ const APP: () = {
let telemetry_period = c let telemetry_period = c
.resources .resources
.settings .settings
.lock(|settings| settings.telemetry_period_secs); .lock(|settings| settings.telemetry_period);
// Schedule the telemetry task in the future. // Schedule the telemetry task in the future.
c.schedule c.schedule

View File

@ -56,7 +56,9 @@ pub struct Settings {
lockin_phase: i32, lockin_phase: i32,
output_conf: [Conf; 2], output_conf: [Conf; 2],
telemetry_period_secs: u16,
// The telemetry period in seconds.
telemetry_period: u16,
} }
impl Default for Settings { impl Default for Settings {
@ -73,7 +75,7 @@ impl Default for Settings {
lockin_phase: 0, // Demodulation LO phase offset lockin_phase: 0, // Demodulation LO phase offset
output_conf: [Conf::InPhase, Conf::Quadrature], output_conf: [Conf::InPhase, Conf::Quadrature],
telemetry_period_secs: 10, telemetry_period: 10,
} }
} }
} }
@ -237,11 +239,10 @@ const APP: () = {
} }
// Update telemetry measurements. // Update telemetry measurements.
c.resources.telemetry.latest_samples = c.resources.telemetry.adcs =
[adc_samples[0][0] as i16, adc_samples[1][0] as i16]; [adc_samples[0][0] as i16, adc_samples[1][0] as i16];
c.resources.telemetry.latest_outputs = c.resources.telemetry.dacs = [dac_samples[0][0], dac_samples[1][0]];
[dac_samples[0][0], dac_samples[1][0]];
} }
#[idle(resources=[network], spawn=[settings_update])] #[idle(resources=[network], spawn=[settings_update])]
@ -285,7 +286,7 @@ const APP: () = {
let telemetry_period = c let telemetry_period = c
.resources .resources
.settings .settings
.lock(|settings| settings.telemetry_period_secs); .lock(|settings| settings.telemetry_period);
// Schedule the telemetry task in the future. // Schedule the telemetry task in the future.
c.schedule c.schedule

View File

@ -69,12 +69,12 @@ impl rtic::Monotonic for SystemTimer {
// is taken when reading and modifying register values. // is taken when reading and modifying register values.
let regs = unsafe { &*hal::device::TIM15::ptr() }; let regs = unsafe { &*hal::device::TIM15::ptr() };
loop { cortex_m::interrupt::free(|_cs| {
// Checking for overflows of the current counter must be performed atomically. Any loop {
// other task that is accessing the current time could potentially race for the // Checking for overflows of the current counter must be performed atomically. Any
// registers. Note that this is only required for writing to global state (e.g. timer // other task that is accessing the current time could potentially race for the
// registers and overflow counter) // registers. Note that this is only required for writing to global state (e.g. timer
if let Some(time) = cortex_m::interrupt::free(|_cs| { // registers and overflow counter)
// Check for overflows and clear the overflow bit atomically. This must be done in // 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. // a critical section to prevent race conditions on the status register.
if regs.sr.read().uif().bit_is_set() { 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() { if regs.sr.read().uif().bit_is_clear() {
// Note(unsafe): We are in a critical section, so it is safe to read the // Note(unsafe): We are in a critical section, so it is safe to read the
// global variable. // global variable.
unsafe { Some((OVERFLOWS * 65535 + current_value) as i32) } return unsafe {
} else { ((OVERFLOWS << 16) + current_value) as i32
None };
} }
}) {
return time;
} }
} })
} }
/// Reset the timer count. /// Reset the timer count.

View File

@ -33,9 +33,9 @@ pub struct TelemetryClient<T: Serialize> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct TelemetryBuffer { pub struct TelemetryBuffer {
/// The latest input sample on ADC0/ADC1. /// The latest input sample on ADC0/ADC1.
pub latest_samples: [i16; 2], pub adcs: [i16; 2],
/// The latest output code on DAC0/DAC1. /// The latest output code on DAC0/DAC1.
pub latest_outputs: [u16; 2], pub dacs: [u16; 2],
/// The latest digital input states during processing. /// The latest digital input states during processing.
pub digital_inputs: [bool; 2], pub digital_inputs: [bool; 2],
} }
@ -47,16 +47,16 @@ pub struct TelemetryBuffer {
/// overhead. /// overhead.
#[derive(Serialize)] #[derive(Serialize)]
pub struct Telemetry { pub struct Telemetry {
input_levels: [f32; 2], adcs: [f32; 2],
output_levels: [f32; 2], dacs: [f32; 2],
digital_inputs: [bool; 2], digital_inputs: [bool; 2],
} }
impl Default for TelemetryBuffer { impl Default for TelemetryBuffer {
fn default() -> Self { fn default() -> Self {
Self { Self {
latest_samples: [0, 0], adcs: [0, 0],
latest_outputs: [0, 0], dacs: [0, 0],
digital_inputs: [false, false], 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 // 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 // the very front-end of the signal, there's an analog input multiplier that is
// configurable by the user. // configurable by the user.
let adc_volts_per_lsb = 5.0 * 4.096 / 2.0 / i16::MAX as f32;
let in0_volts = let in0_volts =
(self.latest_samples[0] as f32 / i16::MAX as f32) * 4.096 / 2.0 (adc_volts_per_lsb * self.adcs[0] as f32) / afe0.as_multiplier();
* 5.0
/ afe0.as_multiplier();
let in1_volts = let in1_volts =
(self.latest_samples[1] as f32 / i16::MAX as f32) * 4.096 / 2.0 (adc_volts_per_lsb * self.adcs[1] as f32) / afe1.as_multiplier();
* 5.0
/ afe1.as_multiplier();
// The output voltage is generated by the DAC with an output range of +/- 4.096 V. This // 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 // 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 // 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, // 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. // 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)) // Note: The MAX code corresponding to +VREF is not programmable, as it is 1 bit larger
- 10.24; // than full-scale.
let out1_volts = (10.24 * 2.0) let dac_volts_per_lsb = 10.24 * 2.0 / (u16::MAX as u32 + 1) as f32;
* (self.latest_outputs[1] as f32 / (u16::MAX as f32)) let dac_offset = -10.24;
- 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 { Telemetry {
input_levels: [in0_volts, in1_volts], adcs: [in0_volts, in1_volts],
output_levels: [out0_volts, out1_volts], dacs: [out0_volts, out1_volts],
digital_inputs: self.digital_inputs, digital_inputs: self.digital_inputs,
} }
} }