From 3d1740b23b70d11268ede38f0695da132f180b04 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 13 May 2020 00:04:55 +0200 Subject: [PATCH] refactor into Channels::poll_adc() --- src/channel_state.rs | 6 ++--- src/channels.rs | 48 +++++++++++++++++++++++++++++++++ src/main.rs | 63 +++++++++++++++----------------------------- src/session.rs | 3 +-- 4 files changed, 73 insertions(+), 47 deletions(-) diff --git a/src/channel_state.rs b/src/channel_state.rs index 75df0b2..26e3f61 100644 --- a/src/channel_state.rs +++ b/src/channel_state.rs @@ -6,7 +6,7 @@ pub struct ChannelState { pub adc_data: Option, pub adc_time: Instant, pub dac_value: u32, - pub pid_enabled: bool, + pub pid_engaged: bool, pub pid: pid::Controller, pub sh: sh::Parameters, } @@ -17,7 +17,7 @@ impl Default for ChannelState { adc_data: None, adc_time: Instant::from_secs(0), dac_value: 0, - pid_enabled: false, + pid_engaged: false, pid: pid::Controller::new(pid::Parameters::default()), sh: sh::Parameters::default(), } @@ -26,7 +26,7 @@ impl Default for ChannelState { impl ChannelState { /// Update PID state on ADC input, calculate new DAC output - pub fn update_adc(&mut self, now: Instant, adc_data: u32) { + pub fn update_pid(&mut self, now: Instant, adc_data: u32) { self.adc_data = Some(adc_data); self.adc_time = now; diff --git a/src/channels.rs b/src/channels.rs index 5fa918c..6937d34 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,9 +1,14 @@ +use stm32f4xx_hal::hal::digital::v2::OutputPin; +use smoltcp::time::Instant; use crate::{ ad7172, channel::{Channel, Channel0, Channel1}, + channel_state::ChannelState, pins, }; +pub const CHANNELS: usize = 2; + pub struct Channels { pub channel0: Channel, pub channel1: Channel, @@ -27,4 +32,47 @@ impl Channels { Channels { channel0, channel1, adc, pwm } } + + pub fn channel_state>(&mut self, channel: I) -> &mut ChannelState { + match channel.into() { + 0 => &mut self.channel0.state, + 1 => &mut self.channel1.state, + _ => unreachable!(), + } + } + + /// ADC input + PID processing + pub fn poll_adc(&mut self, instant: Instant) -> Option { + self.adc.data_ready().unwrap().map(|channel| { + let data = self.adc.read_data().unwrap(); + + let dac_value = { + let state = self.channel_state(channel); + state.update_pid(instant, data); + + if state.pid_engaged { + Some(state.dac_value) + } else { + None + } + }; + if let Some(dac_value) = dac_value { + // Forward PID output to i_set DAC + match channel { + 0 => { + self.channel0.dac.set(dac_value).unwrap(); + self.channel0.shdn.set_high().unwrap(); + } + 1 => { + self.channel1.dac.set(dac_value).unwrap(); + self.channel1.shdn.set_high().unwrap(); + } + _ => + unreachable!(), + } + } + + channel + }) + } } diff --git a/src/main.rs b/src/main.rs index 1f5226b..3cd1036 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,17 +39,16 @@ mod net; mod server; use server::Server; mod session; -use session::{CHANNELS, Session, SessionOutput}; +use session::{Session, SessionOutput}; mod command_parser; use command_parser::{Command, ShowCommand, PwmPin}; mod timer; mod pid; mod steinhart_hart; mod channels; -use channels::Channels; +use channels::{CHANNELS, Channels}; mod channel; mod channel_state; -use channel_state::ChannelState; const HSE: MegaHertz = MegaHertz(8); @@ -96,9 +95,6 @@ fn main() -> ! { dp.ADC1, dp.ADC2, ); let mut channels = Channels::new(pins); - let mut channel_states: [ChannelState; CHANNELS] = [ - ChannelState::default(), ChannelState::default() - ]; timer::setup(cp.SYST, clocks); #[cfg(not(feature = "generate-hwaddr"))] @@ -114,31 +110,10 @@ fn main() -> ! { Server::::run(iface, |server| { loop { let instant = Instant::from_millis(i64::from(timer::now())); - // ADC input - channels.adc.data_ready().unwrap().map(|channel| { - let data = channels.adc.read_data().unwrap(); - - let state = &mut channel_states[usize::from(channel)]; - state.update_adc(instant, data); - - if state.pid_enabled { - // Forward PID output to i_set DAC - match channel { - 0 => { - channels.channel0.dac.set(state.dac_value).unwrap(); - channels.channel0.shdn.set_high().unwrap(); - } - 1 => { - channels.channel1.dac.set(state.dac_value).unwrap(); - channels.channel1.shdn.set_high().unwrap(); - } - _ => - unreachable!(), - } - } - + let updated_channel = channels.poll_adc(instant); + if let Some(channel) = updated_channel { server.for_each(|_, session| session.set_report_pending(channel.into())); - }); + } let instant = Instant::from_millis(i64::from(timer::now())); cortex_m::interrupt::free(net::clear_pending); @@ -165,7 +140,8 @@ fn main() -> ! { let _ = writeln!(socket, "report={}", if session.reporting() { "on" } else { "off" }); } Command::Show(ShowCommand::Input) => { - for (channel, state) in channel_states.iter().enumerate() { + for channel in 0..CHANNELS { + let state = channels.channel_state(channel); if let Some(adc_data) = state.adc_data { let _ = writeln!( socket, "t={} raw{}=0x{:06X}", @@ -180,7 +156,8 @@ fn main() -> ! { let _ = writeln!(socket, "ref0={}", ref0); } Command::Show(ShowCommand::Pid) => { - for (channel, state) in channel_states.iter().enumerate() { + for channel in 0..CHANNELS { + let state = channels.channel_state(channel); let _ = writeln!(socket, "PID settings for channel {}", channel); let pid = &state.pid; let _ = writeln!(socket, "- target={:.4}", pid.target); @@ -206,11 +183,12 @@ fn main() -> ! { } } Command::Show(ShowCommand::Pwm) => { - for (channel, state) in channel_states.iter().enumerate() { + for channel in 0..CHANNELS { + let state = channels.channel_state(channel); let _ = writeln!( socket, "channel {}: PID={}", channel, - if state.pid_enabled { "engaged" } else { "disengaged" } + if state.pid_engaged { "engaged" } else { "disengaged" } ); let _ = writeln!(socket, "- i_set={}/{}", state.dac_value, ad5680::MAX_VALUE); fn show_pwm_channel(mut socket: S, name: &str, pin: &P) @@ -241,7 +219,8 @@ fn main() -> ! { } } Command::Show(ShowCommand::SteinhartHart) => { - for (channel, state) in channel_states.iter().enumerate() { + for channel in 0..CHANNELS { + let state = channels.channel_state(channel); let _ = writeln!( socket, "channel {}: Steinhart-Hart equation parameters", channel, @@ -253,7 +232,7 @@ fn main() -> ! { } } Command::Show(ShowCommand::PostFilter) => { - for (channel, _) in channel_states.iter().enumerate() { + for channel in 0..CHANNELS { match channels.adc.get_postfilter(channel as u8).unwrap() { Some(filter) => { let _ = writeln!( @@ -271,12 +250,12 @@ fn main() -> ! { } } Command::PwmPid { channel } => { - channel_states[channel].pid_enabled = true; + channels.channel_state(channel).pid_engaged = true; let _ = writeln!(socket, "channel {}: PID enabled to control PWM", channel ); } Command::Pwm { channel, pin: PwmPin::ISet, duty } if duty <= ad5680::MAX_VALUE => { - channel_states[channel].pid_enabled = false; + channels.channel_state(channel).pid_engaged = false; match channel { 0 => { channels.channel0.dac.set(duty).unwrap(); @@ -288,7 +267,7 @@ fn main() -> ! { } _ => unreachable!(), } - channel_states[channel].dac_value = duty; + channels.channel_state(channel).dac_value = duty; let _ = writeln!( socket, "channel {}: PWM duty cycle manually set to {}/{}", channel, duty, ad5680::MAX_VALUE @@ -335,7 +314,7 @@ fn main() -> ! { let _ = writeln!(socket, "error: PWM duty range must fit 16 bits"); } Command::Pid { channel, parameter, value } => { - let pid = &mut channel_states[channel].pid; + let pid = &mut channels.channel_state(channel).pid; use command_parser::PidParameter::*; match parameter { Target => @@ -361,7 +340,7 @@ fn main() -> ! { let _ = writeln!(socket, "PID parameter updated"); } Command::SteinhartHart { channel, parameter, value } => { - let sh = &mut channel_states[channel].sh; + let sh = &mut channels.channel_state(channel).sh; use command_parser::ShParameter::*; match parameter { T0 => sh.t0 = value, @@ -397,7 +376,7 @@ fn main() -> ! { } } else if socket.can_send() && socket.send_capacity() - socket.send_queue() > 256 { while let Some(channel) = session.is_report_pending() { - let state = &mut channel_states[usize::from(channel)]; + let state = &mut channels.channel_state(usize::from(channel)); let _ = writeln!( socket, "t={} raw{}=0x{:06X}", state.adc_time, channel, state.adc_data.unwrap_or(0) diff --git a/src/session.rs b/src/session.rs index 664c839..4e594b9 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1,4 +1,5 @@ use super::command_parser::{Command, Error as ParserError}; +use super::channels::CHANNELS; const MAX_LINE_LEN: usize = 64; @@ -50,8 +51,6 @@ impl From> for SessionOutput { } } -pub const CHANNELS: usize = 2; - pub struct Session { reader: LineReader, reporting: bool,