1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![allow(unused_imports)]
use embedded_hal::spi;
use nb;
use crate::{time::Instant, Error, Ready, Sending, DW3000};
impl<SPI> DW3000<SPI, Sending>
where
SPI: spi::SpiDevice<u8>,
{
/// Returns the TX state of the DW3000
pub fn tx_state(&mut self) -> Result<u8, Error<SPI>> {
Ok(self.ll.sys_state().read()?.tx_state())
}
/// Wait for the transmission to finish
///
/// This method returns an `nb::Result` to indicate whether the transmission
/// has finished, or whether it is still ongoing. You can use this to busily
/// wait for the transmission to finish, for example using `nb`'s `block!`
/// macro, or you can use it in tandem with [`DW3000::enable_tx_interrupts`]
/// and the DW3000 IRQ output to wait in a more energy-efficient manner.
///
/// Handling the DW3000's IRQ output line is out of the scope of this
/// driver, but please note that if you're using the DWM1001 module or
/// DWM1001-Dev board, that the `dwm1001` crate has explicit support for
/// this.
#[inline(always)]
pub fn s_wait(&mut self) -> nb::Result<Instant, Error<SPI>> {
// Check Half Period Warning Counter. If this is a delayed transmission,
// this will indicate that the delay was too short, and the frame was
// sent too late.
let evc_hpw = self
.ll
.evc_hpw()
.read()
.map_err(|error| nb::Error::Other(Error::Spi(error)))?
.value();
if evc_hpw != 0 {
return Err(nb::Error::Other(Error::DelayedSendTooLate));
}
// WARNING s:
// If you're changing anything about which SYS_STATUS flags are being
// checked in this method, also make sure to update `enable_interrupts`.
let sys_status = self
.ll
.sys_status()
.read()
.map_err(|error| nb::Error::Other(Error::Spi(error)))?;
// Has the frame been sent?
if sys_status.txfrs() == 0b0 {
// Frame has not been sent
return Err(nb::Error::WouldBlock);
}
// Frame sent
self.reset_flags().map_err(nb::Error::Other)?;
self.state.mark_finished();
let tx_timestamp = self
.ll
.tx_time()
.read()
.map_err(|error| nb::Error::Other(Error::Spi(error)))?
.tx_stamp();
// This is safe because the value read from the device will never be higher than
// the allowed value.
let tx_timestamp = Instant::new(tx_timestamp);
if let Some(ts) = tx_timestamp {
Ok(ts)
} else {
Err(nb::Error::Other(Error::Fcs))
}
}
#[allow(clippy::type_complexity)]
/// Finishes sending and returns to the `Ready` state
///
/// If the send operation has finished, as indicated by `wait`, this is a
/// no-op. If the send operation is still ongoing, it will be aborted.
pub fn finish_sending(mut self) -> Result<DW3000<SPI, Ready>, (Self, Error<SPI>)> {
// In order to avoid undetermined states after a sending, we will force the state to idle
if !self.state.is_finished() {
match self.force_idle() {
Ok(()) => (),
Err(error) => return Err((self, error)),
}
match self.reset_flags() {
Ok(()) => (),
Err(error) => return Err((self, error)),
}
}
Ok(DW3000 {
ll: self.ll,
seq: self.seq,
state: Ready,
})
}
fn reset_flags(&mut self) -> Result<(), Error<SPI>> {
self.ll.sys_status().write(|w| {
w.txfrb(0b1) // Transmit Frame Begins
.txprs(0b1) // Transmit Preamble Sent
.txphs(0b1) // Transmit PHY Header Sent
.txfrs(0b1) // Transmit Frame Sent
})?;
Ok(())
}
}