mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-15 01:23:49 +01:00
Merge pull request #19668 from benpicco/ieee802154_symbol_time_on_demand
ieee802154/submac: calculate symbol time on demand
This commit is contained in:
commit
f67055c3b2
@ -139,13 +139,13 @@ void ieee802154_submac_bh_request(ieee802154_submac_t *submac)
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_ISR);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac, uint16_t us)
|
||||
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
|
||||
ztimer_set(ZTIMER_USEC, &netdev_submac->ack_timer, us);
|
||||
ztimer_set(ZTIMER_USEC, &netdev_submac->ack_timer, submac->ack_timeout_us);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac)
|
||||
|
||||
@ -25,8 +25,9 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "net/eui64.h"
|
||||
#include "modules.h"
|
||||
#include "net/eui64.h"
|
||||
#include "time_units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -119,6 +120,18 @@ extern "C" {
|
||||
*/
|
||||
#define IEEE802154_ACK_TIMEOUT_SYMS (54)
|
||||
|
||||
/**
|
||||
* @brief Symbol time for IEEE 802.15.4 MR-OFDM in µs
|
||||
*/
|
||||
#define IEEE802154_MR_OFDM_SYMBOL_TIME_US (120)
|
||||
|
||||
/**
|
||||
* @brief Symbol time for IEEE 802.15.4 MR-FSK in µs
|
||||
*
|
||||
* symbol time is always 20 µs for MR-FSK (table 0, pg. 7)
|
||||
*/
|
||||
#define IEEE802154_MR_FSK_SYMBOL_TIME_US (20)
|
||||
|
||||
/**
|
||||
* @brief value of measured power when RSSI is zero.
|
||||
*
|
||||
@ -176,17 +189,67 @@ typedef enum {
|
||||
IEEE802154_PHY_OQPSK, /**< Offset Quadrature Phase-Shift Keying */
|
||||
IEEE802154_PHY_MR_OQPSK, /**< Multi-Rate Offset Quadrature Phase-Shift Keying */
|
||||
IEEE802154_PHY_MR_OFDM, /**< Multi-Rate Orthogonal Frequency-Division Multiplexing */
|
||||
IEEE802154_PHY_MR_FSK /**< Multi-Rate Frequency Shift Keying */
|
||||
IEEE802154_PHY_MR_FSK, /**< Multi-Rate Frequency Shift Keying */
|
||||
|
||||
IEEE802154_PHY_NO_OP, /**< don't change PHY configuration */
|
||||
} ieee802154_phy_mode_t;
|
||||
|
||||
/**
|
||||
* @brief 802.15.4 forward error correction schemes
|
||||
*/
|
||||
enum {
|
||||
typedef enum {
|
||||
IEEE802154_FEC_NONE, /**< no forward error correction */
|
||||
IEEE802154_FEC_NRNSC, /**< non-recursive and non-systematic code */
|
||||
IEEE802154_FEC_RSC /**< recursive and systematic code */
|
||||
};
|
||||
} ieee802154_mr_fsk_fec_t;
|
||||
|
||||
/**
|
||||
* @brief 802.15.4 MR-FSK symbol rates
|
||||
*/
|
||||
typedef enum {
|
||||
IEEE802154_MR_FSK_SRATE_50K, /**< 50k Symbols/s */
|
||||
IEEE802154_MR_FSK_SRATE_100K, /**< 100k Symbols/s */
|
||||
IEEE802154_MR_FSK_SRATE_150K, /**< 150k Symbols/s */
|
||||
IEEE802154_MR_FSK_SRATE_200K, /**< 200k Symbols/s */
|
||||
IEEE802154_MR_FSK_SRATE_300K, /**< 300k Symbols/s */
|
||||
IEEE802154_MR_FSK_SRATE_400K, /**< 400k Symbols/s */
|
||||
} ieee802154_mr_fsk_srate_t;
|
||||
|
||||
/**
|
||||
* @brief 802.15.4 MR-OQPSK chip rates
|
||||
*/
|
||||
typedef enum {
|
||||
IEEE802154_MR_OQPSK_CHIPS_100, /**< 100 kChip/s */
|
||||
IEEE802154_MR_OQPSK_CHIPS_200, /**< 200 kChip/s */
|
||||
IEEE802154_MR_OQPSK_CHIPS_1000, /**< 1000 kChip/s */
|
||||
IEEE802154_MR_OQPSK_CHIPS_2000, /**< 2000 kChip/s */
|
||||
} ieee802154_mr_oqpsk_chips_t;
|
||||
|
||||
/**
|
||||
* @brief Get the minimum preamble length for a given symbol rate
|
||||
*
|
||||
* From IEEE 802.15.4g Table 6-64
|
||||
*
|
||||
* @param[in] srate symbol rate
|
||||
* @return preamble length in bytes
|
||||
*/
|
||||
static inline uint8_t ieee802154_mr_fsk_plen(ieee802154_mr_fsk_srate_t srate)
|
||||
{
|
||||
switch (srate) {
|
||||
case IEEE802154_MR_FSK_SRATE_50K:
|
||||
return 2;
|
||||
case IEEE802154_MR_FSK_SRATE_100K:
|
||||
return 3;
|
||||
case IEEE802154_MR_FSK_SRATE_150K:
|
||||
case IEEE802154_MR_FSK_SRATE_200K:
|
||||
case IEEE802154_MR_FSK_SRATE_300K:
|
||||
return 8;
|
||||
case IEEE802154_MR_FSK_SRATE_400K:
|
||||
return 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Special address definitions
|
||||
@ -256,6 +319,62 @@ extern const uint8_t ieee802154_addr_bcast[IEEE802154_ADDR_BCAST_LEN];
|
||||
#define CONFIG_IEEE802154_DEFAULT_SUBGHZ_PAGE (2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-OQPSK default chip rate
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_OQPSK_DEFAULT_CHIPS
|
||||
#define CONFIG_IEEE802154_MR_OQPSK_DEFAULT_CHIPS IEEE802154_MR_OQPSK_CHIPS_1000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-OQPSK default rate mode
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_OQPSK_DEFAULT_RATE
|
||||
#define CONFIG_IEEE802154_MR_OQPSK_DEFAULT_RATE (2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-OFDM default modulation option
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_OFDM_DEFAULT_OPTION
|
||||
#define CONFIG_IEEE802154_MR_OFDM_DEFAULT_OPTION (2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-OFDM default Modulation & Coding Scheme
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_OFDM_DEFAULT_SCHEME
|
||||
#define CONFIG_IEEE802154_MR_OFDM_DEFAULT_SCHEME (2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-FSK default symbol rate
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_FSK_DEFAULT_SRATE
|
||||
#define CONFIG_IEEE802154_MR_FSK_DEFAULT_SRATE IEEE802154_MR_FSK_SRATE_200K
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-FSK default modulation index, fraction of 64
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_IDX
|
||||
#define CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_IDX (64U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-FSK default modulation order
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_ORD
|
||||
#define CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_ORD (2U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 MR-FSK default error correction mode
|
||||
*/
|
||||
#ifndef CONFIG_IEEE802154_MR_FSK_DEFAULT_FEC
|
||||
#define CONFIG_IEEE802154_MR_FSK_DEFAULT_FEC IEEE802154_FEC_NONE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IEEE802.15.4 default PANID
|
||||
*/
|
||||
|
||||
@ -459,6 +459,35 @@ typedef struct {
|
||||
int8_t pow; /**< TX power in dBm */
|
||||
} ieee802154_phy_conf_t;
|
||||
|
||||
/**
|
||||
* @brief extension for IEEE 802.15.4g MR-OQPSK PHY
|
||||
*/
|
||||
typedef struct {
|
||||
ieee802154_phy_conf_t super; /**< common settings */
|
||||
ieee802154_mr_oqpsk_chips_t chips; /**< chip rate */
|
||||
uint8_t rate_mode; /**< rate mode */
|
||||
} ieee802154_mr_oqpsk_conf_t;
|
||||
|
||||
/**
|
||||
* @brief extension for IEEE 802.15.4g MR-ODFM PHY
|
||||
*/
|
||||
typedef struct {
|
||||
ieee802154_phy_conf_t super; /**< common settings */
|
||||
uint8_t option; /**< OFDM Option */
|
||||
uint8_t scheme; /**< Modulation & Coding Scheme */
|
||||
} ieee802154_mr_ofdm_conf_t;
|
||||
|
||||
/**
|
||||
* @brief extension for IEEE 802.15.4g MR-FSK PHY
|
||||
*/
|
||||
typedef struct {
|
||||
ieee802154_phy_conf_t super; /**< common settings */
|
||||
ieee802154_mr_fsk_srate_t srate; /**< symbol rate */
|
||||
uint8_t mod_ord; /**< modulation order, 2 or 4 */
|
||||
uint8_t mod_idx; /**< modulation index */
|
||||
ieee802154_mr_fsk_fec_t fec; /**< forward error correction */
|
||||
} ieee802154_mr_fsk_conf_t;
|
||||
|
||||
/**
|
||||
* @brief IEEE 802.15.4 radio operations
|
||||
*/
|
||||
|
||||
@ -195,6 +195,8 @@ struct ieee802154_submac {
|
||||
const ieee802154_submac_cb_t *cb; /**< pointer to the SubMAC callbacks */
|
||||
ieee802154_csma_be_t be; /**< CSMA-CA backoff exponent params */
|
||||
bool wait_for_ack; /**< SubMAC is waiting for an ACK frame */
|
||||
uint16_t ack_timeout_us; /**< ACK timeout in µs */
|
||||
uint16_t csma_backoff_us; /**< CSMA sender backoff period in µs */
|
||||
uint16_t panid; /**< IEEE 802.15.4 PAN ID */
|
||||
uint16_t channel_num; /**< IEEE 802.15.4 channel number */
|
||||
uint8_t channel_page; /**< IEEE 802.15.4 channel page */
|
||||
@ -310,9 +312,7 @@ static inline ieee802154_phy_mode_t ieee802154_get_phy_mode(
|
||||
* @brief Set IEEE 802.15.4 PHY configuration (channel, TX power)
|
||||
*
|
||||
* @param[in] submac pointer to the SubMAC descriptor
|
||||
* @param[in] channel_num channel number
|
||||
* @param[in] channel_page channel page
|
||||
* @param[in] tx_pow transmission power (in dBm)
|
||||
* @param[in] conf pointer to the PHY configuration
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -ENOTSUP if the PHY settings are not supported
|
||||
@ -321,8 +321,7 @@ static inline ieee802154_phy_mode_t ieee802154_get_phy_mode(
|
||||
* @ref ieee802154_submac_cb_t::tx_done
|
||||
* @return negative errno on error
|
||||
*/
|
||||
int ieee802154_set_phy_conf(ieee802154_submac_t *submac, uint16_t channel_num,
|
||||
uint8_t channel_page, int8_t tx_pow);
|
||||
int ieee802154_set_phy_conf(ieee802154_submac_t *submac, const ieee802154_phy_conf_t *conf);
|
||||
|
||||
/**
|
||||
* @brief Set IEEE 802.15.4 channel number
|
||||
@ -342,8 +341,14 @@ int ieee802154_set_phy_conf(ieee802154_submac_t *submac, uint16_t channel_num,
|
||||
static inline int ieee802154_set_channel_number(ieee802154_submac_t *submac,
|
||||
uint16_t channel_num)
|
||||
{
|
||||
return ieee802154_set_phy_conf(submac, channel_num, submac->channel_page,
|
||||
submac->tx_pow);
|
||||
const ieee802154_phy_conf_t conf = {
|
||||
.phy_mode = IEEE802154_PHY_NO_OP,
|
||||
.channel = channel_num,
|
||||
.page = submac->channel_page,
|
||||
.pow = submac->tx_pow,
|
||||
};
|
||||
|
||||
return ieee802154_set_phy_conf(submac, &conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,8 +369,14 @@ static inline int ieee802154_set_channel_number(ieee802154_submac_t *submac,
|
||||
static inline int ieee802154_set_channel_page(ieee802154_submac_t *submac,
|
||||
uint16_t channel_page)
|
||||
{
|
||||
return ieee802154_set_phy_conf(submac, submac->channel_num, channel_page,
|
||||
submac->tx_pow);
|
||||
const ieee802154_phy_conf_t conf = {
|
||||
.phy_mode = IEEE802154_PHY_NO_OP,
|
||||
.channel = submac->channel_num,
|
||||
.page = channel_page,
|
||||
.pow = submac->tx_pow,
|
||||
};
|
||||
|
||||
return ieee802154_set_phy_conf(submac, &conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -386,8 +397,14 @@ static inline int ieee802154_set_channel_page(ieee802154_submac_t *submac,
|
||||
static inline int ieee802154_set_tx_power(ieee802154_submac_t *submac,
|
||||
int8_t tx_pow)
|
||||
{
|
||||
return ieee802154_set_phy_conf(submac, submac->channel_num,
|
||||
submac->channel_page, tx_pow);
|
||||
const ieee802154_phy_conf_t conf = {
|
||||
.phy_mode = IEEE802154_PHY_NO_OP,
|
||||
.channel = submac->channel_num,
|
||||
.page = submac->channel_page,
|
||||
.pow = tx_pow,
|
||||
};
|
||||
|
||||
return ieee802154_set_phy_conf(submac, &conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,10 +518,8 @@ int ieee802154_submac_init(ieee802154_submac_t *submac, const network_uint16_t *
|
||||
* @note This function should be implemented by the user of the SubMAC.
|
||||
*
|
||||
* @param[in] submac pointer to the SubMAC descriptor
|
||||
* @param[in] us microseconds until the ACK timeout timer is fired
|
||||
*/
|
||||
extern void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac,
|
||||
uint16_t us);
|
||||
extern void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac);
|
||||
|
||||
/**
|
||||
* @brief Cancel the ACK timeout timer
|
||||
|
||||
@ -227,7 +227,7 @@ static ieee802154_fsm_state_t _fsm_state_prepare(ieee802154_submac_t *submac,
|
||||
if (!_does_handle_csma(dev)) {
|
||||
/* delay for an adequate random backoff period */
|
||||
uint32_t bp = (random_uint32() & submac->backoff_mask) *
|
||||
CSMA_SENDER_BACKOFF_PERIOD_UNIT_US;
|
||||
submac->csma_backoff_us;
|
||||
|
||||
ztimer_sleep(ZTIMER_USEC, bp);
|
||||
/* Prepare for next iteration */
|
||||
@ -282,7 +282,7 @@ static ieee802154_fsm_state_t _fsm_state_tx_process_tx_done(ieee802154_submac_t
|
||||
assert (res >= 0);
|
||||
|
||||
/* Handle ACK reception */
|
||||
ieee802154_submac_ack_timer_set(submac, ACK_TIMEOUT_US);
|
||||
ieee802154_submac_ack_timer_set(submac);
|
||||
return IEEE802154_FSM_STATE_WAIT_FOR_ACK;
|
||||
}
|
||||
break;
|
||||
@ -431,6 +431,209 @@ int ieee802154_send(ieee802154_submac_t *submac, const iolist_t *iolist)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* MR-OQPSK timing calculations
|
||||
*
|
||||
* The standard unfortunately does not list the formula, instead it has to be pieced together
|
||||
* from scattered information and tables in the IEEE 802.15.4 document - may contain errors.
|
||||
*/
|
||||
|
||||
static uint8_t _mr_oqpsk_spreading(uint8_t chips, uint8_t mode)
|
||||
{
|
||||
if (mode == 4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t spread = 1 << (3 - mode);
|
||||
|
||||
if (chips == IEEE802154_MR_OQPSK_CHIPS_1000) {
|
||||
return 2 * spread;
|
||||
}
|
||||
|
||||
if (chips == IEEE802154_MR_OQPSK_CHIPS_2000) {
|
||||
return 4 * spread;
|
||||
}
|
||||
|
||||
return spread;
|
||||
}
|
||||
|
||||
static inline uint16_t _mr_oqpsk_symbol_duration_us(uint8_t chips)
|
||||
{
|
||||
/* 802.15.4g, Table 183 / Table 165 */
|
||||
switch (chips) {
|
||||
case IEEE802154_MR_OQPSK_CHIPS_100:
|
||||
return 320;
|
||||
case IEEE802154_MR_OQPSK_CHIPS_200:
|
||||
return 160;
|
||||
case IEEE802154_MR_OQPSK_CHIPS_1000:
|
||||
case IEEE802154_MR_OQPSK_CHIPS_2000:
|
||||
default:
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t _mr_oqpsk_cca_duration_syms(uint8_t chips)
|
||||
{
|
||||
/* 802.15.4g, Table 188 */
|
||||
return (chips < IEEE802154_MR_OQPSK_CHIPS_1000) ? 4 : 8;
|
||||
}
|
||||
|
||||
static inline uint8_t _mr_oqpsk_shr_duration_syms(uint8_t chips)
|
||||
{
|
||||
/* 802.15.4g, Table 184 / Table 165 */
|
||||
return (chips < IEEE802154_MR_OQPSK_CHIPS_1000) ? 48 : 72;
|
||||
}
|
||||
|
||||
static inline uint8_t _mr_oqpsk_ack_psdu_duration_syms(uint8_t chips, uint8_t mode)
|
||||
{
|
||||
/* pg. 119, section 18.3.2.14 */
|
||||
static const uint8_t sym_len[] = { 32, 32, 64, 128 };
|
||||
const uint8_t Ns = sym_len[chips];
|
||||
const uint8_t Rspread = _mr_oqpsk_spreading(chips, mode);
|
||||
/* Nd == 63, since ACK length is 5 or 7 octets only */
|
||||
const uint16_t Npsdu = Rspread * 2 * 63;
|
||||
|
||||
/* phyPSDUDuration = ceiling(Npsdu / Ns) + ceiling(Npsdu / Mp) */
|
||||
/* with Mp = Np * 16, see Table 182 */
|
||||
return (Npsdu + Ns/2) / Ns + (Npsdu + 8 * Ns) / (16 * Ns);
|
||||
}
|
||||
|
||||
MAYBE_UNUSED
|
||||
static inline uint16_t _mr_oqpsk_ack_timeout_us(const ieee802154_mr_oqpsk_conf_t *conf)
|
||||
{
|
||||
/* see 802.15.4g-2012, p. 30 */
|
||||
uint16_t symbols = _mr_oqpsk_cca_duration_syms(conf->chips)
|
||||
+ _mr_oqpsk_shr_duration_syms(conf->chips)
|
||||
+ 15 /* PHR duration */
|
||||
+ _mr_oqpsk_ack_psdu_duration_syms(conf->chips, conf->rate_mode);
|
||||
|
||||
return _mr_oqpsk_symbol_duration_us(conf->chips) * symbols
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
}
|
||||
|
||||
MAYBE_UNUSED
|
||||
static inline uint16_t _mr_oqpsk_csma_backoff_period_us(const ieee802154_mr_oqpsk_conf_t *conf)
|
||||
{
|
||||
return _mr_oqpsk_cca_duration_syms(conf->chips) * _mr_oqpsk_symbol_duration_us(conf->chips)
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
}
|
||||
|
||||
/*
|
||||
* MR-OFDM timing calculations
|
||||
*
|
||||
* The standard unfortunately does not list the formula, instead it has to be pieced together
|
||||
* from scattered information and tables in the IEEE 802.15.4 document - may contain errors.
|
||||
*/
|
||||
|
||||
static unsigned _mr_ofdm_frame_duration(uint8_t option, uint8_t scheme, uint8_t bytes)
|
||||
{
|
||||
/* Table 150 - phySymbolsPerOctet values for MR-OFDM PHY, IEEE 802.15.4g-2012 */
|
||||
static const uint8_t quot[] = { 3, 3, 6, 12, 18, 24, 36 };
|
||||
|
||||
--option;
|
||||
/* phyMaxFrameDuration = phySHRDuration + phyPHRDuration
|
||||
* + ceiling [(aMaxPHYPacketSize + 1) x phySymbolsPerOctet] */
|
||||
const unsigned phySHRDuration = 6;
|
||||
const unsigned phyPHRDuration = option ? 6 : 3;
|
||||
const unsigned phyPDUDuration = ((bytes + 1) * (1 << option) + quot[scheme] - 1)
|
||||
/ quot[scheme];
|
||||
|
||||
return (phySHRDuration + phyPHRDuration + phyPDUDuration) * IEEE802154_MR_OFDM_SYMBOL_TIME_US;
|
||||
}
|
||||
|
||||
static inline uint16_t _mr_ofdm_csma_backoff_period_us(const ieee802154_mr_ofdm_conf_t *conf)
|
||||
{
|
||||
(void)conf;
|
||||
|
||||
return IEEE802154_CCA_DURATION_IN_SYMBOLS * IEEE802154_MR_OFDM_SYMBOL_TIME_US
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
}
|
||||
|
||||
MAYBE_UNUSED
|
||||
static inline uint16_t _mr_ofdm_ack_timeout_us(const ieee802154_mr_ofdm_conf_t *conf)
|
||||
{
|
||||
return _mr_ofdm_csma_backoff_period_us(conf)
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US
|
||||
+ _mr_ofdm_frame_duration(conf->option, conf->scheme, IEEE802154_ACK_FRAME_LEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* MR-FSK timing calculations
|
||||
*
|
||||
* The standard unfortunately does not list the formula, instead it has to be pieced together
|
||||
* from scattered information and tables in the IEEE 802.15.4 document - may contain errors.
|
||||
*/
|
||||
|
||||
MAYBE_UNUSED
|
||||
static inline uint16_t _mr_fsk_csma_backoff_period_us(const ieee802154_mr_fsk_conf_t *conf)
|
||||
{
|
||||
(void)conf;
|
||||
|
||||
return IEEE802154_CCA_DURATION_IN_SYMBOLS * IEEE802154_MR_FSK_SYMBOL_TIME_US
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US;
|
||||
}
|
||||
|
||||
MAYBE_UNUSED
|
||||
static inline uint16_t _mr_fsk_ack_timeout_us(const ieee802154_mr_fsk_conf_t *conf)
|
||||
{
|
||||
uint8_t ack_len = IEEE802154_ACK_FRAME_LEN;
|
||||
uint8_t fsk_pl = ieee802154_mr_fsk_plen(conf->srate);
|
||||
|
||||
/* PHR uses same data rate as PSDU */
|
||||
ack_len += 2;
|
||||
|
||||
/* 4-FSK doubles data rate */
|
||||
if (conf->mod_ord == 4) {
|
||||
ack_len /= 2;
|
||||
}
|
||||
|
||||
/* forward error correction halves data rate */
|
||||
if (conf->fec) {
|
||||
ack_len *= 2;
|
||||
}
|
||||
|
||||
return _mr_fsk_csma_backoff_period_us(conf)
|
||||
+ IEEE802154G_ATURNAROUNDTIME_US
|
||||
/* long Preamble + SFD; SFD=2 */
|
||||
+ ((fsk_pl * 8 + 2) + ack_len) * 8 * IEEE802154_MR_FSK_SYMBOL_TIME_US;
|
||||
}
|
||||
|
||||
static int ieee802154_submac_config_phy(ieee802154_submac_t *submac,
|
||||
const ieee802154_phy_conf_t *conf)
|
||||
{
|
||||
switch (conf->phy_mode) {
|
||||
case IEEE802154_PHY_OQPSK:
|
||||
submac->ack_timeout_us = ACK_TIMEOUT_US;
|
||||
submac->csma_backoff_us = CSMA_SENDER_BACKOFF_PERIOD_UNIT_US;
|
||||
break;
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OQPSK
|
||||
case IEEE802154_PHY_MR_OQPSK:
|
||||
submac->ack_timeout_us = _mr_oqpsk_ack_timeout_us((void *)conf);
|
||||
submac->csma_backoff_us = _mr_oqpsk_csma_backoff_period_us((void *)conf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
case IEEE802154_PHY_MR_OFDM:
|
||||
submac->ack_timeout_us = _mr_ofdm_ack_timeout_us((void *)conf);
|
||||
submac->csma_backoff_us = _mr_ofdm_csma_backoff_period_us((void *)conf);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
case IEEE802154_PHY_MR_FSK:
|
||||
submac->ack_timeout_us = _mr_fsk_ack_timeout_us((void *)conf);
|
||||
submac->csma_backoff_us = _mr_fsk_csma_backoff_period_us((void *)conf);
|
||||
break;
|
||||
#endif
|
||||
case IEEE802154_PHY_NO_OP:
|
||||
case IEEE802154_PHY_DISABLED:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ieee802154_radio_config_phy(&submac->dev, conf);
|
||||
}
|
||||
|
||||
int ieee802154_submac_init(ieee802154_submac_t *submac, const network_uint16_t *short_addr,
|
||||
const eui64_t *ext_addr)
|
||||
{
|
||||
@ -499,13 +702,46 @@ int ieee802154_submac_init(ieee802154_submac_t *submac, const network_uint16_t *
|
||||
ieee802154_radio_config_addr_filter(dev, IEEE802154_AF_PANID, &submac->panid);
|
||||
|
||||
/* Configure PHY settings (mode, channel, TX power) */
|
||||
ieee802154_phy_conf_t conf =
|
||||
{ .phy_mode = submac->phy_mode,
|
||||
.channel = submac->channel_num,
|
||||
.page = submac->channel_page,
|
||||
.pow = submac->tx_pow };
|
||||
union {
|
||||
ieee802154_phy_conf_t super;
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OQPSK
|
||||
ieee802154_mr_oqpsk_conf_t mr_oqpsk;
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
ieee802154_mr_ofdm_conf_t mr_ofdm;
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
ieee802154_mr_fsk_conf_t mr_fsk;
|
||||
#endif
|
||||
} conf;
|
||||
|
||||
ieee802154_radio_config_phy(dev, &conf);
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OQPSK
|
||||
if (submac->phy_mode == IEEE802154_PHY_MR_OQPSK) {
|
||||
conf.mr_oqpsk.chips = CONFIG_IEEE802154_MR_OQPSK_DEFAULT_CHIPS;
|
||||
conf.mr_oqpsk.rate_mode = CONFIG_IEEE802154_MR_OQPSK_DEFAULT_RATE;
|
||||
}
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_OFDM
|
||||
if (submac->phy_mode == IEEE802154_PHY_MR_OFDM) {
|
||||
conf.mr_ofdm.option = CONFIG_IEEE802154_MR_OFDM_DEFAULT_OPTION;
|
||||
conf.mr_ofdm.scheme = CONFIG_IEEE802154_MR_OFDM_DEFAULT_SCHEME;
|
||||
}
|
||||
#endif
|
||||
#ifdef MODULE_NETDEV_IEEE802154_MR_FSK
|
||||
if (submac->phy_mode == IEEE802154_PHY_MR_FSK) {
|
||||
conf.mr_fsk.srate = CONFIG_IEEE802154_MR_FSK_DEFAULT_SRATE;
|
||||
conf.mr_fsk.mod_ord = CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_ORD;
|
||||
conf.mr_fsk.mod_idx = CONFIG_IEEE802154_MR_FSK_DEFAULT_MOD_IDX;
|
||||
conf.mr_fsk.fec = CONFIG_IEEE802154_MR_FSK_DEFAULT_FEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
conf.super.phy_mode = submac->phy_mode;
|
||||
conf.super.channel = submac->channel_num;
|
||||
conf.super.page = submac->channel_page;
|
||||
conf.super.pow = submac->tx_pow;
|
||||
|
||||
ieee802154_submac_config_phy(submac, &conf.super);
|
||||
ieee802154_radio_set_cca_threshold(dev,
|
||||
CONFIG_IEEE802154_CCA_THRESH_DEFAULT);
|
||||
assert(res >= 0);
|
||||
@ -515,15 +751,9 @@ int ieee802154_submac_init(ieee802154_submac_t *submac, const network_uint16_t *
|
||||
return res;
|
||||
}
|
||||
|
||||
int ieee802154_set_phy_conf(ieee802154_submac_t *submac, uint16_t channel_num,
|
||||
uint8_t channel_page, int8_t tx_pow)
|
||||
int ieee802154_set_phy_conf(ieee802154_submac_t *submac, const ieee802154_phy_conf_t *conf)
|
||||
{
|
||||
ieee802154_dev_t *dev = &submac->dev;
|
||||
const ieee802154_phy_conf_t conf =
|
||||
{ .phy_mode = submac->phy_mode,
|
||||
.channel = channel_num,
|
||||
.page = channel_page,
|
||||
.pow = tx_pow };
|
||||
int res;
|
||||
ieee802154_fsm_state_t current_state = submac->fsm_state;
|
||||
|
||||
@ -539,12 +769,15 @@ int ieee802154_set_phy_conf(ieee802154_submac_t *submac, uint16_t channel_num,
|
||||
}
|
||||
}
|
||||
|
||||
res = ieee802154_radio_config_phy(dev, &conf);
|
||||
res = ieee802154_submac_config_phy(submac, conf);
|
||||
|
||||
if (res >= 0) {
|
||||
submac->channel_num = channel_num;
|
||||
submac->channel_page = channel_page;
|
||||
submac->tx_pow = tx_pow;
|
||||
submac->channel_num = conf->channel;
|
||||
submac->channel_page = conf->page;
|
||||
submac->tx_pow = conf->pow;
|
||||
if (conf->phy_mode != IEEE802154_PHY_NO_OP) {
|
||||
submac->phy_mode = conf->phy_mode;
|
||||
}
|
||||
}
|
||||
while (ieee802154_radio_confirm_set_idle(dev) == -EAGAIN) {}
|
||||
|
||||
|
||||
@ -128,10 +128,9 @@ static void _ev_ack_timeout_handler(event_t *event)
|
||||
mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac, uint16_t us)
|
||||
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac)
|
||||
{
|
||||
(void)submac;
|
||||
ztimer_set(ZTIMER_USEC, &ack_timer, us);
|
||||
ztimer_set(ZTIMER_USEC, &ack_timer, submac->ack_timeout_us);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user