diff --git a/README.md b/README.md index ce4d504..955c638 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Send commands as simple text string terminated by `\n`. Responses are formatted as line-delimited JSON. | Syntax | Function | -| --- | --- | +|----------------------------------|----------------------------------------------------------------------| | `report` | Show current input | | `report mode` | Show current report mode | | `report mode ` | Set report mode | @@ -124,6 +124,7 @@ formatted as line-delimited JSON. | `reset` | Reset the device | | `dfu` | Reset device and enters USB device firmware update (DFU) mode | | `ipv4 [Y.Y.Y.Y]` | Configure IPv4 address, netmask length, and optional default gateway | +| `fan` | Show current fan settings and sensors' measurements | | `fan ` | Set fan power with values from 0 to 100, where 0 is auto mode (TODO) | diff --git a/flake.nix b/flake.nix index c28f806..02b7c70 100644 --- a/flake.nix +++ b/flake.nix @@ -69,7 +69,7 @@ buildInputs = with pkgs; [ rustPlatform.rust.rustc rustPlatform.rust.cargo - openocd dfu-util + openocd dfu-util gcc-arm-embedded-10 ] ++ (with python3Packages; [ numpy matplotlib ]); diff --git a/src/channels.rs b/src/channels.rs index 813493e..b40656b 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,3 +1,4 @@ +use core::cmp::max_by; use heapless::{consts::{U2, U1024}, Vec}; use serde::{Serialize, Serializer}; use smoltcp::time::Instant; @@ -82,6 +83,10 @@ impl Channels { } } + pub fn fan_available(&self) -> bool { + self.hw_rev.major == 2 && self.hw_rev.minor == 2 + } + pub fn channel_state>(&mut self, channel: I) -> &mut ChannelState { match channel.into() { 0 => &mut self.channel0.state, @@ -461,7 +466,7 @@ impl Channels { (self.get_pwm(0, PwmPin::Fan) * 100.0) as u32 } - fn report(&mut self, channel: usize, tacho: Option) -> Report { + fn report(&mut self, channel: usize) -> Report { let vref = self.channel_state(channel).vref; let i_set = self.get_i(channel); let i_tec = self.read_itec(channel); @@ -486,15 +491,14 @@ impl Channels { tec_i, tec_u_meas: self.get_tec_v(channel), pid_output, - tacho, hwrev: self.hw_rev } } - pub fn reports_json(&mut self, tacho: Option) -> Result { + pub fn reports_json(&mut self) -> Result { let mut reports = Vec::<_, U2>::new(); for channel in 0..CHANNELS { - let _ = reports.push(self.report(channel, tacho)); + let _ = reports.push(self.report(channel)); } serde_json_core::to_vec(&reports) } @@ -515,7 +519,6 @@ impl Channels { max_v: (self.get_max_v(channel), ElectricPotential::new::(5.0)).into(), max_i_pos: self.get_max_i_pos(channel).into(), max_i_neg: self.get_max_i_neg(channel).into(), - fan: self.get_fan_pwm(), } } @@ -553,6 +556,20 @@ impl Channels { } serde_json_core::to_vec(&summaries) } + + pub fn fan_summary(&mut self, tacho: Option) -> Result { + if self.fan_available() { + let summary = FanSummary { + fan_pwm: self.get_fan_pwm(), + tacho: tacho.unwrap_or(u32::MAX), + abs_max_tec_i: max_by(self.get_tec_i(0).abs().value, self.get_tec_i(1).abs().value, |a, b| a.partial_cmp(b).unwrap()) + }; + serde_json_core::to_vec(&summary) + } else { + let summary: Option<()> = None; + serde_json_core::to_vec(&summary) + } + } } type JsonBuffer = Vec; @@ -574,7 +591,6 @@ pub struct Report { tec_i: ElectricCurrent, tec_u_meas: ElectricPotential, pid_output: ElectricCurrent, - tacho: Option, hwrev: HWRev, } @@ -615,7 +631,6 @@ pub struct PwmSummary { max_v: PwmSummaryField, max_i_pos: PwmSummaryField, max_i_neg: PwmSummaryField, - fan: u32, } #[derive(Serialize)] @@ -629,3 +644,10 @@ pub struct SteinhartHartSummary { channel: usize, params: steinhart_hart::Parameters, } + +#[derive(Serialize)] +pub struct FanSummary { + fan_pwm: u32, + tacho: u32, + abs_max_tec_i: f64, +} diff --git a/src/command_handler.rs b/src/command_handler.rs index ea8d107..0fcf252 100644 --- a/src/command_handler.rs +++ b/src/command_handler.rs @@ -93,8 +93,8 @@ impl Handler { Ok(Handler::Handled) } - fn show_report(socket: &mut TcpSocket, channels: &mut Channels, tacho: Option) -> Result { - match channels.reports_json(tacho) { + fn show_report(socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.reports_json() { Ok(buf) => { send_line(socket, &buf[..]); } @@ -344,14 +344,24 @@ impl Handler { Ok(Handler::Reset) } - fn fan (channels: &mut Channels, fan_pwm: Option) -> Result { + fn fan (socket: &mut TcpSocket, channels: &mut Channels, fan_pwm: Option, tacho_value: Option) -> Result { match fan_pwm { Some(val) => { channels.set_fan_pwm(val); Ok(Handler::Handled) }, None => { - Err(Error::ReportError) + match channels.fan_summary(tacho_value) { + Ok(buf) => { + send_line(socket, &buf); + } + Err(e) => { + error!("unable to serialize fan summary: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); + return Err(Error::ReportError); + } + }; + Ok(Handler::Handled) } } } @@ -361,7 +371,7 @@ impl Handler { Command::Quit => Ok(Handler::CloseSocket), Command::Reporting(_reporting) => Handler::reporting(socket), Command::Show(ShowCommand::Reporting) => Handler::show_report_mode(socket, session), - Command::Show(ShowCommand::Input) => Handler::show_report(socket, channels, tacho_value), + Command::Show(ShowCommand::Input) => Handler::show_report(socket, channels), Command::Show(ShowCommand::Pid) => Handler::show_pid(socket, channels), Command::Show(ShowCommand::Pwm) => Handler::show_pwm(socket, channels), Command::Show(ShowCommand::SteinhartHart) => Handler::show_steinhart_hart(socket, channels), @@ -379,7 +389,7 @@ impl Handler { Command::Ipv4(config) => Handler::set_ipv4(socket, store, config), Command::Reset => Handler::reset(channels), Command::Dfu => Handler::dfu(channels), - Command::Fan {fan_pwm} => Handler::fan(channels, fan_pwm) + Command::Fan {fan_pwm} => Handler::fan(socket, channels, fan_pwm, tacho_value) } } } \ No newline at end of file diff --git a/src/fan_ctrl.rs b/src/fan_ctrl.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.rs b/src/main.rs index 9cb1322..77f6d8b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,7 +152,7 @@ fn main() -> ! { } } - let fan_available = channels.hw_rev.major == 2 && channels.hw_rev.minor == 2; + let fan_available = channels.fan_available(); // default net config: let mut ipv4_config = Ipv4Config { @@ -206,12 +206,9 @@ fn main() -> ! { let instant = Instant::from_millis(i64::from(timer::now())); if fan_available { - let mut tacho_input = false; - cortex_m::interrupt::free(|_cs| { - tacho_input = tacho.check_interrupt(); - tacho.clear_interrupt_pending_bit(); - }); + let tacho_input = tacho.check_interrupt(); if tacho_input { + tacho.clear_interrupt_pending_bit(); tacho_cnt += 1; } @@ -262,7 +259,7 @@ fn main() -> ! { } } else if socket.can_send() { if let Some(channel) = session.is_report_pending() { - match channels.reports_json(tacho_value) { + match channels.reports_json() { Ok(buf) => { send_line(&mut socket, &buf[..]); session.mark_report_sent(channel);