diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index ee01562838..33bbed9def 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -70,6 +70,10 @@ ifneq (,$(filter at86rf215%,$(USEMODULE))) DEFAULT_MODULE += auto_init_at86rf215 DEFAULT_MODULE += at86rf215_subghz + DEFAULT_MODULE += netdev_ieee802154_multimode + + DEFAULT_MODULE += netdev_ieee802154_oqpsk + ifeq (,$(filter at86rf215m,$(USEMODULE))) DEFAULT_MODULE += at86rf215_24ghz endif diff --git a/drivers/at86rf215/at86rf215_getset.c b/drivers/at86rf215/at86rf215_getset.c index 9016340916..940149267b 100644 --- a/drivers/at86rf215/at86rf215_getset.c +++ b/drivers/at86rf215/at86rf215_getset.c @@ -114,6 +114,18 @@ uint16_t at86rf215_get_channel_spacing(at86rf215_t *dev) { return 25 * at86rf215_reg_read(dev, dev->RF->RG_CS); } +uint8_t at86rf215_get_phy_mode(at86rf215_t *dev) +{ + switch (at86rf215_reg_read(dev, dev->BBC->RG_PC) & PC_PT_MASK) { + case 0x1: return IEEE802154_PHY_MR_FSK; + case 0x2: return IEEE802154_PHY_MR_OFDM; + case 0x3: return at86rf215_OQPSK_is_legacy(dev) + ? IEEE802154_PHY_OQPSK + : IEEE802154_PHY_MR_OQPSK; + default: return IEEE802154_PHY_DISABLED; + } +} + uint16_t at86rf215_get_pan(const at86rf215_t *dev, uint8_t filter) { if (filter > 3) { diff --git a/drivers/at86rf215/at86rf215_netdev.c b/drivers/at86rf215/at86rf215_netdev.c index c42b5a7816..21f5308a38 100644 --- a/drivers/at86rf215/at86rf215_netdev.c +++ b/drivers/at86rf215/at86rf215_netdev.c @@ -384,6 +384,12 @@ static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) res = max_len; break; + case NETOPT_IEEE802154_PHY: + assert(max_len >= sizeof(int8_t)); + *((int8_t *)val) = at86rf215_get_phy_mode(dev); + res = max_len; + break; + default: res = -ENOTSUP; break; @@ -528,6 +534,16 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len) res = sizeof(int8_t); break; + case NETOPT_IEEE802154_PHY: + assert(len <= sizeof(uint8_t)); + switch (*(uint8_t *)val) { + case IEEE802154_PHY_OQPSK: + at86rf215_configure_legacy_OQPSK(dev, at86rf215_OQPSK_get_mode_legacy(dev)); + res = sizeof(uint8_t); + break; + default: + return -ENOTSUP; + } default: break; } diff --git a/drivers/at86rf215/include/at86rf215_internal.h b/drivers/at86rf215/include/at86rf215_internal.h index 80f1817e69..091cdb5e6a 100644 --- a/drivers/at86rf215/include/at86rf215_internal.h +++ b/drivers/at86rf215/include/at86rf215_internal.h @@ -158,6 +158,18 @@ void at86rf215_get_random(at86rf215_t *dev, void *data, size_t len); */ int at86rf215_configure_legacy_OQPSK(at86rf215_t *dev, bool high_rate); +/** + * @brief Get the current PHY modulation. + * May be @ref IEEE802154_PHY_MR_FSK, @ref IEEE802154_PHY_MR_OFDM, + * @ref IEEE802154_PHY_MR_OQPSK, @ref IEEE802154_PHY_OQPSK + * or @ref IEEE802154_PHY_DISABLED. + * + * @param[in] dev device to read from + * + * @return the current PHY mode the device is operating with + */ +uint8_t at86rf215_get_phy_mode(at86rf215_t *dev); + /** * @brief Check if a channel number is valid. * The function takes the current frequency band and modulation into diff --git a/drivers/include/at86rf215.h b/drivers/include/at86rf215.h index 22bcf24a94..b54d2178c3 100644 --- a/drivers/include/at86rf215.h +++ b/drivers/include/at86rf215.h @@ -119,6 +119,13 @@ typedef enum { } at86rf215_state_t; /** @} */ +enum { + AT86RF215_MODE_LEGACY_OQPSK, + AT86RF215_MODE_MR_OQPSK, + AT86RF215_MODE_MR_OFDM, + AT86RF215_MODE_MR_FSK +}; + /** * @name Internal device option flags * @{