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
119
120
121
122
123
124
125
use crate::{time::Instant, Error, Ready, Sending, DW1000};
use embedded_hal::{blocking::spi, digital::v2::OutputPin};
use nb;
impl<SPI, CS> DW1000<SPI, CS, Sending>
where
SPI: spi::Transfer<u8> + spi::Write<u8>,
CS: OutputPin,
{
/// 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 [`DW1000::enable_tx_interrupts`]
/// and the DW1000 IRQ output to wait in a more energy-efficient manner.
///
/// Handling the DW1000'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.
pub fn wait_transmit(&mut self) -> nb::Result<Instant, Error<SPI, CS>> {
// 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));
}
// Check Transmitter Power-Up Warning Counter. If this is a delayed
// transmission, this indicates that the transmitter was still powering
// up while sending, and the frame preamble might not have transmit
// correctly.
let evc_tpw = self
.ll
.evc_tpw()
.read()
.map_err(|error| nb::Error::Other(Error::Spi(error)))?
.value();
if evc_tpw != 0 {
return Err(nb::Error::Other(Error::DelayedSendPowerUpWarning));
}
// ATTENTION:
// 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(|error| nb::Error::Other(error))?;
self.state.finished = true;
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 = unsafe { Instant::new_unchecked(tx_timestamp) };
Ok(tx_timestamp)
}
/// 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<DW1000<SPI, CS, Ready>, (Self, Error<SPI, CS>)> {
if !self.state.finished {
// Can't use `map_err` and `?` here, as the compiler will complain
// about `self` moving into the closure.
match self.force_idle(false) {
Ok(()) => (),
Err(error) => return Err((self, error)),
}
match self.reset_flags() {
Ok(()) => (),
Err(error) => return Err((self, error)),
}
}
// Turn off the external transmit synchronization
match self.ll.ec_ctrl().modify(|_, w| w.ostsm(0)) {
Ok(_) => {}
Err(e) => return Err((self, Error::Spi(e))),
}
Ok(DW1000 {
ll: self.ll,
seq: self.seq,
state: Ready,
})
}
fn reset_flags(&mut self) -> Result<(), Error<SPI, CS>> {
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(())
}
}