forked from M-Labs/ionpak-thermostat
main: setup thermostat v1 channels, report avgs at 10hz
This commit is contained in:
parent
c50e1c7766
commit
f8dd7d1912
@ -2,7 +2,7 @@ use embedded_hal::digital::v2::OutputPin;
|
|||||||
use embedded_hal::blocking::spi::Transfer;
|
use embedded_hal::blocking::spi::Transfer;
|
||||||
use super::checksum::{ChecksumMode, Checksum};
|
use super::checksum::{ChecksumMode, Checksum};
|
||||||
use super::AdcError;
|
use super::AdcError;
|
||||||
use super::regs::*;
|
use super::{regs, regs::RegisterData, Input, RefSource};
|
||||||
|
|
||||||
/// AD7172-2 implementation
|
/// AD7172-2 implementation
|
||||||
///
|
///
|
||||||
@ -27,32 +27,44 @@ impl<SPI: Transfer<u8>, NSS: OutputPin> Adc<SPI, NSS> {
|
|||||||
|
|
||||||
/// `0x00DX` for AD7271-2
|
/// `0x00DX` for AD7271-2
|
||||||
pub fn identify(&mut self) -> Result<u16, AdcError<SPI::Error>> {
|
pub fn identify(&mut self) -> Result<u16, AdcError<SPI::Error>> {
|
||||||
self.read_reg(&Id)
|
self.read_reg(®s::Id)
|
||||||
.map(|id| id.id())
|
.map(|id| id.id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_checksum_mode(&mut self, mode: ChecksumMode) -> Result<(), AdcError<SPI::Error>> {
|
pub fn set_checksum_mode(&mut self, mode: ChecksumMode) -> Result<(), AdcError<SPI::Error>> {
|
||||||
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);
|
ifmode.set_crc(mode);
|
||||||
self.checksum_mode = mode;
|
self.checksum_mode = mode;
|
||||||
self.write_reg(&IfMode, &mut ifmode)?;
|
self.write_reg(®s::IfMode, &mut ifmode)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn setup(&mut self) -> Result<(), SPI::Error> {
|
pub fn setup_channel(
|
||||||
// let mut buf = [0, 0, 0];
|
&mut self, index: u8, in_pos: Input, in_neg: Input
|
||||||
// adc.write_reg(Register::AdcMode, &mut buf)?;
|
) -> Result<(), AdcError<SPI::Error>> {
|
||||||
// let mut buf = [0, 1, 0];
|
self.update_reg(®s::SetupCon { index }, |data| {
|
||||||
// adc.write_reg(Register::IfMode, &mut buf)?;
|
data.set_bi_unipolar(false);
|
||||||
// let mut buf = [0, 0, 0];
|
data.set_refbuf_pos(true);
|
||||||
// adc.write_reg(Register::GpioCon, &mut buf)?;
|
data.set_refbuf_neg(true);
|
||||||
|
data.set_ainbuf_pos(true);
|
||||||
// Ok(())
|
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
|
/// Returns the channel the data is from
|
||||||
pub fn data_ready(&mut self) -> Result<Option<u8>, AdcError<SPI::Error>> {
|
pub fn data_ready(&mut self) -> Result<Option<u8>, AdcError<SPI::Error>> {
|
||||||
self.read_reg(&Status)
|
self.read_reg(®s::Status)
|
||||||
.map(|status| {
|
.map(|status| {
|
||||||
if status.ready() {
|
if status.ready() {
|
||||||
Some(status.channel())
|
Some(status.channel())
|
||||||
@ -64,11 +76,11 @@ impl<SPI: Transfer<u8>, NSS: OutputPin> Adc<SPI, NSS> {
|
|||||||
|
|
||||||
/// Get data
|
/// Get data
|
||||||
pub fn read_data(&mut self) -> Result<u32, AdcError<SPI::Error>> {
|
pub fn read_data(&mut self) -> Result<u32, AdcError<SPI::Error>> {
|
||||||
self.read_reg(&Data)
|
self.read_reg(®s::Data)
|
||||||
.map(|data| data.data())
|
.map(|data| data.data())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_reg<R: Register>(&mut self, reg: &R) -> Result<R::Data, AdcError<SPI::Error>> {
|
fn read_reg<R: regs::Register>(&mut self, reg: &R) -> Result<R::Data, AdcError<SPI::Error>> {
|
||||||
let mut reg_data = R::Data::empty();
|
let mut reg_data = R::Data::empty();
|
||||||
let address = 0x40 | reg.address();
|
let address = 0x40 | reg.address();
|
||||||
let mut checksum = Checksum::new(self.checksum_mode);
|
let mut checksum = Checksum::new(self.checksum_mode);
|
||||||
@ -85,7 +97,7 @@ impl<SPI: Transfer<u8>, NSS: OutputPin> Adc<SPI, NSS> {
|
|||||||
Ok(reg_data)
|
Ok(reg_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_reg<R: Register>(&mut self, reg: &R, reg_data: &mut R::Data) -> Result<(), AdcError<SPI::Error>> {
|
fn write_reg<R: regs::Register>(&mut self, reg: &R, reg_data: &mut R::Data) -> Result<(), AdcError<SPI::Error>> {
|
||||||
let address = reg.address();
|
let address = reg.address();
|
||||||
let mut checksum = Checksum::new(match self.checksum_mode {
|
let mut checksum = Checksum::new(match self.checksum_mode {
|
||||||
ChecksumMode::Off => ChecksumMode::Off,
|
ChecksumMode::Off => ChecksumMode::Off,
|
||||||
@ -102,9 +114,9 @@ impl<SPI: Transfer<u8>, NSS: OutputPin> Adc<SPI, NSS> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_reg<R, F, A>(&mut self, reg: &R, f: F) -> Result<A, AdcError<SPI::Error>>
|
fn update_reg<R, F, A>(&mut self, reg: &R, f: F) -> Result<A, AdcError<SPI::Error>>
|
||||||
where
|
where
|
||||||
R: Register,
|
R: regs::Register,
|
||||||
F: FnOnce(&mut R::Data) -> A,
|
F: FnOnce(&mut R::Data) -> A,
|
||||||
{
|
{
|
||||||
let mut reg_data = self.read_reg(reg)?;
|
let mut reg_data = self.read_reg(reg)?;
|
||||||
|
@ -85,6 +85,9 @@ macro_rules! create_socket {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In nanoseconds
|
||||||
|
const REPORT_INTERVAL: u64 = 100_000;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
@ -146,6 +149,10 @@ fn main() -> ! {
|
|||||||
writeln!(stdout, "Corrupt ADC id: {:04X}", id).unwrap(),
|
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());
|
let mut hardware_addr = EthernetAddress(board::get_mac_address());
|
||||||
if hardware_addr.is_multicast() {
|
if hardware_addr.is_multicast() {
|
||||||
@ -195,31 +202,34 @@ fn main() -> ! {
|
|||||||
(Session::new(), tcp_handle7),
|
(Session::new(), tcp_handle7),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut read_times = [0, 0];
|
let mut last_report = get_time();
|
||||||
let mut data = None;
|
// cumulative (sum, count)
|
||||||
// if a socket has sent the latest data
|
let mut sample = [(0u64, 0usize); 2];
|
||||||
|
let mut report = None;
|
||||||
loop {
|
loop {
|
||||||
let _ = adc.data_ready()
|
// ADC input
|
||||||
.and_then(|channel|
|
adc.data_ready()
|
||||||
channel.map(|channel|
|
.unwrap_or_else(|e| {
|
||||||
adc.read_data().map(|new_data| {
|
writeln!(stdout, "ADC error: {:?}", e);
|
||||||
let now = get_time();
|
None
|
||||||
read_times[0] = read_times[1];
|
}).map(|channel| {
|
||||||
read_times[1] = now;
|
let data = adc.read_data().unwrap();
|
||||||
data = Some((now, Ok((channel, new_data))));
|
sample[usize::from(channel)].0 += u64::from(data);
|
||||||
for (session, _) in sessions_handles.iter_mut() {
|
sample[usize::from(channel)].1 += 1;
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
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() {
|
for (session, tcp_handle) in sessions_handles.iter_mut() {
|
||||||
let socket = &mut *sockets.get::<TcpSocket>(*tcp_handle);
|
let socket = &mut *sockets.get::<TcpSocket>(*tcp_handle);
|
||||||
if !socket.is_open() {
|
if !socket.is_open() {
|
||||||
@ -256,18 +266,14 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if socket.may_send() && session.is_report_pending() {
|
if socket.may_send() && session.is_report_pending() {
|
||||||
match &data {
|
match &report {
|
||||||
Some((time, Ok((channel, input)))) => {
|
Some((time, samples)) => {
|
||||||
let interval = read_times[1] - read_times[0];
|
let _ = writeln!(socket, "t={} sens0={} sens1={}\r",
|
||||||
let _ = writeln!(socket, "t={}-{} channel={} input={}\r", time, interval, channel, input);
|
time, samples[0], samples[1]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Some((time, Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input))))) => {
|
None =>
|
||||||
let _ = writeln!(socket, "t={} checksum_expected={:02X} checksum_input={:02X}\r", time, expected, input);
|
panic!("report_pending while is there is none yet"),
|
||||||
}
|
|
||||||
Some((time, Err(e))) => {
|
|
||||||
let _ = writeln!(socket, "t={} adc_error={:?}\r", time, e);
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
session.mark_report_sent();
|
session.mark_report_sent();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user