mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
2227 lines
78 KiB
Markdown
2227 lines
78 KiB
Markdown
|
- RDM: 2
|
||
|
- Title: The IEEE802.15.4 radio HAL
|
||
|
- Authors: José Álamos
|
||
|
- Status: Active
|
||
|
- Type: Design
|
||
|
- Created: March 2020
|
||
|
|
||
|
# 1. Abstract
|
||
|
|
||
|
This memo describes a Hardware Abstraction Layer (HAL) for radios compliant
|
||
|
with the IEEE802.15.4 standard. The work follows a technology-specific approach
|
||
|
to provide well defined hardware access that allows to implement agnostic
|
||
|
IEEE802.15.4 PHY and MAC layers on top. Additionally, the new HAL enables
|
||
|
integration of network stacks that require direct access to the radio.
|
||
|
|
||
|
# 2. Status
|
||
|
|
||
|
This document is currently under open discussions. The content of this document
|
||
|
is licensed with a Creative Commons CC-BY-SA license.
|
||
|
|
||
|
## 2.1 Terminology
|
||
|
This memo uses the [RFC2119](https://www.ietf.org/rfc/rfc2119.txt) terminology
|
||
|
and the following acronyms and definitions:
|
||
|
|
||
|
## 2.2 Acronyms
|
||
|
- RDM: RIOT Developer Memo
|
||
|
- PIB: Physical Information Base.
|
||
|
- MIB: MAC Information Base.
|
||
|
|
||
|
## 2.3 Definitions
|
||
|
- SubMAC: Lower layer of the IEEE802.15.4 MAC that provides the
|
||
|
retransmissions with CSMA-CA logic, address filtering and CRC validation.
|
||
|
- Standalone CCA: Single run of the Clear Channel Assessment procedure.
|
||
|
- Continuous CCA: Clear Channel Assessment procedure followed by transmission
|
||
|
(required by the CSMA-CA algorithm)
|
||
|
- Caps: Short word for capabilities. In this context, capabilities are the
|
||
|
the features (hardware acceleration) present in a radio device.
|
||
|
- Ops: Short word for operations. In this context, operations are a set of
|
||
|
instructions to control the radio device.
|
||
|
|
||
|
# 3. Introduction
|
||
|
This document is a product of the
|
||
|
[Uniform Network Stack Integration](https://github.com/RIOT-OS/RIOT/issues/13771)
|
||
|
and aims to describe the architecture of a Hardware Abstraction Layer for
|
||
|
IEEE802.15.4 compliant radios.
|
||
|
|
||
|
The IEEE802.15.4 Radio HAL abstracts common functionalities of
|
||
|
IEEE802.15.4 compliant radios such as loading packets, transmitting,
|
||
|
configuring PHY parameters, etc. This abstraction is required for upper layers
|
||
|
that require hardware-independent access to drive IEEE802.15.4 radio devices
|
||
|
(802.15.4 MAC, network stacks, test applications, etc).
|
||
|
|
||
|
In the current RIOT lower network stack architecture, all network interfaces
|
||
|
are driven by the `netdev` interface. The work presented in this document
|
||
|
addresses deficits of using `netdev` as a Hardware Abstraction Layer:
|
||
|
|
||
|
- `netdev` is too generic to be used as a HAL to cover the wide range of
|
||
|
different technologies in RIOT (IEEE802.15.4, BLE, Ethernet, WiFi,
|
||
|
Proprietary devices, ...). The semantics of a standardized radio are
|
||
|
technology specific and in most cases well defined. In the case of
|
||
|
IEEE802.15.4 devices, they are defined by the IEEE.
|
||
|
- `netdev` includes PHY and MAC components that are not in the scope of a
|
||
|
hardware abstraction layer. The `netdev` interface is implemented as a device
|
||
|
driver but it additionally includes technology-dependent components for every
|
||
|
single device. For the case of IEEE802.15.4, this includes components of the
|
||
|
802.15.4 MAC/PHY such as transmission of Physical Service Data Units (PSDU),
|
||
|
or retransmissions with CSMA-CA and ACK handling. As a consequence,
|
||
|
code is duplicated, feature sets of similar devices heavily depend on the
|
||
|
specific implementation, and integration of new devices is more complex than
|
||
|
need be. Furthermore, duplication and unspecified device access complicate
|
||
|
code maintenance.
|
||
|
- `netdev` hardcodes MAC layer functionalities, which is likely the consequence
|
||
|
of hardware MAC acceleration on certain devices. These capabilities are
|
||
|
currently only available if the hardware provides integrated support. An
|
||
|
indication mechanism which MAC features are provided within a `netdev`
|
||
|
implementation is missing. A full MAC layer that is situated on top of the HAL
|
||
|
requires a defined access to specific radio functionalities in order to meet
|
||
|
timing constraints or energy requirements. That means, varying properties
|
||
|
between implementations and partly implemented MAC features within the device
|
||
|
driver interfere with the concept of transparent hardware access by one MAC
|
||
|
layer implementation.
|
||
|
|
||
|
|
||
|
Other components of the 802.15.4 MAC are present in the GNRC Netif
|
||
|
implementation for the 802.15.4 Link Layer (`gnrc_netif_ieee802154`). These
|
||
|
components prepare and parse 802.15.4 frames in order to send and receive data.
|
||
|
However, mandatory 802.15.4 MAC features are missing (commissioning, security,
|
||
|
channel scanning, etc). One major drawback of this approach is the fact that
|
||
|
802.15.4 MAC components of `gnrc_netif_ieee802154` are GNRC specific and
|
||
|
cannot be reused in other network stacks that require a 802.15.4 MAC.
|
||
|
|
||
|
As a solution, the lower layer should be separated into three main components:
|
||
|
1. 802.15.4 Radio HAL: hardware-agnostic interface to drive radio devices
|
||
|
(proposed in this RDM).
|
||
|
2. 802.15.4 MAC: full link layer including PHY definition.
|
||
|
3. Network Stack interface (netif): controls the 802.15.4 MAC layer to send
|
||
|
and receive packets. It provides transparent and technology-independent
|
||
|
access to the medium.
|
||
|
|
||
|
The 802.15.4 MAC and netif are not part of this document, but they are affected
|
||
|
by this work, thus, they are mentioned to give an outlook for upcoming efforts
|
||
|
on the lower network stack.
|
||
|
|
||
|
The following picture compares the current RIOT lower network stack
|
||
|
architecture (left) with the approach described in this document (right). As
|
||
|
can be seen, the new approach adds IEEE802.15.4 specific APIs and layers
|
||
|
between the lower layer network stack interface (GNRC Netif) and the hardware
|
||
|
dependent device driver. In contrast, the `netdev` based solution misses a
|
||
|
specific Radio HAL which prevents to run a hardware-agnostic MAC on top.
|
||
|
|
||
|
|
||
|
```
|
||
|
OLD | NEW
|
||
|
=== | ===
|
||
|
|
|
||
|
+---------------------+ | +---------------------+ +---------------------+
|
||
|
| | | | | | |
|
||
|
| GNRC Network Stack | | | GNRC Network Stack | | |
|
||
|
| | | | | | |
|
||
|
+---------------------+ | +---------------------+ | |
|
||
|
^ | ^ | |
|
||
|
| | | | |
|
||
|
gnrc_netapi | gnrc_netapi | OpenThread, OpenWSN |
|
||
|
| | | | |
|
||
|
v | v | |
|
||
|
+---------------------+ | +---------------------+ | |
|
||
|
| | | | | | |
|
||
|
| GNRC Netif | | | GNRC Netif | | |
|
||
|
| | | | | | |
|
||
|
+---------------------+ | +---------------------+ +---------------------+
|
||
|
^ | ^ ^
|
||
|
| | | |
|
||
|
gnrc_netif_ops_t | gnrc_netif_ops_t |
|
||
|
| | | |
|
||
|
v | v |
|
||
|
+---------------------+ | +---------------------+ |
|
||
|
| | | | | |
|
||
|
|gnrc_netif_ieee802154| | |gnrc_netif_ieee802154| |
|
||
|
| | | | | |
|
||
|
+---------------------+ | +---------------------+ |
|
||
|
^ | ^ |
|
||
|
| | | |
|
||
|
| | 802.15.4 MAC API Radio HAL API
|
||
|
| | | |
|
||
|
| | v |
|
||
|
| | +---------------------+ |
|
||
|
| | | | |
|
||
|
netdev_driver_t | | 802.15.4 MAC | |
|
||
|
| | | | |
|
||
|
| | +---------------------+ |
|
||
|
| | ^ |
|
||
|
| | | |
|
||
|
| | Radio HAL API ----------------+
|
||
|
| | | |
|
||
|
v | v v
|
||
|
+---------------------+ | +---------------------+-------------------------+
|
||
|
| | | | | | |
|
||
|
| netdev | Device | | | 802.15.4 Radio HAL | |
|
||
|
| | Driver | | | | Device Driver |
|
||
|
|----------+ | | +---------------------+ |
|
||
|
| | | | |
|
||
|
+---------------------+ | +-----------------------------------------------+
|
||
|
```
|
||
|
|
||
|
|
||
|
# 4. Architecture
|
||
|
```
|
||
|
+-----------------------------------------------------------------------------+
|
||
|
| |
|
||
|
| Upper layer |
|
||
|
| |
|
||
|
+-----------------------------------------------------------------------------+
|
||
|
| ^
|
||
|
| |
|
||
|
| |
|
||
|
| |
|
||
|
Radio Ops Event Notification +----------------------------+
|
||
|
| | IRQ Handler | |
|
||
|
| | +----------------------| Bottom-Half processor |
|
||
|
| | | | |
|
||
|
| | | +----------------------------+
|
||
|
| | | ^
|
||
|
| | | |
|
||
|
v | v IRQ
|
||
|
+-----------------------------+ |
|
||
|
| 802.15.4 Radio HAL | HW independent |
|
||
|
|-----------------------------|-------------------------------|----------------
|
||
|
| | HW dependent |
|
||
|
| | |
|
||
|
| Device Driver | |
|
||
|
| |-------------------------------+
|
||
|
| |
|
||
|
+-----------------------------+
|
||
|
```
|
||
|
|
||
|
As shown in the above figure, the IEEE802.15.4 Radio HAL is a central component
|
||
|
that provides any upper layer a technology-dependent and unified access to the
|
||
|
device driver, by implementing the Radio HAL API.
|
||
|
|
||
|
The HAL uses an Event Notification mechanism to inform the upper layer about
|
||
|
radio events (`IEEE802154_RADIO_CONFIRM_TX_DONE`,
|
||
|
`IEEE802154_RADIO_INDICATION_RX_DONE`, `IEEE802154_RADIO_CONFIRM_CCA`, etc).
|
||
|
This mechanism can either run in interrupt context or thread context, if the
|
||
|
device is not able to resolve events during ISR (e.g SPI devices). For the
|
||
|
latter, the radio HAL requires an upper layer to take over the Bottom-Half
|
||
|
processing which means, offloading the ISR to thread context.
|
||
|
|
||
|
## 4.1 Upper Layer
|
||
|
Upper layers are users that requires direct access to the primitive operations
|
||
|
of a radio and its hardware acceleration features, if available.
|
||
|
|
||
|
Examples for Upper Layers:
|
||
|
- A MAC layer can use the Radio HAL to implement parts of a PHY layer (data
|
||
|
communication, set/get parameters, perform CCA, etc.) .
|
||
|
- A network stack that requires low level access to the radio (OpenWSN,
|
||
|
OpenThread) can use the Radio HAL to implement the integration code.
|
||
|
- A developer who implements a simple application to send and receive data
|
||
|
between 802.15.4 radios (relying on hardware accelerated MAC features, if
|
||
|
available).
|
||
|
|
||
|
The upper layer accesses the radio using the Radio HAL API. Events that are
|
||
|
triggered by the device (packet received, transmission finished)
|
||
|
are indicated by the event notification mechanism, described below.
|
||
|
|
||
|
## 4.2 Bottom-Half Processor
|
||
|
The Bottom-Half (BH) processor is a component to offload the IRQ processing to
|
||
|
thread context. The component is required for radios that cannot resolve radio
|
||
|
events during ISR (SPI devices).
|
||
|
|
||
|
The component registers an IRQ handler during initialization
|
||
|
which is executed when the device triggers and interrupt. This handler uses
|
||
|
internal mechanisms to call the Radio API IRQ handler from a safe context.
|
||
|
The IRQ handler may run on a higher priority context. Although the API
|
||
|
implementation SHOULD NOT implement reentrancy, it MUST handle concurrent calls
|
||
|
between the IRQ handler and API functions.
|
||
|
|
||
|
The BH processor can be implemented dependent or independent of the network
|
||
|
stack. A network stack independent solution is preferred in order to reuse
|
||
|
functionality between different network stacks.
|
||
|
|
||
|
The term "Bottom Half" was originally introduced by the Linux kernel. See
|
||
|
[Top and Bottom Halves](http://www.makelinux.net/ldd3/chp-10-sect-4.shtml)
|
||
|
|
||
|
## 4.3 Radio HAL
|
||
|
|
||
|
The Radio HAL is defined by the Radio HAL API which consists of three main
|
||
|
components: Radio Operations, Event Notification, and the Device Specific
|
||
|
IEEE802.15.4 HAL implementation.
|
||
|
|
||
|
The Radio HAL Implementation provides a set of functionalities to control the
|
||
|
operation of the device, to process the IRQ handler and to receive event
|
||
|
notifications from the device.
|
||
|
|
||
|
### 4.3.1 Radio Operations
|
||
|
The Radio Operations (`radio_ops`) interface exposes operations that are common
|
||
|
to control 802.15.4 devices and to request their hardware capabilities
|
||
|
information (i.e., MAC acceleration hardware)
|
||
|
|
||
|
The interface defines a collection of mandatory functions:
|
||
|
- Set the transceiver state
|
||
|
- Set the PHY configuration (channel, tx power, etc)
|
||
|
- Load and transmit a frame
|
||
|
- Get device capabilities
|
||
|
|
||
|
The interface provides a collection of optional functions that may or may not
|
||
|
be implemented, dependent on the hardware acceleration features of a device.
|
||
|
These functions include:
|
||
|
- Read the number of retransmission attempts.
|
||
|
- Set address filter addresses (extended, short, PAN ID).
|
||
|
- Set CSMA-CA backoff parameters.
|
||
|
|
||
|
All `radio_ops` functions are non-blocking and some of them follow a
|
||
|
Request/Confirm scheme which means, the end of a request is indicated by a
|
||
|
confirmation function. The confirmation function may be polled. In such case,
|
||
|
the function uses standard error codes to indicate the status (success, error
|
||
|
or request has not finished).
|
||
|
|
||
|
The full list of functions can be found in the Interface Definition section.
|
||
|
|
||
|
### 4.3.2 Event Notification
|
||
|
|
||
|
The Radio HAL provides an Event Notification mechanism to inform the upper
|
||
|
layer about an event (a packet was received, a transmission finished, etc).
|
||
|
|
||
|
The upper layer can subscribe to these events to perform different actions. As
|
||
|
an example, a MAC layer would subscribe to the RX done event to allocate the
|
||
|
received packet. The TX done event is commonly used to release resources or
|
||
|
update statistics.
|
||
|
|
||
|
As described before, the Event Notification mechanism can be called during ISR
|
||
|
or thread context (BH processor). Thus, this must be taken into consideration
|
||
|
for the implementation of the Event Notification callback (e.g the
|
||
|
`IEEE802154_RADIO_INDICATION_RX_DONE` event might post an event to an event
|
||
|
queue in order to fetch the packet).
|
||
|
|
||
|
The full list of events and implications are defined in the Interface
|
||
|
Definition section.
|
||
|
|
||
|
### 4.3.3 Device Driver
|
||
|
|
||
|
The Device Driver implements the hardware-dependent part of the IEEE802.15.4
|
||
|
Radio HAL by wrapping the `radio_ops` interface around the device specific
|
||
|
code, which grants access to all device operations.
|
||
|
|
||
|
The Device Driver additionally provides a mechanism to expose the ISR of
|
||
|
radios that require the Bottom-Half processor.
|
||
|
|
||
|
The function set of the Device Driver can include device specific features that
|
||
|
are not exposed by the Radio HAL API (e.g., Smart Listening with AT86RF2xx
|
||
|
radios).
|
||
|
|
||
|
# 5 Implementation Details
|
||
|
## 5.1 Initialization of device drivers
|
||
|
In order to implement the 802.15.4 abstraction on top of a device driver, it
|
||
|
is required an initialization procedure that performs the following tasks:
|
||
|
|
||
|
1. Set up IRQ callback
|
||
|
2. Reset the device
|
||
|
3. Confirm connectivity and perform self tests
|
||
|
4. Bring device into a low power state
|
||
|
5. Set up IRQs and disable them to use less power.
|
||
|
|
||
|
The `radio_ops` interface provides an "on" function that turns on the device
|
||
|
and enables interrupts. It is expected that the upper layer will call this
|
||
|
function to enable the radio device, if the initialization procedure succeeded.
|
||
|
|
||
|
## 5.2 Abstract State Machine
|
||
|
|
||
|
The Radio HAL defines an Abstract State Machine. In order to ensure a uniform
|
||
|
behavior in all devices, all Radio HAL device drivers should be implemented
|
||
|
against this. Transient states (e.g pending requests) are not included in this
|
||
|
diagram. However, the upper layer MUST NOT trigger another request if there is
|
||
|
already a pending one.
|
||
|
|
||
|
```
|
||
|
+---------+
|
||
|
| |
|
||
|
| OFF |<------ Any state
|
||
|
| | OFF
|
||
|
+---------+
|
||
|
|
|
||
|
ON |
|
||
|
|
|
||
|
v
|
||
|
+---------+
|
||
|
+--------| |--------+
|
||
|
| | TRX_OFF |<----+ |
|
||
|
| +----->| | | |
|
||
|
| | +---------+ | |
|
||
|
SET_TRX_STATE | | | | SET_TRX_STATE
|
||
|
| | | |
|
||
|
v | | v
|
||
|
+---------+ +---------+
|
||
|
| |------------->| |
|
||
|
| IDLE | | RX |
|
||
|
| |<-------------| |
|
||
|
+---------+ +---------+
|
||
|
SET_TRX_STATE
|
||
|
```
|
||
|
|
||
|
|
||
|
### 5.2.1 State specification
|
||
|
A specification for each state is described in the following items.
|
||
|
|
||
|
- OFF: If radio initialization succeeds, the Abstract State Machine begins in
|
||
|
`OFF` state. During this state the device consumes the least power and all
|
||
|
hardware components (transceiver, crypto acceleration) are disabled.
|
||
|
|
||
|
- TRX OFF: During this state the device is on but the transceiver is off (PLL
|
||
|
not locked). The power consumption is higher than the `OFF` state but the
|
||
|
device is able to operate the transceiver and other hardware components (e.g
|
||
|
crypto accelerator).
|
||
|
|
||
|
- IDLE: This state is device specific and represents a state where the device
|
||
|
is ready to transmit, fetch a received frame, change the Physical Information
|
||
|
Base or perform Stand-Alone CCA.
|
||
|
|
||
|
- RX ON: During RX ON state the radio is able to detect Start Frame Delimiter
|
||
|
(SFD) and thus, receive frames.
|
||
|
|
||
|
## 5.3 Prepare and Transmit
|
||
|
|
||
|
The Radio HAL doesn't define an explicit send function. Unlike the `netdev`
|
||
|
approach, it bases on separation of the send procedure into frame loading
|
||
|
and triggering the transmissions start.
|
||
|
|
||
|
Although it is possible to load and start using the `netdev` interface with the
|
||
|
`NETOPT_PRELOADING` option, the Radio HAL approach is easier and more
|
||
|
lightweight to implement since it doesn't require internal state variables.
|
||
|
|
||
|
Separated load and start is required for MAC layers
|
||
|
with timing constraints (E.g. TSCH mode of 802.15.4 MAC).
|
||
|
|
||
|
In the rare case a radio device doesn't support loading the frame buffer without
|
||
|
triggering a transmission, it is still possible to implement the load and
|
||
|
transmit pattern using an internal buffer. However, this case is very unlikely
|
||
|
because such a device could not meet 802.15.4 timing requirements.
|
||
|
|
||
|
It is expected that a higher layer "send" function is defined for convenience
|
||
|
which handles both loading and frame sending. Typically, this would be a
|
||
|
802.15.4 MAC implementation which preloads the devices buffer once accessible,
|
||
|
and triggers a send operation at a scheduled time slot. Alternatively, this
|
||
|
could be a helper function for non MAC users.
|
||
|
|
||
|
## 5.4 TX and RX Information
|
||
|
|
||
|
Sometimes upper layers require information associated to the transmission
|
||
|
or reception of a packet. The TSCH mode of the 802.15.4 MAC may require
|
||
|
LQI and RSSI data from a received packet to schedule new cells.
|
||
|
The 802.15.4 MAC may also require the information associated to the
|
||
|
frame retransmission component (frame pending bit, number of retransmission,
|
||
|
status) if the hardware provides support for hardware retransmissions.
|
||
|
|
||
|
The 802.15.4 Radio HAL API provides functions to retrieve this data.
|
||
|
Note that retrieving this information is optional in cases where the RX
|
||
|
information is not needed or when the device doesn't support frame
|
||
|
retransmissions.
|
||
|
|
||
|
# 6 802.15.4 Radio HAL Interface definition
|
||
|
|
||
|
## 6.1 Radio Operations
|
||
|
The Radio Ops interface is implemented using function pointers.
|
||
|
|
||
|
These functions should be implemented with device specific validations only.
|
||
|
Parameters that are not device specific (valid channel settings, address
|
||
|
lengths, etc) should be checked by higher layers in order to avoids redundancy.
|
||
|
|
||
|
Note that the Radio Ops interface only implements a few get functions. The
|
||
|
reason behind this is the fact most members of the PHY and MAC Information
|
||
|
Base (such as address, TX power, channel number) are already stored in RAM.
|
||
|
|
||
|
The full documentation of Radio Ops functions is available in the Appendix A.
|
||
|
|
||
|
### 6.1.1 Summary of Radio Ops
|
||
|
The following table summarizes the Radio Ops and the state in which the Ops can
|
||
|
be invoked (marked with `X`).
|
||
|
|
||
|
```
|
||
|
- Send/Receive
|
||
|
+---------------------------------+
|
||
|
|`OFF` | `TRX_OFF` | `IDLE` | `RX`|
|
||
|
+------------------------------------------------------------+
|
||
|
| `write` | _ | X | X | _ |
|
||
|
| `len` | _ | X | X | _ |
|
||
|
| `read` | _ | X | X | _ |
|
||
|
| `*_op(*_TRANSMIT)` | _ | _ | X | _ |
|
||
|
+------------------------------------------------------------+
|
||
|
|
||
|
- CCA related
|
||
|
+---------------------------------+
|
||
|
|`OFF` | `TRX_OFF` | `IDLE` | `RX`|
|
||
|
+------------------------------------------------------------+
|
||
|
| `set_cca_threshold` | [ ] | [X] | [X] | [X]|
|
||
|
| `set_cca_mode` | [ ] | [X] | [X] | [X]|
|
||
|
| `*_op(*_CCA)` | [ ] | [ ] | [X] | [ ]|
|
||
|
+------------------------------------------------------------+
|
||
|
|
||
|
- PIB/MIB related
|
||
|
+---------------------------------+
|
||
|
|`OFF` | `TRX_OFF` | `IDLE` | `RX`|
|
||
|
+------------------------------------------------------------+
|
||
|
| `config_phy` | [ ] | [X] | [X] | [ ]|
|
||
|
| `set_frame_retrans` | [ ] | [X] | [X] | [X]|
|
||
|
| `set_csma_params` | [ ] | [X] | [X] | [X]|
|
||
|
| `set_frame_filter_mode` | [ ] | [X] | [X] | [X]|
|
||
|
| `config_addr_filter` | [ ] | [X] | [X] | [X]|
|
||
|
| `config_src_addr_match` | [ ] | [X] | [X] | [X]|
|
||
|
+------------------------------------------------------------+
|
||
|
|
||
|
- Device State Management
|
||
|
+---------------------------------+
|
||
|
|`OFF` | `TRX_OFF` | `IDLE` | `RX`|
|
||
|
+------------------------------------------------------------+
|
||
|
| `*_op(*_SET_{IDLE,RX})` | [ ] | [X] | [X] | [X]|
|
||
|
| `*_on` | [X] | [ ] | [ ] | [ ]|
|
||
|
| `off` | [X] | [X] | [X] | [X]|
|
||
|
+------------------------------------------------------------+
|
||
|
|
||
|
```
|
||
|
|
||
|
## 6.2 Event Notification
|
||
|
|
||
|
The Event Notification mechanism is implemented with a function callback.
|
||
|
The callback function is supposed to be implemented by the upper layer.
|
||
|
|
||
|
The events follow the naming convention of the IEEE Services Access Points (SAP).
|
||
|
This means, events that are a triggered as a result of a Request are prefixed with
|
||
|
"CONFIRM". All the other events are prefixed with "INDICATION".
|
||
|
|
||
|
The callback signature, the events and their expected behavior are documented
|
||
|
in the Appendix A.
|
||
|
|
||
|
MAC specific events such as TX done with frame pending, CSMA-CA medium
|
||
|
busy or exceeded number of retransmissions are not explicitly reported because
|
||
|
they can be extracted after the TX done event using the Radio HAL API.
|
||
|
|
||
|
Some radio devices support events such as ACK Timeout, CSMA Backoff timeout or
|
||
|
PLL lock. Such events are out of the scope of this document. However, these
|
||
|
may be added and implemented at any time if required by upper layers.
|
||
|
|
||
|
The following table summarizes the events, whether an event is mandatory, the
|
||
|
states which may generate the event notification and special handling. Although
|
||
|
mandatory events may be ignored or disabled by the upper layer, all Radio HAL
|
||
|
implementations must generate at least the mandatory events. The presence of
|
||
|
optional events MUST be indicated using Radio Caps (see Section 6.3).
|
||
|
|
||
|
```
|
||
|
Event | Mandatory | Trig. state |
|
||
|
+-------------------------------------------+-----------+-------------+
|
||
|
| IEEE802154_RADIO_INDICATION_RX_START | [ ] | RX |
|
||
|
| IEEE802154_RADIO_INDICATION_RX_DONE [1] | [X] | RX |
|
||
|
| IEEE802154_RADIO_INDICATION_CRC_ERROR [2] | [ ] | RX |
|
||
|
| IEEE802154_RADIO_INDICATION_TX_START | [ ] | IDLE |
|
||
|
| IEEE802154_RADIO_CONFIRM_TX_DONE [3] | [X] | IDLE |
|
||
|
| IEEE802154_RADIO_CONFIRM_CCA [4] | [ ] | IDLE |
|
||
|
+-------------------------------------------+-----------+-------------+
|
||
|
|
||
|
[1]: The upper layer MUST set the Abstract State Machine state to `IDLE` or
|
||
|
`TRX_OFF` before calling `read` or `len`.
|
||
|
[2]: Should be treated as the `IEEE802154_RADIO_INDICATION_RX_DONE` event. Use
|
||
|
the `read` function to drop the frame.
|
||
|
[3]: On occurrence, the upper layer MUST call
|
||
|
`confirm_op(IEEE802154_RADIO_CONFIRM_TX_DONE)` to finish the transmission. The
|
||
|
Abstract State Machine stays in IDLE.
|
||
|
[4]: On occurrence, the upper layer MUST call
|
||
|
`confirm_op(IEEE802154_RADIO_CONFIRM_CCA` to finish the CCA procedure and fetch
|
||
|
the channel state. The Abstract State Machine stays in IDLE, ready to transmit
|
||
|
the next frame.
|
||
|
```
|
||
|
|
||
|
## 6.3 Radio Caps
|
||
|
The Radio HAL implementation exposes a set of capabilities (Caps) in order to
|
||
|
indicate the presence of a specific hardware feature. The Caps are encoded
|
||
|
using bit flags. The Radio HAL header defines a set of `ieee802154_radio_has_*`
|
||
|
functions that check whether the radio supports a capability.
|
||
|
See Appendix A for a full list of capabilities.
|
||
|
|
||
|
A Radio HAL implementation MUST indicate all capabilities supported by the
|
||
|
device and driver implementation.
|
||
|
|
||
|
# 7 Future Proof Considerations
|
||
|
|
||
|
The Radio HAL is designed to be agnostic to different versions of the
|
||
|
IEEE802.15.4 standard. A single radio device typically implements hardware
|
||
|
acceleration for only one standard, whereas different standards are not always
|
||
|
compatible. As an example, IEEE802.15.4--2006 devices do not support Enhanced
|
||
|
Acknowledgement packets which are required by the TSCH layer of
|
||
|
IEEE802.15.4--2012. For compatibility, a software MAC can provide such
|
||
|
functionality. The Radio HAL adapts considerations to enable different versions
|
||
|
of the IEEE802.15.4 MAC on top of the abstraction layer.
|
||
|
|
||
|
### Transmission Modes
|
||
|
|
||
|
The Radio HAL interface defines three transmission modes to allow sending
|
||
|
frames using (i) CSMA-CA, (ii) CCA, or (iii) directly without any contention
|
||
|
mechanism.
|
||
|
In that way, a MAC layer can easily send data frames benefiting from hardware
|
||
|
accelerated CSMA-CA or Beacons that have to meet timing constraints and thus,
|
||
|
require a direct send function.
|
||
|
|
||
|
A HAL implementation can provide several transmit modes, but it MUST implement
|
||
|
at least one. It is recommended that the implementation provides modes that
|
||
|
exploit the internal devices capabilities. Implementing a direct mode is
|
||
|
desired for software MAC layers on top.
|
||
|
|
||
|
### PHY Definition
|
||
|
|
||
|
PHY definitions are specific to a IEEE802.15.4 version. As an example, older
|
||
|
standards define PHY channels with a `channel number`. In modern standards,
|
||
|
channels are represented using a (`channel number`, `channel page`, `channel
|
||
|
modulation`) tuple. The `config_phy` function is called with a pointer to a
|
||
|
`ieee802154_phy_conf_t` structure which describes the PHY configuration. In
|
||
|
order to support newer versions, this structure can be extended without changing
|
||
|
the Radio HAL API.
|
||
|
|
||
|
### Future Radio Operations
|
||
|
|
||
|
The Radio Operations interface `radio_ops` can be extended to support
|
||
|
functionalities of newer standards. As an example, most SubGHz radios support a
|
||
|
Listen Before Talk feature that can be implemented as a new and optional
|
||
|
operation.
|
||
|
|
||
|
# 8 Acknowledgements
|
||
|
|
||
|
Thanks to Peter Kietzmann, Benjamin Valentin, Marian Buschsieweke, Leandro
|
||
|
Lanzieri and Martine Lenders for their reviews, comments and suggestions.
|
||
|
|
||
|
# 9 References
|
||
|
|
||
|
- [Uniform Network Stack Integration](https://github.com/RIOT-OS/RIOT/issues/13771)
|
||
|
- [Top and Bottom Halves](http://www.makelinux.net/ldd3/chp-10-sect-4.shtml)
|
||
|
|
||
|
# 10 Revision
|
||
|
|
||
|
- Rev0: initial document
|
||
|
|
||
|
# 11 Contact
|
||
|
|
||
|
The author of this memo can be contacted via email at jose.alamos@haw-hamburg.de
|
||
|
|
||
|
# Appendix A: Radio HAL header file (2023-02)
|
||
|
|
||
|
```c
|
||
|
/*
|
||
|
* Copyright (C) 2020 HAW Hamburg
|
||
|
*
|
||
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
||
|
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||
|
* details.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @defgroup drivers_ieee802154_hal IEEE802.15.4 Radio Hardware Abstraction Layer
|
||
|
* @ingroup drivers
|
||
|
* @experimental This API is experimental and in an early state - expect
|
||
|
* changes!
|
||
|
|
||
|
* @brief This is a Hardware Abstraction Layer for IEEE802.15.4 compatible
|
||
|
* radios.
|
||
|
* @{
|
||
|
*
|
||
|
* @author José I. Alamos <jose.alamos@haw-hamburg.de>
|
||
|
*/
|
||
|
|
||
|
#ifndef NET_IEEE802154_RADIO_H
|
||
|
#define NET_IEEE802154_RADIO_H
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
#include <stdbool.h>
|
||
|
#include "iolist.h"
|
||
|
#include "sys/uio.h"
|
||
|
#include "bitarithm.h"
|
||
|
#include "byteorder.h"
|
||
|
#include "net/eui64.h"
|
||
|
#include "net/ieee802154.h"
|
||
|
#include "errno.h"
|
||
|
|
||
|
/**
|
||
|
* @brief Forward declaration of the radio ops structure.
|
||
|
*/
|
||
|
typedef struct ieee802154_radio_ops ieee802154_radio_ops_t;
|
||
|
|
||
|
/**
|
||
|
* @brief IEEE802.15.4 Radio capabilities
|
||
|
*
|
||
|
* These flags represent the hardware capabilities of a given device.
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief the device supports frame retransmissions with CSMA-CA
|
||
|
*
|
||
|
* The device supports sending with CSMA-CA and retransmissions. If the
|
||
|
* CSMA-CA fails, the device reports a @ref TX_STATUS_MEDIUM_BUSY when
|
||
|
* calling @ref ieee802154_radio_confirm_transmit. In case CSMA-CA
|
||
|
* succeeds and the ACK frame is expected, the
|
||
|
* device reports a @ref TX_STATUS_SUCCESS if the ACK frame is received
|
||
|
* during any retransmission attempt. Otherwise, it reports a @ref
|
||
|
* TX_STATUS_NO_ACK
|
||
|
*
|
||
|
* ACK frames are not indicated to the upper layer.
|
||
|
*
|
||
|
* @note it's implicit that a radio supports @ref
|
||
|
* IEEE802154_CAP_AUTO_CSMA if this cap is available
|
||
|
*/
|
||
|
IEEE802154_CAP_FRAME_RETRANS = BIT0,
|
||
|
/**
|
||
|
* @brief the device supports Auto CSMA-CA
|
||
|
*
|
||
|
* The device supports performing CSMA-CA before transmitting a frame. If
|
||
|
* CSMA-CA procedure succeeds, the device sends the frame and reports a
|
||
|
* @ref TX_STATUS_SUCCESS when calling @ref
|
||
|
* ieee802154_radio_confirm_transmit. If it fails, the device reports
|
||
|
* @ref TX_STATUS_MEDIUM_BUSY.
|
||
|
*/
|
||
|
IEEE802154_CAP_AUTO_CSMA = BIT1,
|
||
|
/**
|
||
|
* @brief the device support ACK timeout interrupt
|
||
|
*
|
||
|
* The device will automatically attempt to receive and handle the ACK
|
||
|
* frame if expected.
|
||
|
* If the ACK frame is not received, the device reports @ref
|
||
|
* TX_STATUS_NO_ACK when calling @ref ieee802154_radio_confirm_transmit.
|
||
|
* Otherwise, it reports @ref TX_STATUS_SUCCESS.
|
||
|
*
|
||
|
* The ACK frame is not indicated to the upper layer.
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_ACK_TIMEOUT = BIT2,
|
||
|
/**
|
||
|
* @brief the device supports the IEEE802.15.4 2.4 GHz band
|
||
|
*
|
||
|
* It's assumed that @ref IEEE802154_CAP_IRQ_TX_DONE is present.
|
||
|
*/
|
||
|
IEEE802154_CAP_24_GHZ = BIT3,
|
||
|
/**
|
||
|
* @brief the device support the IEEE802.15.4 Sub GHz band
|
||
|
*/
|
||
|
IEEE802154_CAP_SUB_GHZ = BIT4,
|
||
|
/**
|
||
|
* @brief the device reports reception off frames with invalid CRC.
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_CRC_ERROR = BIT5,
|
||
|
/**
|
||
|
* @brief the device reports when the transmission is done
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_TX_DONE = BIT6,
|
||
|
/**
|
||
|
* @brief the device reports the start of a frame (SFD) when received.
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_RX_START = BIT7,
|
||
|
/**
|
||
|
* @brief the device reports the start of a frame (SFD) was sent.
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_TX_START = BIT8,
|
||
|
/**
|
||
|
* @brief the device reports the end of the CCA procedure
|
||
|
*/
|
||
|
IEEE802154_CAP_IRQ_CCA_DONE = BIT9,
|
||
|
/**
|
||
|
* @brief the device provides the number of retransmissions
|
||
|
*
|
||
|
* It's assumed that @ref IEEE802154_CAP_FRAME_RETRANS is present.
|
||
|
*/
|
||
|
IEEE802154_CAP_FRAME_RETRANS_INFO = BIT10,
|
||
|
/**
|
||
|
* @brief the device retains all register values when off.
|
||
|
*/
|
||
|
IEEE802154_CAP_REG_RETENTION = BIT11,
|
||
|
/**
|
||
|
* @brief Binary Phase Shift Keying PHY mode
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_BPSK = BIT12,
|
||
|
/**
|
||
|
* @brief Amplitude-Shift Keying PHY mode
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_ASK = BIT13,
|
||
|
/**
|
||
|
* @brief Offset Quadrature Phase-Shift Keying
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_OQPSK = BIT14,
|
||
|
/**
|
||
|
* @brief Multi-Rate Offset Quadrature Phase-Shift Keying PHY mode
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_MR_OQPSK = BIT15,
|
||
|
/**
|
||
|
* @brief Multi-Rate Orthogonal Frequency-Division Multiplexing PHY mode
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_MR_OFDM = BIT16,
|
||
|
/**
|
||
|
* @brief Multi-Rate Frequency Shift Keying PHY mode
|
||
|
*/
|
||
|
IEEE802154_CAP_PHY_MR_FSK = BIT17,
|
||
|
/**
|
||
|
* @brief the device supports source address match table.
|
||
|
*
|
||
|
* A Source Address Match table contains source addresses with pending
|
||
|
* data. When a coordinator device receives an IEEE 802.15.4 Data
|
||
|
* Request command from a child node, the Frame Pending bit of the ACK is
|
||
|
* set if the source address matches one from the table.
|
||
|
*/
|
||
|
IEEE802154_CAP_SRC_ADDR_MATCH = BIT18,
|
||
|
} ieee802154_rf_caps_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Bit-mask for PHY modes capabilities.
|
||
|
*/
|
||
|
#define IEEE802154_RF_CAPS_PHY_MASK \
|
||
|
(IEEE802154_CAP_PHY_BPSK \
|
||
|
| IEEE802154_CAP_PHY_ASK \
|
||
|
| IEEE802154_CAP_PHY_OQPSK \
|
||
|
| IEEE802154_CAP_PHY_MR_OQPSK \
|
||
|
| IEEE802154_CAP_PHY_MR_OFDM \
|
||
|
| IEEE802154_CAP_PHY_MR_FSK) \
|
||
|
|
||
|
/**
|
||
|
* @brief Transmission status
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief the transceiver successfully sent a frame.
|
||
|
*
|
||
|
* Depending of the type of transmissions and available caps, this could
|
||
|
* mean one of the following:
|
||
|
*
|
||
|
* If the device supports @ref IEEE802154_CAP_FRAME_RETRANS or
|
||
|
* @ref IEEE802154_CAP_IRQ_ACK_TIMEOUT this means either:
|
||
|
* - The frame was sent without ACK Req bit
|
||
|
* - The frame was sent with the ACK Req bit and a valid ACK was received.
|
||
|
*
|
||
|
* Otherwise, this notifies that a frame was sent.
|
||
|
*/
|
||
|
TX_STATUS_SUCCESS,
|
||
|
/**
|
||
|
* @brief the transceiver received a valid ACK with the frame pending bit
|
||
|
*
|
||
|
* This status is present only if the device supports @ref
|
||
|
* IEEE802154_CAP_FRAME_RETRANS or @ref IEEE802154_CAP_IRQ_ACK_TIMEOUT.
|
||
|
*/
|
||
|
TX_STATUS_FRAME_PENDING,
|
||
|
/**
|
||
|
* @brief the transceiver ran out of retransmission
|
||
|
*
|
||
|
* This status is present only if the device supports @ref
|
||
|
* IEEE802154_CAP_FRAME_RETRANS or @ref IEEE802154_CAP_IRQ_ACK_TIMEOUT.
|
||
|
*/
|
||
|
TX_STATUS_NO_ACK,
|
||
|
/**
|
||
|
* @brief the CSMA-CA algorithm or CCA failed to measure a clear channel
|
||
|
*/
|
||
|
TX_STATUS_MEDIUM_BUSY,
|
||
|
} ieee802154_tx_status_t;
|
||
|
|
||
|
/**
|
||
|
* @brief IEEE802.15.4 Radio HAL events
|
||
|
*
|
||
|
* To follow the IEEE802.15.4 convention, an event that responds to a Request
|
||
|
* is a confirmation (Confirm). Otherwise an Indication.
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief the transceiver detected a valid SFD
|
||
|
*
|
||
|
* This event is present if radio has @ref IEEE802154_CAP_IRQ_RX_START cap.
|
||
|
*/
|
||
|
IEEE802154_RADIO_INDICATION_RX_START,
|
||
|
|
||
|
/**
|
||
|
* @brief the transceiver received a frame with an invalid crc.
|
||
|
*
|
||
|
* @note some radios won't flush the framebuffer on reception of a frame
|
||
|
* with invalid CRC. Therefore it's required to call @ref
|
||
|
* ieee802154_radio_read.
|
||
|
*
|
||
|
* @note since the behavior of radios after frame reception is undefined,
|
||
|
* the upper layer should set the transceiver state to IDLE as soon as
|
||
|
* possible before calling @ref ieee802154_radio_read
|
||
|
*/
|
||
|
IEEE802154_RADIO_INDICATION_CRC_ERROR,
|
||
|
|
||
|
/**
|
||
|
* @brief the transceiver sent out a valid SFD
|
||
|
*
|
||
|
* This event is present if radio has @ref IEEE802154_CAP_IRQ_TX_START cap.
|
||
|
*
|
||
|
* @note The SFD of an outgoing ACK (AUTOACK) should not be indicated
|
||
|
*/
|
||
|
IEEE802154_RADIO_INDICATION_TX_START,
|
||
|
|
||
|
/**
|
||
|
* @brief the transceiver received a frame and lies in the
|
||
|
* internal framebuffer.
|
||
|
*
|
||
|
* This indication should be generated only if CRC is valid and the frame
|
||
|
* passes the address matching filter (this includes ACK and Beacon frames).
|
||
|
* The latter only applies if the radio is not in promiscuous mode.
|
||
|
*
|
||
|
* The transceiver or driver MUST handle the ACK reply if the Ack Request
|
||
|
* bit is set in the received frame and promiscuous mode is disabled.
|
||
|
*
|
||
|
* The transceiver might be in a "FB Lock" state where no more frames are
|
||
|
* received. This is done in order to avoid overwriting the Frame Buffer
|
||
|
* with new frame arrivals. In order to leave this state, the upper layer
|
||
|
* must call @ref ieee802154_radio_read
|
||
|
*
|
||
|
* @note since the behavior of radios after frame reception is undefined,
|
||
|
* the upper layer should set the transceiver state to IDLE as soon as
|
||
|
* possible before calling @ref ieee802154_radio_read
|
||
|
*/
|
||
|
IEEE802154_RADIO_INDICATION_RX_DONE,
|
||
|
|
||
|
/**
|
||
|
* @brief the transceiver either finished sending a frame, the retransmission
|
||
|
* procedure or the channel activity detection prior transmission.
|
||
|
*
|
||
|
* This event is present if radio has @ref IEEE802154_CAP_IRQ_TX_DONE cap.
|
||
|
* The upper layer should immediately call @ref
|
||
|
* ieee802154_radio_confirm_transmit when on this event.
|
||
|
*/
|
||
|
IEEE802154_RADIO_CONFIRM_TX_DONE,
|
||
|
/**
|
||
|
* @brief the CCA procedure finished
|
||
|
*
|
||
|
* This event is present if radio has @ref IEEE802154_CAP_IRQ_CCA_DONE.
|
||
|
*/
|
||
|
IEEE802154_RADIO_CONFIRM_CCA,
|
||
|
} ieee802154_trx_ev_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Source Address Match commands.
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief Enable or disable source address match.
|
||
|
*
|
||
|
* Enabling it sets the frame pending to all ACK frames in
|
||
|
* response to a Data Request command (if the radio doesn't
|
||
|
* support Source Address Matching) or to a specific address
|
||
|
* in the Source Address Matching table
|
||
|
*/
|
||
|
IEEE802154_SRC_MATCH_EN,
|
||
|
/**
|
||
|
* @brief Add a short address to entry.
|
||
|
*
|
||
|
* This command should only be implemented if @ref IEEE802154_CAP_SRC_ADDR_MATCH
|
||
|
* is available.
|
||
|
*/
|
||
|
IEEE802154_SRC_MATCH_SHORT_ADD,
|
||
|
/**
|
||
|
* @brief Clear short address from entry.
|
||
|
* This command should only be implemented if @ref IEEE802154_CAP_SRC_ADDR_MATCH
|
||
|
* is available.
|
||
|
*/
|
||
|
IEEE802154_SRC_MATCH_SHORT_CLEAR,
|
||
|
/**
|
||
|
* @brief Add a extended address to entry.
|
||
|
* This command should only be implemented if @ref IEEE802154_CAP_SRC_ADDR_MATCH
|
||
|
* is available.
|
||
|
*/
|
||
|
IEEE802154_SRC_MATCH_EXT_ADD,
|
||
|
/**
|
||
|
* @brief Clear extended address from entry.
|
||
|
*
|
||
|
* This command should only be implemented if @ref IEEE802154_CAP_SRC_ADDR_MATCH
|
||
|
* is available.
|
||
|
*/
|
||
|
IEEE802154_SRC_MATCH_EXT_CLEAR,
|
||
|
} ieee802154_src_match_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Address filter command
|
||
|
*/
|
||
|
typedef enum {
|
||
|
IEEE802154_AF_SHORT_ADDR, /**< Set short IEEE 802.15.4 address (network_uint16_t) */
|
||
|
IEEE802154_AF_EXT_ADDR, /**< Set extended IEEE 802.15.4 address (eui64_t) */
|
||
|
IEEE802154_AF_PANID, /**< Set PAN ID (uint16_t) */
|
||
|
IEEE802154_AF_PAN_COORD, /**< Set device as PAN coordinator (bool) */
|
||
|
} ieee802154_af_cmd_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Frame Filter mode
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief accept all valid frames that match address filter configuration
|
||
|
*/
|
||
|
IEEE802154_FILTER_ACCEPT,
|
||
|
/**
|
||
|
* @brief accept only ACK frames
|
||
|
*
|
||
|
* @note This mode should only be implemented if the transceiver doesn't
|
||
|
* handle ACK frame reception (when @ref IEEE802154_CAP_FRAME_RETRANS and
|
||
|
* @ref IEEE802154_CAP_IRQ_ACK_TIMEOUT are not present).
|
||
|
*/
|
||
|
IEEE802154_FILTER_ACK_ONLY,
|
||
|
/**
|
||
|
* @brief accept all valid frames
|
||
|
*
|
||
|
* @note This mode is optional
|
||
|
*/
|
||
|
IEEE802154_FILTER_PROMISC,
|
||
|
/**
|
||
|
* @brief accept all frames, regardless of FCS
|
||
|
*
|
||
|
* @note This mode is optional
|
||
|
*/
|
||
|
IEEE802154_FILTER_SNIFFER,
|
||
|
} ieee802154_filter_mode_t;
|
||
|
|
||
|
/**
|
||
|
* @brief CSMA-CA exponential backoff parameters.
|
||
|
*/
|
||
|
typedef struct {
|
||
|
uint8_t min; /**< minimum value of the exponential backoff */
|
||
|
uint8_t max; /**< maximum value of the exponential backoff */
|
||
|
} ieee802154_csma_be_t;
|
||
|
|
||
|
/**
|
||
|
* @brief RX information associated to a frame
|
||
|
*/
|
||
|
typedef struct {
|
||
|
/**
|
||
|
* @brief RSSI of the received frame.
|
||
|
*
|
||
|
* The RSSI is a measure of the RF power in dBm for the received frame.
|
||
|
* The minimum and maximum values are 0 (-174 dBm) and 254 (80 dBm).
|
||
|
*/
|
||
|
uint8_t rssi;
|
||
|
uint8_t lqi; /**< LQI of the received frame */
|
||
|
} ieee802154_rx_info_t;
|
||
|
|
||
|
/**
|
||
|
* @brief TX information of the last transmitted frame.
|
||
|
*/
|
||
|
typedef struct {
|
||
|
ieee802154_tx_status_t status; /**< status of the last transmission */
|
||
|
int8_t retrans; /**< number of frame retransmissions of the last TX */
|
||
|
} ieee802154_tx_info_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Forward declaration of the IEEE802.15.4 device descriptor
|
||
|
*/
|
||
|
typedef struct ieee802154_dev ieee802154_dev_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Prototype of the IEEE802.15.4 device event callback
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] status the status
|
||
|
*/
|
||
|
typedef void (*ieee802154_cb_t)(ieee802154_dev_t *dev,
|
||
|
ieee802154_trx_ev_t status);
|
||
|
|
||
|
/**
|
||
|
* @brief the IEEE802.15.4 device descriptor
|
||
|
*/
|
||
|
struct ieee802154_dev {
|
||
|
/**
|
||
|
* @brief pointer to the operations of the device
|
||
|
*/
|
||
|
const ieee802154_radio_ops_t *driver;
|
||
|
/**
|
||
|
* @brief pointer to the private descriptor of the device
|
||
|
*/
|
||
|
void *priv;
|
||
|
/**
|
||
|
* @brief the event callback of the device
|
||
|
*/
|
||
|
ieee802154_cb_t cb;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief IEEE802.15.4 CCA modes
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief CCA using first mode (energy detection)
|
||
|
*/
|
||
|
IEEE802154_CCA_MODE_ED_THRESHOLD,
|
||
|
/**
|
||
|
* @brief CCA using second mode (carrier sensing)
|
||
|
*/
|
||
|
IEEE802154_CCA_MODE_CARRIER_SENSING,
|
||
|
/**
|
||
|
* @brief CCA using third mode (energy detection AND carrier sensing)
|
||
|
*/
|
||
|
IEEE802154_CCA_MODE_ED_THRESH_AND_CS,
|
||
|
/**
|
||
|
* @brief CCA using third mode (energy detection OR carrier sensing)
|
||
|
*/
|
||
|
IEEE802154_CCA_MODE_ED_THRESH_OR_CS,
|
||
|
} ieee802154_cca_mode_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Holder of the PHY configuration
|
||
|
*/
|
||
|
typedef struct {
|
||
|
ieee802154_phy_mode_t phy_mode; /**< IEEE802.15.4 PHY mode */
|
||
|
uint16_t channel; /**< IEEE802.15.4 channel number */
|
||
|
uint8_t page; /**< IEEE802.15.4 channel page */
|
||
|
int8_t pow; /**< TX power in dBm */
|
||
|
} ieee802154_phy_conf_t;
|
||
|
|
||
|
/**
|
||
|
* @brief IEEE 802.15.4 radio operations
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* @brief Transmission of a preloaded frame.
|
||
|
*/
|
||
|
IEEE802154_HAL_OP_TRANSMIT,
|
||
|
/**
|
||
|
* @brief Set the transceiver state to RX.
|
||
|
*/
|
||
|
IEEE802154_HAL_OP_SET_RX,
|
||
|
/**
|
||
|
* @brief Set the transceiver state to IDLE (RX off).
|
||
|
*/
|
||
|
IEEE802154_HAL_OP_SET_IDLE,
|
||
|
/**
|
||
|
* @brief Request Clear Channel Assessment
|
||
|
*/
|
||
|
IEEE802154_HAL_OP_CCA,
|
||
|
|
||
|
/* add more as needed (e.g Energy Scanning, transmit slotted ACK) */
|
||
|
} ieee802154_hal_op_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Radio ops struct declaration
|
||
|
*/
|
||
|
struct ieee802154_radio_ops {
|
||
|
/**
|
||
|
* @brief Radio device capabilities
|
||
|
*
|
||
|
* This field contains bitflags of supported capabilities
|
||
|
* (@ref ieee802154_rf_caps_t) by the device.
|
||
|
*/
|
||
|
const uint32_t caps;
|
||
|
|
||
|
/**
|
||
|
* @brief Write a frame into the framebuffer.
|
||
|
*
|
||
|
* This function shouldn't do any checks, so the frame MUST be valid. The
|
||
|
* previous content of the framebuffer is replaced by @p psdu.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] psdu PSDU frame to be sent
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*write)(ieee802154_dev_t *dev, const iolist_t *psdu);
|
||
|
|
||
|
/**
|
||
|
* @brief Get the length of the received PSDU frame.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
* @pre the radio already received a frame (e.g
|
||
|
* @ref ieee802154_dev::cb with @ref IEEE802154_RADIO_INDICATION_RX_DONE).
|
||
|
*
|
||
|
* @post the frame buffer is still protected against new frame arrivals.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return length of the frame
|
||
|
*/
|
||
|
int (*len)(ieee802154_dev_t *dev);
|
||
|
|
||
|
/**
|
||
|
* @brief Read a frame from the internal framebuffer
|
||
|
*
|
||
|
* This function reads the received frame from the internal framebuffer.
|
||
|
* It should try to copy the received PSDU frame into @p buf. The FCS
|
||
|
* field will **not** be copied and its size **not** be taken into account
|
||
|
* for the return value. If the radio provides any kind of framebuffer
|
||
|
* protection, this function should release it.
|
||
|
*
|
||
|
* @post Don't call this function if there was no reception event
|
||
|
* (either @ref IEEE802154_RADIO_INDICATION_RX_DONE or @ref
|
||
|
* IEEE802154_RADIO_INDICATION_CRC_ERROR). Otherwise there's risk of RX
|
||
|
* underflow.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[out] buf buffer to write the received PSDU frame into.
|
||
|
* @param[in] size size of @p buf
|
||
|
* @param[in] info information of the received frame (LQI, RSSI). Can be
|
||
|
* NULL if this information is not needed.
|
||
|
*
|
||
|
* @return number of bytes written in @p buffer (0 if @p buf == NULL)
|
||
|
* @return -ENOBUFS if the frame doesn't fit in @p
|
||
|
*/
|
||
|
int (*read)(ieee802154_dev_t *dev, void *buf, size_t size, ieee802154_rx_info_t *info);
|
||
|
/**
|
||
|
* @brief Turn off the device
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* When this function returns, the radio shall be off.
|
||
|
*
|
||
|
* @post the device is off
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*off)(ieee802154_dev_t *dev);
|
||
|
|
||
|
/**
|
||
|
* @brief Request to turn on the device
|
||
|
*
|
||
|
* @note @ref ieee802154_radio_ops::confirm_on MUST be used to finish the
|
||
|
* procedure.
|
||
|
*
|
||
|
* @pre the init function of the radio succeeded.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*request_on)(ieee802154_dev_t *dev);
|
||
|
|
||
|
/**
|
||
|
* @brief Confirmation function for @ref ieee802154_radio_ops::request_on.
|
||
|
*
|
||
|
* @pre call to @ref ieee802154_radio_ops::request_on was successful.
|
||
|
*
|
||
|
* @post the transceiver state is IDLE
|
||
|
* During boot or in case the radio doesn't support @ref
|
||
|
* IEEE802154_CAP_REG_RETENTION when @ref off was called, the
|
||
|
* Physical Information Base will be undefined. Thus, take into
|
||
|
* consideration that the following functions should be called right after
|
||
|
* the radio is turned on again:
|
||
|
* - @ref set_cca_threshold
|
||
|
* - @ref set_cca_mode
|
||
|
* - @ref config_phy
|
||
|
* - @ref config_addr_filter
|
||
|
* - @ref set_csma_params
|
||
|
* - @ref set_frame_filter_mode
|
||
|
* - @ref config_src_addr_match
|
||
|
* - @ref set_frame_retrans (if available)
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return 0 if the device is on
|
||
|
* @return -EAGAIN if the device is still busy turning on
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*confirm_on)(ieee802154_dev_t *dev);
|
||
|
|
||
|
/**
|
||
|
* @brief Request a radio operation.
|
||
|
*
|
||
|
* This functions is used to request a radio operation. See @ref
|
||
|
* ieee802154_hal_op_t for a list of available operations.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] op operation to be executed
|
||
|
* @param[in] ctx operation specific context
|
||
|
*
|
||
|
* @return status of the request
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
int (*request_op)(ieee802154_dev_t *dev, ieee802154_hal_op_t op, void *ctx);
|
||
|
|
||
|
/**
|
||
|
* @brief Confirmation function for @ref ieee802154_radio_ops::request_op
|
||
|
*
|
||
|
* This function must be called to finish a given @ref ieee802154_hal_op_t.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] op operation to be confirmed
|
||
|
* @param[in] ctx operation specific context
|
||
|
*
|
||
|
* @return status of the request
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
int (*confirm_op)(ieee802154_dev_t *dev, ieee802154_hal_op_t op, void *ctx);
|
||
|
|
||
|
/**
|
||
|
* @brief Set the threshold for the Energy Detection (first mode of CCA)
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] threshold the threshold in dBm.
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*set_cca_threshold)(ieee802154_dev_t *dev, int8_t threshold);
|
||
|
|
||
|
/**
|
||
|
* @brief Set CCA mode
|
||
|
*
|
||
|
* All radios MUST at least implement the first CCA mode (ED Threshold).
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] mode the CCA mode
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return -ENOTSUP if the mode is not supported
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*set_cca_mode)(ieee802154_dev_t *dev, ieee802154_cca_mode_t mode);
|
||
|
|
||
|
/**
|
||
|
* @brief Set IEEE802.15.4 PHY configuration (channel, TX power)
|
||
|
*
|
||
|
* This function SHOULD NOT validate the PHY configurations unless
|
||
|
* it's specific to the device. The upper layer is responsible of all kind
|
||
|
* of validations.
|
||
|
* In case a configuration is not valid (e.g parameters out of range), this
|
||
|
* function should return -EINVAL
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
* @pre the transceiver state is IDLE.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] conf the PHY configuration
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return -EINVAL if the configuration is not valid for the device.
|
||
|
* @return <0 error, return value is negative errno indicating the cause.
|
||
|
*/
|
||
|
int (*config_phy)(ieee802154_dev_t *dev, const ieee802154_phy_conf_t *conf);
|
||
|
|
||
|
/**
|
||
|
* @brief Set number of frame retransmissions
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @note this function pointer can be NULL if the device doesn't support
|
||
|
* frame retransmissions
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] retrans the number of retransmissions attempts.
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*set_frame_retrans)(ieee802154_dev_t *dev, uint8_t retrans);
|
||
|
|
||
|
/**
|
||
|
* @brief Set the CSMA-CA parameters.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] bd parameters of the exponential backoff. If NULL, the
|
||
|
* parameters are not altered.
|
||
|
* @param[in] retries number of CSMA-CA retries. If @p retries < 0,
|
||
|
* retransmissions with CSMA-CA MUST be disabled.
|
||
|
* If @p retries == 0, the @ref
|
||
|
* ieee802154_radio_request_transmit function is
|
||
|
* equivalent to CCA send.
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return -EINVAL if the settings are not supported.
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*set_csma_params)(ieee802154_dev_t *dev, const ieee802154_csma_be_t *bd,
|
||
|
int8_t retries);
|
||
|
|
||
|
/**
|
||
|
* @brief Set the frame filter moder.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] mode address filter mode
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*set_frame_filter_mode)(ieee802154_dev_t *dev, ieee802154_filter_mode_t mode);
|
||
|
|
||
|
/**
|
||
|
* @brief Configure the address filter.
|
||
|
*
|
||
|
* This functions is used for configuring the address filter parameters
|
||
|
* required by the IEEE 802.15.4 standard.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] cmd command for the address filter
|
||
|
* @param[in] value value for @p cmd.
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*config_addr_filter)(ieee802154_dev_t *dev, ieee802154_af_cmd_t cmd, const void *value);
|
||
|
|
||
|
/**
|
||
|
* @brief Set the source address match configuration.
|
||
|
*
|
||
|
* This function configures the source address match filter in order to set
|
||
|
* the Frame Pending bit in ACK frames accordingly.
|
||
|
* In case the radio doesn't support @ref IEEE802154_CAP_SRC_ADDR_MATCH,
|
||
|
* this functions is used to activate the Frame Pending bit for all ACK
|
||
|
* frames (in order to be compliant with the IEEE 802.15.4 standard).
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] cmd command for the source address match configuration
|
||
|
* @param[in] value value associated to @p cmd.
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
int (*config_src_addr_match)(ieee802154_dev_t *dev, ieee802154_src_match_t cmd,
|
||
|
const void *value);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::write
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] psdu PSDU frame to be sent
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::write
|
||
|
*/
|
||
|
static inline int ieee802154_radio_write(ieee802154_dev_t *dev, const iolist_t *psdu)
|
||
|
{
|
||
|
return dev->driver->write(dev, psdu);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Transmit a preloaded frame
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::request_op with @ref
|
||
|
* IEEE802154_HAL_OP_TRANSMIT and NULL context.
|
||
|
*
|
||
|
* @pre The upper layer should have called set the transceiver to IDLE (see
|
||
|
* @ref ieee802154_radio_set_idle) and the frame is already in the framebuffer
|
||
|
* (@ref ieee802154_radio_ops_t::write).
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @note @ref ieee802154_radio_confirm_transmit MUST be used to
|
||
|
* finish the transmission.
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_request_transmit
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_request_transmit(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->request_op(dev, IEEE802154_HAL_OP_TRANSMIT, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Confirmation function for @ref ieee802154_radio_request_transmit
|
||
|
* This function must be called to finish the transmission procedure and
|
||
|
* get the transmission status. This function should be called on @ref
|
||
|
* IEEE802154_RADIO_CONFIRM_TX_DONE. If no interrupt is available, this
|
||
|
* function can be polled.
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::confirm_op with @ref
|
||
|
* IEEE802154_HAL_OP_TRANSMIT and sets the context to @p info.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
* @pre call to @ref ieee802154_radio_request_transmit was successful.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[out] info the TX information. Pass NULL
|
||
|
* if the information is not needed. If the radio supports AutoCCA, the
|
||
|
* status should indicate transmission done or channel busy. If the radio
|
||
|
* supports frame retransmissions, the status should indicate if medium
|
||
|
* was busy, no ACK was received or transmission succeeded.
|
||
|
*
|
||
|
* @retval whether the transmission finished or not
|
||
|
*
|
||
|
* @return 0 if the transmission finished
|
||
|
* @return -EAGAIN otherwise
|
||
|
*/
|
||
|
static inline int ieee802154_radio_confirm_transmit(ieee802154_dev_t *dev,
|
||
|
ieee802154_tx_info_t *info)
|
||
|
{
|
||
|
return dev->driver->confirm_op(dev, IEEE802154_HAL_OP_TRANSMIT, info);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::len
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::len
|
||
|
*/
|
||
|
static inline int ieee802154_radio_len(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->len(dev);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::read
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[out] buf buffer to write the received frame into.
|
||
|
* @param[in] size size of @p buf
|
||
|
* @param[in] info information of the received frame (LQI, RSSI). Can be
|
||
|
* NULL if this information is not needed.
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::read
|
||
|
*/
|
||
|
static inline int ieee802154_radio_read(ieee802154_dev_t *dev,
|
||
|
void *buf,
|
||
|
size_t size,
|
||
|
ieee802154_rx_info_t *info)
|
||
|
{
|
||
|
return dev->driver->read(dev, buf, size, info);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::set_cca_threshold
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] threshold the threshold in dBm
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::set_cca_threshold
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_cca_threshold(ieee802154_dev_t *dev,
|
||
|
int8_t threshold)
|
||
|
{
|
||
|
return dev->driver->set_cca_threshold(dev, threshold);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::set_cca_mode
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] mode the CCA mode
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::set_cca_mode
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_cca_mode(ieee802154_dev_t *dev,
|
||
|
ieee802154_cca_mode_t mode)
|
||
|
{
|
||
|
return dev->driver->set_cca_mode(dev, mode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::config_phy
|
||
|
*
|
||
|
* @pre the transceiver state is IDLE.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] conf the PHY configuration
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::config_phy
|
||
|
*/
|
||
|
static inline int ieee802154_radio_config_phy(ieee802154_dev_t *dev,
|
||
|
const ieee802154_phy_conf_t *conf)
|
||
|
{
|
||
|
return dev->driver->config_phy(dev, conf);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::config_src_addr_match
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] cmd command for the source address match configuration
|
||
|
* @param[in] value value associated to @p cmd.
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::config_src_addr_match
|
||
|
*/
|
||
|
static inline int ieee802154_radio_config_src_address_match(ieee802154_dev_t *dev,
|
||
|
ieee802154_src_match_t cmd,
|
||
|
const void *value)
|
||
|
{
|
||
|
return dev->driver->config_src_addr_match(dev, cmd, value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::off
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @post the transceiver state is IDLE.
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::off
|
||
|
*/
|
||
|
static inline int ieee802154_radio_off(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->off(dev);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::config_addr_filter
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] cmd command for the address filter
|
||
|
* @param[in] value value for @p cmd.
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::config_addr_filter
|
||
|
*/
|
||
|
static inline int ieee802154_radio_config_addr_filter(ieee802154_dev_t *dev,
|
||
|
ieee802154_af_cmd_t cmd,
|
||
|
const void* value)
|
||
|
{
|
||
|
return dev->driver->config_addr_filter(dev, cmd, value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::set_frame_filter_mode
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] mode frame filter mode
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::set_frame_filter_mode
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_frame_filter_mode(ieee802154_dev_t *dev,
|
||
|
ieee802154_filter_mode_t mode)
|
||
|
{
|
||
|
return dev->driver->set_frame_filter_mode(dev, mode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::set_frame_retrans
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
* @pre the device supports frame retransmissions
|
||
|
* (@ref ieee802154_radio_has_frame_retrans() == true)
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] retrans the number of retransmissions
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::set_frame_retrans
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_frame_retrans(ieee802154_dev_t *dev,
|
||
|
uint8_t retrans)
|
||
|
{
|
||
|
return dev->driver->set_frame_retrans(dev, retrans);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::set_csma_params
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
* @pre the device supports frame retransmissions
|
||
|
* (@ref ieee802154_radio_has_frame_retrans() == true)
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] bd parameters of the exponential backoff
|
||
|
* @param[in] retries number of CSMA-CA retries. If @p restries < 0,
|
||
|
* retransmissions with CSMA-CA are disabled
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::set_csma_params
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_csma_params(ieee802154_dev_t *dev,
|
||
|
const ieee802154_csma_be_t *bd,
|
||
|
int8_t retries)
|
||
|
{
|
||
|
return dev->driver->set_csma_params(dev, bd, retries);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::request_on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::request_on
|
||
|
*/
|
||
|
static inline int ieee802154_radio_request_on(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->request_on(dev);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_ops::confirm_on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return result of @ref ieee802154_radio_ops::confirm_on
|
||
|
*/
|
||
|
static inline int ieee802154_radio_confirm_on(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->confirm_on(dev);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Request the transceiver state to IDLE.
|
||
|
*
|
||
|
* During IDLE, the radio won't be able to receive frames but it's still
|
||
|
* responsive to other HAL functions.
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::request_op with @ref
|
||
|
* IEEE802154_HAL_OP_SET_IDLE and sets the context to @p force
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @note @ref ieee802154_radio_confirm_set_idle MUST be used to
|
||
|
* finish the state transition.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] force whether the state transition should be forced or not. If
|
||
|
* forced, the transceiver aborts any ongoing operation.
|
||
|
*
|
||
|
* @return status of the request
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_request_set_idle(ieee802154_dev_t *dev, bool force)
|
||
|
{
|
||
|
return dev->driver->request_op(dev, IEEE802154_HAL_OP_SET_IDLE, &force);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Confirmation function for @ref ieee802154_radio_request_set_idle
|
||
|
*
|
||
|
* @pre call to @ref ieee802154_radio_request_set_idle was successful.
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return whether the state transition finished or not
|
||
|
*
|
||
|
* @return 0 if the transition finished
|
||
|
* @return -EAGAIN otherwise.
|
||
|
*/
|
||
|
static inline int ieee802154_radio_confirm_set_idle(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->confirm_op(dev, IEEE802154_HAL_OP_SET_IDLE, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Request the transceiver state to RX.
|
||
|
*
|
||
|
* During RX, the radio will listen to incoming frames
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::request_op with @ref
|
||
|
* IEEE802154_HAL_OP_SET_RX and NULL context.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @note @ref ieee802154_radio_confirm_set_rx MUST be used to
|
||
|
* finish the state transition.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return status of the request
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_request_set_rx(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->request_op(dev, IEEE802154_HAL_OP_SET_RX, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Confirmation function for @ref ieee802154_radio_request_set_rx
|
||
|
*
|
||
|
* @pre call to @ref ieee802154_radio_request_set_rx was successful.
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return whether the state transition finished or not
|
||
|
*
|
||
|
* @return 0 if the transition finished
|
||
|
* @return -EAGAIN otherwise.
|
||
|
*/
|
||
|
static inline int ieee802154_radio_confirm_set_rx(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->confirm_op(dev, IEEE802154_HAL_OP_SET_RX, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set transceiver state to IDLE (blocking)
|
||
|
*
|
||
|
* This function will internally call @ref ieee802154_radio_request_set_idle
|
||
|
* and poll @ref ieee802154_radio_confirm_set_idle.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
* @param[in] force whether the state transition should be forced or not. If
|
||
|
* forced, the transceiver aborts any ongoing operation.
|
||
|
*
|
||
|
* @return result of the state transition
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_idle(ieee802154_dev_t *dev, bool force)
|
||
|
{
|
||
|
int res = ieee802154_radio_request_set_idle(dev, force);
|
||
|
if (res < 0) {
|
||
|
return res;
|
||
|
}
|
||
|
while (ieee802154_radio_confirm_set_idle(dev) == -EAGAIN) {}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set transceiver state to RX (blocking)
|
||
|
*
|
||
|
* This function will internally call @ref ieee802154_radio_request_set_rx
|
||
|
* and poll @ref ieee802154_radio_confirm_set_rx.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return result of the state transition
|
||
|
*
|
||
|
* @retval 0 on success
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_set_rx(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
int res = ieee802154_radio_request_set_rx(dev);
|
||
|
if (res < 0) {
|
||
|
return res;
|
||
|
}
|
||
|
while (ieee802154_radio_confirm_set_rx(dev) == -EAGAIN) {}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Request Stand-Alone Clear Channel Assessment
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::request_op with @ref
|
||
|
* IEEE802154_HAL_OP_CCA and NULL context.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @note @ref ieee802154_radio_confirm_cca MUST be used to
|
||
|
* finish the CCA procedure and get the channel status.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return 0 on success
|
||
|
* @return negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_request_cca(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return dev->driver->request_op(dev, IEEE802154_HAL_OP_CCA, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Shortcut to @ref ieee802154_radio_confirm_cca
|
||
|
*
|
||
|
* This function must be called to finish the CCA procedure. This
|
||
|
* function should be called on @ref IEEE802154_RADIO_CONFIRM_CCA,
|
||
|
* If no interrupt is available, this function can be polled.
|
||
|
*
|
||
|
* This functions calls ieee802154_radio_ops::request_op with @ref
|
||
|
* IEEE802154_HAL_OP_CCA and sets the context to a boolean where the result
|
||
|
* of the CCA should be store. Setting it to true means the channel is clear.
|
||
|
*
|
||
|
* @pre call to @ref ieee802154_radio_request_cca was successful.
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return status of the CCA procedure
|
||
|
*
|
||
|
* @retval positive number if the channel is clear
|
||
|
* @retval 0 if the channel is busy
|
||
|
* @retval -EAGAIN if the CCA procedure hasn't finished.
|
||
|
*/
|
||
|
static inline int ieee802154_radio_confirm_cca(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
bool clear;
|
||
|
int res = dev->driver->confirm_op(dev, IEEE802154_HAL_OP_CCA, &clear);
|
||
|
if (res < 0) {
|
||
|
return res;
|
||
|
}
|
||
|
return clear;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Perform a Clear Channel Assessment (blocking)
|
||
|
*
|
||
|
* This function will internally call @ref ieee802154_radio_request_cca
|
||
|
* and poll @ref ieee802154_radio_confirm_cca.
|
||
|
*
|
||
|
* @pre the device is on
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return status of the CCA
|
||
|
*
|
||
|
* @retval positive number if the channel is clear
|
||
|
* @retval 0 if the channel is busy
|
||
|
* @retval negative errno on error
|
||
|
*/
|
||
|
static inline int ieee802154_radio_cca(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
int res = ieee802154_radio_request_cca(dev);
|
||
|
if (res < 0) {
|
||
|
return res;
|
||
|
}
|
||
|
while ((res = ieee802154_radio_confirm_cca(dev)) == -EAGAIN) {}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports ACK timeout
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_IRQ_ACK_TIMEOUT.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_irq_ack_timeout(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_IRQ_ACK_TIMEOUT);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports frame retransmissions (with CSMA-CA).
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_FRAME_RETRANS.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_frame_retrans(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_FRAME_RETRANS);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports Auto CSMA-CA for transmissions.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_AUTO_CSMA.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_auto_csma(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_AUTO_CSMA);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the IEEE802.15.4 Sub-GHz band
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_SUB_GHZ.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_sub_ghz(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_SUB_GHZ);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the IEEE802.15.4 2.4 GHz band
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_24_GHZ.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_24_ghz(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_24_GHZ);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports TX done interrupt
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_IRQ_TX_DONE.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_irq_tx_done(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_IRQ_TX_DONE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports RX start interrupt
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_IRQ_RX_START.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_irq_rx_start(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_IRQ_RX_START);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports TX start interrupt
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_IRQ_TX_START.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_irq_tx_start(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_IRQ_TX_START);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports CCA done interrupt
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps with @ref
|
||
|
* IEEE802154_CAP_IRQ_CCA_DONE.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_irq_cca_done(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_IRQ_CCA_DONE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device reports the number of retransmissions of the last
|
||
|
* TX procedure.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_FRAME_RETRANS_INFO.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_frame_retrans_info(
|
||
|
ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_FRAME_RETRANS_INFO);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the BPSK PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_BPSK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_bpsk(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_BPSK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the ASK PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_ASK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_ask(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_ASK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the O-QPSK PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_OQPSK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_oqpsk(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_OQPSK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the MR-O-QPSK PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_MR_OQPSK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_mr_oqpsk(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_MR_OQPSK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the MR-OFDM PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_MR_OFDM.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_mr_ofdm(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_MR_OFDM);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if the device supports the MR-FSK PHY mode.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and checks for
|
||
|
* @ref IEEE802154_CAP_PHY_MR_FSK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return true if the device has support
|
||
|
* @return false otherwise
|
||
|
*/
|
||
|
static inline bool ieee802154_radio_has_phy_mr_fsk(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_CAP_PHY_MR_FSK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get supported PHY modes of the device.
|
||
|
*
|
||
|
* Internally this function reads ieee802154_radio_ops::caps and returns only
|
||
|
* the bits from @ref IEEE802154_RF_CAPS_PHY_MASK.
|
||
|
*
|
||
|
* @param[in] dev IEEE802.15.4 device descriptor
|
||
|
*
|
||
|
* @return PHY modes bit mask.
|
||
|
*/
|
||
|
static inline uint32_t ieee802154_radio_get_phy_modes(ieee802154_dev_t *dev)
|
||
|
{
|
||
|
return (dev->driver->caps & IEEE802154_RF_CAPS_PHY_MASK);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Convert a @ref ieee802154_phy_mode_t to a @ref ieee802154_rf_caps_t
|
||
|
* value.
|
||
|
*
|
||
|
* @param[in] phy_mode PHY mode
|
||
|
*
|
||
|
* @return Equivalent capability given the PHY mode.
|
||
|
* @return 0 on invalid values
|
||
|
* @return 0 when @ref IEEE802154_PHY_DISABLED is given as the parameter.
|
||
|
*/
|
||
|
static inline uint32_t ieee802154_phy_mode_to_cap(
|
||
|
ieee802154_phy_mode_t phy_mode)
|
||
|
{
|
||
|
switch (phy_mode) {
|
||
|
case IEEE802154_PHY_BPSK:
|
||
|
return IEEE802154_CAP_PHY_BPSK;
|
||
|
case IEEE802154_PHY_ASK:
|
||
|
return IEEE802154_CAP_PHY_ASK;
|
||
|
case IEEE802154_PHY_OQPSK:
|
||
|
return IEEE802154_CAP_PHY_OQPSK;
|
||
|
case IEEE802154_PHY_MR_OQPSK:
|
||
|
return IEEE802154_CAP_PHY_MR_OQPSK;
|
||
|
case IEEE802154_PHY_MR_OFDM:
|
||
|
return IEEE802154_CAP_PHY_MR_OFDM;
|
||
|
case IEEE802154_PHY_MR_FSK:
|
||
|
return IEEE802154_CAP_PHY_MR_FSK;
|
||
|
|
||
|
case IEEE802154_PHY_DISABLED:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Convert a @ref ieee802154_rf_caps_t to a @ref ieee802154_phy_mode_t
|
||
|
* value.
|
||
|
*
|
||
|
* @note The @p parameter must be one of the PHY capabilities.
|
||
|
*
|
||
|
* @param[in] cap The IEEE 802.15.4 capability.
|
||
|
*
|
||
|
* @return Equivalent phy mode given the capability.
|
||
|
* @return 0 on invalid values
|
||
|
*/
|
||
|
static inline ieee802154_phy_mode_t ieee802154_cap_to_phy_mode(uint32_t cap)
|
||
|
{
|
||
|
switch (cap) {
|
||
|
case IEEE802154_CAP_PHY_BPSK:
|
||
|
return IEEE802154_PHY_BPSK;
|
||
|
case IEEE802154_CAP_PHY_ASK:
|
||
|
return IEEE802154_PHY_ASK;
|
||
|
case IEEE802154_CAP_PHY_OQPSK:
|
||
|
return IEEE802154_PHY_OQPSK;
|
||
|
case IEEE802154_CAP_PHY_MR_OQPSK:
|
||
|
return IEEE802154_PHY_MR_OQPSK;
|
||
|
case IEEE802154_PHY_MR_OFDM:
|
||
|
return IEEE802154_PHY_MR_OFDM;
|
||
|
case IEEE802154_CAP_PHY_MR_FSK:
|
||
|
return IEEE802154_PHY_MR_FSK;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return IEEE802154_PHY_DISABLED;
|
||
|
}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif /* NET_IEEE802154_RADIO_H */
|
||
|
/** @} */
|
||
|
```
|