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],
|
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
|
||||||
|
@ -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
|
||||||
|
@ -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() };
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|_cs| {
|
||||||
loop {
|
loop {
|
||||||
// Checking for overflows of the current counter must be performed atomically. Any
|
// 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
|
// 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. Note that this is only required for writing to global state (e.g. timer
|
||||||
// registers and overflow counter)
|
// 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
|
// 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.
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user