diff --git a/firmware/src/ad7172/adc.rs b/firmware/src/ad7172/adc.rs index 1bc7d5e..780ab92 100644 --- a/firmware/src/ad7172/adc.rs +++ b/firmware/src/ad7172/adc.rs @@ -2,7 +2,7 @@ use embedded_hal::digital::v2::OutputPin; use embedded_hal::blocking::spi::Transfer; use super::checksum::{ChecksumMode, Checksum}; use super::AdcError; -use super::regs::*; +use super::{regs, regs::RegisterData, Input, RefSource}; /// AD7172-2 implementation /// @@ -27,32 +27,44 @@ impl, NSS: OutputPin> Adc { /// `0x00DX` for AD7271-2 pub fn identify(&mut self) -> Result> { - self.read_reg(&Id) + self.read_reg(®s::Id) .map(|id| id.id()) } pub fn set_checksum_mode(&mut self, mode: ChecksumMode) -> Result<(), AdcError> { - let mut ifmode = self.read_reg(&IfMode)?; + // Cannot use update_reg() here because checksum_mode is + // updated between read_reg() and write_reg(). + let mut ifmode = self.read_reg(®s::IfMode)?; ifmode.set_crc(mode); self.checksum_mode = mode; - self.write_reg(&IfMode, &mut ifmode)?; + self.write_reg(®s::IfMode, &mut ifmode)?; Ok(()) } - // pub fn setup(&mut self) -> Result<(), SPI::Error> { - // let mut buf = [0, 0, 0]; - // adc.write_reg(Register::AdcMode, &mut buf)?; - // let mut buf = [0, 1, 0]; - // adc.write_reg(Register::IfMode, &mut buf)?; - // let mut buf = [0, 0, 0]; - // adc.write_reg(Register::GpioCon, &mut buf)?; - - // Ok(()) - // } + pub fn setup_channel( + &mut self, index: u8, in_pos: Input, in_neg: Input + ) -> Result<(), AdcError> { + self.update_reg(®s::SetupCon { index }, |data| { + data.set_bi_unipolar(false); + data.set_refbuf_pos(true); + data.set_refbuf_neg(true); + data.set_ainbuf_pos(true); + data.set_ainbuf_neg(true); + // TODO: which RefSource? + data.set_ref_sel(RefSource::Internal); + })?; + self.update_reg(®s::Channel { index }, |data| { + data.set_setup(index); + data.set_enabled(true); + data.set_a_in_pos(in_pos); + data.set_a_in_neg(in_neg); + })?; + Ok(()) + } /// Returns the channel the data is from pub fn data_ready(&mut self) -> Result, AdcError> { - self.read_reg(&Status) + self.read_reg(®s::Status) .map(|status| { if status.ready() { Some(status.channel()) @@ -64,11 +76,11 @@ impl, NSS: OutputPin> Adc { /// Get data pub fn read_data(&mut self) -> Result> { - self.read_reg(&Data) + self.read_reg(®s::Data) .map(|data| data.data()) } - pub fn read_reg(&mut self, reg: &R) -> Result> { + fn read_reg(&mut self, reg: &R) -> Result> { let mut reg_data = R::Data::empty(); let address = 0x40 | reg.address(); let mut checksum = Checksum::new(self.checksum_mode); @@ -85,7 +97,7 @@ impl, NSS: OutputPin> Adc { Ok(reg_data) } - pub fn write_reg(&mut self, reg: &R, reg_data: &mut R::Data) -> Result<(), AdcError> { + fn write_reg(&mut self, reg: &R, reg_data: &mut R::Data) -> Result<(), AdcError> { let address = reg.address(); let mut checksum = Checksum::new(match self.checksum_mode { ChecksumMode::Off => ChecksumMode::Off, @@ -102,9 +114,9 @@ impl, NSS: OutputPin> Adc { Ok(()) } - pub fn update_reg(&mut self, reg: &R, f: F) -> Result> + fn update_reg(&mut self, reg: &R, f: F) -> Result> where - R: Register, + R: regs::Register, F: FnOnce(&mut R::Data) -> A, { let mut reg_data = self.read_reg(reg)?; diff --git a/firmware/src/main.rs b/firmware/src/main.rs index f75ba5d..5b50f25 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -85,6 +85,9 @@ macro_rules! create_socket { ) } +/// In nanoseconds +const REPORT_INTERVAL: u64 = 100_000; + #[entry] fn main() -> ! { let mut stdout = hio::hstdout().unwrap(); @@ -146,6 +149,10 @@ fn main() -> ! { writeln!(stdout, "Corrupt ADC id: {:04X}", id).unwrap(), }; } + // SENS0_{P,N} + adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap(); + // SENS1_{P,N} + adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap(); let mut hardware_addr = EthernetAddress(board::get_mac_address()); if hardware_addr.is_multicast() { @@ -195,31 +202,34 @@ fn main() -> ! { (Session::new(), tcp_handle7), ]; - let mut read_times = [0, 0]; - let mut data = None; - // if a socket has sent the latest data + let mut last_report = get_time(); + // cumulative (sum, count) + let mut sample = [(0u64, 0usize); 2]; + let mut report = None; loop { - let _ = adc.data_ready() - .and_then(|channel| - channel.map(|channel| - adc.read_data().map(|new_data| { - let now = get_time(); - read_times[0] = read_times[1]; - read_times[1] = now; - data = Some((now, Ok((channel, new_data)))); - for (session, _) in sessions_handles.iter_mut() { - session.set_report_pending(); - } - }) - ).unwrap_or(Ok(())) - ) - .map_err(|e| { - let now = get_time(); - data = Some((now, Err(e))); - for (session, _) in sessions_handles.iter_mut() { - session.set_report_pending(); - } + // ADC input + adc.data_ready() + .unwrap_or_else(|e| { + writeln!(stdout, "ADC error: {:?}", e); + None + }).map(|channel| { + 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 >= last_report + REPORT_INTERVAL { + last_report = now; + // TODO: calculate med instead of avg? + report = Some((now, [ + sample[0].0 / (sample[0].1 as u64), + sample[1].0 / (sample[1].1 as u64), + ])); + for (session, _) in sessions_handles.iter_mut() { + session.set_report_pending(); + } + } + for (session, tcp_handle) in sessions_handles.iter_mut() { let socket = &mut *sockets.get::(*tcp_handle); if !socket.is_open() { @@ -256,18 +266,14 @@ fn main() -> ! { } } if socket.may_send() && session.is_report_pending() { - match &data { - Some((time, Ok((channel, input)))) => { - let interval = read_times[1] - read_times[0]; - let _ = writeln!(socket, "t={}-{} channel={} input={}\r", time, interval, channel, input); + match &report { + Some((time, samples)) => { + let _ = writeln!(socket, "t={} sens0={} sens1={}\r", + time, samples[0], samples[1] + ); } - Some((time, Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input))))) => { - let _ = writeln!(socket, "t={} checksum_expected={:02X} checksum_input={:02X}\r", time, expected, input); - } - Some((time, Err(e))) => { - let _ = writeln!(socket, "t={} adc_error={:?}\r", time, e); - } - None => {} + None => + panic!("report_pending while is there is none yet"), } session.mark_report_sent(); }