1use crate::{
2 app::{Addresses, FramedConsumer, FramedProducer},
3 payload::{EsbHeader, PayloadR, PayloadW},
4 peripherals::{EsbRadio, EsbTimer, Interrupt, RxPayloadState},
5 Config, Error, RAMP_UP_TIME,
6};
7use core::{
8 marker::PhantomData,
9 sync::atomic::{AtomicBool, Ordering},
10};
11use cortex_m::peripheral::NVIC;
12
13pub struct Disabled;
15
16#[derive(PartialEq, Copy, Clone, Debug)]
18pub enum StatePTX {
19 IdleTx,
21 TransmitterTx,
23 TransmitterTxNoAck,
24 TransmitterWaitAck,
26 TransmitterWaitRetransmit,
28}
29
30#[derive(PartialEq, Copy, Clone, Debug)]
32pub enum StatePRX {
33 IdleRx,
35 Receiver,
37 TransmittingAck,
39 TransmittingRepeatedAck,
41}
42
43pub struct IrqTimer<T: EsbTimer> {
44 pub(crate) timer_flag: &'static AtomicBool,
46 pub(crate) _timer: PhantomData<T>,
47}
48
49impl<T: EsbTimer> IrqTimer<T> {
50 pub fn timer_interrupt(&mut self) {
52 let retransmit_event = T::is_retransmit_pending();
54 let ack_timeout_event = T::is_ack_pending();
55
56 if retransmit_event {
57 T::clear_interrupt_retransmit();
58 }
59 if ack_timeout_event {
61 T::clear_interrupt_ack();
62 }
63 self.timer_flag.store(true, Ordering::Release);
64 NVIC::pend(Interrupt::RADIO);
65 }
66}
67
68pub struct EsbIrq<const OUT: usize, const IN: usize, Timer, STATE>
74where
75 Timer: EsbTimer,
76{
77 pub(crate) prod_to_app: FramedProducer<IN>,
79
80 pub(crate) cons_from_app: FramedConsumer<OUT>,
82
83 pub(crate) timer: Timer,
85
86 pub(crate) radio: EsbRadio<OUT, IN>,
88
89 pub(crate) state: STATE,
91
92 pub(crate) addresses: Addresses,
94
95 pub(crate) attempts: u8,
97
98 pub(crate) timer_flag: &'static AtomicBool,
100
101 pub(crate) config: Config,
103}
104
105struct Events {
106 disabled: bool,
107 timer: bool,
108}
109
110impl<const OUT: usize, const IN: usize, Timer, STATE> EsbIrq<OUT, IN, Timer, STATE>
111where
112 Timer: EsbTimer,
113{
114 pub fn into_disabled(mut self) -> EsbIrq<OUT, IN, Timer, Disabled> {
116 self.radio.stop(true);
118 Timer::clear_interrupt_retransmit();
119 Timer::clear_interrupt_ack();
120 let _ = self.check_and_clear_flags();
121
122 EsbIrq {
123 prod_to_app: self.prod_to_app,
124 cons_from_app: self.cons_from_app,
125 timer: self.timer,
126 radio: self.radio,
127 state: Disabled,
128 addresses: self.addresses,
129 attempts: 0,
130 timer_flag: self.timer_flag,
131 config: self.config,
132 }
133 }
134
135 fn check_and_clear_flags(&mut self) -> Events {
136 let evts = Events {
137 disabled: self.radio.check_disabled_event(),
138 timer: self.timer_flag.load(Ordering::Acquire),
139 };
140
141 if evts.disabled {
142 self.radio.clear_disabled_event();
143 }
144 if evts.timer {
145 self.timer_flag.store(false, Ordering::Release);
146 }
147
148 NVIC::unpend(Interrupt::RADIO);
150
151 evts
152 }
153}
154
155impl<const OUT: usize, const IN: usize, Timer> EsbIrq<OUT, IN, Timer, Disabled>
156where
157 Timer: EsbTimer,
158{
159 pub fn into_ptx(self) -> EsbIrq<OUT, IN, Timer, StatePTX> {
161 EsbIrq {
162 prod_to_app: self.prod_to_app,
163 cons_from_app: self.cons_from_app,
164 timer: self.timer,
165 radio: self.radio,
166 state: StatePTX::IdleTx,
167 addresses: self.addresses,
168 attempts: 0,
169 timer_flag: self.timer_flag,
170 config: self.config,
171 }
172 }
173
174 pub fn into_prx(self) -> EsbIrq<OUT, IN, Timer, StatePRX> {
177 EsbIrq {
178 prod_to_app: self.prod_to_app,
179 cons_from_app: self.cons_from_app,
180 timer: self.timer,
181 radio: self.radio,
182 state: StatePRX::IdleRx,
183 addresses: self.addresses,
184 attempts: 0,
185 timer_flag: self.timer_flag,
186 config: self.config,
187 }
188 }
189}
190
191impl<const OUT: usize, const IN: usize, Timer> EsbIrq<OUT, IN, Timer, StatePTX>
192where
193 Timer: EsbTimer,
194{
195 pub fn radio_interrupt(&mut self) -> Result<StatePTX, Error> {
197 let Events { disabled, timer } = self.check_and_clear_flags();
198
199 let user_event = !disabled && !timer;
202
203 if user_event && self.state != StatePTX::IdleTx {
204 return Ok(self.state);
205 }
206
207 match self.state {
208 StatePTX::IdleTx => {
209 debug_assert!(user_event, "TransmitterTx de: {}, te: {}", disabled, timer);
211 if user_event {
212 self.send_packet();
213 }
214 }
215 StatePTX::TransmitterTxNoAck => {
216 self.radio.finish_tx_no_ack();
218 self.send_packet();
219 }
220 StatePTX::TransmitterTx => {
221 debug_assert!(disabled, "TransmitterTx de: {}, te: {}", disabled, timer);
222
223 let packet = self
224 .prod_to_app
225 .grant(u16::from(self.config.maximum_payload_size) + EsbHeader::header_size())
226 .map(PayloadW::new_from_radio);
227 if let Ok(packet) = packet {
228 self.radio.prepare_for_ack(packet);
229 self.state = StatePTX::TransmitterWaitAck;
230 } else {
231 self.radio.stop(true);
232 self.state = StatePTX::IdleTx;
233 return Err(Error::IncomingQueueFull);
234 }
235
236 self.timer
239 .set_interrupt_retransmit(self.config.retransmit_delay - RAMP_UP_TIME);
240
241 self.timer
243 .set_interrupt_ack(self.config.wait_for_ack_timeout + RAMP_UP_TIME);
244 }
245 StatePTX::TransmitterWaitAck => {
246 let mut retransmit = false;
247 if disabled {
248 Timer::clear_interrupt_ack();
250 if self.radio.check_ack()? {
251 Timer::clear_interrupt_retransmit();
254 self.attempts = 0;
255 self.send_packet();
256 } else {
257 retransmit = true;
259 }
260 } else {
261 debug_assert!(timer, "TransmitterWaitAck de: {}, te: {}", disabled, timer);
262 retransmit = true;
264 }
265 if retransmit {
266 self.radio.stop(true);
267 self.attempts += 1;
268 self.state = StatePTX::TransmitterWaitRetransmit;
269 }
270 if self.attempts > self.config.maximum_transmit_attempts {
271 Timer::clear_interrupt_retransmit();
272
273 if let Ok(old_packet) = self.cons_from_app.read() {
276 old_packet.release();
277 }
278 self.attempts = 0;
279 self.send_packet();
280 return Err(Error::MaximumAttempts);
281 }
282 }
283 StatePTX::TransmitterWaitRetransmit => {
284 debug_assert!(
285 timer,
286 "TransmitterWaitRetransmit de: {}, te: {}",
287 disabled, timer
288 );
289 self.send_packet();
291 }
292 }
293 Ok(self.state)
294 }
295
296 fn send_packet(&mut self) {
297 if let Ok(packet) = self.cons_from_app.read().map(PayloadR::new) {
298 let ack = !packet.no_ack();
299 self.radio.transmit(packet, ack);
300 if ack {
301 self.state = StatePTX::TransmitterTx;
302 } else {
303 self.state = StatePTX::TransmitterTxNoAck;
304 }
305 } else {
306 self.radio.disable_disabled_interrupt();
307 self.state = StatePTX::IdleTx;
308 }
309 }
310}
311
312impl<const OUT: usize, const IN: usize, Timer> EsbIrq<OUT, IN, Timer, StatePRX>
313where
314 Timer: EsbTimer,
315{
316 pub fn radio_interrupt(&mut self) -> Result<StatePRX, Error> {
318 let Events { disabled, timer } = self.check_and_clear_flags();
319
320 let user_event = !disabled && !timer;
323
324 if user_event && self.state != StatePRX::IdleRx {
325 return Ok(self.state);
326 }
327
328 match self.state {
329 StatePRX::Receiver => {
330 debug_assert!(disabled, "Receiver de: {}, te: {}", disabled, timer);
331 match self.radio.check_packet(&mut self.cons_from_app)? {
333 RxPayloadState::BadCRC => {}
335 RxPayloadState::NoAck => {
336 self.prepare_receiver(|this, grant| {
337 this.radio.complete_rx_no_ack(Some(grant));
338 Ok(())
339 })?;
340 }
341 RxPayloadState::RepeatedNoAck => {
342 self.radio.complete_rx_no_ack(None);
344 }
345 RxPayloadState::Ack => {
346 self.state = StatePRX::TransmittingAck;
347 }
348 RxPayloadState::RepeatedAck => {
349 self.state = StatePRX::TransmittingRepeatedAck;
350 }
351 }
352 }
353 StatePRX::TransmittingAck => {
354 debug_assert!(disabled, "TransmittingAck de: {}, te: {}", disabled, timer);
355 self.prepare_receiver(|this, grant| {
357 this.radio.complete_rx_ack(Some(grant))?;
359 this.state = StatePRX::Receiver;
360 Ok(())
361 })?;
362 }
363 StatePRX::TransmittingRepeatedAck => {
364 debug_assert!(
365 disabled,
366 "TransmittingRepeatedAck de: {}, te: {}",
367 disabled, timer
368 );
369 self.radio.complete_rx_ack(None)?;
371 self.state = StatePRX::Receiver;
372 }
373 StatePRX::IdleRx => {
374 debug_assert!(
375 user_event,
376 "TransmittingRepeatedAck de: {}, te: {}",
377 disabled, timer
378 );
379 self.start_receiving()?;
380 }
381 }
382 Ok(self.state)
383 }
384
385 pub fn start_receiving(&mut self) -> Result<(), Error> {
387 if self.state == StatePRX::IdleRx {
388 self.prepare_receiver(|this, grant| {
389 this.radio.start_receiving(grant, this.config.enabled_pipes);
390 this.state = StatePRX::Receiver;
391 Ok(())
392 })?;
393 }
394 Ok(())
395 }
396
397 pub fn stop_receiving(&mut self) {
399 self.radio.stop(true);
401 Timer::clear_interrupt_retransmit();
402 Timer::clear_interrupt_ack();
403 let _ = self.check_and_clear_flags();
404
405 self.state = StatePRX::IdleRx;
406 }
407
408 fn prepare_receiver<F>(&mut self, f: F) -> Result<(), Error>
409 where
410 F: FnOnce(&mut Self, PayloadW<IN>) -> Result<(), Error>,
411 {
412 if let Ok(grant) = self
413 .prod_to_app
414 .grant(u16::from(self.config.maximum_payload_size) + EsbHeader::header_size())
415 .map(PayloadW::new_from_radio)
416 {
417 f(self, grant)?;
418 Ok(())
419 } else {
420 self.radio.stop(true);
421 self.state = StatePRX::IdleRx;
422 Err(Error::IncomingQueueFull)
423 }
424 }
425}