1use crate::radio::{prelude::EsbPayloadLength, Nrf24Error, RF24};
2use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiDevice};
3
4use super::{commands, registers, Feature};
5
6impl<SPI, DO, DELAY> EsbPayloadLength for RF24<SPI, DO, DELAY>
7where
8 SPI: SpiDevice,
9 DO: OutputPin,
10 DELAY: DelayNs,
11{
12 type PayloadLengthErrorType = Nrf24Error<SPI::Error, DO::Error>;
13
14 fn set_payload_length(&mut self, length: u8) -> Result<(), Self::PayloadLengthErrorType> {
15 let len = length.clamp(1, 32);
16 for i in 0..6 {
17 self.spi_write_byte(registers::RX_PW_P0 + i, len)?;
18 }
19 self._payload_length = len;
20 Ok(())
21 }
22
23 fn get_payload_length(&mut self) -> Result<u8, Self::PayloadLengthErrorType> {
24 self.spi_read(1, registers::RX_PW_P0)?;
25 Ok(self._buf[1])
26 }
27
28 fn set_dynamic_payloads(&mut self, enable: bool) -> Result<(), Self::PayloadLengthErrorType> {
29 self.spi_read(1, registers::FEATURE)?;
30 self._feature =
31 Feature::from_bits(self._feature.into_bits() & !Feature::REG_MASK | self._buf[1])
32 .with_dynamic_payloads(enable);
33 self.spi_write_byte(
34 registers::FEATURE,
35 self._feature.into_bits() & Feature::REG_MASK,
36 )?;
37 self.spi_write_byte(registers::DYNPD, 0x3F * enable as u8)?;
38 Ok(())
39 }
40
41 fn get_dynamic_payloads(&self) -> bool {
42 self._feature.dynamic_payloads()
43 }
44
45 fn get_dynamic_payload_length(&mut self) -> Result<u8, Self::PayloadLengthErrorType> {
46 self.spi_read(1, commands::R_RX_PL_WID)?;
47 if self._buf[1] > 32 {
48 return Err(Nrf24Error::BinaryCorruption);
49 }
50 Ok(self._buf[1])
51 }
52}
53
54#[cfg(test)]
57mod test {
58 extern crate std;
59 use crate::radio::prelude::{EsbAutoAck, EsbPayloadLength};
60 use crate::radio::Nrf24Error;
61 use crate::spi_test_expects;
62
63 use super::{commands, registers, RF24};
64 use embedded_hal_mock::eh1::delay::NoopDelay;
65 use embedded_hal_mock::eh1::digital::Mock as PinMock;
66 use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction};
67 use std::vec;
68
69 const EN_ACK_PAY: u8 = 1 << 1;
70 const EN_DPL: u8 = 1 << 2;
71
72 #[test]
73 fn dynamic_payloads() {
74 let pin_expectations = [];
75 let mut pin_mock = PinMock::new(&pin_expectations);
76
77 let delay_mock = NoopDelay::new();
79
80 let spi_expectations = spi_test_expects![
81 (vec![registers::FEATURE, 0u8], vec![0xEu8, 0u8],),
83 (
84 vec![registers::FEATURE | commands::W_REGISTER, EN_DPL],
85 vec![0xEu8, 0u8],
86 ),
87 (
88 vec![registers::DYNPD | commands::W_REGISTER, 0x3Fu8],
89 vec![0xEu8, 0],
90 ),
91 (vec![commands::R_RX_PL_WID, 0u8], vec![0xEu8, 0xFFu8]),
93 (vec![commands::R_RX_PL_WID, 0xFFu8], vec![0xEu8, 32u8]),
95 (
97 vec![registers::FEATURE, 32u8],
98 vec![0xEu8, EN_ACK_PAY | EN_DPL],
99 ),
100 (
101 vec![registers::FEATURE | commands::W_REGISTER, 0u8],
102 vec![0xEu8, 0u8],
103 ),
104 (
105 vec![registers::DYNPD | commands::W_REGISTER, 0u8],
106 vec![0xEu8, 0],
107 ),
108 ];
109 let mut spi_mock = SpiMock::new(&spi_expectations);
110 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
111 radio.set_dynamic_payloads(true).unwrap();
112 assert!(radio.get_dynamic_payloads());
113 assert_eq!(
114 radio.get_dynamic_payload_length(),
115 Err(Nrf24Error::BinaryCorruption)
116 );
117 assert_eq!(radio.get_dynamic_payload_length().unwrap(), 32u8);
118 radio.set_dynamic_payloads(false).unwrap();
119 assert!(!radio.get_dynamic_payloads());
120 assert!(!radio.get_ack_payloads());
121 spi_mock.done();
122 pin_mock.done();
123 }
124
125 #[test]
126 pub fn set_payload_length() {
127 let pin_expectations = [];
129 let mut pin_mock = PinMock::new(&pin_expectations);
130
131 let delay_mock = NoopDelay::new();
133
134 let spi_expectations = spi_test_expects![
135 (
137 vec![registers::RX_PW_P0 | commands::W_REGISTER, 32u8],
138 vec![0xEu8, 0u8]
139 ),
140 (
141 vec![(registers::RX_PW_P0 + 1) | commands::W_REGISTER, 32u8],
142 vec![0xEu8, 0u8]
143 ),
144 (
145 vec![(registers::RX_PW_P0 + 2) | commands::W_REGISTER, 32u8],
146 vec![0xEu8, 0u8]
147 ),
148 (
149 vec![(registers::RX_PW_P0 + 3) | commands::W_REGISTER, 32u8],
150 vec![0xEu8, 0u8]
151 ),
152 (
153 vec![(registers::RX_PW_P0 + 4) | commands::W_REGISTER, 32u8],
154 vec![0xEu8, 0u8]
155 ),
156 (
157 vec![(registers::RX_PW_P0 + 5) | commands::W_REGISTER, 32u8],
158 vec![0xEu8, 0u8]
159 ),
160 (vec![registers::RX_PW_P0, 0u8], vec![0xEu8, 32u8]),
162 ];
163 let mut spi_mock = SpiMock::new(&spi_expectations);
164 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
165 radio.set_payload_length(76).unwrap();
166 assert_eq!(radio.get_payload_length().unwrap(), 32u8);
167 spi_mock.done();
168 pin_mock.done();
169 }
170}