net/ieee802154: add PHY mode capabilities

- Adds capabilities for each PHY mode. Converts the uint16_t caps field to an
uint32_t in order to hold all capability bits, size of the structure remains
unchanged due to alignment.
- Modifies the test application to configure the PHY mode using the shell
command. Also adds the PHY modes to the capabilities shell command.
- Updates the nrf802154 and cc2538 radio drivers to specify the PHY mode
supported.

Signed-off-by: Jean Pierre Dudey <me@jeandudey.tech>
This commit is contained in:
Jean Pierre Dudey 2021-02-20 12:24:44 +01:00
parent 0cd3deb74c
commit 4ca37c96b3
4 changed files with 298 additions and 11 deletions

View File

@ -525,7 +525,8 @@ static const ieee802154_radio_ops_t cc2538_rf_ops = {
| IEEE802154_CAP_IRQ_TX_DONE
| IEEE802154_CAP_IRQ_CCA_DONE
| IEEE802154_CAP_IRQ_RX_START
| IEEE802154_CAP_IRQ_TX_START,
| IEEE802154_CAP_IRQ_TX_START
| IEEE802154_CAP_PHY_OQPSK,
.write = _write,
.read = _read,

View File

@ -782,7 +782,8 @@ static const ieee802154_radio_ops_t nrf802154_ops = {
| IEEE802154_CAP_IRQ_RX_START
| IEEE802154_CAP_IRQ_TX_START
| IEEE802154_CAP_IRQ_TX_DONE
| IEEE802154_CAP_IRQ_CCA_DONE,
| IEEE802154_CAP_IRQ_CCA_DONE
| IEEE802154_CAP_PHY_OQPSK,
.write = _write,
.read = _read,

View File

@ -32,6 +32,7 @@ extern "C" {
#include "bitarithm.h"
#include "byteorder.h"
#include "net/eui64.h"
#include "net/ieee802154.h"
/**
* @brief Forward declaration of the radio ops structure.
@ -123,8 +124,43 @@ typedef enum {
* @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,
} 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
*/
@ -374,6 +410,7 @@ typedef enum {
* @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 */
@ -389,7 +426,7 @@ struct ieee802154_radio_ops {
* This field contains bitflags of supported capabilities
* (@ref ieee802154_rf_caps_t) by the device.
*/
const uint16_t caps;
const uint32_t caps;
/**
* @brief Write a frame into the framebuffer.
@ -1155,6 +1192,117 @@ static inline bool ieee802154_radio_has_frame_retrans_info(
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 Shortcut to @ref ieee802154_radio_ops::set_rx_mode
*
@ -1169,6 +1317,75 @@ static inline int ieee802154_radio_set_rx_mode(ieee802154_dev_t *dev,
return dev->driver->set_rx_mode(dev, mode);
}
/**
* @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

View File

@ -20,6 +20,7 @@
#include <assert.h>
#include <stdio.h>
#include <strings.h>
#include "common.h"
#include "errno.h"
@ -488,13 +489,43 @@ static int rx_mode_cmd(int argc, char **argv)
int config_phy(int argc, char **argv)
{
if (argc < 3) {
puts("Usage: config_phy <channel> <tx_pow>");
if (argc < 4) {
puts("Usage: config_phy <phy_mode> <channel> <tx_pow>");
return 1;
}
uint8_t channel = atoi(argv[1]);
int8_t tx_pow = atoi(argv[2]);
ieee802154_phy_mode_t phy_mode;
if (strcasecmp(argv[1], "BPSK")) {
phy_mode = IEEE802154_PHY_BPSK;
}
else if (strcasecmp(argv[1], "ASK")) {
phy_mode = IEEE802154_PHY_ASK;
}
else if (strcasecmp(argv[1], "O-QPSK")) {
phy_mode = IEEE802154_PHY_OQPSK;
}
else if (strcasecmp(argv[1], "MR-O-QPSK")) {
phy_mode = IEEE802154_PHY_MR_OQPSK;
}
else if (strcasecmp(argv[1], "MR-OFDM")) {
phy_mode = IEEE802154_PHY_MR_OFDM;
}
else if (strcasecmp(argv[1], "MR-FSK")) {
phy_mode = IEEE802154_PHY_MR_FSK;
}
else {
puts("Wrong PHY mode specified. Must be one of:");
puts(" * BPSK");
puts(" * ASK");
puts(" * O-QPSK");
puts(" * MR-O-QPSK");
puts(" * MR-OFDM");
puts(" * MR-FSK");
return 1;
}
uint8_t channel = atoi(argv[2]);
int8_t tx_pow = atoi(argv[3]);
if (channel < 11 || channel > 26) {
puts("Wrong channel configuration (11 <= channel <= 26).");
@ -502,7 +533,7 @@ int config_phy(int argc, char **argv)
}
_set_trx_state(IEEE802154_TRX_STATE_TRX_OFF, false);
ieee802154_dev_t *dev = ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID);
ieee802154_phy_conf_t conf = {.channel=channel, .page=0, .pow=tx_pow};
ieee802154_phy_conf_t conf = {.phy_mode=phy_mode, .channel=channel, .page=0, .pow=tx_pow};
if (ieee802154_radio_config_phy(dev, &conf) < 0) {
puts("Channel or TX power settings not supported");
}
@ -602,6 +633,12 @@ static int _caps_cmd(int argc, char **argv)
bool has_irq_ack_timeout = false;
bool has_irq_cca_done = false;
bool has_frame_retrans_info = false;
bool has_phy_bpsk = false;
bool has_phy_ask = false;
bool has_phy_oqpsk = false;
bool has_phy_mr_oqpsk = false;
bool has_phy_mr_ofdm = false;
bool has_phy_mr_fsk = false;
if (ieee802154_radio_has_frame_retrans(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_frame_retrans = true;
@ -639,6 +676,30 @@ static int _caps_cmd(int argc, char **argv)
has_frame_retrans_info = true;
}
if (ieee802154_radio_has_phy_bpsk(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_bpsk = true;
}
if (ieee802154_radio_has_phy_ask(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_ask = true;
}
if (ieee802154_radio_has_phy_oqpsk(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_oqpsk = true;
}
if (ieee802154_radio_has_phy_mr_oqpsk(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_mr_oqpsk = true;
}
if (ieee802154_radio_has_phy_mr_ofdm(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_mr_ofdm = true;
}
if (ieee802154_radio_has_phy_mr_fsk(ieee802154_hal_test_get_dev(RADIO_DEFAULT_ID))) {
has_phy_mr_fsk = true;
}
puts(" CAPS ");
puts("=================================");
printf("- Frame Retransmissions: %s\n", has_frame_retrans ? "y" : "n");
@ -650,6 +711,13 @@ static int _caps_cmd(int argc, char **argv)
printf(" * ACK Timeout indication: %s\n", has_irq_ack_timeout ? "y" : "n");
printf("- RX_START indication: %s\n", has_irq_rx_start ? "y" : "n");
printf("- CCA Done indication: %s\n", has_irq_cca_done ? "y" : "n");
printf("- PHY modes: \n");
printf("- * BPSK: %s\n", has_phy_bpsk ? "y" : "n");
printf("- * ASK: %s\n", has_phy_ask ? "y" : "n");
printf("- * O-QPSK: %s\n", has_phy_oqpsk ? "y" : "n");
printf("- * MR-O-QPSK: %s\n", has_phy_mr_oqpsk ? "y" : "n");
printf("- * MR-OFDM: %s\n", has_phy_mr_ofdm ? "y" : "n");
printf("- * MR-FSK: %s\n", has_phy_mr_fsk? "y" : "n");
return 0;
}