Compare commits
8 Commits
4c3c8498e9
...
a102e5fcec
Author | SHA1 | Date |
---|---|---|
Astro | a102e5fcec | |
Astro | 10f7020c02 | |
Astro | da65ea21a4 | |
Astro | 9c3485d05f | |
Astro | 8e41c44303 | |
Astro | 1cba8e56c9 | |
Astro | 63cc1d2fe1 | |
Astro | 194871c85a |
|
@ -2,11 +2,10 @@ use core::fmt;
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
use embedded_hal::blocking::spi::Transfer;
|
use embedded_hal::blocking::spi::Transfer;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use super::checksum::{ChecksumMode, Checksum};
|
|
||||||
use super::AdcError;
|
|
||||||
use super::{
|
use super::{
|
||||||
regs::{self, Register, RegisterData},
|
regs::{self, Register, RegisterData},
|
||||||
Input, RefSource, PostFilter, DigitalFilterOrder,
|
checksum::{ChecksumMode, Checksum},
|
||||||
|
Mode, Input, RefSource, PostFilter, DigitalFilterOrder,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// AD7172-2 implementation
|
/// AD7172-2 implementation
|
||||||
|
@ -19,7 +18,7 @@ pub struct Adc<SPI: Transfer<u8>, NSS: OutputPin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS> {
|
||||||
pub fn new(spi: SPI, mut nss: NSS) -> Result<Self, AdcError<SPI::Error>> {
|
pub fn new(spi: SPI, mut nss: NSS) -> Result<Self, SPI::Error> {
|
||||||
let _ = nss.set_high();
|
let _ = nss.set_high();
|
||||||
let mut adc = Adc {
|
let mut adc = Adc {
|
||||||
spi, nss,
|
spi, nss,
|
||||||
|
@ -42,18 +41,19 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
|
|
||||||
let mut adc_mode = <regs::AdcMode as Register>::Data::empty();
|
let mut adc_mode = <regs::AdcMode as Register>::Data::empty();
|
||||||
adc_mode.set_ref_en(true);
|
adc_mode.set_ref_en(true);
|
||||||
adc.write_reg(®s::AdcMode, &mut adc_mode);
|
adc_mode.set_mode(Mode::ContinuousConversion);
|
||||||
|
adc.write_reg(®s::AdcMode, &mut adc_mode)?;
|
||||||
|
|
||||||
Ok(adc)
|
Ok(adc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `0x00DX` for AD7172-2
|
/// `0x00DX` for AD7172-2
|
||||||
pub fn identify(&mut self) -> Result<u16, AdcError<SPI::Error>> {
|
pub fn identify(&mut self) -> Result<u16, SPI::Error> {
|
||||||
self.read_reg(®s::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<(), SPI::Error> {
|
||||||
// Cannot use update_reg() here because checksum_mode is
|
// Cannot use update_reg() here because checksum_mode is
|
||||||
// updated between read_reg() and write_reg().
|
// updated between read_reg() and write_reg().
|
||||||
let mut ifmode = self.read_reg(®s::IfMode)?;
|
let mut ifmode = self.read_reg(®s::IfMode)?;
|
||||||
|
@ -63,7 +63,7 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sync_enable(&mut self, enable: bool) -> Result<(), AdcError<SPI::Error>> {
|
pub fn set_sync_enable(&mut self, enable: bool) -> Result<(), SPI::Error> {
|
||||||
self.update_reg(®s::GpioCon, |data| {
|
self.update_reg(®s::GpioCon, |data| {
|
||||||
data.set_sync_en(enable);
|
data.set_sync_en(enable);
|
||||||
})
|
})
|
||||||
|
@ -71,23 +71,20 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
|
|
||||||
pub fn setup_channel(
|
pub fn setup_channel(
|
||||||
&mut self, index: u8, in_pos: Input, in_neg: Input
|
&mut self, index: u8, in_pos: Input, in_neg: Input
|
||||||
) -> Result<(), AdcError<SPI::Error>> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.update_reg(®s::SetupCon { index }, |data| {
|
self.update_reg(®s::SetupCon { index }, |data| {
|
||||||
data.set_bipolar(false);
|
data.set_bipolar(false);
|
||||||
data.set_refbuf_pos(true);
|
data.set_refbuf_pos(true);
|
||||||
data.set_refbuf_neg(true);
|
data.set_refbuf_neg(true);
|
||||||
data.set_ainbuf_pos(true);
|
data.set_ainbuf_pos(true);
|
||||||
data.set_ainbuf_neg(true);
|
data.set_ainbuf_neg(true);
|
||||||
data.set_ref_sel(RefSource::Internal);
|
data.set_ref_sel(RefSource::External);
|
||||||
})?;
|
})?;
|
||||||
self.update_reg(®s::FiltCon { index }, |data| {
|
self.update_reg(®s::FiltCon { index }, |data| {
|
||||||
data.set_enh_filt_en(true);
|
data.set_enh_filt_en(true);
|
||||||
data.set_enh_filt(PostFilter::F16SPS);
|
data.set_enh_filt(PostFilter::F16SPS);
|
||||||
data.set_order(DigitalFilterOrder::Sinc5Sinc1);
|
data.set_order(DigitalFilterOrder::Sinc5Sinc1);
|
||||||
})?;
|
})?;
|
||||||
let mut offset = <regs::Offset as regs::Register>::Data::empty();
|
|
||||||
offset.set_offset(0);
|
|
||||||
self.write_reg(®s::Offset { index }, &mut offset);
|
|
||||||
self.update_reg(®s::Channel { index }, |data| {
|
self.update_reg(®s::Channel { index }, |data| {
|
||||||
data.set_setup(index);
|
data.set_setup(index);
|
||||||
data.set_enabled(true);
|
data.set_enabled(true);
|
||||||
|
@ -97,7 +94,21 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_postfilter(&mut self, index: u8) -> Result<Option<PostFilter>, AdcError<SPI::Error>> {
|
/// Calibrates offset registers
|
||||||
|
pub fn calibrate_offset(&mut self) -> Result<(), SPI::Error> {
|
||||||
|
self.update_reg(®s::AdcMode, |adc_mode| {
|
||||||
|
adc_mode.set_mode(Mode::SystemOffsetCalibration);
|
||||||
|
})?;
|
||||||
|
while ! self.read_reg(®s::Status)?.ready() {}
|
||||||
|
|
||||||
|
self.update_reg(®s::AdcMode, |adc_mode| {
|
||||||
|
adc_mode.set_mode(Mode::ContinuousConversion);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_postfilter(&mut self, index: u8) -> Result<Option<PostFilter>, SPI::Error> {
|
||||||
self.read_reg(®s::FiltCon { index })
|
self.read_reg(®s::FiltCon { index })
|
||||||
.map(|data| {
|
.map(|data| {
|
||||||
if data.enh_filt_en() {
|
if data.enh_filt_en() {
|
||||||
|
@ -108,7 +119,7 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_postfilter(&mut self, index: u8, filter: Option<PostFilter>) -> Result<(), AdcError<SPI::Error>> {
|
pub fn set_postfilter(&mut self, index: u8, filter: Option<PostFilter>) -> Result<(), SPI::Error> {
|
||||||
self.update_reg(®s::FiltCon { index }, |data| {
|
self.update_reg(®s::FiltCon { index }, |data| {
|
||||||
match filter {
|
match filter {
|
||||||
None => data.set_enh_filt_en(false),
|
None => data.set_enh_filt_en(false),
|
||||||
|
@ -121,7 +132,7 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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>, SPI::Error> {
|
||||||
self.read_reg(®s::Status)
|
self.read_reg(®s::Status)
|
||||||
.map(|status| {
|
.map(|status| {
|
||||||
if status.ready() {
|
if status.ready() {
|
||||||
|
@ -133,12 +144,12 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> 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, SPI::Error> {
|
||||||
self.read_reg(®s::Data)
|
self.read_reg(®s::Data)
|
||||||
.map(|data| data.data())
|
.map(|data| data.data())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_reg<R: regs::Register>(&mut self, reg: &R) -> Result<R::Data, AdcError<SPI::Error>> {
|
fn read_reg<R: regs::Register>(&mut self, reg: &R) -> Result<R::Data, 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);
|
||||||
|
@ -154,12 +165,13 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Retry
|
// Retry
|
||||||
warn!("read_reg checksum error, retrying");
|
warn!("read_reg {:02X}: checksum error: {:?}!={:?}, retrying", reg.address(), checksum_expected, checksum_in);
|
||||||
}
|
}
|
||||||
Ok(reg_data)
|
Ok(reg_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_reg<R: regs::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<(), SPI::Error> {
|
||||||
|
loop {
|
||||||
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,
|
||||||
|
@ -170,17 +182,19 @@ impl<SPI: Transfer<u8, Error = E>, NSS: OutputPin, E: fmt::Debug> Adc<SPI, NSS>
|
||||||
checksum.feed(&[address]);
|
checksum.feed(&[address]);
|
||||||
checksum.feed(®_data);
|
checksum.feed(®_data);
|
||||||
let checksum_out = checksum.result();
|
let checksum_out = checksum.result();
|
||||||
loop {
|
|
||||||
let checksum_in = self.transfer(address, reg_data.as_mut(), checksum_out)?;
|
let mut data = reg_data.clone();
|
||||||
if checksum_in.unwrap_or(0) == 0 {
|
let checksum_in = self.transfer(address, data.as_mut(), checksum_out)?;
|
||||||
break;
|
|
||||||
|
let readback_data = self.read_reg(reg)?;
|
||||||
|
if *readback_data == **reg_data {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
warn!("write_reg: checksum={:02X}, retrying", checksum_in.unwrap_or(0));
|
warn!("write_reg {:02X}: readback error, {:?}!={:?}, retrying", address, &*readback_data, &**reg_data);
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, SPI::Error>
|
||||||
where
|
where
|
||||||
R: regs::Register,
|
R: regs::Register,
|
||||||
F: FnOnce(&mut R::Data) -> A,
|
F: FnOnce(&mut R::Data) -> A,
|
||||||
|
|
|
@ -21,15 +21,33 @@ pub const SPI_CLOCK: MegaHertz = MegaHertz(2);
|
||||||
|
|
||||||
pub const MAX_VALUE: u32 = 0xFF_FFFF;
|
pub const MAX_VALUE: u32 = 0xFF_FFFF;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum AdcError<SPI> {
|
#[derive(Clone, Copy, Debug)]
|
||||||
SPI(SPI),
|
#[repr(u8)]
|
||||||
ChecksumMismatch(Option<u8>, Option<u8>),
|
pub enum Mode {
|
||||||
|
ContinuousConversion = 0b000,
|
||||||
|
SingleConversion = 0b001,
|
||||||
|
Standby = 0b010,
|
||||||
|
PowerDown = 0b011,
|
||||||
|
InternalOffsetCalibration = 0b100,
|
||||||
|
Invalid,
|
||||||
|
SystemOffsetCalibration = 0b110,
|
||||||
|
SystemGainCalibration = 0b111,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SPI> From<SPI> for AdcError<SPI> {
|
impl From<u8> for Mode {
|
||||||
fn from(e: SPI) -> Self {
|
fn from(x: u8) -> Self {
|
||||||
AdcError::SPI(e)
|
use Mode::*;
|
||||||
|
match x {
|
||||||
|
0b000 => ContinuousConversion,
|
||||||
|
0b001 => SingleConversion,
|
||||||
|
0b010 => Standby,
|
||||||
|
0b011 => PowerDown,
|
||||||
|
0b100 => InternalOffsetCalibration,
|
||||||
|
0b110 => SystemOffsetCalibration,
|
||||||
|
0b111 => SystemGainCalibration,
|
||||||
|
_ => Invalid,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ pub trait Register {
|
||||||
type Data: RegisterData;
|
type Data: RegisterData;
|
||||||
fn address(&self) -> u8;
|
fn address(&self) -> u8;
|
||||||
}
|
}
|
||||||
pub trait RegisterData: Deref<Target=[u8]> + DerefMut {
|
|
||||||
|
pub trait RegisterData: Clone + Deref<Target=[u8]> + DerefMut {
|
||||||
fn empty() -> Self;
|
fn empty() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ macro_rules! def_reg {
|
||||||
}
|
}
|
||||||
mod $reg {
|
mod $reg {
|
||||||
/// Register contents
|
/// Register contents
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Data(pub [u8; $size]);
|
pub struct Data(pub [u8; $size]);
|
||||||
impl super::RegisterData for Data {
|
impl super::RegisterData for Data {
|
||||||
/// Generate zeroed register contents
|
/// Generate zeroed register contents
|
||||||
|
@ -55,6 +57,7 @@ macro_rules! def_reg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod $reg {
|
mod $reg {
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Data(pub [u8; $size]);
|
pub struct Data(pub [u8; $size]);
|
||||||
impl super::RegisterData for Data {
|
impl super::RegisterData for Data {
|
||||||
fn empty() -> Self {
|
fn empty() -> Self {
|
||||||
|
@ -155,12 +158,12 @@ impl status::Data {
|
||||||
|
|
||||||
def_reg!(AdcMode, adc_mode, 0x01, 2);
|
def_reg!(AdcMode, adc_mode, 0x01, 2);
|
||||||
impl adc_mode::Data {
|
impl adc_mode::Data {
|
||||||
reg_bits!(clockset, set_clocksel, 1, 2..3, "Clock source");
|
reg_bits!(delay, set_delay, 0, 0..=2, "Delay after channel switch");
|
||||||
reg_bits!(mode, set_mode, 1, 4..6, "Operating mode");
|
reg_bit!(sing_cyc, set_sing_cyc, 0, 5, "Can only used with single channel");
|
||||||
reg_bits!(delay, set_delay, 0, 0..2, "Delay after channel switch");
|
reg_bit!(hide_delay, set_hide_delay, 0, 6, "Hide delay");
|
||||||
reg_bit!(sing_cyc, set_sing_cyc, 1, 5, "Can only used with single channel");
|
|
||||||
reg_bit!(hide_delay, set_hide_delay, 1, 6, "Hide delay");
|
|
||||||
reg_bit!(ref_en, set_ref_en, 0, 7, "Enable internal reference, output buffered 2.5 V to REFOUT");
|
reg_bit!(ref_en, set_ref_en, 0, 7, "Enable internal reference, output buffered 2.5 V to REFOUT");
|
||||||
|
reg_bits!(clockset, set_clocksel, 1, 2..=3, "Clock source");
|
||||||
|
reg_bits!(mode, set_mode, 1, 4..=6, Mode, "Operating mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
def_reg!(IfMode, if_mode, 0x02, 2);
|
def_reg!(IfMode, if_mode, 0x02, 2);
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -94,6 +94,7 @@ fn main() -> ! {
|
||||||
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
|
let mut adc = ad7172::Adc::new(pins.adc_spi, pins.adc_nss).unwrap();
|
||||||
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
|
adc.setup_channel(0, ad7172::Input::Ain0, ad7172::Input::Ain1).unwrap();
|
||||||
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
|
adc.setup_channel(1, ad7172::Input::Ain2, ad7172::Input::Ain3).unwrap();
|
||||||
|
adc.calibrate_offset().unwrap();
|
||||||
let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync);
|
let mut dac0 = ad5680::Dac::new(pins.dac0_spi, pins.dac0_sync);
|
||||||
dac0.set(0).unwrap();
|
dac0.set(0).unwrap();
|
||||||
let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync);
|
let mut dac1 = ad5680::Dac::new(pins.dac1_spi, pins.dac1_sync);
|
||||||
|
@ -118,14 +119,14 @@ fn main() -> ! {
|
||||||
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
|
net::run(dp.ETHERNET_MAC, dp.ETHERNET_DMA, hwaddr, |iface| {
|
||||||
Server::<Session>::run(iface, |server| {
|
Server::<Session>::run(iface, |server| {
|
||||||
loop {
|
loop {
|
||||||
let now = timer::now().0;
|
let instant = Instant::from_millis(i64::from(timer::now()));
|
||||||
let instant = Instant::from_millis(i64::from(now));
|
|
||||||
cortex_m::interrupt::free(net::clear_pending);
|
cortex_m::interrupt::free(net::clear_pending);
|
||||||
server.poll(instant)
|
server.poll(instant)
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
warn!("poll: {:?}", e);
|
warn!("poll: {:?}", e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let instant = Instant::from_millis(i64::from(timer::now()));
|
||||||
// ADC input
|
// ADC input
|
||||||
adc.data_ready().unwrap().map(|channel| {
|
adc.data_ready().unwrap().map(|channel| {
|
||||||
let data = adc.read_data().unwrap();
|
let data = adc.read_data().unwrap();
|
||||||
|
@ -152,10 +153,8 @@ fn main() -> ! {
|
||||||
server.for_each(|mut socket, session| {
|
server.for_each(|mut socket, session| {
|
||||||
if ! socket.is_open() {
|
if ! socket.is_open() {
|
||||||
let _ = socket.listen(TCP_PORT);
|
let _ = socket.listen(TCP_PORT);
|
||||||
if session.is_dirty() {
|
|
||||||
session.reset();
|
session.reset();
|
||||||
}
|
} else if socket.can_send() && socket.can_recv() && socket.send_capacity() - socket.send_queue() > 1024 {
|
||||||
} else if socket.can_send() && socket.can_recv() && socket.send_capacity() - socket.send_queue() > 128 {
|
|
||||||
match socket.recv(|buf| session.feed(buf)) {
|
match socket.recv(|buf| session.feed(buf)) {
|
||||||
Ok(SessionOutput::Nothing) => {}
|
Ok(SessionOutput::Nothing) => {}
|
||||||
Ok(SessionOutput::Command(command)) => match command {
|
Ok(SessionOutput::Command(command)) => match command {
|
||||||
|
@ -391,7 +390,7 @@ fn main() -> ! {
|
||||||
while let Some(channel) = session.is_report_pending() {
|
while let Some(channel) = session.is_report_pending() {
|
||||||
let state = &mut channel_states[usize::from(channel)];
|
let state = &mut channel_states[usize::from(channel)];
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
socket, "t={} raw{}=0x{:04X}",
|
socket, "t={} raw{}=0x{:06X}",
|
||||||
state.adc_time, channel, state.adc_data.unwrap_or(0)
|
state.adc_time, channel, state.adc_data.unwrap_or(0)
|
||||||
).map(|_| {
|
).map(|_| {
|
||||||
session.mark_report_sent(channel);
|
session.mark_report_sent(channel);
|
||||||
|
|
|
@ -79,10 +79,6 @@ impl Session {
|
||||||
self.report_pending = [false; CHANNELS];
|
self.report_pending = [false; CHANNELS];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_dirty(&self) -> bool {
|
|
||||||
self.reader.pos > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reporting(&self) -> bool {
|
pub fn reporting(&self) -> bool {
|
||||||
self.reporting
|
self.reporting
|
||||||
}
|
}
|
||||||
|
|
13
src/timer.rs
13
src/timer.rs
|
@ -1,15 +1,16 @@
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
use core::ops::Deref;
|
||||||
use cortex_m::interrupt::Mutex;
|
use cortex_m::interrupt::Mutex;
|
||||||
use cortex_m_rt::exception;
|
use cortex_m_rt::exception;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
rcc::Clocks,
|
rcc::Clocks,
|
||||||
time::{U32Ext, MilliSeconds},
|
time::U32Ext,
|
||||||
timer::{Timer, Event as TimerEvent},
|
timer::{Timer, Event as TimerEvent},
|
||||||
stm32::SYST,
|
stm32::SYST,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Rate in Hz
|
/// Rate in Hz
|
||||||
const TIMER_RATE: u32 = 20;
|
const TIMER_RATE: u32 = 500;
|
||||||
/// Interval duration in milliseconds
|
/// Interval duration in milliseconds
|
||||||
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
||||||
/// Elapsed time in milliseconds
|
/// Elapsed time in milliseconds
|
||||||
|
@ -31,10 +32,10 @@ fn SysTick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain current time in milliseconds
|
/// Obtain current time in milliseconds
|
||||||
pub fn now() -> MilliSeconds {
|
pub fn now() -> u32 {
|
||||||
let ms = cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
*TIMER_MS.borrow(cs)
|
*TIMER_MS.borrow(cs)
|
||||||
.borrow()
|
.borrow()
|
||||||
});
|
.deref()
|
||||||
ms.ms()
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue