From 4ca37c96b389e6f375902d3a385e01e60a0cf5d2 Mon Sep 17 00:00:00 2001 From: Jean Pierre Dudey Date: Sat, 20 Feb 2021 12:24:44 +0100 Subject: [PATCH] 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 --- cpu/cc2538/radio/cc2538_rf_radio_ops.c | 3 +- cpu/nrf52/radio/nrf802154/nrf802154_radio.c | 3 +- sys/include/net/ieee802154/radio.h | 225 +++++++++++++++++++- tests/ieee802154_hal/main.c | 78 ++++++- 4 files changed, 298 insertions(+), 11 deletions(-) diff --git a/cpu/cc2538/radio/cc2538_rf_radio_ops.c b/cpu/cc2538/radio/cc2538_rf_radio_ops.c index f4c2cc2abe..529f0192b7 100644 --- a/cpu/cc2538/radio/cc2538_rf_radio_ops.c +++ b/cpu/cc2538/radio/cc2538_rf_radio_ops.c @@ -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, diff --git a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c index 0773ab0151..58fe27b39f 100644 --- a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c +++ b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c @@ -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, diff --git a/sys/include/net/ieee802154/radio.h b/sys/include/net/ieee802154/radio.h index 86f438bf3a..aa2ef4b6a6 100644 --- a/sys/include/net/ieee802154/radio.h +++ b/sys/include/net/ieee802154/radio.h @@ -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,9 +410,10 @@ typedef enum { * @brief Holder of the PHY configuration */ typedef struct { - 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_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; /** @@ -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 diff --git a/tests/ieee802154_hal/main.c b/tests/ieee802154_hal/main.c index 22dce9ffa0..a3bf2be2c7 100644 --- a/tests/ieee802154_hal/main.c +++ b/tests/ieee802154_hal/main.c @@ -20,6 +20,7 @@ #include #include +#include #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 "); + if (argc < 4) { + puts("Usage: config_phy "); 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; }