Merge pull request #14959 from benpicco/at86rf215-mr-fsk
drivers/at86rf215: implement MR-FSK
This commit is contained in:
commit
9681c204d6
@ -72,6 +72,11 @@ config AT86RF215_DEFAULT_MR_OFDM
|
||||
help
|
||||
MR-O-OFDM according to IEEE 802.15.4g
|
||||
|
||||
config AT86RF215_DEFAULT_MR_FSK
|
||||
bool "MR-FSK"
|
||||
help
|
||||
MR-FSK according to IEEE 802.15.4g
|
||||
|
||||
endchoice
|
||||
|
||||
menu "O-QPSK (802.15.4) configuration"
|
||||
@ -148,4 +153,52 @@ config AT86RF215_DEFAULT_MR_OFDM_MCS
|
||||
|
||||
endmenu
|
||||
|
||||
menu "MR-FSK (802.15.4g) configuration"
|
||||
depends on AT86RF215_DEFAULT_MR_FSK
|
||||
|
||||
config AT86RF215_DEFAULT_MR_FSK_SRATE
|
||||
int "Default MR-FSK Symbol Rate"
|
||||
range 0 5
|
||||
default 3
|
||||
help
|
||||
Default Symbol Rate of the MR-FSK PHY
|
||||
|
||||
0: 50 kHz
|
||||
1: 100 kHZ
|
||||
2: 150 kHZ
|
||||
3: 200 kHZ
|
||||
4: 300 kHZ
|
||||
5: 400 kHZ
|
||||
|
||||
config AT86RF215_DEFAULT_MR_FSK_MOD_IDX
|
||||
int "Default MR-FSK Modulation Index"
|
||||
range 0 128
|
||||
default 64
|
||||
help
|
||||
Default Modulation Index of the MR-FSK PHY as a fraction of 64.
|
||||
(32/64 = 0.5; 64/64 = 1 …)
|
||||
|
||||
config AT86RF215_DEFAULT_MR_FSK_MORD
|
||||
int "Default MR-FSK Modulation Order"
|
||||
range 0 1
|
||||
default 1
|
||||
help
|
||||
Default FSK Modulation Order
|
||||
|
||||
0: 2-FSK
|
||||
1: 4-FSk
|
||||
|
||||
config AT86RF215_DEFAULT_MR_FSK_FEC
|
||||
int "Default MR-FSK Forward Error Correction Scheme"
|
||||
range 0 2
|
||||
default 0
|
||||
help
|
||||
Default Settings for Forward Error Correction
|
||||
|
||||
0: No Forward Error Correction
|
||||
1: Non-recursive and non-systematic code
|
||||
2: Recursive and systematic code
|
||||
|
||||
endmenu
|
||||
|
||||
endif # KCONFIG_USEMODULE_AT86RF215
|
||||
|
||||
@ -14,6 +14,7 @@ DEFAULT_MODULE += netdev_ieee802154_multimode
|
||||
DEFAULT_MODULE += netdev_ieee802154_oqpsk
|
||||
DEFAULT_MODULE += netdev_ieee802154_mr_oqpsk
|
||||
DEFAULT_MODULE += netdev_ieee802154_mr_ofdm
|
||||
DEFAULT_MODULE += netdev_ieee802154_mr_fsk
|
||||
|
||||
FEATURES_REQUIRED += periph_gpio
|
||||
FEATURES_REQUIRED += periph_gpio_irq
|
||||
|
||||
@ -160,6 +160,12 @@ if (!IS_ACTIVE(CONFIG_AT86RF215_USE_CLOCK_OUTPUT)){
|
||||
at86rf215_configure_OFDM(dev, CONFIG_AT86RF215_DEFAULT_MR_OFDM_OPT,
|
||||
CONFIG_AT86RF215_DEFAULT_MR_OFDM_MCS);
|
||||
}
|
||||
if (CONFIG_AT86RF215_DEFAULT_PHY_MODE == IEEE802154_PHY_MR_FSK) {
|
||||
at86rf215_configure_FSK(dev, CONFIG_AT86RF215_DEFAULT_MR_FSK_SRATE,
|
||||
CONFIG_AT86RF215_DEFAULT_MR_FSK_MOD_IDX,
|
||||
CONFIG_AT86RF215_DEFAULT_MR_FSK_MORD,
|
||||
CONFIG_AT86RF215_DEFAULT_MR_FSK_FEC);
|
||||
}
|
||||
|
||||
/* set default channel */
|
||||
at86rf215_set_chan(dev, dev->netdev.chan);
|
||||
|
||||
617
drivers/at86rf215/at86rf215_fsk.c
Normal file
617
drivers/at86rf215/at86rf215_fsk.c
Normal file
@ -0,0 +1,617 @@
|
||||
/*
|
||||
* Copyright (C) 2019 ML!PA Consulting GmbH
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_at86rf215
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Configuration of the MR-FSK PHY on the AT86RF215 chip
|
||||
*
|
||||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "at86rf215.h"
|
||||
#include "at86rf215_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/* symbol time is always 20 µs for MR-FSK (table 0, pg. 7) */
|
||||
#define FSK_SYMBOL_TIME_US 20
|
||||
|
||||
/* also used by at86rf215_netdev.c */
|
||||
const uint8_t _at86rf215_fsk_srate_10kHz[] = {
|
||||
[FSK_SRATE_50K] = 5,
|
||||
[FSK_SRATE_100K] = 10,
|
||||
[FSK_SRATE_150K] = 15,
|
||||
[FSK_SRATE_200K] = 20,
|
||||
[FSK_SRATE_300K] = 30,
|
||||
[FSK_SRATE_400K] = 40
|
||||
};
|
||||
|
||||
/* also used by at86rf215_netdev.c */
|
||||
const uint8_t _at86rf215_fsk_channel_spacing_25kHz[] = {
|
||||
[FSK_CHANNEL_SPACING_200K] = 8,
|
||||
[FSK_CHANNEL_SPACING_400K] = 16,
|
||||
};
|
||||
|
||||
/* IEEE Std 802.15.4™-2015
|
||||
* Table 10-10—Channel numbering for SUN PHYs,
|
||||
* index is channel spacing */
|
||||
static const uint16_t _chan_center_freq0_subghz_25khz[] = {
|
||||
[FSK_CHANNEL_SPACING_200K] = 863125U / 25,
|
||||
[FSK_CHANNEL_SPACING_400K] = 863225U / 25
|
||||
};
|
||||
|
||||
/* IEEE Std 802.15.4™-2015
|
||||
* Table 10-10—Channel numbering for SUN PHYs,
|
||||
* index is channel spacing */
|
||||
static const uint16_t _chan_center_freq0_24ghz_25khz[] = {
|
||||
[FSK_CHANNEL_SPACING_200K] = (2400200U - CCF0_24G_OFFSET) / 25,
|
||||
[FSK_CHANNEL_SPACING_400K] = (2400400U - CCF0_24G_OFFSET) / 25
|
||||
};
|
||||
|
||||
/* Table 6-57, index is symbol rate */
|
||||
static const uint8_t _FSKPE_Val[3][6] = {
|
||||
{ 0x02, 0x0E, 0x3E, 0x74, 0x05, 0x13 }, /* FSKPE0 */
|
||||
{ 0x03, 0x0F, 0x3F, 0x7F, 0x3C, 0x29 }, /* FSKPE1 */
|
||||
{ 0xFC, 0xF0, 0xC0, 0x80, 0xC3, 0xC7 } /* FSKPE2 */
|
||||
};
|
||||
|
||||
/* table 6-51: Symbol Rate Settings */
|
||||
static uint8_t _TXDFE_SR(at86rf215_t *dev, uint8_t srate)
|
||||
{
|
||||
const uint8_t version = at86rf215_reg_read(dev, RG_RF_VN);
|
||||
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return version == 1 ? RF_SR_400K : RF_SR_500K;
|
||||
case FSK_SRATE_100K:
|
||||
return version == 1 ? RF_SR_800K : RF_SR_1000K;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
return RF_SR_2000K;
|
||||
case FSK_SRATE_300K:
|
||||
case FSK_SRATE_400K:
|
||||
return RF_SR_4000K;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* table 6-51: Symbol Rate Settings */
|
||||
static uint8_t _RXDFE_SR(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_SR_400K;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_SR_800K;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
return RF_SR_1000K;
|
||||
case FSK_SRATE_300K:
|
||||
case FSK_SRATE_400K:
|
||||
return RF_SR_2000K;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* table 6-53 Recommended Configuration of the Transmitter Frontend */
|
||||
static uint8_t _TXCUTC_PARAMP(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_PARAMP32U;
|
||||
case FSK_SRATE_100K:
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
return RF_PARAMP16U;
|
||||
case FSK_SRATE_300K:
|
||||
case FSK_SRATE_400K:
|
||||
return RF_PARAMP8U;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-53. Recommended Configuration of the Transmitter Frontend (modulation index 0.5) */
|
||||
static uint8_t _TXCUTC_LPFCUT_half(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_FLC80KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_FLC100KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
return RF_FLC160KHZ;
|
||||
case FSK_SRATE_200K:
|
||||
return RF_FLC200KHZ;
|
||||
case FSK_SRATE_300K:
|
||||
return RF_FLC315KHZ;
|
||||
case FSK_SRATE_400K:
|
||||
return RF_FLC400KHZ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-54. Recommended Configuration of the Transmitter Frontend (modulation index 1) */
|
||||
static uint8_t _TXCUTC_LPFCUT_full(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_FLC80KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_FLC160KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
return RF_FLC250KHZ;
|
||||
case FSK_SRATE_200K:
|
||||
return RF_FLC315KHZ;
|
||||
case FSK_SRATE_300K:
|
||||
return RF_FLC500KHZ;
|
||||
case FSK_SRATE_400K:
|
||||
return RF_FLC625KHZ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t _TXCUTC_LPFCUT(uint8_t srate, bool half)
|
||||
{
|
||||
return half ? _TXCUTC_LPFCUT_half(srate) : _TXCUTC_LPFCUT_full(srate);
|
||||
}
|
||||
|
||||
/* Table 6-60. Recommended Configuration values of the sub-1GHz Receiver Frontend (modulation index 1/2) */
|
||||
static uint8_t _RXBWC_BW_subGHz_half(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_BW160KHZ_IF250KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_BW200KHZ_IF250KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
return RF_BW320KHZ_IF500KHZ;
|
||||
case FSK_SRATE_300K:
|
||||
return (RF_BW500KHZ_IF500KHZ | (1 << RXBWC_IFS_SHIFT));
|
||||
case FSK_SRATE_400K:
|
||||
return RF_BW630KHZ_IF1000KHZ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-61. Recommended Configuration values of the 2.4GHz Receiver Frontend (modulation index 1/2) */
|
||||
static uint8_t _RXBWC_BW_2dot4GHz_half(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_BW160KHZ_IF250KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_BW200KHZ_IF250KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
return RF_BW320KHZ_IF500KHZ;
|
||||
case FSK_SRATE_200K:
|
||||
return RF_BW400KHZ_IF500KHZ;
|
||||
case FSK_SRATE_300K:
|
||||
return RF_BW630KHZ_IF1000KHZ;
|
||||
case FSK_SRATE_400K:
|
||||
return RF_BW800KHZ_IF1000KHZ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-62. Recommended Configuration values of the sub-1GHz Receiver Frontend (modulation index 1) */
|
||||
static uint8_t _RXBWC_BW_subGHz_full(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_BW160KHZ_IF250KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_BW320KHZ_IF500KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
return RF_BW400KHZ_IF500KHZ;
|
||||
case FSK_SRATE_200K:
|
||||
return (RF_BW500KHZ_IF500KHZ | (1 << RXBWC_IFS_SHIFT));
|
||||
case FSK_SRATE_300K:
|
||||
return RF_BW630KHZ_IF1000KHZ;
|
||||
case FSK_SRATE_400K:
|
||||
return (RF_BW1000KHZ_IF1000KHZ | (1 << RXBWC_IFS_SHIFT));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-63. Recommended Configuration values of the 2.4 GHz Receiver Frontend (modulation index 1) */
|
||||
static uint8_t _RXBWC_BW_2dot4GHz_full(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return RF_BW200KHZ_IF250KHZ;
|
||||
case FSK_SRATE_100K:
|
||||
return RF_BW400KHZ_IF500KHZ;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
return RF_BW630KHZ_IF1000KHZ;
|
||||
case FSK_SRATE_300K:
|
||||
return RF_BW800KHZ_IF1000KHZ;
|
||||
case FSK_SRATE_400K:
|
||||
return (RF_BW1000KHZ_IF1000KHZ | (1 << RXBWC_IFS_SHIFT));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t _RXBWC_BW(uint8_t srate, bool subGHz, bool half)
|
||||
{
|
||||
if (subGHz) {
|
||||
return half ? _RXBWC_BW_subGHz_half(srate) : _RXBWC_BW_subGHz_full(srate);
|
||||
} else {
|
||||
return half ? _RXBWC_BW_2dot4GHz_half(srate) : _RXBWC_BW_2dot4GHz_full(srate);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _RXDFE_RCUT_half(uint8_t srate, bool subGHz)
|
||||
{
|
||||
if (srate == FSK_SRATE_200K) {
|
||||
return RF_RCUT_FS_BY_5P3;
|
||||
}
|
||||
|
||||
if (srate == FSK_SRATE_400K && !subGHz) {
|
||||
return RF_RCUT_FS_BY_5P3;
|
||||
}
|
||||
|
||||
return RF_RCUT_FS_BY_8;
|
||||
}
|
||||
|
||||
static uint8_t _RXDFE_RCUT_full(uint8_t srate, bool subGHz)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
case FSK_SRATE_100K:
|
||||
case FSK_SRATE_300K:
|
||||
return RF_RCUT_FS_BY_5P3;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_400K:
|
||||
return subGHz ? RF_RCUT_FS_BY_5P3 : RF_RCUT_FS_BY_4;
|
||||
case FSK_SRATE_200K:
|
||||
return subGHz ? RF_RCUT_FS_BY_4 : RF_RCUT_FS_BY_2P6;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table 6-64. Minimum Preamble Length */
|
||||
static uint8_t _FSKPL(uint8_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case FSK_SRATE_50K:
|
||||
return 2;
|
||||
case FSK_SRATE_100K:
|
||||
return 3;
|
||||
case FSK_SRATE_150K:
|
||||
case FSK_SRATE_200K:
|
||||
case FSK_SRATE_300K:
|
||||
return 8;
|
||||
case FSK_SRATE_400K:
|
||||
return 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fsk modulation indices / 8 */
|
||||
static const uint8_t _fsk_mod_idx[] = {
|
||||
3, 4, 6, 8, 10, 12, 14, 16
|
||||
};
|
||||
|
||||
/* FSK modulation scale / 8 */
|
||||
static const uint8_t _fsk_mod_idx_scale[] = {
|
||||
7, 8, 9, 10
|
||||
};
|
||||
|
||||
static void _fsk_mod_idx_get(uint8_t num, uint8_t *idx, uint8_t *scale)
|
||||
{
|
||||
*idx = 0;
|
||||
*scale = 0;
|
||||
|
||||
uint8_t diff = 0xFF;
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(_fsk_mod_idx_scale); ++i) {
|
||||
for (uint8_t j = 0; j < ARRAY_SIZE(_fsk_mod_idx); ++j) {
|
||||
if (abs(num - _fsk_mod_idx_scale[i] * _fsk_mod_idx[j]) < diff) {
|
||||
diff = abs(num - _fsk_mod_idx_scale[i] * _fsk_mod_idx[j]);
|
||||
*idx = j;
|
||||
*scale = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t _RXDFE_RCUT(uint8_t srate, bool subGHz, bool half)
|
||||
{
|
||||
return half ? _RXDFE_RCUT_half(srate, subGHz) : _RXDFE_RCUT_full(srate, subGHz);
|
||||
}
|
||||
|
||||
void at86rf215_FSK_prepare_rx(at86rf215_t *dev)
|
||||
{
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKPLL, dev->fsk_pl);
|
||||
|
||||
/* Preamble detection takes RSSI values into account if the preamble length is less than 8 octets. */
|
||||
if (dev->fsk_pl < 8) {
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKC2, FSKC2_PDTM_MASK);
|
||||
} else {
|
||||
at86rf215_reg_and(dev, dev->BBC->RG_FSKC2, (uint8_t) ~FSKC2_PDTM_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void at86rf215_FSK_prepare_tx(at86rf215_t *dev)
|
||||
{
|
||||
/* send long preamble when TXing */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKPLL, dev->fsk_pl * 8);
|
||||
}
|
||||
|
||||
static void _set_srate(at86rf215_t *dev, uint8_t srate, bool mod_idx_half)
|
||||
{
|
||||
/* Set Receiver Bandwidth: fBW = 160 kHz, fIF = 250 kHz */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_RXBWC, _RXBWC_BW(srate, is_subGHz(dev), mod_idx_half));
|
||||
/* fS = 400 kHz; fCUT = fS/5.333 = 75 kHz */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_RXDFE, _RXDFE_SR(srate)
|
||||
| _RXDFE_RCUT(srate, is_subGHz(dev), mod_idx_half));
|
||||
/* Power Amplifier Ramp Time = 32 µs; fLPCUT = 80 kHz */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_TXCUTC, _TXCUTC_PARAMP(srate)
|
||||
| _TXCUTC_LPFCUT(srate, mod_idx_half));
|
||||
/* fS = 500 kHz; fCUT = fS/2 = 250 kHz */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_TXDFE, _TXDFE_SR(dev, srate)
|
||||
| (mod_idx_half ? RF_RCUT_FS_BY_8 : RF_RCUT_FS_BY_2)
|
||||
| TXDFE_DM_MASK);
|
||||
|
||||
/* configure pre-emphasis */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKPE0, _FSKPE_Val[0][srate]);
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKPE1, _FSKPE_Val[1][srate]);
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKPE2, _FSKPE_Val[2][srate]);
|
||||
|
||||
/* set preamble length in octets */
|
||||
dev->fsk_pl = _FSKPL(srate);
|
||||
|
||||
at86rf215_FSK_prepare_rx(dev);
|
||||
|
||||
/* t_on = t_off = t_min (time to TX minimal preamble length) */
|
||||
uint8_t t_on = 4 * _FSKPL(srate) * 100 / _at86rf215_fsk_srate_10kHz[srate];
|
||||
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKRPCONT, t_on);
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKRPCOFFT, t_on);
|
||||
|
||||
DEBUG("[at86rf215] t_on: %d µs\n", t_on);
|
||||
|
||||
/* set symbol rate, preamble is less than 256 so set high bits 0 */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKC1, srate);
|
||||
}
|
||||
|
||||
static void _set_ack_timeout(at86rf215_t *dev, bool mord4, bool fec)
|
||||
{
|
||||
uint8_t ack_len = AT86RF215_ACK_PSDU_BYTES;
|
||||
|
||||
/* PHR uses same data rate as PSDU */
|
||||
ack_len += 2;
|
||||
|
||||
/* 4-FSK doubles data rate */
|
||||
if (mord4) {
|
||||
ack_len /= 2;
|
||||
}
|
||||
|
||||
/* forward error correction halves data rate */
|
||||
if (fec) {
|
||||
ack_len *= 2;
|
||||
}
|
||||
|
||||
dev->ack_timeout_usec = dev->csma_backoff_period
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US
|
||||
/* long Preamble + SFD; SFD=2 */
|
||||
+ ((dev->fsk_pl * 8 + 2)
|
||||
+ ack_len) * 8 * FSK_SYMBOL_TIME_US;
|
||||
|
||||
DEBUG("[%s] ACK timeout: %"PRIu32" µs\n", "FSK", dev->ack_timeout_usec);
|
||||
}
|
||||
|
||||
static void _set_csma_backoff_period(at86rf215_t *dev)
|
||||
{
|
||||
dev->csma_backoff_period = IEEE802154_CCA_DURATION_IN_SYMBOLS * FSK_SYMBOL_TIME_US
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
|
||||
DEBUG("[%s] CSMA BACKOFF: %"PRIu32" µs\n", "FSK", dev->csma_backoff_period);
|
||||
}
|
||||
|
||||
int at86rf215_configure_FSK(at86rf215_t *dev, uint8_t srate, uint8_t mod_idx, uint8_t mod_order, uint8_t fec)
|
||||
{
|
||||
if (srate > FSK_SRATE_400K) {
|
||||
DEBUG("[%s] invalid symbol rate: %d\n", __func__, srate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bool mod_idx_half = mod_idx <= 32;
|
||||
uint8_t _mod_idx, _mod_idx_scale;
|
||||
_fsk_mod_idx_get(mod_idx, &_mod_idx, &_mod_idx_scale);
|
||||
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
/* disable radio */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_PC, 0);
|
||||
|
||||
_set_srate(dev, srate, mod_idx_half);
|
||||
|
||||
/* set receiver gain target according to data sheet */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_AGCS, 1 << AGCS_TGT_SHIFT);
|
||||
/* enable automatic receiver gain */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_AGCC, AGCC_EN_MASK);
|
||||
|
||||
/* set Bandwidth Time Product, Modulation Index & Modulation Order */
|
||||
/* effective modulation index = MIDXS * MIDX */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKC0, FSK_BT_20
|
||||
| (_mod_idx << FSKC0_MIDX_SHIFT)
|
||||
| (_mod_idx_scale << FSKC0_MIDXS_SHIFT)
|
||||
| mod_order
|
||||
);
|
||||
|
||||
/* enable direct modulation */
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKDM, FSKDM_EN_MASK | FSKDM_PE_MASK);
|
||||
|
||||
/* 16 µs base time */
|
||||
uint8_t fskrpc = 0x5;
|
||||
|
||||
/* Enable / Disable Reduced Power Consumption */
|
||||
if (dev->flags & AT86RF215_OPT_RPC) {
|
||||
fskrpc |= FSKRPC_EN_MASK;
|
||||
}
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKRPC, fskrpc);
|
||||
|
||||
/* set forward error correction */
|
||||
at86rf215_FSK_set_fec(dev, fec);
|
||||
|
||||
at86rf215_FSK_set_channel_spacing(dev, FSK_CHANNEL_SPACING_400K);
|
||||
|
||||
at86rf215_enable_radio(dev, BB_MRFSK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t at86rf215_FSK_get_mod_order(at86rf215_t *dev)
|
||||
{
|
||||
return at86rf215_reg_read(dev, dev->BBC->RG_FSKC0) & FSKC0_MORD_MASK;
|
||||
}
|
||||
|
||||
int at86rf215_FSK_set_mod_order(at86rf215_t *dev, uint8_t mod_order) {
|
||||
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
if (mod_order) {
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKC0, FSK_MORD_4SFK);
|
||||
} else {
|
||||
at86rf215_reg_and(dev, dev->BBC->RG_FSKC0, ~FSK_MORD_4SFK);
|
||||
}
|
||||
|
||||
_set_ack_timeout(dev, mod_order, at86rf215_FSK_get_fec(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t at86rf215_FSK_get_mod_idx(at86rf215_t *dev)
|
||||
{
|
||||
uint8_t fskc0 = at86rf215_reg_read(dev, dev->BBC->RG_FSKC0);
|
||||
uint8_t _mod_idx = (fskc0 & FSKC0_MIDX_MASK) >> FSKC0_MIDX_SHIFT;
|
||||
uint8_t _mod_idx_scale = (fskc0 & FSKC0_MIDXS_MASK) >> FSKC0_MIDXS_SHIFT;
|
||||
|
||||
return _fsk_mod_idx[_mod_idx] * _fsk_mod_idx_scale[_mod_idx_scale];
|
||||
}
|
||||
|
||||
int at86rf215_FSK_set_mod_idx(at86rf215_t *dev, uint8_t mod_idx)
|
||||
{
|
||||
uint8_t _mod_idx, _mod_idx_scale;
|
||||
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
_set_srate(dev, at86rf215_FSK_get_srate(dev), mod_idx <= 32);
|
||||
|
||||
_fsk_mod_idx_get(mod_idx, &_mod_idx, &_mod_idx_scale);
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_FSKC0, FSK_BT_20
|
||||
| (_mod_idx << FSKC0_MIDX_SHIFT)
|
||||
| (_mod_idx_scale << FSKC0_MIDXS_SHIFT)
|
||||
| at86rf215_FSK_get_mod_order(dev)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t at86rf215_FSK_get_srate(at86rf215_t *dev)
|
||||
{
|
||||
return at86rf215_reg_read(dev, dev->BBC->RG_FSKC1) & FSKC1_SRATE_MASK;
|
||||
}
|
||||
|
||||
int at86rf215_FSK_set_srate(at86rf215_t *dev, uint8_t srate)
|
||||
{
|
||||
if (srate > FSK_SRATE_400K) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
_set_srate(dev, srate, at86rf215_FSK_get_mod_idx(dev) <= 32);
|
||||
_set_csma_backoff_period(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int at86rf215_FSK_set_fec(at86rf215_t *dev, uint8_t mode)
|
||||
{
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
switch (mode) {
|
||||
case IEEE802154_FEC_NONE:
|
||||
at86rf215_reg_and(dev, dev->BBC->RG_FSKPHRTX, ~FSKPHRTX_SFD_MASK);
|
||||
break;
|
||||
case IEEE802154_FEC_NRNSC:
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKPHRTX, FSKPHRTX_SFD_MASK);
|
||||
at86rf215_reg_and(dev, dev->BBC->RG_FSKC2, ~FSKC2_FECS_MASK);
|
||||
break;
|
||||
case IEEE802154_FEC_RSC:
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKPHRTX, FSKPHRTX_SFD_MASK);
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKC2, FSKC2_FECS_MASK);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
_set_ack_timeout(dev, mode, at86rf215_FSK_get_mod_order(dev));
|
||||
_set_csma_backoff_period(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t at86rf215_FSK_get_fec(at86rf215_t *dev)
|
||||
{
|
||||
/* SFD0 -> Uncoded IEEE mode */
|
||||
/* SFD1 -> Coded IEEE mode */
|
||||
if (!(at86rf215_reg_read(dev, dev->BBC->RG_FSKPHRTX) & FSKPHRTX_SFD_MASK)) {
|
||||
return IEEE802154_FEC_NONE;
|
||||
}
|
||||
|
||||
if (at86rf215_reg_read(dev, dev->BBC->RG_FSKC2) & FSKC2_FECS_MASK) {
|
||||
return IEEE802154_FEC_RSC;
|
||||
} else {
|
||||
return IEEE802154_FEC_NRNSC;
|
||||
}
|
||||
}
|
||||
|
||||
int at86rf215_FSK_set_channel_spacing(at86rf215_t *dev, uint8_t ch_space)
|
||||
{
|
||||
if (ch_space > FSK_CHANNEL_SPACING_400K) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
at86rf215_await_state_end(dev, RF_STATE_TX);
|
||||
|
||||
/* set channel spacing, same for both sub-GHz & 2.4 GHz */
|
||||
at86rf215_reg_write(dev, dev->RF->RG_CS, _at86rf215_fsk_channel_spacing_25kHz[ch_space]);
|
||||
|
||||
/* set center frequency */
|
||||
if (is_subGHz(dev)) {
|
||||
at86rf215_reg_write16(dev, dev->RF->RG_CCF0L, _chan_center_freq0_subghz_25khz[ch_space]);
|
||||
} else {
|
||||
at86rf215_reg_write16(dev, dev->RF->RG_CCF0L, _chan_center_freq0_24ghz_25khz[ch_space]);
|
||||
}
|
||||
|
||||
DEBUG("CCF0 configured as: %lu kHz\n",
|
||||
25UL * at86rf215_reg_read16(dev, dev->RF->RG_CCF0L) + (is_subGHz(dev) ? 0 : CCF0_24G_OFFSET));
|
||||
|
||||
/* adjust channel spacing */
|
||||
dev->num_chans = is_subGHz(dev) ? 34 / (ch_space + 1) : (416 / (ch_space + 1)) - (ch_space * 2);
|
||||
dev->netdev.chan = at86rf215_chan_valid(dev, dev->netdev.chan);
|
||||
at86rf215_reg_write16(dev, dev->RF->RG_CNL, dev->netdev.chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -212,6 +212,13 @@ void at86rf215_enable_rpc(at86rf215_t *dev)
|
||||
|
||||
/* no Reduced Power mode available for OFDM */
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
if (dev->fsk_pl) {
|
||||
/* MR-FSK */
|
||||
at86rf215_reg_or(dev, dev->BBC->RG_FSKRPC, FSKRPC_EN_MASK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OQPSK
|
||||
{
|
||||
/* MR-O-QPSK */
|
||||
@ -228,6 +235,13 @@ void at86rf215_disable_rpc(at86rf215_t *dev)
|
||||
|
||||
/* no Reduced Power mode available for OFDM */
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
if (dev->fsk_pl) {
|
||||
/* MR-FSK */
|
||||
at86rf215_reg_and(dev, dev->BBC->RG_FSKRPC, ~FSKRPC_EN_MASK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OQPSK
|
||||
{
|
||||
/* MR-O-QPSK */
|
||||
|
||||
@ -67,6 +67,20 @@ static bool _is_busy(at86rf215_t *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t _get_best_match(const uint8_t *array, uint8_t len, uint8_t val)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
uint8_t best = 0xFF;
|
||||
for (uint8_t i = 0; i < len; ++i) {
|
||||
if (abs((int)array[i] - val) < best) {
|
||||
best = abs((int)array[i] - val);
|
||||
res = i;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* executed in the GPIO ISR context */
|
||||
static void _irq_handler(void *arg)
|
||||
{
|
||||
@ -393,7 +407,40 @@ static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len)
|
||||
*((int8_t *)val) = at86rf215_get_phy_mode(dev);
|
||||
res = max_len;
|
||||
break;
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
case NETOPT_MR_FSK_MODULATION_INDEX:
|
||||
assert(max_len >= sizeof(int8_t));
|
||||
*((int8_t *)val) = at86rf215_FSK_get_mod_idx(dev);
|
||||
res = max_len;
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_MODULATION_ORDER:
|
||||
assert(max_len >= sizeof(int8_t));
|
||||
/* 0 -> 2-FSK, 1 -> 4-FSK */
|
||||
*((int8_t *)val) = 2 + 2 * at86rf215_FSK_get_mod_order(dev);
|
||||
res = max_len;
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_SRATE:
|
||||
assert(max_len >= sizeof(uint16_t));
|
||||
/* netopt expects symbol rate in kHz, internally it's stored in 10kHz steps */
|
||||
*((uint16_t *)val) = _at86rf215_fsk_srate_10kHz[at86rf215_FSK_get_srate(dev)]
|
||||
* 10;
|
||||
res = max_len;
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_FEC:
|
||||
assert(max_len >= sizeof(uint8_t));
|
||||
*((uint8_t *)val) = at86rf215_FSK_get_fec(dev);
|
||||
res = max_len;
|
||||
break;
|
||||
|
||||
case NETOPT_CHANNEL_SPACING:
|
||||
assert(max_len >= sizeof(uint16_t));
|
||||
*((uint16_t *)val) = at86rf215_get_channel_spacing(dev);
|
||||
res = max_len;
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
case NETOPT_MR_OFDM_OPTION:
|
||||
assert(max_len >= sizeof(int8_t));
|
||||
@ -601,11 +648,93 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
|
||||
res = sizeof(uint8_t);
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_OFDM */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
case IEEE802154_PHY_MR_FSK:
|
||||
at86rf215_configure_FSK(dev,
|
||||
at86rf215_FSK_get_srate(dev),
|
||||
at86rf215_FSK_get_mod_idx(dev),
|
||||
at86rf215_FSK_get_mod_order(dev),
|
||||
at86rf215_FSK_get_fec(dev));
|
||||
res = sizeof(uint8_t);
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
case NETOPT_MR_FSK_MODULATION_INDEX:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_FSK) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (at86rf215_FSK_set_mod_idx(dev, *(uint8_t *)val) == 0) {
|
||||
res = at86rf215_FSK_get_mod_idx(dev);
|
||||
} else {
|
||||
res = -ERANGE;
|
||||
}
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_MODULATION_ORDER:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_FSK) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (*(uint8_t *)val != 2 && *(uint8_t *)val != 4) {
|
||||
res = -ERANGE;
|
||||
} else {
|
||||
/* 4-FSK -> 1, 2-FSK -> 0 */
|
||||
at86rf215_FSK_set_mod_order(dev, *(uint8_t *)val >> 2);
|
||||
res = sizeof(uint8_t);
|
||||
}
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_SRATE:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_FSK) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* find the closest symbol rate value (in 10 kHz) that matches
|
||||
the requested input (in kHz) */
|
||||
res = _get_best_match(_at86rf215_fsk_srate_10kHz,
|
||||
FSK_SRATE_400K + 1, *(uint16_t *)val / 10);
|
||||
if (at86rf215_FSK_set_srate(dev, res) == 0) {
|
||||
res = 10 * _at86rf215_fsk_srate_10kHz[res];
|
||||
} else {
|
||||
res = -ERANGE;
|
||||
}
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_FEC:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_FSK) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (at86rf215_FSK_set_fec(dev, *(uint8_t *)val) == 0) {
|
||||
res = sizeof(uint8_t);
|
||||
} else {
|
||||
res = -ERANGE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NETOPT_CHANNEL_SPACING:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_FSK) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* find the closest channel spacing value (in 25 kHz) that matches
|
||||
the requested input (in kHz) */
|
||||
res = _get_best_match(_at86rf215_fsk_channel_spacing_25kHz,
|
||||
FSK_CHANNEL_SPACING_400K + 1, *(uint16_t *)val / 25);
|
||||
if (at86rf215_FSK_set_channel_spacing(dev, res) == 0) {
|
||||
res = 25 * _at86rf215_fsk_channel_spacing_25kHz[res];
|
||||
} else {
|
||||
res = -ERANGE;
|
||||
}
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
case NETOPT_MR_OFDM_OPTION:
|
||||
if (at86rf215_get_phy_mode(dev) != IEEE802154_PHY_MR_OFDM) {
|
||||
@ -937,6 +1066,13 @@ static void _isr(netdev_t *netdev)
|
||||
rx_ack_req = 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
/* listen for short preamble in RX */
|
||||
if (bb_irq_mask & BB_IRQ_TXFE && dev->fsk_pl) {
|
||||
at86rf215_FSK_prepare_rx(dev);
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
|
||||
if (dev->flags & AT86RF215_OPT_CCA_PENDING) {
|
||||
|
||||
/* Start ED or handle result */
|
||||
@ -957,6 +1093,13 @@ static void _isr(netdev_t *netdev)
|
||||
/* start transmitting the frame */
|
||||
if (rf_irq_mask & RF_IRQ_TRXRDY) {
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
/* send long preamble in TX */
|
||||
if (dev->fsk_pl) {
|
||||
at86rf215_FSK_prepare_tx(dev);
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
|
||||
/* automatically switch to RX when TX is done */
|
||||
_enable_tx2rx(dev);
|
||||
|
||||
|
||||
@ -314,13 +314,15 @@ static void _set_ack_timeout(at86rf215_t *dev, uint8_t chips, uint8_t mode)
|
||||
|
||||
static inline void _set_csma_backoff_period(at86rf215_t *dev, uint8_t chips)
|
||||
{
|
||||
dev->csma_backoff_period = AT86RF215_BACKOFF_PERIOD_IN_SYMBOLS * _get_symbol_duration_us(chips);
|
||||
dev->csma_backoff_period = _get_cca_duration_syms(chips) * _get_symbol_duration_us(chips)
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
DEBUG("[%s] CSMA BACKOFF: %"PRIu32" µs\n", "O-QPSK", dev->csma_backoff_period);
|
||||
}
|
||||
|
||||
static inline void _set_csma_backoff_period_legacy(at86rf215_t *dev)
|
||||
{
|
||||
dev->csma_backoff_period = AT86RF215_BACKOFF_PERIOD_IN_SYMBOLS * LEGACY_QPSK_SYMBOL_TIME_US;
|
||||
dev->csma_backoff_period = (IEEE802154_ATURNAROUNDTIME_IN_SYMBOLS + IEEE802154_CCA_DURATION_IN_SYMBOLS)
|
||||
* LEGACY_QPSK_SYMBOL_TIME_US;
|
||||
DEBUG("[%s] CSMA BACKOFF: %"PRIu32" µs\n", "legacy O-QPSK", dev->csma_backoff_period);
|
||||
}
|
||||
|
||||
@ -343,6 +345,11 @@ void _end_configure_OQPSK(at86rf215_t *dev)
|
||||
dev->netdev.chan = at86rf215_chan_valid(dev, dev->netdev.chan);
|
||||
at86rf215_reg_write16(dev, dev->RF->RG_CNL, dev->netdev.chan);
|
||||
|
||||
/* disable FSK preamble switching */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
dev->fsk_pl = 0;
|
||||
#endif
|
||||
|
||||
at86rf215_enable_radio(dev, BB_MROQPSK);
|
||||
}
|
||||
|
||||
|
||||
@ -268,13 +268,19 @@ int at86rf215_configure_OFDM(at86rf215_t *dev, uint8_t option, uint8_t scheme)
|
||||
|
||||
at86rf215_reg_write(dev, dev->BBC->RG_OFDMPHRTX, scheme);
|
||||
|
||||
dev->csma_backoff_period = AT86RF215_BACKOFF_PERIOD_IN_SYMBOLS *
|
||||
OFDM_SYMBOL_TIME_US;
|
||||
dev->csma_backoff_period = IEEE802154G_ATURNAROUNDTIME_US
|
||||
+ IEEE802154_CCA_DURATION_IN_SYMBOLS
|
||||
* OFDM_SYMBOL_TIME_US;
|
||||
DEBUG("[%s] CSMA BACKOFF: %" PRIu32 " µs\n", "OFDM",
|
||||
dev->csma_backoff_period);
|
||||
|
||||
_set_ack_timeout(dev, option, scheme);
|
||||
|
||||
/* disable FSK preamble switching */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
dev->fsk_pl = 0;
|
||||
#endif
|
||||
|
||||
at86rf215_enable_radio(dev, BB_MROFDM);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -43,12 +43,6 @@ extern "C" {
|
||||
/** Default energy detect threshold for CSMA (reset value) */
|
||||
#define AT86RF215_EDT_DEFAULT (-84) /* dBm */
|
||||
|
||||
/**
|
||||
* This is used to calculate the csma backoff based on the bitrate.
|
||||
*/
|
||||
/** 20 symbols is the std period length */
|
||||
#define AT86RF215_BACKOFF_PERIOD_IN_SYMBOLS (20U)
|
||||
|
||||
/**
|
||||
* Default Parameters for 802.15.4 retransmissions & CSMA
|
||||
* @{
|
||||
@ -139,6 +133,171 @@ void at86rf215_filter_ack(at86rf215_t *dev, bool on);
|
||||
*/
|
||||
void at86rf215_get_random(at86rf215_t *dev, void *data, size_t len);
|
||||
|
||||
/**
|
||||
* @ingroup drivers_at86rf215
|
||||
* @defgroup drivers_at86rf215_fsk AT86RF215 MR-FSK PHY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Symbol Rates for register values, in 10kHz
|
||||
*/
|
||||
extern const uint8_t _at86rf215_fsk_srate_10kHz[];
|
||||
|
||||
/**
|
||||
* @brief Channel Spacing for register values, in 25kHz
|
||||
*/
|
||||
extern const uint8_t _at86rf215_fsk_channel_spacing_25kHz[];
|
||||
|
||||
/**
|
||||
* @brief Configure the radio to make use of FSK modulation
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] srate symbol rate, possible values: FSK_SRATE_50K … FSK_SRATE_400K
|
||||
* @param[in] mod_idx modulation index, multiplied by 64 (½ -> 32; 1 -> 64)
|
||||
* @param[in] mod_order modulation order, may be FSK_MORD_2SFK or FSK_MORD_4SFK
|
||||
* @param[in] fec forward error correction, may be @ref IEEE802154_FEC_NONE,
|
||||
* @ref IEEE802154_FEC_NRNSC or @ref IEEE802154_FEC_RSC
|
||||
*
|
||||
* @return 0 on success, error otherwise
|
||||
*/
|
||||
int at86rf215_configure_FSK(at86rf215_t *dev, uint8_t srate, uint8_t mod_idx, uint8_t mod_order, uint8_t fec);
|
||||
|
||||
/**
|
||||
* @brief Configure the symbol rate of the FSK modulation
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] srate symbol rate, possible values: FSK_SRATE_50K … FSK_SRATE_400K
|
||||
*/
|
||||
int at86rf215_FSK_set_srate(at86rf215_t *dev, uint8_t srate);
|
||||
|
||||
/**
|
||||
* @brief Get the symbol rate of the FSK modulation
|
||||
*
|
||||
* @param[in] dev device to read from
|
||||
*
|
||||
* @return symbol rate, possible values: FSK_SRATE_50K … FSK_SRATE_400K
|
||||
*/
|
||||
uint8_t at86rf215_FSK_get_srate(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Configure the modulation index of the FSK modulation
|
||||
* The modulation index is a fractional value, it is represented as
|
||||
* fractions of 64.
|
||||
* Not all possible fractional values are configurable by the hardware.
|
||||
* If the fractional can not be mapped to the hardware, the nearest matching
|
||||
* one is chosen.
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] mod_idx modulation index, multiplied by 64 (½ -> 32; 1 -> 64)
|
||||
*
|
||||
* @return 0 on success, failure otherwise
|
||||
*/
|
||||
int at86rf215_FSK_set_mod_idx(at86rf215_t *dev, uint8_t mod_idx);
|
||||
|
||||
/**
|
||||
* @brief Get the current modulation index of the FSK modulation
|
||||
* The modulation index is a fractional value, it is represented as
|
||||
* fractions of 64.
|
||||
*
|
||||
* @param[in] dev device to read from
|
||||
*
|
||||
* @return the current modulation index, multiplied by 64
|
||||
*/
|
||||
uint8_t at86rf215_FSK_get_mod_idx(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Configure the Forward Error Correction (coding) scheme for FSK modulation.
|
||||
* Supported values are:
|
||||
* - no error correction
|
||||
* - non-recursive and non-systematic code (NRNSC)
|
||||
* - recursive and systematic code (RSC)
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] mode forward error correction, may be @ref IEEE802154_FEC_NONE,
|
||||
* @ref IEEE802154_FEC_NRNSC or @ref IEEE802154_FEC_RSC
|
||||
*
|
||||
* @return 0 on success, failure otherwise
|
||||
*/
|
||||
int at86rf215_FSK_set_fec(at86rf215_t *dev, uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get the Forward Error Correction (coding) scheme for FSK modulation.
|
||||
* Supported values are:
|
||||
* - no error correction
|
||||
* - non-recursive and non-systematic code (NRNSC)
|
||||
* - recursive and systematic code (RSC)
|
||||
*
|
||||
* @param[in] dev device to read from
|
||||
*
|
||||
* @return current coding scheme, may be @ref IEEE802154_FEC_NONE,
|
||||
* @ref IEEE802154_FEC_NRNSC or @ref IEEE802154_FEC_RSC
|
||||
*/
|
||||
uint8_t at86rf215_FSK_get_fec(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Configure the channel spacing for the FSK modulation
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] ch_space channel spacing, possible values: FSK_CHANNEL_SPACING_200K … _400K
|
||||
*
|
||||
* @return 0 on success, failure otherwise
|
||||
*/
|
||||
int at86rf215_FSK_set_channel_spacing(at86rf215_t *dev, uint8_t ch_space);
|
||||
|
||||
/**
|
||||
* @brief Get the configured channel spacing
|
||||
*
|
||||
* @param[in] dev device to read from
|
||||
*
|
||||
* @return channel spacing in kHz
|
||||
*/
|
||||
uint16_t at86rf215_get_channel_spacing(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Configure the FSK modulation order.
|
||||
* You can choose between 2-level and 4-level FSK
|
||||
*
|
||||
* @param[in] dev device to configure
|
||||
* @param[in] mod_order modulation order, may be FSK_MORD_2SFK or FSK_MORD_4SFK
|
||||
*
|
||||
* @return 0 on success, failure otherwise
|
||||
*/
|
||||
int at86rf215_FSK_set_mod_order(at86rf215_t *dev, uint8_t mod_order);
|
||||
|
||||
/**
|
||||
* @brief Get the current FSK modulation order.
|
||||
* You can choose between 2-level and 4-level FSK
|
||||
*
|
||||
* @param[in] dev device to read from
|
||||
*
|
||||
* @return modulation order, may be FSK_MORD_2SFK or FSK_MORD_4SFK
|
||||
*/
|
||||
uint8_t at86rf215_FSK_get_mod_order(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief The FSK premable length needs to be switched between RX and TX
|
||||
* This function takes care of putting FSK into RX mode.
|
||||
*
|
||||
* @param[in] dev device that is entering RX mode
|
||||
*/
|
||||
void at86rf215_FSK_prepare_rx(at86rf215_t *dev);
|
||||
|
||||
/**
|
||||
* @brief The FSK premable length needs to be switched between RX and TX
|
||||
* This function takes care of putting FSK into TX mode.
|
||||
*
|
||||
* @param[in] dev device that is entering TX mode
|
||||
*/
|
||||
void at86rf215_FSK_prepare_tx(at86rf215_t *dev);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @ingroup drivers_at86rf215
|
||||
* @defgroup drivers_at86rf215_ofdm AT86RF215 MR-OFDM PHY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configure the radio to make use of OFDM modulation.
|
||||
* There are 4 OFDM options, each with a different number of active tones.
|
||||
@ -190,6 +349,8 @@ int at86rf215_OFDM_set_option(at86rf215_t *dev, uint8_t option);
|
||||
*/
|
||||
uint8_t at86rf215_OFDM_get_option(at86rf215_t *dev);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @ingroup drivers_at86rf215
|
||||
* @defgroup drivers_at86rf215_oqpsk AT86RF215 MR-O-QPSK PHY
|
||||
|
||||
@ -196,6 +196,42 @@ enum {
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Default MR-FSK Symbol Rate
|
||||
* @{
|
||||
*/
|
||||
#ifndef CONFIG_AT86RF215_DEFAULT_MR_FSK_SRATE
|
||||
#define CONFIG_AT86RF215_DEFAULT_MR_FSK_SRATE FSK_SRATE_200K
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Default MR-FSK Modulation Index, fraction of 64
|
||||
* @{
|
||||
*/
|
||||
#ifndef CONFIG_AT86RF215_DEFAULT_MR_FSK_MOD_IDX
|
||||
#define CONFIG_AT86RF215_DEFAULT_MR_FSK_MOD_IDX (64)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Default MR-FSK Modulation Order
|
||||
* @{
|
||||
*/
|
||||
#ifndef CONFIG_AT86RF215_DEFAULT_MR_FSK_MORD
|
||||
#define CONFIG_AT86RF215_DEFAULT_MR_FSK_MORD FSK_MORD_4SFK
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Default MR-FSK Forward Error Correction Scheme
|
||||
* @{
|
||||
*/
|
||||
#ifndef CONFIG_AT86RF215_DEFAULT_MR_FSK_FEC
|
||||
#define CONFIG_AT86RF215_DEFAULT_MR_FSK_FEC IEEE802154_FEC_NONE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Default TX power (0dBm)
|
||||
*/
|
||||
@ -290,6 +326,9 @@ typedef struct at86rf215 {
|
||||
uint8_t retries; /**< retries left */
|
||||
uint8_t csma_retries_max; /**< number of retries until channel is clear */
|
||||
uint8_t csma_retries; /**< CSMA retries left */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
uint8_t fsk_pl; /**< FSK Preamble Length */
|
||||
#endif
|
||||
uint8_t csma_minbe; /**< CSMA minimum backoff exponent */
|
||||
uint8_t csma_maxbe; /**< CSMA maximum backoff exponent */
|
||||
int8_t csma_ed; /**< CSMA energy detect threshold */
|
||||
|
||||
@ -126,7 +126,22 @@ extern "C" {
|
||||
*
|
||||
* 802.15.4g, Table 70 (p. 43)
|
||||
*/
|
||||
#define IEEE802154G_ATURNAROUNDTIME_US (1 * US_PER_MS)
|
||||
#define IEEE802154G_ATURNAROUNDTIME_US (1 * US_PER_MS)
|
||||
|
||||
/**
|
||||
* IEEE Std 802.15.4-2020
|
||||
* Table 11-1—PHY constants: The value is 12 for all other PHYs.
|
||||
*/
|
||||
#define IEEE802154_ATURNAROUNDTIME_IN_SYMBOLS (12)
|
||||
|
||||
/**
|
||||
* IEEE Std 802.15.4-2020
|
||||
* Table 11-1—PHY constants: For all other PHYs¹, the duration of
|
||||
* 8 symbol periods.
|
||||
*
|
||||
* [1] all but MR-O-QPSK
|
||||
*/
|
||||
#define IEEE802154_CCA_DURATION_IN_SYMBOLS (8)
|
||||
|
||||
/**
|
||||
* @brief 802.15.4 PHY modes
|
||||
|
||||
@ -689,6 +689,26 @@ typedef enum {
|
||||
*/
|
||||
NETOPT_MR_OFDM_MCS,
|
||||
|
||||
/**
|
||||
* @brief (uint8_t) MR-FSK PHY Modulation Index (x 64)
|
||||
*/
|
||||
NETOPT_MR_FSK_MODULATION_INDEX,
|
||||
|
||||
/**
|
||||
* @brief (uint8_t) MR-FSK Modulation Order
|
||||
*/
|
||||
NETOPT_MR_FSK_MODULATION_ORDER,
|
||||
|
||||
/**
|
||||
* @brief (uint8_t) MR-FSK PHY Symbol Rate (kHz)
|
||||
*/
|
||||
NETOPT_MR_FSK_SRATE,
|
||||
|
||||
/**
|
||||
* @brief (uint8_t) MR-FSK PHY Forward Error Correction
|
||||
*/
|
||||
NETOPT_MR_FSK_FEC,
|
||||
|
||||
/**
|
||||
* @brief (uint8_t) PHY Channel Spacing (kHz)
|
||||
*/
|
||||
|
||||
@ -113,6 +113,10 @@ static const char *_netopt_strmap[] = {
|
||||
[NETOPT_MR_OQPSK_RATE] = "NETOPT_MR-O-QPSK_RATE",
|
||||
[NETOPT_MR_OFDM_OPTION] = "NETOPT_MR-OFDM_OPTION",
|
||||
[NETOPT_MR_OFDM_MCS] = "NETOPT_MR-OFDM_MCS",
|
||||
[NETOPT_MR_FSK_MODULATION_INDEX] = "NETOPT_MR-FSK_MODULATION_INDEX",
|
||||
[NETOPT_MR_FSK_MODULATION_ORDER] = "NETOPT_MR-FSK_MODULATION_ORDER",
|
||||
[NETOPT_MR_FSK_SRATE] = "NETOPT_MR-FSK_SRATE",
|
||||
[NETOPT_MR_FSK_FEC] = "NETOPT_MR-FSK_FEC",
|
||||
[NETOPT_CHANNEL_SPACING] = "NETOPT_CHANNEL_SPACING",
|
||||
[NETOPT_SYNCWORD] = "NETOPT_SYNCWORD",
|
||||
[NETOPT_RANDOM] = "NETOPT_RANDOM",
|
||||
|
||||
@ -97,6 +97,42 @@ static void str_toupper(char *str)
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((unused))
|
||||
static uint8_t gcd(uint8_t a, uint8_t b)
|
||||
{
|
||||
if (a == 0 || b == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t r = a % b;
|
||||
a = b;
|
||||
b = r;
|
||||
} while (b);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
__attribute__ ((unused))
|
||||
static void frac_short(uint8_t *a, uint8_t *b)
|
||||
{
|
||||
uint8_t d = gcd(*a, *b);
|
||||
|
||||
if (d == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
*a /= d;
|
||||
*b /= d;
|
||||
}
|
||||
|
||||
__attribute__ ((unused))
|
||||
static void frac_extend(uint8_t *a, uint8_t *b, uint8_t base)
|
||||
{
|
||||
*a *= base / *b;
|
||||
*b = base;
|
||||
}
|
||||
|
||||
#ifdef MODULE_NETSTATS
|
||||
static const char *_netstats_module_to_str(uint8_t module)
|
||||
{
|
||||
@ -195,6 +231,13 @@ static void _set_usage(char *cmd_name)
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
" * \"option\" - OFDM option\n"
|
||||
" * \"scheme\" - OFDM modulation & coding scheme\n"
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
" * \"modulation_index\" - FSK modulation index\n"
|
||||
" * \"modulation_order\" - FSK modulation order\n"
|
||||
" * \"symbol_rate\" - FSK symbol rate\n"
|
||||
" * \"fec\" - FSK forward error correction\n"
|
||||
" * \"channel_spacing\" - channel spacing\n"
|
||||
#endif
|
||||
" * \"power\" - TX power in dBm\n"
|
||||
" * \"retrans\" - max. number of retransmissions\n"
|
||||
@ -362,6 +405,29 @@ static void _print_netopt(netopt_t opt)
|
||||
break;
|
||||
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_OFDM */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
|
||||
case NETOPT_MR_FSK_MODULATION_INDEX:
|
||||
printf("FSK modulation index");
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_MODULATION_ORDER:
|
||||
printf("FSK modulation order");
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_SRATE:
|
||||
printf("FSK symbol rate");
|
||||
break;
|
||||
|
||||
case NETOPT_MR_FSK_FEC:
|
||||
printf("FSK Forward Error Correction");
|
||||
break;
|
||||
|
||||
case NETOPT_CHANNEL_SPACING:
|
||||
printf("Channel Spacing");
|
||||
break;
|
||||
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
|
||||
case NETOPT_CHECKSUM:
|
||||
printf("checksum");
|
||||
@ -442,6 +508,14 @@ static const char *_netopt_ofdm_mcs_str[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
static const char *_netopt_fec_str[] = {
|
||||
[IEEE802154_FEC_NONE] = "none",
|
||||
[IEEE802154_FEC_NRNSC] = "NRNSC",
|
||||
[IEEE802154_FEC_RSC] = "RSC"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* for some lines threshold might just be 0, so we can't use _LINE_THRESHOLD
|
||||
* here */
|
||||
static unsigned _newline(unsigned threshold, unsigned line_thresh)
|
||||
@ -628,6 +702,38 @@ static void _netif_list(netif_t *iface)
|
||||
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_OFDM */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
case IEEE802154_PHY_MR_FSK:
|
||||
printf("\n ");
|
||||
res = netif_get_opt(iface, NETOPT_MR_FSK_MODULATION_INDEX, 0, &u8, sizeof(u8));
|
||||
if (res >= 0) {
|
||||
hwaddr[0] = 64; /* convenient temp var */
|
||||
frac_short(&u8, hwaddr);
|
||||
if (hwaddr[0] == 1) {
|
||||
printf(" modulation index: %u ", u8);
|
||||
} else {
|
||||
printf(" modulation index: %u/%u ", u8, hwaddr[0]);
|
||||
}
|
||||
}
|
||||
res = netif_get_opt(iface, NETOPT_MR_FSK_MODULATION_ORDER, 0, &u8, sizeof(u8));
|
||||
if (res >= 0) {
|
||||
printf(" %u-FSK ", u8);
|
||||
}
|
||||
res = netif_get_opt(iface, NETOPT_MR_FSK_SRATE, 0, &u16, sizeof(u16));
|
||||
if (res >= 0) {
|
||||
printf(" symbol rate: %u kHz ", u16);
|
||||
}
|
||||
res = netif_get_opt(iface, NETOPT_MR_FSK_FEC, 0, &u8, sizeof(u8));
|
||||
if (res >= 0) {
|
||||
printf(" FEC: %s ", _netopt_fec_str[u8]);
|
||||
}
|
||||
res = netif_get_opt(iface, NETOPT_CHANNEL_SPACING, 0, &u16, sizeof(u16));
|
||||
if (res >= 0) {
|
||||
printf(" BW: %ukHz ", u16);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
}
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154 */
|
||||
@ -921,6 +1027,57 @@ static int _netif_set_coding_rate(netif_t *iface, char *value)
|
||||
}
|
||||
#endif /* MODULE_GNRC_NETIF_CMD_LORA */
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
static int _netif_set_fsk_fec(netif_t *iface, char *value)
|
||||
{
|
||||
/* ignore case */
|
||||
str_toupper(value);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(_netopt_fec_str); ++i) {
|
||||
|
||||
if (strcmp(value, _netopt_fec_str[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (netif_set_opt(iface, NETOPT_MR_FSK_FEC, 0, &i, sizeof(uint8_t)) < 0) {
|
||||
printf("error: unable to set forward error correction to %s\n", value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("success: set forward error correction to %s\n", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
puts("usage: ifconfig <if_id> set fec [none|NRNSC|RSC]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _netif_set_fsk_modulation_index(netif_t *iface, char *value)
|
||||
{
|
||||
uint8_t a, b;
|
||||
char* frac = strchr(value, '/');
|
||||
if (frac) {
|
||||
*frac = 0;
|
||||
b = atoi(frac + 1);
|
||||
} else {
|
||||
b = 1;
|
||||
}
|
||||
a = atoi(value);
|
||||
|
||||
frac_extend(&a, &b, 64);
|
||||
|
||||
int res = netif_set_opt(iface, NETOPT_MR_FSK_MODULATION_INDEX, 0, &a, sizeof(uint8_t));
|
||||
if (res < 0) {
|
||||
printf("error: unable to set modulation index to %d/%d\n", a, b);
|
||||
return 1;
|
||||
} else {
|
||||
printf("success: set modulation index to %d/%d\n", res, b);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MULTIMODE
|
||||
static int _netif_set_ieee802154_phy_mode(netif_t *iface, char *value)
|
||||
{
|
||||
@ -1359,6 +1516,23 @@ static int _netif_set(char *cmd_name, netif_t *iface, char *key, char *value)
|
||||
return _netif_set_u8(iface, NETOPT_MR_OFDM_MCS, 0, value);
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_OFDM */
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
else if ((strcmp("modulation_index", key) == 0) || (strcmp("midx", key) == 0)) {
|
||||
return _netif_set_fsk_modulation_index(iface, value);
|
||||
}
|
||||
else if ((strcmp("modulation_order", key) == 0) || (strcmp("mord", key) == 0)) {
|
||||
return _netif_set_u8(iface, NETOPT_MR_FSK_MODULATION_ORDER, 0, value);
|
||||
}
|
||||
else if ((strcmp("symbol_rate", key) == 0) || (strcmp("srate", key) == 0)) {
|
||||
return _netif_set_u16(iface, NETOPT_MR_FSK_SRATE, 0, value);
|
||||
}
|
||||
else if ((strcmp("forward_error_correction", key) == 0) || (strcmp("fec", key) == 0)) {
|
||||
return _netif_set_fsk_fec(iface, value);
|
||||
}
|
||||
else if ((strcmp("channel_spacing", key) == 0) || (strcmp("bw", key) == 0)) {
|
||||
return _netif_set_u16(iface, NETOPT_CHANNEL_SPACING, 0, value);
|
||||
}
|
||||
#endif /* MODULE_NETDEV_IEEE802154_MR_FSK */
|
||||
else if ((strcmp("channel", key) == 0) || (strcmp("chan", key) == 0)) {
|
||||
return _netif_set_u16(iface, NETOPT_CHANNEL, 0, value);
|
||||
}
|
||||
|
||||
@ -5,8 +5,10 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega1284p \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
mega-xplained \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user