capsules_extra/
rf233.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! SyscallDriver for sending 802.15.4 packets with an Atmel RF233.
6//!
7//! This implementation is completely non-blocking. This means that the state
8//! machine is somewhat complex, as it must interleave interrupt handling with
9//! requests and radio state management. See the SPI `read_write_done` handler
10//! for details.
11//
12// Author: Philip Levis
13// Date: Jan 12 2017
14//
15
16#![allow(unused_parens)]
17
18use crate::rf233_const::{
19    ExternalState, InteruptFlags, RF233BusCommand, RF233Register, RF233TrxCmd,
20};
21use core::cell::Cell;
22use kernel::hil::gpio;
23use kernel::hil::radio;
24use kernel::hil::spi;
25use kernel::utilities::cells::MapCell;
26use kernel::utilities::cells::OptionalCell;
27use kernel::utilities::leasable_buffer::SubSliceMut;
28use kernel::ErrorCode;
29
30use crate::rf233_const::CSMA_SEED_1;
31use crate::rf233_const::IRQ_MASK;
32use crate::rf233_const::PHY_CC_CCA_MODE_CS_OR_ED;
33use crate::rf233_const::PHY_RSSI_RX_CRC_VALID;
34use crate::rf233_const::PHY_TX_PWR;
35use crate::rf233_const::SHORT_ADDR_0;
36use crate::rf233_const::SHORT_ADDR_1;
37use crate::rf233_const::TRX_CTRL_1;
38use crate::rf233_const::TRX_CTRL_2;
39use crate::rf233_const::TRX_RPC;
40use crate::rf233_const::TRX_TRAC_CHANNEL_ACCESS_FAILURE;
41use crate::rf233_const::TRX_TRAC_MASK;
42use crate::rf233_const::XAH_CTRL_0;
43use crate::rf233_const::XAH_CTRL_1;
44
45#[allow(non_camel_case_types, dead_code)]
46#[derive(Copy, Clone, PartialEq)]
47enum InternalState {
48    // There are 6 high-level states:
49    // START -- the initialization sequence
50    // ON    -- turning the radio on to receive
51    // READY -- waiting to receive packets
52    // RX    -- receiving a packet
53    // TX    -- transmitting a packet
54    // CONFIG -- reconfiguring the radio
55    START,
56    START_PART_READ,
57    START_STATUS_READ,
58    START_TURNING_OFF,
59    START_CTRL1_SET,
60    START_CCA_SET,
61    START_PWR_SET,
62    START_CTRL2_SET,
63    START_IRQMASK_SET,
64    START_XAH1_SET,
65    START_XAH0_SET,
66    START_PANID0_SET,
67    START_PANID1_SET,
68    START_IEEE0_SET,
69    START_IEEE1_SET,
70    START_IEEE2_SET,
71    START_IEEE3_SET,
72    START_IEEE4_SET,
73    START_IEEE5_SET,
74    START_IEEE6_SET,
75    START_IEEE7_SET,
76    START_SHORT0_SET,
77    START_SHORT1_SET,
78    START_CSMA_0_SEEDED,
79    START_CSMA_1_SEEDED,
80    START_RPC_SET,
81
82    // Radio is configured, turning it on.
83    ON_STATUS_READ,
84    ON_PLL_WAITING,
85    ON_PLL_SET,
86
87    // Radio is in the RX_AACK_ON state, ready to receive packets.
88    READY,
89
90    // States that transition the radio to and from SLEEP
91    SLEEP_TRX_OFF,
92    SLEEP,
93    SLEEP_WAKE,
94
95    // States pertaining to packet transmission.
96    // Note that this state machine can be aborted due to
97    // an incoming packet; self.transmitting keeps track
98    // of whether a transmission is pending.
99    TX_STATUS_PRECHECK1,
100    TX_WRITING_FRAME,
101    TX_WRITING_FRAME_DONE,
102    TX_STATUS_PRECHECK2,
103    TX_PLL_START,
104    TX_PLL_WAIT,
105    TX_ARET_ON,
106    TX_TRANSMITTING,
107    TX_READ_ACK,
108    TX_DONE,
109    TX_RETURN_TO_RX,
110
111    // This state denotes we began a transmission, but
112    // before we could transition to PLL_ON a packet began
113    // to be received. When we handle the initial RX interrupt,
114    // we'll transition to the correct state. We can't return to READY
115    // because we need to block other operations.
116    TX_PENDING,
117
118    // Intermediate states when committing configuration from RAM
119    // to the chiP; short address, PAN address, tx power and channel
120    CONFIG_SHORT0_SET,
121    CONFIG_SHORT1_SET,
122    CONFIG_PAN0_SET,
123    CONFIG_PAN1_SET,
124    CONFIG_IEEE0_SET,
125    CONFIG_IEEE1_SET,
126    CONFIG_IEEE2_SET,
127    CONFIG_IEEE3_SET,
128    CONFIG_IEEE4_SET,
129    CONFIG_IEEE5_SET,
130    CONFIG_IEEE6_SET,
131    CONFIG_IEEE7_SET,
132    CONFIG_POWER_SET,
133    CONFIG_DONE,
134
135    // RX is a short-lived state for when software has detected
136    // the chip is receiving a packet (by internal state) but has
137    // not received the interrupt yet. I.e., the SFD has been
138    // received but not the rest of the packet yet.
139    RX,
140    // The packet has been successfully received
141    RX_TURNING_OFF,       // Disabling packet reception
142    RX_READY_TO_READ,     // Reception disabled, handle interrupt and start reading
143    RX_START_READING,     // Starting to read a packet out of the radio
144    RX_READING_FRAME_LEN, // We've read the length of the frame
145    RX_READING_FRAME_LEN_DONE,
146    RX_READING_FRAME,      // Reading the packet out of the radio
147    RX_READING_FRAME_DONE, // Now read a register to verify FCS
148    RX_READING_FRAME_FCS_DONE,
149    RX_ENABLING_RECEPTION, // Re-enabling reception
150}
151
152// There are two tricky parts to this capsule: buffer management
153// and the finite state machine.
154//
155// Buffer management is tricky because the implementation tries to
156// minimize the different buffers it uses. It needs to be able to send
157// 2-byte register reads and writes on initialization. So it needs 2
158// 2-byte buffers for these. When it is transmitting a packet, it
159// performs one long write over SPI to move the packet to the radio.
160// It needs a read buffer of equal length so it can check the radio
161// state.  Similarly, when it reads a packet out of RAM into a buffer,
162// it needs an equal length buffer for the SPI write. Finally, it
163// needs a buffer to receive packets into, so it doesn't drop a packet
164// just because an application didn't read in time. Therefore, the
165// structure needs four buffers: 2 2-byte buffers and two
166// packet-length buffers.  Since the SPI callback does not distinguish
167// which buffers are being used, the read_write_done callback checks
168// which state the stack is in and places the buffers back
169// accordingly. A bug here would mean a memory leak and later panic
170// when a buffer that should be present has been lost.
171//
172// The finite state machine is tricky for two reasons. First, the
173// radio can issue an interrupt at any time, and the stack handles the
174// interrupt (clearing it) by reading the IRQ_STATUS
175// register. Therefore, when an interrupt occurs, the next SPI
176// operation needs to read IRQ_STATUS (and potentially change
177// self.state) before returning to the main state
178// machine. self.interrupt_pending indicates if an interrupt has fired
179// and therefore must be handled by reading IRQ_STATUS and acting
180// accordingly. self.interrupt_handling indicates that a read of
181// IRQ_STATUS is pending and so the read_write_done should enact state
182// transitions based on the interrupt.
183//
184// Second, it is possible that a packet starts arriving while the
185// stack is preparing a transmission. In this case, the transmission
186// needs to be aborted, but restarted once the reception
187// completes. The stack keeps track of this with self.transmitting.
188// The final state before transmission is TX_ARET_ON; the next step is
189// to start transmission. If a start-of-frame interrupt is handled at
190// any point in the TX state machine, the stack moves to the RX state
191// and waits for the interrupt specifying the entire packet has been
192// received.
193
194pub const SPI_REGISTER_TRANSACTION_LENGTH: usize = 2;
195
196pub struct RF233<'a, S: spi::SpiMasterDevice<'a>> {
197    spi: &'a S,
198    radio_on: Cell<bool>,
199    transmitting: Cell<bool>,
200    receiving: Cell<bool>,
201    spi_busy: Cell<bool>,
202    crc_valid: Cell<bool>,
203    interrupt_handling: Cell<bool>,
204    interrupt_pending: Cell<bool>,
205    config_pending: Cell<bool>,
206    sleep_pending: Cell<bool>,
207    wake_pending: Cell<bool>,
208    power_client_pending: Cell<bool>,
209    reset_pin: &'a dyn gpio::Pin,
210    sleep_pin: &'a dyn gpio::Pin,
211    irq_pin: &'a dyn gpio::InterruptPin<'a>,
212    state: Cell<InternalState>,
213    tx_buf: MapCell<SubSliceMut<'static, u8>>,
214    rx_buf: MapCell<SubSliceMut<'static, u8>>,
215    tx_len: Cell<u8>,
216    tx_client: OptionalCell<&'a dyn radio::TxClient>,
217    rx_client: OptionalCell<&'a dyn radio::RxClient>,
218    cfg_client: OptionalCell<&'a dyn radio::ConfigClient>,
219    power_client: OptionalCell<&'a dyn radio::PowerClient>,
220    addr: Cell<u16>,
221    addr_long: Cell<[u8; 8]>,
222    pan: Cell<u16>,
223    tx_power: Cell<i8>,
224    channel: Cell<radio::RadioChannel>,
225    spi_rx: MapCell<SubSliceMut<'static, u8>>,
226    spi_tx: MapCell<SubSliceMut<'static, u8>>,
227    spi_buf: MapCell<SubSliceMut<'static, u8>>,
228}
229
230fn setting_to_power(setting: u8) -> i8 {
231    match setting {
232        0x00 => 4,
233        0x01 => 4,
234        0x02 => 3,
235        0x03 => 3,
236        0x04 => 2,
237        0x05 => 2,
238        0x06 => 1,
239        0x07 => 0,
240        0x08 => -1,
241        0x09 => -2,
242        0x0A => -3,
243        0x0B => -4,
244        0x0C => -6,
245        0x0D => -8,
246        0x0E => -12,
247        0x0F => -17,
248        _ => -127,
249    }
250}
251
252fn power_to_setting(power: i8) -> u8 {
253    if (power >= 4) {
254        0x00
255    } else if (power >= 3) {
256        0x03
257    } else if (power >= 2) {
258        0x05
259    } else if (power >= 1) {
260        0x06
261    } else if (power >= 0) {
262        0x07
263    } else if (power >= -1) {
264        0x08
265    } else if (power >= -2) {
266        0x09
267    } else if (power >= -3) {
268        0x0A
269    } else if (power >= -4) {
270        0x0B
271    } else if (power >= -6) {
272        0x0C
273    } else if (power >= -8) {
274        0x0D
275    } else if (power >= -12) {
276        0x0E
277    } else {
278        0x0F
279    }
280}
281
282fn interrupt_included(mask: u8, interrupt: InteruptFlags) -> bool {
283    let int = interrupt as u8;
284    (mask & int) == int
285}
286
287impl<'a, S: spi::SpiMasterDevice<'a>> spi::SpiMasterClient for RF233<'a, S> {
288    // This function is a bit confusing because the order of the logic in the
289    // function is different than the order of operations during transmission
290    // and reception.
291    fn read_write_done(
292        &self,
293        mut _write: SubSliceMut<'static, u8>,
294        mut read: Option<SubSliceMut<'static, u8>>,
295        _spi_status: Result<usize, ErrorCode>,
296    ) {
297        self.spi_busy.set(false);
298        let rbuf = read.take().unwrap();
299        let status = rbuf[0] & 0x1f;
300        let result = rbuf[1];
301
302        // Need to put buffers back. Four cases:
303        // 1. a frame read completed, need to put RX buf back and put the
304        //    used write buf back into spi_buf
305        // 2. a frame length read completed, need to put RX buf back and
306        //    put the used write buf back into spi_buf
307        // 3. a frame write completed, need to put TX buf back and put the
308        //    used read buf back into spi_buf
309        // 4. a register op completed, need to but the used read buf back into
310        //    spi_rx and the used write buf into spi_tx. interrupt handling
311        //    is implicitly a register op.
312        // Note that in cases 1-3, we need to enact a state transition
313        // so that, if an interrupt is pending, we don't put the buffers
314        // back again. The _DONE states denote that the frame transfer
315        // has completed. So we'll put the buffers back only once.
316        let state = self.state.get();
317
318        let handling = self.interrupt_handling.get();
319        if !handling && state == InternalState::RX_READING_FRAME_LEN {
320            self.spi_buf.replace(_write);
321            self.rx_buf.replace(rbuf);
322            self.state.set(InternalState::RX_READING_FRAME_LEN_DONE);
323        } else if !handling && state == InternalState::RX_READING_FRAME {
324            self.spi_buf.replace(_write);
325            self.rx_buf.replace(rbuf);
326            self.state.set(InternalState::RX_READING_FRAME_DONE);
327        } else if !handling && state == InternalState::TX_WRITING_FRAME {
328            self.spi_buf.replace(rbuf);
329            self.tx_buf.replace(_write);
330            self.state.set(InternalState::TX_WRITING_FRAME_DONE);
331        } else {
332            self.spi_rx.replace(rbuf);
333            self.spi_tx.replace(_write);
334        }
335
336        let state = self.state.get();
337
338        // This case is when the SPI operation is reading the IRQ_STATUS
339        // register from handling an interrupt. Note that we're done handling
340        // the interrupt and continue with the state machine.
341        if handling {
342            self.interrupt_handling.set(false);
343
344            let interrupt = result;
345
346            // If we're going to sleep, ignore the interrupt and continue
347            if state != InternalState::SLEEP_TRX_OFF && state != InternalState::SLEEP {
348                if state == InternalState::ON_PLL_WAITING {
349                    if interrupt_included(interrupt, InteruptFlags::IRQ_0_PLL_LOCK) {
350                        self.state.set(InternalState::ON_PLL_SET);
351                    }
352                } else if state == InternalState::TX_TRANSMITTING
353                    && interrupt_included(interrupt, InteruptFlags::IRQ_3_TRX_END)
354                {
355                    self.state.set(InternalState::TX_DONE);
356                }
357                if interrupt_included(interrupt, InteruptFlags::IRQ_2_RX_START) {
358                    // Start of frame
359                    self.receiving.set(true);
360                    self.state.set(InternalState::RX);
361                }
362
363                // We've received  an entire frame into the frame buffer. This should be
364                // in the InternalState::RX_READY_TO_READ state.
365                // There are three cases:
366                //   1. we have a receive buffer: copy it out
367                //   2. no receive buffer, but transmission pending: send
368                //   3. no receive buffer, no transmission: return to waiting
369                if (interrupt_included(interrupt, InteruptFlags::IRQ_3_TRX_END)
370                    && self.receiving.get())
371                {
372                    self.receiving.set(false);
373                    if self.rx_buf.is_some() {
374                        self.state.set(InternalState::RX_START_READING);
375                    } else if self.transmitting.get() {
376                        self.state_transition_read(
377                            RF233Register::MIN,
378                            InternalState::TX_STATUS_PRECHECK1,
379                        );
380                        return;
381                    } else {
382                        self.state_transition_read(RF233Register::TRX_STATUS, InternalState::READY);
383                        return;
384                    }
385                }
386            }
387        }
388
389        // No matter what, if the READY state is reached, the radio is on. This
390        // needs to occur before handling the interrupt below.
391        if self.state.get() == InternalState::READY {
392            self.wake_pending.set(false);
393
394            // If we just woke up, note that we need to call the PowerClient
395            if !self.radio_on.get() {
396                self.power_client_pending.set(true);
397            }
398            self.radio_on.set(true);
399        }
400
401        // An interrupt can only be pending if an interrupt was fired during an
402        // SPI operation: we wait for the SPI operation to complete then handle
403        // the interrupt by reading the IRQ_STATUS register over the SPI.
404        //
405        // However, we should not handle the interrupt if we are in the midst of
406        // receiving a frame.
407        if self.interrupt_pending.get() {
408            match self.state.get() {
409                InternalState::RX_TURNING_OFF
410                | InternalState::RX_START_READING
411                | InternalState::RX_READING_FRAME_DONE
412                | InternalState::RX_READING_FRAME_FCS_DONE => {}
413                _ => {
414                    self.interrupt_pending.set(false);
415                    self.handle_interrupt();
416                    return;
417                }
418            }
419        }
420        // Similarly, if a configuration is pending, we only start the
421        // configuration process when we are in a state where it is legal to
422        // start the configuration process.
423        if self.config_pending.get() && self.state.get() == InternalState::READY {
424            self.state_transition_write(
425                RF233Register::SHORT_ADDR_0,
426                (self.addr.get() & 0xff) as u8,
427                InternalState::CONFIG_SHORT0_SET,
428            );
429        }
430
431        match self.state.get() {
432            // Default on state; wait for transmit() call or receive interrupt
433            InternalState::READY => {
434                // If stop() was called, start turning off the radio.
435                if self.sleep_pending.get() {
436                    self.sleep_pending.set(false);
437                    self.radio_on.set(false);
438                    self.state_transition_write(
439                        RF233Register::TRX_STATE,
440                        RF233TrxCmd::OFF as u8,
441                        InternalState::SLEEP_TRX_OFF,
442                    );
443                } else if self.power_client_pending.get() {
444                    // fixes bug where client would start transmitting before this state completed
445                    self.power_client_pending.set(false);
446                    self.power_client.map(|p| {
447                        p.changed(self.radio_on.get());
448                    });
449                }
450            }
451            // Starting state, begin start sequence.
452            InternalState::START => {
453                self.state_transition_read(
454                    RF233Register::IRQ_STATUS,
455                    InternalState::START_PART_READ,
456                );
457            }
458            InternalState::START_PART_READ => {
459                self.state_transition_read(
460                    RF233Register::TRX_STATUS,
461                    InternalState::START_STATUS_READ,
462                );
463            }
464            InternalState::START_STATUS_READ => {
465                if status == ExternalState::ON as u8 {
466                    self.state_transition_write(
467                        RF233Register::TRX_STATE,
468                        RF233TrxCmd::OFF as u8,
469                        InternalState::START_TURNING_OFF,
470                    );
471                } else {
472                    self.state_transition_write(
473                        RF233Register::TRX_CTRL_1,
474                        TRX_CTRL_1,
475                        InternalState::START_CTRL1_SET,
476                    );
477                }
478            }
479            InternalState::START_TURNING_OFF => {
480                self.irq_pin.make_input();
481                self.irq_pin.clear();
482                self.irq_pin
483                    .set_floating_state(gpio::FloatingState::PullNone);
484                self.irq_pin
485                    .enable_interrupts(gpio::InterruptEdge::RisingEdge);
486
487                self.state_transition_write(
488                    RF233Register::TRX_CTRL_1,
489                    TRX_CTRL_1,
490                    InternalState::START_CTRL1_SET,
491                );
492            }
493            InternalState::START_CTRL1_SET => {
494                let val = self.channel.get().get_channel_number() | PHY_CC_CCA_MODE_CS_OR_ED;
495                self.state_transition_write(
496                    RF233Register::PHY_CC_CCA,
497                    val,
498                    InternalState::START_CCA_SET,
499                );
500            }
501            InternalState::START_CCA_SET => {
502                let val = power_to_setting(self.tx_power.get());
503                self.state_transition_write(
504                    RF233Register::PHY_TX_PWR,
505                    val,
506                    InternalState::START_PWR_SET,
507                );
508            }
509            InternalState::START_PWR_SET => self.state_transition_write(
510                RF233Register::TRX_CTRL_2,
511                TRX_CTRL_2,
512                InternalState::START_CTRL2_SET,
513            ),
514            InternalState::START_CTRL2_SET => {
515                self.state_transition_write(
516                    RF233Register::IRQ_MASK,
517                    IRQ_MASK,
518                    InternalState::START_IRQMASK_SET,
519                );
520            }
521
522            InternalState::START_IRQMASK_SET => {
523                self.state_transition_write(
524                    RF233Register::XAH_CTRL_1,
525                    XAH_CTRL_1,
526                    InternalState::START_XAH1_SET,
527                );
528            }
529
530            InternalState::START_XAH1_SET => {
531                // This encapsulates the frame retry and CSMA retry
532                // settings in the RF233 C code
533                self.state_transition_write(
534                    RF233Register::XAH_CTRL_0,
535                    XAH_CTRL_0,
536                    InternalState::START_XAH0_SET,
537                );
538            }
539            InternalState::START_XAH0_SET => {
540                self.state_transition_write(
541                    RF233Register::PAN_ID_0,
542                    (self.pan.get() >> 8) as u8,
543                    InternalState::START_PANID0_SET,
544                );
545            }
546            InternalState::START_PANID0_SET => {
547                self.state_transition_write(
548                    RF233Register::PAN_ID_1,
549                    (self.pan.get() & 0xff) as u8,
550                    InternalState::START_PANID1_SET,
551                );
552            }
553            InternalState::START_PANID1_SET => {
554                self.state_transition_write(
555                    RF233Register::IEEE_ADDR_0,
556                    self.addr_long.get()[0],
557                    InternalState::START_IEEE0_SET,
558                );
559            }
560            InternalState::START_IEEE0_SET => {
561                self.state_transition_write(
562                    RF233Register::IEEE_ADDR_1,
563                    self.addr_long.get()[1],
564                    InternalState::START_IEEE1_SET,
565                );
566            }
567            InternalState::START_IEEE1_SET => {
568                self.state_transition_write(
569                    RF233Register::IEEE_ADDR_2,
570                    self.addr_long.get()[2],
571                    InternalState::START_IEEE2_SET,
572                );
573            }
574            InternalState::START_IEEE2_SET => {
575                self.state_transition_write(
576                    RF233Register::IEEE_ADDR_3,
577                    self.addr_long.get()[3],
578                    InternalState::START_IEEE3_SET,
579                );
580            }
581            InternalState::START_IEEE3_SET => {
582                self.state_transition_write(
583                    RF233Register::IEEE_ADDR_4,
584                    self.addr_long.get()[4],
585                    InternalState::START_IEEE4_SET,
586                );
587            }
588            InternalState::START_IEEE4_SET => {
589                self.state_transition_write(
590                    RF233Register::IEEE_ADDR_5,
591                    self.addr_long.get()[5],
592                    InternalState::START_IEEE5_SET,
593                );
594            }
595            InternalState::START_IEEE5_SET => {
596                self.state_transition_write(
597                    RF233Register::IEEE_ADDR_6,
598                    self.addr_long.get()[6],
599                    InternalState::START_IEEE6_SET,
600                );
601            }
602            InternalState::START_IEEE6_SET => {
603                self.state_transition_write(
604                    RF233Register::IEEE_ADDR_7,
605                    self.addr_long.get()[7],
606                    InternalState::START_IEEE7_SET,
607                );
608            }
609            InternalState::START_IEEE7_SET => {
610                self.state_transition_write(
611                    RF233Register::SHORT_ADDR_0,
612                    (self.addr.get() & 0xff) as u8,
613                    InternalState::START_SHORT0_SET,
614                );
615            }
616            InternalState::START_SHORT0_SET => {
617                self.state_transition_write(
618                    RF233Register::SHORT_ADDR_1,
619                    (self.addr.get() >> 8) as u8,
620                    InternalState::START_SHORT1_SET,
621                );
622            }
623            InternalState::START_SHORT1_SET => {
624                self.state_transition_write(
625                    RF233Register::CSMA_SEED_0,
626                    SHORT_ADDR_0 + SHORT_ADDR_1,
627                    InternalState::START_CSMA_0_SEEDED,
628                );
629            }
630            InternalState::START_CSMA_0_SEEDED => {
631                self.state_transition_write(
632                    RF233Register::CSMA_SEED_1,
633                    CSMA_SEED_1,
634                    InternalState::START_CSMA_1_SEEDED,
635                );
636            }
637            InternalState::START_CSMA_1_SEEDED => {
638                self.state_transition_write(
639                    RF233Register::TRX_RPC,
640                    TRX_RPC,
641                    InternalState::START_RPC_SET,
642                );
643            }
644            InternalState::START_RPC_SET => {
645                // If asleep, turn on
646                self.state_transition_read(
647                    RF233Register::TRX_STATUS,
648                    InternalState::ON_STATUS_READ,
649                );
650            }
651            InternalState::ON_STATUS_READ => {
652                self.state_transition_write(
653                    RF233Register::TRX_STATE,
654                    RF233TrxCmd::PLL_ON as u8,
655                    InternalState::ON_PLL_WAITING,
656                );
657            }
658            InternalState::ON_PLL_WAITING => {
659                // Waiting for the PLL interrupt, do nothing
660            }
661
662            // Final startup state, transition to READY and turn radio on.
663            InternalState::ON_PLL_SET => {
664                // We've completed the SPI operation to read the
665                // IRQ_STATUS register, triggered by an interrupt
666                // denoting moving to the PLL_ON state, so move
667                // to RX_ON (see Sec 7, pg 36 of RF233 datasheet
668                self.state_transition_write(
669                    RF233Register::TRX_STATE,
670                    RF233TrxCmd::RX_AACK_ON as u8,
671                    InternalState::READY,
672                );
673            }
674            InternalState::SLEEP_TRX_OFF => {
675                // Toggle the sleep pin to put the radio into sleep mode
676                self.sleep_pin.set();
677
678                // If start() was called while we were shutting down,
679                // immediately start turning the radio back on
680                if self.wake_pending.get() {
681                    self.state_transition_read(
682                        RF233Register::TRX_STATUS,
683                        InternalState::SLEEP_WAKE,
684                    );
685                // Inform power client that the radio turned off successfully
686                } else {
687                    self.state.set(InternalState::SLEEP);
688                    self.power_client.map(|p| {
689                        p.changed(self.radio_on.get());
690                    });
691                    self.irq_pin.disable_interrupts(); // Lets MCU sleep
692                }
693            }
694            // Do nothing; a call to start() is required to restart radio
695            InternalState::SLEEP => {}
696
697            InternalState::SLEEP_WAKE => {
698                // Toggle the sleep pin to take the radio out of sleep mode into
699                // InternalState::TRX_OFF, then transition directly to RX_AACK_ON.
700                self.sleep_pin.clear();
701                self.irq_pin
702                    .enable_interrupts(gpio::InterruptEdge::RisingEdge);
703                self.state_transition_write(
704                    RF233Register::TRX_STATE,
705                    RF233TrxCmd::RX_AACK_ON as u8,
706                    InternalState::READY,
707                );
708            }
709            InternalState::TX_STATUS_PRECHECK1 => {
710                if (status == ExternalState::BUSY_RX_AACK as u8
711                    || status == ExternalState::BUSY_TX_ARET as u8
712                    || status == ExternalState::BUSY_RX as u8)
713                {
714                    self.state.set(InternalState::TX_PENDING);
715                } else {
716                    // Something wrong here?
717                    self.state.set(InternalState::TX_WRITING_FRAME);
718                    let wbuf = self.tx_buf.take().unwrap();
719                    let _ = self.frame_write(wbuf.take(), self.tx_len.get());
720                }
721            }
722            InternalState::TX_WRITING_FRAME => {} // Should never get here
723            InternalState::TX_WRITING_FRAME_DONE => {
724                self.state_transition_read(
725                    RF233Register::TRX_STATUS,
726                    InternalState::TX_STATUS_PRECHECK2,
727                );
728            }
729            InternalState::TX_STATUS_PRECHECK2 => {
730                if (status == ExternalState::BUSY_RX_AACK as u8
731                    || status == ExternalState::BUSY_TX_ARET as u8
732                    || status == ExternalState::BUSY_RX as u8)
733                {
734                    self.receiving.set(true);
735                    self.state.set(InternalState::RX);
736                } else {
737                    self.state_transition_write(
738                        RF233Register::TRX_STATE,
739                        RF233TrxCmd::PLL_ON as u8,
740                        InternalState::TX_PLL_START,
741                    );
742                }
743            }
744            InternalState::TX_PLL_START => {
745                self.state_transition_read(RF233Register::TRX_STATUS, InternalState::TX_PLL_WAIT);
746            }
747            InternalState::TX_PLL_WAIT => {
748                self.transmitting.set(true);
749                if status == ExternalState::STATE_TRANSITION_IN_PROGRESS as u8 {
750                    self.state_transition_read(
751                        RF233Register::TRX_STATUS,
752                        InternalState::TX_PLL_WAIT,
753                    );
754                } else if status != ExternalState::PLL_ON as u8 {
755                    self.state_transition_write(
756                        RF233Register::TRX_STATE,
757                        RF233TrxCmd::PLL_ON as u8,
758                        InternalState::TX_PLL_WAIT,
759                    );
760                } else {
761                    self.state_transition_write(
762                        RF233Register::TRX_STATE,
763                        RF233TrxCmd::TX_ARET_ON as u8,
764                        InternalState::TX_ARET_ON,
765                    );
766                }
767            }
768            InternalState::TX_ARET_ON => {
769                self.state_transition_write(
770                    RF233Register::TRX_STATE,
771                    RF233TrxCmd::TX_START as u8,
772                    InternalState::TX_TRANSMITTING,
773                );
774            }
775            InternalState::TX_TRANSMITTING => {
776                // Do nothing, wait for TRX_END interrupt denoting transmission
777                // completed. The code at the top of this SPI handler for
778                // interrupt handling will transition to the TX_DONE state.
779            }
780            InternalState::TX_DONE => {
781                self.state_transition_write(
782                    RF233Register::TRX_STATE,
783                    RF233TrxCmd::RX_AACK_ON as u8,
784                    InternalState::TX_READ_ACK,
785                );
786            }
787            InternalState::TX_READ_ACK => {
788                self.state_transition_read(
789                    RF233Register::TRX_STATE,
790                    InternalState::TX_RETURN_TO_RX,
791                );
792            }
793
794            // Insert read of TRX_STATUS here, checking TRAC
795            InternalState::TX_RETURN_TO_RX => {
796                let ack: bool = (result & TRX_TRAC_MASK) == 0;
797                if status == ExternalState::RX_AACK_ON as u8 {
798                    let return_code = if (result & TRX_TRAC_MASK) == TRX_TRAC_CHANNEL_ACCESS_FAILURE
799                    {
800                        Err(ErrorCode::FAIL)
801                    } else {
802                        Ok(())
803                    };
804
805                    self.transmitting.set(false);
806                    let buf = self.tx_buf.take();
807                    self.state_transition_read(RF233Register::TRX_STATUS, InternalState::READY);
808
809                    self.tx_client.map(|c| {
810                        c.send_done(buf.unwrap().take(), ack, return_code);
811                    });
812                } else {
813                    let _ = self.register_read(RF233Register::TRX_STATUS);
814                }
815            }
816
817            // This state occurs when, in the midst of starting a
818            // transmission, we discovered that the radio had moved into
819            // a receive state. Since this will trigger interrupts,
820            // we enter this dead state and just wait for the interrupt
821            // handlers.
822            InternalState::TX_PENDING => {}
823
824            // No operations in the RX state, an SFD interrupt should
825            // take us out of it.
826            InternalState::RX => {}
827            InternalState::RX_TURNING_OFF => {
828                // This is the case when the driver turns off reception in
829                // response to receiving a frame, to make sure it is not
830                // overwritten. Now we are reading to handle the interrupt and
831                // start reading out the frame.
832                self.state_transition_read(
833                    RF233Register::IRQ_STATUS,
834                    InternalState::RX_READY_TO_READ,
835                );
836                self.interrupt_handling.set(true);
837            }
838            // This state is when the driver handles the pending TRX_END interrupt
839            // on reception, so is handled above in the interrupt logic.
840            // the pending interrupt will be handled
841            InternalState::RX_READY_TO_READ => {}
842
843            // Read the length out
844            InternalState::RX_START_READING => {
845                self.state.set(InternalState::RX_READING_FRAME_LEN);
846                // A frame read of frame_length 0 results in the received SPI
847                // buffer only containing two bytes, the chip status and the
848                // frame length.
849                let _ = self.frame_read(self.rx_buf.take().unwrap().take(), 0);
850            }
851
852            InternalState::RX_READING_FRAME_LEN => {} // Should not get this
853            InternalState::RX_READING_FRAME_LEN_DONE => {
854                // A frame read starts with a 1-byte chip status followed by a
855                // 1-byte PHY header, which is the length of the frame.
856                // Then, the frame follows, and there are 3 more bytes at the
857                // end corresponding to LQI, ED, and RX_STATUS. Performing a
858                // shorter frame read just drops these bytes.
859                let frame_len = result;
860                // If the packet isn't too long to fit in the SPI buffer, read it
861                if (frame_len <= radio::MAX_FRAME_SIZE as u8
862                    && frame_len >= radio::MIN_FRAME_SIZE as u8)
863                {
864                    self.state.set(InternalState::RX_READING_FRAME);
865                    let rbuf = self.rx_buf.take().unwrap();
866                    let _ = self.frame_read(rbuf.take(), frame_len);
867                } else if self.transmitting.get() {
868                    // Packet was too long and a transmission is pending,
869                    // start the transmission
870                    self.state_transition_read(
871                        RF233Register::TRX_STATUS,
872                        InternalState::TX_STATUS_PRECHECK1,
873                    );
874                } else {
875                    // Packet was too long and no pending transmission,
876                    // return to waiting for packets.
877                    self.state_transition_read(RF233Register::TRX_STATUS, InternalState::READY);
878                }
879            }
880            InternalState::RX_READING_FRAME => {} // Should never get this state
881            InternalState::RX_READING_FRAME_DONE => {
882                // Now read the PHY_RSSI register to obtain the RX_CRC_VALID bit
883                self.state_transition_read(
884                    RF233Register::PHY_RSSI,
885                    InternalState::RX_READING_FRAME_FCS_DONE,
886                );
887            }
888            InternalState::RX_READING_FRAME_FCS_DONE => {
889                // Store whether the CRC was valid, then turn the radio back on.
890                self.crc_valid.set((result & PHY_RSSI_RX_CRC_VALID) != 0);
891                self.state_transition_write(
892                    RF233Register::TRX_STATE,
893                    RF233TrxCmd::RX_AACK_ON as u8,
894                    InternalState::RX_ENABLING_RECEPTION,
895                );
896            }
897            InternalState::RX_ENABLING_RECEPTION => {
898                self.receiving.set(false);
899
900                // Stay awake if we receive a packet, another call to stop()
901                // is therefore necessary to shut down the radio. Currently
902                // mainly benefits the XMAC wrapper that would like to avoid
903                // a shutdown when in the expected case the radio should stay
904                // awake.
905                self.sleep_pending.set(false);
906
907                // Just read a packet: if a transmission is pending,
908                // start the transmission state machine
909                if self.transmitting.get() {
910                    self.state_transition_read(
911                        RF233Register::TRX_STATUS,
912                        InternalState::TX_STATUS_PRECHECK1,
913                    );
914                } else {
915                    self.state_transition_read(RF233Register::TRX_STATUS, InternalState::READY);
916                }
917                self.rx_client.map(|client| {
918                    let rbuf = self.rx_buf.take().unwrap();
919                    let frame_len = rbuf[1] as usize - radio::MFR_SIZE;
920
921                    // lqi is currently unimplemented for rf233 and is subsequently hardcoded to zero
922                    client.receive(rbuf.take(), frame_len, 0, self.crc_valid.get(), Ok(()));
923                });
924            }
925
926            InternalState::CONFIG_SHORT0_SET => {
927                self.state_transition_write(
928                    RF233Register::SHORT_ADDR_1,
929                    (self.addr.get() >> 8) as u8,
930                    InternalState::CONFIG_SHORT1_SET,
931                );
932            }
933            InternalState::CONFIG_SHORT1_SET => {
934                self.state_transition_write(
935                    RF233Register::PAN_ID_0,
936                    (self.pan.get() & 0xff) as u8,
937                    InternalState::CONFIG_PAN0_SET,
938                );
939            }
940            InternalState::CONFIG_PAN0_SET => {
941                self.state_transition_write(
942                    RF233Register::PAN_ID_1,
943                    (self.pan.get() >> 8) as u8,
944                    InternalState::CONFIG_PAN1_SET,
945                );
946            }
947            InternalState::CONFIG_PAN1_SET => {
948                self.state_transition_write(
949                    RF233Register::IEEE_ADDR_0,
950                    self.addr_long.get()[0],
951                    InternalState::CONFIG_IEEE0_SET,
952                );
953            }
954            InternalState::CONFIG_IEEE0_SET => {
955                self.state_transition_write(
956                    RF233Register::IEEE_ADDR_1,
957                    self.addr_long.get()[1],
958                    InternalState::CONFIG_IEEE1_SET,
959                );
960            }
961            InternalState::CONFIG_IEEE1_SET => {
962                self.state_transition_write(
963                    RF233Register::IEEE_ADDR_2,
964                    self.addr_long.get()[2],
965                    InternalState::CONFIG_IEEE2_SET,
966                );
967            }
968            InternalState::CONFIG_IEEE2_SET => {
969                self.state_transition_write(
970                    RF233Register::IEEE_ADDR_3,
971                    self.addr_long.get()[3],
972                    InternalState::CONFIG_IEEE3_SET,
973                );
974            }
975            InternalState::CONFIG_IEEE3_SET => {
976                self.state_transition_write(
977                    RF233Register::IEEE_ADDR_4,
978                    self.addr_long.get()[4],
979                    InternalState::CONFIG_IEEE4_SET,
980                );
981            }
982            InternalState::CONFIG_IEEE4_SET => {
983                self.state_transition_write(
984                    RF233Register::IEEE_ADDR_5,
985                    self.addr_long.get()[5],
986                    InternalState::CONFIG_IEEE5_SET,
987                );
988            }
989            InternalState::CONFIG_IEEE5_SET => {
990                self.state_transition_write(
991                    RF233Register::IEEE_ADDR_6,
992                    self.addr_long.get()[6],
993                    InternalState::CONFIG_IEEE6_SET,
994                );
995            }
996            InternalState::CONFIG_IEEE6_SET => {
997                self.state_transition_write(
998                    RF233Register::IEEE_ADDR_7,
999                    self.addr_long.get()[7],
1000                    InternalState::CONFIG_IEEE7_SET,
1001                );
1002            }
1003            InternalState::CONFIG_IEEE7_SET => {
1004                let val = power_to_setting(self.tx_power.get());
1005                self.state_transition_write(
1006                    RF233Register::PHY_TX_PWR,
1007                    val,
1008                    InternalState::CONFIG_POWER_SET,
1009                );
1010            }
1011            InternalState::CONFIG_POWER_SET => {
1012                let val = self.channel.get().get_channel_number() | PHY_CC_CCA_MODE_CS_OR_ED;
1013                self.state_transition_write(
1014                    RF233Register::PHY_CC_CCA,
1015                    val,
1016                    InternalState::CONFIG_DONE,
1017                );
1018            }
1019            InternalState::CONFIG_DONE => {
1020                self.config_pending.set(false);
1021                self.state_transition_read(RF233Register::TRX_STATUS, InternalState::READY);
1022                self.cfg_client.map(|c| {
1023                    c.config_done(Ok(()));
1024                });
1025            }
1026        }
1027    }
1028}
1029
1030impl<'a, S: spi::SpiMasterDevice<'a>> gpio::Client for RF233<'a, S> {
1031    fn fired(&self) {
1032        self.handle_interrupt();
1033    }
1034}
1035
1036impl<'a, S: spi::SpiMasterDevice<'a>> RF233<'a, S> {
1037    pub fn new(
1038        spi: &'a S,
1039        spi_buf: &'static mut [u8],
1040        reg_write: &'static mut [u8; SPI_REGISTER_TRANSACTION_LENGTH],
1041        reg_read: &'static mut [u8; SPI_REGISTER_TRANSACTION_LENGTH],
1042        reset: &'a dyn gpio::Pin,
1043        sleep: &'a dyn gpio::Pin,
1044        irq: &'a dyn gpio::InterruptPin<'a>,
1045        channel: radio::RadioChannel,
1046    ) -> RF233<'a, S> {
1047        RF233 {
1048            spi,
1049            reset_pin: reset,
1050            sleep_pin: sleep,
1051            irq_pin: irq,
1052            radio_on: Cell::new(false),
1053            transmitting: Cell::new(false),
1054            receiving: Cell::new(false),
1055            spi_busy: Cell::new(false),
1056            crc_valid: Cell::new(false),
1057            state: Cell::new(InternalState::START),
1058            interrupt_handling: Cell::new(false),
1059            interrupt_pending: Cell::new(false),
1060            config_pending: Cell::new(false),
1061            sleep_pending: Cell::new(false),
1062            wake_pending: Cell::new(false),
1063            power_client_pending: Cell::new(false),
1064            tx_buf: MapCell::empty(),
1065            rx_buf: MapCell::empty(),
1066            tx_len: Cell::new(0),
1067            tx_client: OptionalCell::empty(),
1068            rx_client: OptionalCell::empty(),
1069            cfg_client: OptionalCell::empty(),
1070            power_client: OptionalCell::empty(),
1071            addr: Cell::new(0),
1072            addr_long: Cell::new([0x00; 8]),
1073            pan: Cell::new(0),
1074            tx_power: Cell::new(setting_to_power(PHY_TX_PWR)),
1075            channel: Cell::new(channel),
1076            spi_rx: MapCell::new((&mut reg_read[..]).into()),
1077            spi_tx: MapCell::new((&mut reg_write[..]).into()),
1078            spi_buf: MapCell::new(spi_buf.into()),
1079        }
1080    }
1081
1082    fn handle_interrupt(&self) {
1083        // In most cases, the first thing the driver does on handling an interrupt is
1084        // read the IRQ status; this pushes most logic to the SPI handler.
1085        // The one exception is when the radio receives a packet; to prevent this
1086        // packet from being overwritten before reading it from the radio,
1087        // the driver needs to disable reception. This has to be done in the first
1088        // SPI operation.
1089        if !self.spi_busy.get() {
1090            if self.state.get() == InternalState::RX {
1091                // We've received a complete frame; need to disable
1092                // reception until we've read it out from RAM,
1093                // otherwise subsequent packets may corrupt it.
1094                // Dynamic Frame Buffer protection (RF233 manual, Sec
1095                // 11.8) is insufficient because we perform multiple
1096                // SPI operations to read a frame, and the RF233
1097                // releases its protection after the first SPI
1098                // operation.
1099                self.state_transition_write(
1100                    RF233Register::TRX_STATE,
1101                    RF233TrxCmd::PLL_ON as u8,
1102                    InternalState::RX_TURNING_OFF,
1103                );
1104            } else {
1105                self.interrupt_handling.set(true);
1106                let _ = self.register_read(RF233Register::IRQ_STATUS);
1107            }
1108        } else {
1109            self.interrupt_pending.set(true);
1110        }
1111    }
1112
1113    fn register_write(&self, reg: RF233Register, val: u8) -> Result<(), ErrorCode> {
1114        if (self.spi_busy.get() || self.spi_tx.is_none() || self.spi_rx.is_none()) {
1115            return Err(ErrorCode::BUSY);
1116        }
1117        let mut wbuf = self.spi_tx.take().unwrap();
1118        let rbuf = self.spi_rx.take().unwrap();
1119        wbuf[0] = (reg as u8) | RF233BusCommand::REGISTER_WRITE as u8;
1120        wbuf[1] = val;
1121        wbuf.slice(0..2);
1122        // TODO verify SPI return value
1123        let _ = self.spi.read_write_bytes(wbuf, Some(rbuf));
1124        self.spi_busy.set(true);
1125
1126        Ok(())
1127    }
1128
1129    fn register_read(&self, reg: RF233Register) -> Result<(), ErrorCode> {
1130        if (self.spi_busy.get() || self.spi_tx.is_none() || self.spi_rx.is_none()) {
1131            return Err(ErrorCode::BUSY);
1132        }
1133
1134        let mut wbuf = self.spi_tx.take().unwrap();
1135        let rbuf = self.spi_rx.take().unwrap();
1136        wbuf.reset();
1137        wbuf.slice(0..2);
1138        wbuf[0] = (reg as u8) | RF233BusCommand::REGISTER_READ as u8;
1139        wbuf[1] = 0;
1140        // TODO verify SPI return value
1141        let _ = self.spi.read_write_bytes(wbuf, Some(rbuf));
1142        self.spi_busy.set(true);
1143
1144        Ok(())
1145    }
1146
1147    fn frame_write(&self, buf: &'static mut [u8], frame_len: u8) -> Result<(), ErrorCode> {
1148        if self.spi_busy.get() {
1149            return Err(ErrorCode::BUSY);
1150        }
1151
1152        let buf_len = radio::PSDU_OFFSET + frame_len as usize;
1153        buf[0] = RF233BusCommand::FRAME_WRITE as u8;
1154        let mut buf: SubSliceMut<'static, u8> = buf.into();
1155        buf.slice(0..buf_len);
1156        // TODO verify SPI return value
1157        let _ = self.spi.read_write_bytes(buf, self.spi_buf.take());
1158        self.spi_busy.set(true);
1159        Ok(())
1160    }
1161
1162    fn frame_read(&self, buf: &'static mut [u8], frame_len: u8) -> Result<(), ErrorCode> {
1163        if self.spi_busy.get() {
1164            return Err(ErrorCode::BUSY);
1165        }
1166
1167        let buf_len = radio::PSDU_OFFSET + frame_len as usize;
1168        let mut wbuf = self.spi_buf.take().unwrap();
1169        wbuf[0] = RF233BusCommand::FRAME_READ as u8;
1170        wbuf.reset();
1171        wbuf.slice(0..buf_len);
1172        // TODO verify SPI return value
1173        let _ = self.spi.read_write_bytes(wbuf, Some(buf.into()));
1174        self.spi_busy.set(true);
1175        Ok(())
1176    }
1177
1178    fn state_transition_write(&self, reg: RF233Register, val: u8, state: InternalState) {
1179        self.state.set(state);
1180        let _ = self.register_write(reg, val);
1181    }
1182
1183    fn state_transition_read(&self, reg: RF233Register, state: InternalState) {
1184        self.state.set(state);
1185        let _ = self.register_read(reg);
1186    }
1187}
1188
1189impl<'a, S: spi::SpiMasterDevice<'a>> radio::RadioConfig<'a> for RF233<'a, S> {
1190    fn initialize(&self) -> Result<(), ErrorCode> {
1191        Ok(())
1192    }
1193
1194    fn reset(&self) -> Result<(), ErrorCode> {
1195        self.spi.configure(
1196            spi::ClockPolarity::IdleLow,
1197            spi::ClockPhase::SampleLeading,
1198            100000,
1199        )?;
1200        self.reset_pin.make_output();
1201        self.sleep_pin.make_output();
1202        for _i in 0..10000 {
1203            self.reset_pin.clear();
1204        }
1205        self.reset_pin.set();
1206        self.sleep_pin.clear();
1207        self.transmitting.set(false);
1208        Ok(())
1209    }
1210
1211    fn start(&self) -> Result<(), ErrorCode> {
1212        self.sleep_pending.set(false);
1213
1214        if self.state.get() != InternalState::START && self.state.get() != InternalState::SLEEP {
1215            return Err(ErrorCode::ALREADY);
1216        }
1217
1218        if self.state.get() == InternalState::SLEEP {
1219            self.state_transition_read(RF233Register::TRX_STATUS, InternalState::SLEEP_WAKE);
1220        } else {
1221            // Delay wakeup until the radio turns all the way off
1222            self.wake_pending.set(true);
1223            let _ = self.register_read(RF233Register::PART_NUM);
1224        }
1225
1226        Ok(())
1227    }
1228
1229    fn stop(&self) -> Result<(), ErrorCode> {
1230        if self.state.get() == InternalState::SLEEP
1231            || self.state.get() == InternalState::SLEEP_TRX_OFF
1232        {
1233            return Err(ErrorCode::ALREADY);
1234        }
1235
1236        match self.state.get() {
1237            InternalState::READY | InternalState::ON_PLL_WAITING => {
1238                self.radio_on.set(false);
1239                self.state_transition_write(
1240                    RF233Register::TRX_STATE,
1241                    RF233TrxCmd::OFF as u8,
1242                    InternalState::SLEEP_TRX_OFF,
1243                );
1244            }
1245            _ => {
1246                self.sleep_pending.set(true);
1247            }
1248        }
1249
1250        Ok(())
1251    }
1252
1253    fn is_on(&self) -> bool {
1254        self.radio_on.get()
1255    }
1256
1257    fn busy(&self) -> bool {
1258        self.state.get() != InternalState::READY && self.state.get() != InternalState::SLEEP
1259    }
1260
1261    fn set_config_client(&self, client: &'a dyn radio::ConfigClient) {
1262        self.cfg_client.set(client);
1263    }
1264
1265    fn set_power_client(&self, client: &'a dyn radio::PowerClient) {
1266        self.power_client.set(client);
1267    }
1268
1269    fn set_address(&self, addr: u16) {
1270        self.addr.set(addr);
1271    }
1272
1273    fn set_address_long(&self, addr: [u8; 8]) {
1274        self.addr_long.set(addr);
1275    }
1276
1277    fn set_pan(&self, id: u16) {
1278        self.pan.set(id);
1279    }
1280
1281    fn set_tx_power(&self, power: i8) -> Result<(), ErrorCode> {
1282        if (power > 4 || power < -17) {
1283            Err(ErrorCode::INVAL)
1284        } else {
1285            self.tx_power.set(power);
1286            Ok(())
1287        }
1288    }
1289
1290    fn set_channel(&self, chan: radio::RadioChannel) {
1291        self.channel.set(chan);
1292    }
1293
1294    fn get_address(&self) -> u16 {
1295        self.addr.get()
1296    }
1297
1298    fn get_address_long(&self) -> [u8; 8] {
1299        self.addr_long.get()
1300    }
1301
1302    /// The 16-bit PAN ID
1303    fn get_pan(&self) -> u16 {
1304        self.pan.get()
1305    }
1306    /// The transmit power, in dBm
1307    fn get_tx_power(&self) -> i8 {
1308        self.tx_power.get()
1309    }
1310    /// The 802.15.4 channel
1311    fn get_channel(&self) -> u8 {
1312        self.channel.get().get_channel_number()
1313    }
1314
1315    fn config_commit(&self) {
1316        let pending = self.config_pending.get();
1317        if !pending {
1318            self.config_pending.set(true);
1319            let state = self.state.get();
1320
1321            if state == InternalState::READY {
1322                // Start configuration commit
1323                self.state_transition_write(
1324                    RF233Register::SHORT_ADDR_0,
1325                    (self.addr.get() & 0xff) as u8,
1326                    InternalState::CONFIG_SHORT0_SET,
1327                );
1328            } else {
1329                // Do nothing --
1330                // Configuration will be pushed automatically on boot,
1331                // or pending flag will be checked on return to READY
1332                // and commit started
1333            }
1334        }
1335    }
1336}
1337
1338impl<'a, S: spi::SpiMasterDevice<'a>> radio::RadioData<'a> for RF233<'a, S> {
1339    fn set_transmit_client(&self, client: &'a dyn radio::TxClient) {
1340        self.tx_client.set(client);
1341    }
1342
1343    fn set_receive_client(&self, client: &'a dyn radio::RxClient) {
1344        self.rx_client.set(client);
1345    }
1346
1347    fn set_receive_buffer(&self, buffer: &'static mut [u8]) {
1348        self.rx_buf.replace(buffer.into());
1349    }
1350
1351    // The payload length is the length of the MAC payload, not the PSDU
1352    fn transmit(
1353        &self,
1354        spi_buf: &'static mut [u8],
1355        frame_len: usize,
1356    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
1357        let state = self.state.get();
1358        let frame_len = frame_len + radio::MFR_SIZE;
1359
1360        if !self.radio_on.get() {
1361            return Err((ErrorCode::OFF, spi_buf));
1362        } else if self.tx_buf.is_some() || self.transmitting.get() {
1363            return Err((ErrorCode::BUSY, spi_buf));
1364        } else if radio::PSDU_OFFSET + frame_len >= spi_buf.len() {
1365            // Not enough room for CRC
1366            return Err((ErrorCode::SIZE, spi_buf));
1367        }
1368
1369        // Set PHY header to be the frame length
1370        spi_buf[1] = frame_len as u8;
1371        self.tx_buf.replace(spi_buf.into());
1372        self.tx_len.set(frame_len as u8);
1373        self.transmitting.set(true);
1374
1375        if !self.receiving.get() && state == InternalState::READY {
1376            self.state_transition_read(
1377                RF233Register::TRX_STATUS,
1378                InternalState::TX_STATUS_PRECHECK1,
1379            );
1380        }
1381        Ok(())
1382    }
1383}