diff --git a/firmware/src/command_parser.rs b/firmware/src/command_parser.rs index b1f6cd5..db72ab5 100644 --- a/firmware/src/command_parser.rs +++ b/firmware/src/command_parser.rs @@ -10,7 +10,6 @@ use nom::{ error::ErrorKind, }; use lexical_core as lexical; -use super::session::ReportMode; #[derive(Clone, Debug)] @@ -63,7 +62,8 @@ impl fmt::Display for Error { #[derive(Debug, Clone)] pub enum ShowCommand { - ReportMode, + Input, + Reporting, Pid, } @@ -83,7 +83,7 @@ pub enum PidParameter { pub enum Command { Quit, Show(ShowCommand), - Report(ReportMode), + Reporting(bool), Pwm { width: u32, total: u32, @@ -112,10 +112,9 @@ fn float(input: &[u8]) -> IResult<&[u8], Result> { Ok((input, result)) } -fn report_mode(input: &[u8]) -> IResult<&[u8], ReportMode> { - alt((value(ReportMode::Off, tag("off")), - value(ReportMode::Once, tag("once")), - value(ReportMode::Continuous, tag("continuous")) +fn off_on(input: &[u8]) -> IResult<&[u8], bool> { + alt((value(false, tag("off")), + value(true, tag("on")) ))(input) } @@ -133,13 +132,16 @@ fn report(input: &[u8]) -> IResult<&[u8], Command> { alt(( preceded( whitespace, - map(report_mode, - |mode| Command::Report(mode)) + // `report mode ` - Switch repoting mode + map(off_on, + |reporting| Command::Reporting(reporting)) ), - |input| Ok((input, Command::Show(ShowCommand::ReportMode))) + // `report mode` - Show current reporting state + |input| Ok((input, Command::Show(ShowCommand::Reporting))) )) )), - |input| Ok((input, Command::Report(ReportMode::Once))) + // `report` - Report once + |input| Ok((input, Command::Show(ShowCommand::Input))) )) )(input) } diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 2572e32..7fa4fa0 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -76,8 +76,6 @@ macro_rules! create_socket { ) } -/// In nanoseconds -const REPORT_INTERVAL: u64 = 100_000; const DEFAULT_PID_PARAMETERS: pid::Parameters = pid::Parameters { kp: 1.0, ki: 1.0, @@ -88,6 +86,8 @@ const DEFAULT_PID_PARAMETERS: pid::Parameters = pid::Parameters { integral_max: 0xffff as f32, }; +pub const CHANNELS: usize = 2; + #[entry] fn main() -> ! { let mut stdout = hio::hstdout().unwrap(); @@ -204,11 +204,7 @@ fn main() -> ! { (Session::new(), tcp_handle7), ]; - let mut last_report = get_time(); - let mut next_report = get_time(); - // cumulative (sum, count) - let mut sample = [(0u64, 0usize); 2]; - let mut report = [None; 2]; + let mut report = [None; CHANNELS]; loop { // ADC input adc.data_ready() @@ -216,30 +212,14 @@ fn main() -> ! { writeln!(stdout, "ADC error: {:?}", e).unwrap(); None }).map(|channel| { + let now = get_time(); let data = adc.read_data().unwrap(); - sample[usize::from(channel)].0 += u64::from(data); - sample[usize::from(channel)].1 += 1; - }); - let now = get_time(); - if now >= next_report { - if now < next_report + REPORT_INTERVAL { - // Try to keep interval constant - next_report += REPORT_INTERVAL; - } else { - // Bad jitter, catch up - next_report = now + REPORT_INTERVAL; - } - for (channel, sample) in sample.iter().enumerate() { - if sample.1 > 0 { - // TODO: calculate med instead of avg? - report[channel] = Some(sample.0 / (sample.1 as u64)); + report[usize::from(channel)] = Some((now, data)); + + for (session, _) in sessions_handles.iter_mut() { + session.set_report_pending(channel.into()); } - } - for (session, _) in sessions_handles.iter_mut() { - session.set_report_pending(); - } - last_report = get_time(); - } + }); for (session, tcp_handle) in sessions_handles.iter_mut() { let socket = &mut *sockets.get::(*tcp_handle); @@ -260,11 +240,18 @@ fn main() -> ! { Ok(SessionOutput::Command(command)) => match command { Command::Quit => socket.close(), - Command::Report(mode) => { - let _ = writeln!(socket, "Report mode: {}", mode); + Command::Reporting(reporting) => { + let _ = writeln!(socket, "Report mode set to {}", if reporting { "on" } else { "off" }); } - Command::Show(ShowCommand::ReportMode) => { - let _ = writeln!(socket, "Report mode: {}", session.report_mode()); + Command::Show(ShowCommand::Reporting) => { + let _ = writeln!(socket, "Report mode: {}", if session.reporting() { "on" } else { "off" }); + } + Command::Show(ShowCommand::Input) => { + for (channel, report) in report.iter().enumerate() { + report.map(|(time, data)| { + let _ = writeln!(socket, "t={}, sens{}={}", time, channel, data); + }); + } } Command::Show(ShowCommand::Pid) => { let _ = writeln!(socket, "PID settings"); @@ -316,15 +303,13 @@ fn main() -> ! { Err(_) => {} } } - if socket.may_send() && session.is_report_pending() { - let _ = write!(socket, "t={}", last_report); - for (channel, report_data) in report.iter().enumerate() { - report_data.map(|report_data| { - let _ = write!(socket, " sens{}={:06X}", channel, report_data); + if socket.may_send() { + if let Some(channel) = session.is_report_pending() { + report[channel].map(|(time, data)| { + let _ = writeln!(socket, "t={} sens{}={:06X}", time, channel, data); }); + session.mark_report_sent(channel); } - let _ = writeln!(socket, ""); - session.mark_report_sent(); } } match iface.poll(&mut sockets, Instant::from_millis((get_time() / 1000) as i64)) { diff --git a/firmware/src/session.rs b/firmware/src/session.rs index b6c22ef..dc9faec 100644 --- a/firmware/src/session.rs +++ b/firmware/src/session.rs @@ -1,6 +1,6 @@ use core::ops::Deref; -use core::fmt; use super::command_parser::{Command, Error as ParserError}; +use super::CHANNELS; const MAX_LINE_LEN: usize = 64; @@ -54,23 +54,6 @@ impl Deref for LineResult { } } -#[derive(Debug, Clone, Copy)] -pub enum ReportMode { - Off, - Once, - Continuous, -} - -impl fmt::Display for ReportMode { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - ReportMode::Off => "off", - ReportMode::Once => "once", - ReportMode::Continuous => "continuous", - }.fmt(fmt) - } -} - pub enum SessionOutput { Nothing, Command(Command), @@ -86,16 +69,16 @@ impl From> for SessionOutput { pub struct Session { reader: LineReader, - report_mode: ReportMode, - report_pending: bool, + reporting: bool, + report_pending: [bool; CHANNELS], } impl Session { pub fn new() -> Self { Session { reader: LineReader::new(), - report_mode: ReportMode::Off, - report_pending: false, + reporting: false, + report_pending: [false; CHANNELS], } } @@ -103,30 +86,34 @@ impl Session { self.reader.pos > 0 } - pub fn report_mode(&self) -> ReportMode { - self.report_mode + pub fn reporting(&self) -> bool { + self.reporting } - pub fn set_report_pending(&mut self) { - self.report_pending = true; - } - - pub fn is_report_pending(&self) -> bool { - match self.report_mode { - ReportMode::Off => false, - _ => self.report_pending, + pub fn set_report_pending(&mut self, channel: usize) { + if self.reporting { + self.report_pending[channel] = true; } } - pub fn mark_report_sent(&mut self) { - self.report_pending = false; - match self.report_mode { - ReportMode::Once => - self.report_mode = ReportMode::Off, - _ => {} + pub fn is_report_pending(&self) -> Option { + if ! self.reporting { + None + } else { + self.report_pending.iter() + .enumerate() + .fold(None, |result, (channel, report_pending)| { + result.or_else(|| { + if *report_pending { Some(channel) } else { None } + }) + }) } } + pub fn mark_report_sent(&mut self, channel: usize) { + self.report_pending[channel] = false; + } + pub fn feed(&mut self, buf: &[u8]) -> (usize, SessionOutput) { let mut buf_bytes = 0; for (i, b) in buf.iter().enumerate() { @@ -136,8 +123,8 @@ impl Session { Some(line) => { let command = Command::parse(&line); match command { - Ok(Command::Report(mode)) => { - self.report_mode = mode; + Ok(Command::Reporting(reporting)) => { + self.reporting = reporting; } _ => {} }