From eb7a9106388a4e43c5e43028a011fe9abe7befe0 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Fri, 18 Jan 2019 21:43:51 +0800 Subject: [PATCH] [efr32] add support for OQPSK modulation in 915MHz band (#3315) --- examples/platforms/efr32/Makefile.am | 6 + .../platforms/efr32/brd4161a/board_config.h | 40 +++ .../platforms/efr32/brd4166a/board_config.h | 40 +++ .../platforms/efr32/brd4170a/board_config.h | 41 +++ .../platforms/efr32/brd4170a/hal-config.h | 1 - .../platforms/efr32/brd4304a/board_config.h | 40 +++ examples/platforms/efr32/platform-band.h | 55 +++ examples/platforms/efr32/radio.c | 324 ++++++++++++++---- examples/platforms/efr32/rail_config.h | 5 + third_party/silabs/LICENSE.txt | 2 + third_party/silabs/README.md | 19 + third_party/silabs/rail_config/rail_config.c | 184 ++++++++++ 12 files changed, 692 insertions(+), 65 deletions(-) create mode 100644 examples/platforms/efr32/brd4161a/board_config.h create mode 100644 examples/platforms/efr32/brd4166a/board_config.h create mode 100644 examples/platforms/efr32/brd4170a/board_config.h create mode 100644 examples/platforms/efr32/brd4304a/board_config.h create mode 100644 examples/platforms/efr32/platform-band.h create mode 100644 third_party/silabs/LICENSE.txt create mode 100644 third_party/silabs/README.md create mode 100644 third_party/silabs/rail_config/rail_config.c diff --git a/examples/platforms/efr32/Makefile.am b/examples/platforms/efr32/Makefile.am index f3126a0d5..11ff9960b 100644 --- a/examples/platforms/efr32/Makefile.am +++ b/examples/platforms/efr32/Makefile.am @@ -38,6 +38,8 @@ override CXXFLAGS := $(filter-out -Wconversion,$(CXXF override CFLAGS := $(filter-out -pedantic-errors,$(CFLAGS)) override CXXFLAGS := $(filter-out -pedantic-errors,$(CXXFLAGS)) +EFR32_BOARD_DIR = $(shell echo $(BOARD) | tr A-Z a-z) + EFR32MG_SDK_SRCDIR = $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v2.3 libopenthread_efr32_a_CPPFLAGS = \ @@ -45,7 +47,9 @@ libopenthread_efr32_a_CPPFLAGS = -D__STARTUP_CLEAR_BSS \ -I$(top_srcdir)/include \ -I$(top_srcdir)/examples/platforms \ + -I$(top_srcdir)/examples/platforms/efr32/$(EFR32_BOARD_DIR) \ -I$(top_srcdir)/src/core \ + -I$(top_srcdir)/third_party/silabs/rail_config \ -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/common \ -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/chip/efr32 \ -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/protocol/ieee802154 \ @@ -86,6 +90,7 @@ PLATFORM_SOURCES = $(NULL) nodist_libopenthread_efr32_a_SOURCES = \ + @top_builddir@/third_party/silabs/rail_config/rail_config.c \ @top_builddir@/third_party/silabs/gecko_sdk_suite/v2.3/hardware/kit/common/bsp/bsp_bcc.c \ @top_builddir@/third_party/silabs/gecko_sdk_suite/v2.3/hardware/kit/common/bsp/bsp_init.c \ @top_builddir@/third_party/silabs/gecko_sdk_suite/v2.3/hardware/kit/common/bsp/bsp_stk.c \ @@ -121,6 +126,7 @@ nodist_libopenthread_efr32_a_SOURCES noinst_HEADERS = \ platform-efr32.h \ + platform-band.h \ $(NULL) libopenthread_efr32_a_SOURCES = \ diff --git a/examples/platforms/efr32/brd4161a/board_config.h b/examples/platforms/efr32/brd4161a/board_config.h new file mode 100644 index 000000000..0112b4719 --- /dev/null +++ b/examples/platforms/efr32/brd4161a/board_config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes dev borad compile-time configuration constants for efr32. + * + */ + +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#define RADIO_SUPPORT_2P4GHZ_OQPSK 1 ///< Dev board suppports OQPSK modulation in 2.4GHz band. + +#endif // __BOARD_CONFIG_H__ diff --git a/examples/platforms/efr32/brd4166a/board_config.h b/examples/platforms/efr32/brd4166a/board_config.h new file mode 100644 index 000000000..0112b4719 --- /dev/null +++ b/examples/platforms/efr32/brd4166a/board_config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes dev borad compile-time configuration constants for efr32. + * + */ + +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#define RADIO_SUPPORT_2P4GHZ_OQPSK 1 ///< Dev board suppports OQPSK modulation in 2.4GHz band. + +#endif // __BOARD_CONFIG_H__ diff --git a/examples/platforms/efr32/brd4170a/board_config.h b/examples/platforms/efr32/brd4170a/board_config.h new file mode 100644 index 000000000..b71741781 --- /dev/null +++ b/examples/platforms/efr32/brd4170a/board_config.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes dev borad compile-time configuration constants for efr32. + * + */ + +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#define RADIO_SUPPORT_2P4GHZ_OQPSK 1 ///< Dev board suppports OQPSK modulation in 2.4GHz band. +#define RADIO_SUPPORT_915MHZ_OQPSK 1 ///< Dev board suppports OQPSK modulation in 915MHz band. + +#endif // __BOARD_CONFIG_H__ diff --git a/examples/platforms/efr32/brd4170a/hal-config.h b/examples/platforms/efr32/brd4170a/hal-config.h index 37d50152e..adba5742e 100644 --- a/examples/platforms/efr32/brd4170a/hal-config.h +++ b/examples/platforms/efr32/brd4170a/hal-config.h @@ -196,7 +196,6 @@ // $[SERIAL] #define HAL_SERIAL_USART0_ENABLE (0) -#define BSP_SERIAL_APP_PORT (HAL_SERIAL_PORT_USART0) #define HAL_SERIAL_LEUART0_ENABLE (0) #define HAL_SERIAL_USART1_ENABLE (0) #define HAL_SERIAL_USART2_ENABLE (0) diff --git a/examples/platforms/efr32/brd4304a/board_config.h b/examples/platforms/efr32/brd4304a/board_config.h new file mode 100644 index 000000000..0112b4719 --- /dev/null +++ b/examples/platforms/efr32/brd4304a/board_config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes dev borad compile-time configuration constants for efr32. + * + */ + +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#define RADIO_SUPPORT_2P4GHZ_OQPSK 1 ///< Dev board suppports OQPSK modulation in 2.4GHz band. + +#endif // __BOARD_CONFIG_H__ diff --git a/examples/platforms/efr32/platform-band.h b/examples/platforms/efr32/platform-band.h new file mode 100644 index 000000000..9afdd02c2 --- /dev/null +++ b/examples/platforms/efr32/platform-band.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file defines the frequency band configuration structure for efr32. + * + */ + +#ifndef PLATFORM_BAND_H_ +#define PLATFORM_BAND_H_ + +#include + +#include "rail.h" +#include "rail_config.h" +#include "rail_ieee802154.h" + +typedef struct efr32BandConfig +{ + RAIL_Handle_t mRailHandle; + RAIL_Config_t mRailConfig; + RAILSched_Config_t mRailSchedState; + const RAIL_ChannelConfig_t *mChannelConfig; + uint8_t mRailTxFifo[OT_RADIO_FRAME_MAX_SIZE + 1]; + uint8_t mChannelMin; + uint8_t mChannelMax; +} efr32BandConfig; + +#endif // PLATFORM_BAND_H_ diff --git a/examples/platforms/efr32/radio.c b/examples/platforms/efr32/radio.c index 92210bec5..56a65e657 100644 --- a/examples/platforms/efr32/radio.c +++ b/examples/platforms/efr32/radio.c @@ -42,10 +42,12 @@ #include "common/logging.hpp" #include "utils/code_utils.h" +#include "board_config.h" #include "em_core.h" #include "em_system.h" #include "openthread-core-efr32-config.h" #include "pa_conversions_efr32.h" +#include "platform-band.h" #include "rail.h" #include "rail_config.h" #include "rail_ieee802154.h" @@ -64,7 +66,33 @@ enum enum { - EFR32_RECEIVE_SENSITIVITY = -100, // dBm + EFR32_915MHZ_OQPSK_CHANNEL_MIN = 1, + EFR32_915MHZ_OQPSK_CHANNEL_MAX = 10, + EFR32_2P4GHZ_OQPSK_CHANNEL_MIN = 11, + EFR32_2P4GHZ_OQPSK_CHANNEL_MAX = 26, +}; + +enum +{ + EFR32_RECEIVE_SENSITIVITY = -100, // dBm + EFR32_RSSI_AVERAGING_TIME = 16, // us + EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us +}; + +enum +{ + EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY = 10, // High priority + EFR32_SCHEDULER_TX_PRIORITY = 10, // High priority + EFR32_SCHEDULER_RX_PRIORITY = 20, // Low priority +}; + +enum +{ +#if RADIO_SUPPORT_2P4GHZ_OQPSK && RADIO_SUPPORT_915MHZ_OQPSK + EFR32_NUM_BAND_CONFIGS = 2, +#else + EFR32_NUM_BAND_CONFIGS = 1, +#endif }; static uint16_t sPanId = 0; @@ -73,6 +101,9 @@ static bool sPromiscuous = false; static bool sIsSrcMatchEnabled = false; static otRadioState sState = OT_RADIO_STATE_DISABLED; +static volatile bool sSampleRssiDone; +static volatile int8_t sRssi; + static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH]; static otRadioFrame sReceiveFrame; static otError sReceiveError; @@ -90,16 +121,10 @@ typedef struct srcMatchEntry static sSrcMatchEntry srcMatchShortEntry[RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM]; static sSrcMatchEntry srcMatchExtEntry[RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM]; -static uint8_t sRailTxFifo[1 + IEEE802154_MAX_LENGTH]; +efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS]; static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents); -static RAIL_Config_t sRailConfig = { - .eventsCallback = &RAILCb_Generic, - .protocol = NULL, - .scheduler = NULL, -}; - static const RAIL_IEEE802154_Config_t sRailIeee802154Config = { NULL, // addresses { @@ -131,17 +156,17 @@ static const RAIL_IEEE802154_Config_t sRailIeee802154Config = { false, // isPanCoordinator }; -static RAIL_Handle_t sRailHandle = NULL; - RAIL_DECLARE_TX_POWER_VBAT_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp); -void efr32RadioInit(void) +static int8_t sTxPowerDbm = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER; + +static efr32BandConfig *sTxBandConfig = NULL; +static efr32BandConfig *sRxBandConfig = NULL; + +RAIL_Handle_t efr32RailConfigInit(efr32BandConfig *aBandConfig) { - RAIL_Status_t status; - - sRailHandle = RAIL_Init(&sRailConfig, NULL); - assert(sRailHandle != NULL); - + RAIL_Status_t status; + RAIL_Handle_t handle; RAIL_DataConfig_t railDataConfig = { TX_PACKET_DATA, RX_PACKET_DATA, @@ -149,22 +174,36 @@ void efr32RadioInit(void) PACKET_MODE, }; - status = RAIL_ConfigData(sRailHandle, &railDataConfig); + handle = RAIL_Init(&aBandConfig->mRailConfig, NULL); + assert(handle != NULL); + + status = RAIL_ConfigData(handle, &railDataConfig); assert(status == RAIL_STATUS_NO_ERROR); - status = RAIL_ConfigCal(sRailHandle, RAIL_CAL_ALL); + RAIL_Idle(handle, RAIL_IDLE, true); + + status = RAIL_ConfigCal(handle, RAIL_CAL_ALL); assert(status == RAIL_STATUS_NO_ERROR); - status = RAIL_IEEE802154_Config2p4GHzRadio(sRailHandle); + if (aBandConfig->mChannelConfig != NULL) + { + RAIL_ConfigChannels(handle, aBandConfig->mChannelConfig, NULL); + } + else + { + status = RAIL_IEEE802154_Config2p4GHzRadio(handle); + assert(status == RAIL_STATUS_NO_ERROR); + } + + status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config); assert(status == RAIL_STATUS_NO_ERROR); - status = RAIL_IEEE802154_Init(sRailHandle, &sRailIeee802154Config); - assert(status == RAIL_STATUS_NO_ERROR); - - status = RAIL_ConfigEvents(sRailHandle, RAIL_EVENTS_ALL, + status = RAIL_ConfigEvents(handle, RAIL_EVENTS_ALL, RAIL_EVENT_RX_ACK_TIMEOUT | // RAIL_EVENT_TX_PACKET_SENT | // RAIL_EVENT_RX_PACKET_RECEIVED | // + RAIL_EVENT_RSSI_AVERAGE_DONE | // + RAIL_EVENT_SCHEDULER_STATUS | // RAIL_EVENT_TX_CHANNEL_BUSY | // RAIL_EVENT_TX_ABORTED | // RAIL_EVENT_TX_BLOCKED | // @@ -174,24 +213,93 @@ void efr32RadioInit(void) ); assert(status == RAIL_STATUS_NO_ERROR); + RAIL_SetTxFifo(handle, aBandConfig->mRailTxFifo, 0, sizeof(aBandConfig->mRailTxFifo)); + + return handle; +} + +static void efr32RadioSetTxPower(RAIL_Handle_t aRailHandle, + const RAIL_ChannelConfig_t *aChannelConfig, + uint8_t aPowerDbm) +{ + RAIL_Status_t status; RAIL_TxPowerCurvesConfig_t txPowerCurvesConfig = {curves24Hp, curvesSg, curves24Lp, piecewiseSegments}; - status = RAIL_InitTxPowerCurves(&txPowerCurvesConfig); + RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_HP, 3300, 10}; + + if ((aChannelConfig != NULL) && (aChannelConfig->configs[0].baseFrequency < 1000000000UL)) + { + txPowerConfig.mode = RAIL_TX_POWER_MODE_SUBGIG; + } + + status = RAIL_InitTxPowerCurves(&txPowerCurvesConfig); assert(status == RAIL_STATUS_NO_ERROR); - RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_HP, 3300, 10}; - status = RAIL_ConfigTxPower(sRailHandle, &txPowerConfig); + status = RAIL_ConfigTxPower(aRailHandle, &txPowerConfig); assert(status == RAIL_STATUS_NO_ERROR); - status = RAIL_SetTxPowerDbm(sRailHandle, ((RAIL_TxPower_t)OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER) * 10); + status = RAIL_SetTxPowerDbm(aRailHandle, ((RAIL_TxPower_t)aPowerDbm) * 10); assert(status == RAIL_STATUS_NO_ERROR); +} - RAIL_SetTxFifo(sRailHandle, sRailTxFifo, 0, sizeof(sRailTxFifo)); +efr32BandConfig *efr32RadioGetBandConfig(uint8_t aChannel) +{ + efr32BandConfig *config = NULL; + + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax)) + { + config = &sBandConfigs[i]; + break; + } + } + + return config; +} + +void efr32BandConfigInit(void (*aEventCallback)(RAIL_Handle_t railHandle, RAIL_Events_t events)) +{ + uint8_t index = 0; + +#if RADIO_SUPPORT_2P4GHZ_OQPSK + sBandConfigs[index].mRailConfig.eventsCallback = aEventCallback; + sBandConfigs[index].mRailConfig.protocol = NULL; + sBandConfigs[index].mRailConfig.scheduler = &sBandConfigs[index].mRailSchedState; + sBandConfigs[index].mChannelConfig = NULL; + sBandConfigs[index].mChannelMin = EFR32_2P4GHZ_OQPSK_CHANNEL_MIN; + sBandConfigs[index].mChannelMax = EFR32_2P4GHZ_OQPSK_CHANNEL_MAX; + + assert((sBandConfigs[index].mRailHandle = efr32RailConfigInit(&sBandConfigs[index])) != NULL); + index++; +#endif + +#if RADIO_SUPPORT_915MHZ_OQPSK + sBandConfigs[index].mRailConfig.eventsCallback = aEventCallback; + sBandConfigs[index].mRailConfig.protocol = NULL; + sBandConfigs[index].mRailConfig.scheduler = &sBandConfigs[index].mRailSchedState; + sBandConfigs[index].mChannelConfig = channelConfigs[0]; + sBandConfigs[index].mChannelMin = EFR32_915MHZ_OQPSK_CHANNEL_MIN; + sBandConfigs[index].mChannelMax = EFR32_915MHZ_OQPSK_CHANNEL_MAX; + + assert((sBandConfigs[index].mRailHandle = efr32RailConfigInit(&sBandConfigs[index])) != NULL); +#endif +} + +void efr32RadioInit(void) +{ + efr32BandConfigInit(RAILCb_Generic); sReceiveFrame.mLength = 0; sReceiveFrame.mPsdu = sReceivePsdu; sTransmitFrame.mLength = 0; sTransmitFrame.mPsdu = sTransmitPsdu; + sRxBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL); + assert(sRxBandConfig != NULL); + + sTxBandConfig = sRxBandConfig; + efr32RadioSetTxPower(sTxBandConfig->mRailHandle, sTxBandConfig->mChannelConfig, sTxPowerDbm); + otLogInfoPlat("Initialized", NULL); } @@ -199,10 +307,18 @@ void efr32RadioDeinit(void) { RAIL_Status_t status; - RAIL_Idle(sRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true); + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true); - status = RAIL_IEEE802154_Deinit(sRailHandle); - assert(status == RAIL_STATUS_NO_ERROR); + status = RAIL_IEEE802154_Deinit(sBandConfigs[i].mRailHandle); + assert(status == RAIL_STATUS_NO_ERROR); + + sBandConfigs[i].mRailHandle = NULL; + } + + sTxBandConfig = NULL; + sRxBandConfig = NULL; } void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) @@ -230,8 +346,12 @@ void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId) otLogInfoPlat("PANID=%X", aPanId); sPanId = aPanId; - status = RAIL_IEEE802154_SetPanId(sRailHandle, aPanId, 0); - assert(status == RAIL_STATUS_NO_ERROR); + + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + status = RAIL_IEEE802154_SetPanId(sBandConfigs[i].mRailHandle, aPanId, 0); + assert(status == RAIL_STATUS_NO_ERROR); + } } void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress) @@ -243,8 +363,11 @@ void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aA otLogInfoPlat("ExtAddr=%X%X%X%X%X%X%X%X", aAddress->m8[7], aAddress->m8[6], aAddress->m8[5], aAddress->m8[4], aAddress->m8[3], aAddress->m8[2], aAddress->m8[1], aAddress->m8[0]); - status = RAIL_IEEE802154_SetLongAddress(sRailHandle, (uint8_t *)aAddress->m8, 0); - assert(status == RAIL_STATUS_NO_ERROR); + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + status = RAIL_IEEE802154_SetLongAddress(sBandConfigs[i].mRailHandle, (uint8_t *)aAddress->m8, 0); + assert(status == RAIL_STATUS_NO_ERROR); + } } void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress) @@ -255,8 +378,11 @@ void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress) otLogInfoPlat("ShortAddr=%X", aAddress); - status = RAIL_IEEE802154_SetShortAddress(sRailHandle, aAddress, 0); - assert(status == RAIL_STATUS_NO_ERROR); + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + status = RAIL_IEEE802154_SetShortAddress(sBandConfigs[i].mRailHandle, aAddress, 0); + assert(status == RAIL_STATUS_NO_ERROR); + } } bool otPlatRadioIsEnabled(otInstance *aInstance) @@ -300,7 +426,10 @@ otError otPlatRadioSleep(otInstance *aInstance) otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL); sState = OT_RADIO_STATE_SLEEP; - RAIL_Idle(sRailHandle, RAIL_IDLE, true); + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE, true); + } exit: return error; @@ -308,14 +437,24 @@ exit: otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) { + otError error = OT_ERROR_NONE; + RAIL_SchedulerInfo_t schedulerInfo = {.priority = EFR32_SCHEDULER_RX_PRIORITY}; + RAIL_Status_t status; + efr32BandConfig * config; + OT_UNUSED_VARIABLE(aInstance); - - otError error = OT_ERROR_NONE; - RAIL_Status_t status; - otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE); - status = RAIL_StartRx(sRailHandle, aChannel, NULL); + config = efr32RadioGetBandConfig(aChannel); + otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS); + + if (sRxBandConfig != config) + { + RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, false); + sRxBandConfig = config; + } + + status = RAIL_StartRx(sRxBandConfig->mRailHandle, aChannel, &schedulerInfo); otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED); otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL); @@ -328,20 +467,31 @@ exit: otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) { - otError error = OT_ERROR_NONE; - RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA; - RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_NONE; - RAIL_Status_t status; + otError error = OT_ERROR_NONE; + RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA; + RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_NONE; + RAIL_SchedulerInfo_t schedulerInfo = {.priority = EFR32_SCHEDULER_TX_PRIORITY}; + efr32BandConfig * config; + RAIL_Status_t status; otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT), error = OT_ERROR_INVALID_STATE); + config = efr32RadioGetBandConfig(aFrame->mChannel); + otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS); + sState = OT_RADIO_STATE_TRANSMIT; sTransmitError = OT_ERROR_NONE; sTransmitBusy = true; - RAIL_WriteTxFifo(sRailHandle, &aFrame->mLength, sizeof(aFrame->mLength), true); - RAIL_WriteTxFifo(sRailHandle, aFrame->mPsdu, aFrame->mLength - 2, false); + if (sTxBandConfig != config) + { + efr32RadioSetTxPower(config->mRailHandle, config->mChannelConfig, sTxPowerDbm); + sTxBandConfig = config; + } + + RAIL_WriteTxFifo(sTxBandConfig->mRailHandle, &aFrame->mLength, sizeof(aFrame->mLength), true); + RAIL_WriteTxFifo(sTxBandConfig->mRailHandle, aFrame->mPsdu, aFrame->mLength - 2, false); if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST) { @@ -350,12 +500,14 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled) { - status = RAIL_StartCcaCsmaTx(sRailHandle, aFrame->mChannel, txOptions, &csmaConfig, NULL); + status = + RAIL_StartCcaCsmaTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &schedulerInfo); } else { - status = RAIL_StartTx(sRailHandle, aFrame->mChannel, txOptions, NULL); + status = RAIL_StartTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &schedulerInfo); } + assert(status == RAIL_STATUS_NO_ERROR); otPlatRadioTxStarted(aInstance, aFrame); @@ -373,9 +525,28 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance) { + RAIL_Status_t status; + RAIL_SchedulerInfo_t schedulerInfo = {.priority = EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY}; + uint32_t start; OT_UNUSED_VARIABLE(aInstance); - return (int8_t)(RAIL_GetAverageRssi(sRailHandle) >> 2); + RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, true); + + sSampleRssiDone = false; + sRssi = OT_RADIO_RSSI_INVALID; + + status = RAIL_StartAverageRssi(sRxBandConfig->mRailHandle, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME, + &schedulerInfo); + otEXPECT(status == RAIL_STATUS_NO_ERROR); + + start = RAIL_GetTime(); + + // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE + while (!sSampleRssiDone && ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT)) + ; + +exit: + return sRssi; } otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) @@ -399,8 +570,12 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) RAIL_Status_t status; sPromiscuous = aEnable; - status = RAIL_IEEE802154_SetPromiscuousMode(sRailHandle, aEnable); - assert(status == RAIL_STATUS_NO_ERROR); + + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + status = RAIL_IEEE802154_SetPromiscuousMode(sBandConfigs[i].mRailHandle, aEnable); + assert(status == RAIL_STATUS_NO_ERROR); + } } int8_t findSrcMatchAvailEntry(bool aShortAddress) @@ -618,12 +793,12 @@ static void processNextRxPacket(otInstance *aInstance, RAIL_Handle_t aRailHandle packetDetails.timeReceived.timePosition = RAIL_PACKET_TIME_INVALID; packetDetails.timeReceived.totalPacketBytes = 0; status = RAIL_GetRxPacketDetails(aRailHandle, packetHandle, &packetDetails); - otEXPECT(status != RAIL_STATUS_INVALID_STATE); - assert(status == RAIL_STATUS_NO_ERROR); + otEXPECT(status == RAIL_STATUS_NO_ERROR); + length = packetInfo.packetBytes + 1; // check the length in recv packet info structure - assert(length == packetInfo.firstPortionData[0]); + otEXPECT(length == packetInfo.firstPortionData[0]); // check the length validity of recv packet otEXPECT(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH); @@ -667,7 +842,7 @@ static void processNextRxPacket(otInstance *aInstance, RAIL_Handle_t aRailHandle } else { - assert(length != IEEE802154_ACK_LENGTH); + otEXPECT(length != IEEE802154_ACK_LENGTH); sReceiveError = OT_ERROR_NONE; @@ -727,16 +902,21 @@ static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle) static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents) { - if (aEvents & (RAIL_EVENT_TX_ABORTED | RAIL_EVENT_TX_BLOCKED | RAIL_EVENT_TX_UNDERFLOW)) + if (aEvents & + (RAIL_EVENT_TX_ABORTED | RAIL_EVENT_TX_BLOCKED | RAIL_EVENT_TX_UNDERFLOW | RAIL_EVENT_SCHEDULER_STATUS)) { sTransmitError = OT_ERROR_ABORT; sTransmitBusy = false; + + RAIL_YieldRadio(aRailHandle); } if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT) { sTransmitError = OT_ERROR_NO_ACK; sTransmitBusy = false; + + RAIL_YieldRadio(aRailHandle); } if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED) @@ -755,6 +935,8 @@ static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents) { sTransmitError = OT_ERROR_NONE; sTransmitBusy = false; + + RAIL_YieldRadio(aRailHandle); } } @@ -762,6 +944,8 @@ static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents) { sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE; sTransmitBusy = false; + + RAIL_YieldRadio(aRailHandle); } if (aEvents & RAIL_EVENT_CAL_NEEDED) @@ -771,6 +955,14 @@ static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents) status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING); assert(status == RAIL_STATUS_NO_ERROR); } + + if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE) + { + sSampleRssiDone = true; + sRssi = (int8_t)(RAIL_GetAverageRssi(aRailHandle) >> 2); + + RAIL_YieldRadio(aRailHandle); + } } otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) @@ -794,7 +986,6 @@ void efr32RadioProcess(otInstance *aInstance) sState = OT_RADIO_STATE_RECEIVE; #if OPENTHREAD_ENABLE_DIAG - if (otPlatDiagModeGet()) { otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError); @@ -811,7 +1002,7 @@ void efr32RadioProcess(otInstance *aInstance) } } - processNextRxPacket(aInstance, sRailHandle); + processNextRxPacket(aInstance, sRxBandConfig->mRailHandle); } otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) @@ -821,7 +1012,7 @@ otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) otError error = OT_ERROR_NONE; otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS); - *aPower = (int8_t)(RAIL_GetTxPowerDbm(sRailHandle) / 10); + *aPower = sTxPowerDbm; exit: return error; @@ -833,8 +1024,13 @@ otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) RAIL_Status_t status; - status = RAIL_SetTxPowerDbm(sRailHandle, ((RAIL_TxPower_t)aPower) * 10); - assert(status == RAIL_STATUS_NO_ERROR); + for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++) + { + status = RAIL_SetTxPowerDbm(sBandConfigs[i].mRailHandle, ((RAIL_TxPower_t)aPower) * 10); + assert(status == RAIL_STATUS_NO_ERROR); + } + + sTxPowerDbm = aPower; return OT_ERROR_NONE; } diff --git a/examples/platforms/efr32/rail_config.h b/examples/platforms/efr32/rail_config.h index 8b643556c..9e493100d 100644 --- a/examples/platforms/efr32/rail_config.h +++ b/examples/platforms/efr32/rail_config.h @@ -3,7 +3,12 @@ #include #include "rail_types.h" +#include "board_config.h" #define RADIO_CONFIG_XTAL_FREQUENCY 38400000UL +#if RADIO_SUPPORT_915MHZ_OQPSK +extern const RAIL_ChannelConfig_t *channelConfigs[]; +#endif + #endif // __RAIL_CONFIG_H__ diff --git a/third_party/silabs/LICENSE.txt b/third_party/silabs/LICENSE.txt new file mode 100644 index 000000000..24811ac4f --- /dev/null +++ b/third_party/silabs/LICENSE.txt @@ -0,0 +1,2 @@ +Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com +Copyright 2018 Silicon Laboratories, Inc. http://www.silabs.com diff --git a/third_party/silabs/README.md b/third_party/silabs/README.md new file mode 100644 index 000000000..e00ffcf71 --- /dev/null +++ b/third_party/silabs/README.md @@ -0,0 +1,19 @@ +# silabs + +## URL + +https://www.silabs.com/products/development-tools/software/simplicity-studio + +## Version + +Radio Configurator Version: 3.8.0 +RAIL Adapter Version: 2.2.5 +RAIL Compatibility: 2.x + +## License File + +[LICENSE](LICENSE.txt) + +## Description + +The file in rail_config is auto-generated by Hardware Configurator in Simplicity Studio. diff --git a/third_party/silabs/rail_config/rail_config.c b/third_party/silabs/rail_config/rail_config.c new file mode 100644 index 000000000..28be2569d --- /dev/null +++ b/third_party/silabs/rail_config/rail_config.c @@ -0,0 +1,184 @@ +// Copyright 2018 Silicon Laboratories, Inc. +// +// + +/// @file rail_config.c +/// @brief RAIL Configuration +/// @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com +// ============================================================================= +// +// WARNING: Auto-Generated Radio Config - DO NOT EDIT +// Radio Configurator Version: 3.8.0 +// RAIL Adapter Version: 2.2.5 +// RAIL Compatibility: 2.x +// +// ============================================================================= +#include "em_common.h" +#include "rail_config.h" + +uint32_t RAILCb_CalcSymbolRate(RAIL_Handle_t railHandle) +{ + (void) railHandle; + return 0U; +} + +uint32_t RAILCb_CalcBitRate(RAIL_Handle_t railHandle) +{ + (void) railHandle; + return 0U; +} + +void RAILCb_ConfigFrameTypeLength(RAIL_Handle_t railHandle, + const RAIL_FrameType_t *frameType) +{ + (void) railHandle; + (void) frameType; +} + +static const uint8_t generated_irCalConfig[] = { + 24, 71, 3, 6, 4, 16, 0, 1, 1, 3, 1, 6, 0, 16, 39, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint32_t generated_phyInfo[] = { + 3UL, + 0x00924924UL, // 146.285714286 + (uint32_t) NULL, + (uint32_t) generated_irCalConfig, +#ifdef RADIO_CONFIG_ENABLE_TIMING + (uint32_t) &generated_timing, +#else + (uint32_t) NULL, +#endif + 0x00000000UL, + 7500000UL, + 42000000UL, + 1000000UL, + (16UL << 8) | 4UL, +}; + +const uint32_t generated[] = { + 0x01031FF0UL, 0x003F003FUL, + /* 1FF4 */ 0x00000000UL, + /* 1FF8 */ (uint32_t) &generated_phyInfo, + 0x00020004UL, 0x00157001UL, + /* 0008 */ 0x0000007FUL, + 0x00020018UL, 0x00000000UL, + /* 001C */ 0x00000000UL, + 0x00070028UL, 0x00000000UL, + /* 002C */ 0x00000000UL, + /* 0030 */ 0x00000000UL, + /* 0034 */ 0x00000000UL, + /* 0038 */ 0x00000000UL, + /* 003C */ 0x00000000UL, + /* 0040 */ 0x000007A0UL, + 0x00010048UL, 0x00000000UL, + 0x00020054UL, 0x00000000UL, + /* 0058 */ 0x00000000UL, + 0x000400A0UL, 0x00004000UL, + /* 00A4 */ 0x00004CFFUL, + /* 00A8 */ 0x00004100UL, + /* 00AC */ 0x00004DFFUL, + 0x00012000UL, 0x000007C4UL, + 0x00012010UL, 0x00000000UL, + 0x00012018UL, 0x00008408UL, + 0x00013008UL, 0x0100AC13UL, + 0x00023030UL, 0x00107800UL, + /* 3034 */ 0x00000003UL, + 0x00013040UL, 0x00000000UL, + 0x000140A0UL, 0x0F0027AAUL, + 0x000140B8UL, 0x00B3C000UL, + 0x000140F4UL, 0x00001020UL, + 0x00024134UL, 0x00000880UL, + /* 4138 */ 0x000087F6UL, + 0x00024140UL, 0x00880086UL, + /* 4144 */ 0x4D52E6C0UL, + 0x00044160UL, 0x00000000UL, + /* 4164 */ 0x00000000UL, + /* 4168 */ 0x00000006UL, + /* 416C */ 0x00000006UL, + 0x00086014UL, 0x00000010UL, + /* 6018 */ 0x00127920UL, + /* 601C */ 0x00520007UL, + /* 6020 */ 0x000000C8UL, + /* 6024 */ 0x000A0000UL, + /* 6028 */ 0x03000000UL, + /* 602C */ 0x00000000UL, + /* 6030 */ 0x00000000UL, + 0x00066050UL, 0x00FF04C8UL, + /* 6054 */ 0x00000C41UL, + /* 6058 */ 0x00000008UL, + /* 605C */ 0x00100410UL, + /* 6060 */ 0x000000A7UL, + /* 6064 */ 0x00000000UL, + 0x000C6078UL, 0x08E00107UL, + /* 607C */ 0x0000A47CUL, + /* 6080 */ 0x00000018UL, + /* 6084 */ 0x01959000UL, + /* 6088 */ 0x00000001UL, + /* 608C */ 0x00000000UL, + /* 6090 */ 0x00000000UL, + /* 6094 */ 0x00000000UL, + /* 6098 */ 0x00000000UL, + /* 609C */ 0x00000000UL, + /* 60A0 */ 0x00000000UL, + /* 60A4 */ 0x00000000UL, + 0x000760E4UL, 0xCBA10881UL, + /* 60E8 */ 0x00000000UL, + /* 60EC */ 0x07830464UL, + /* 60F0 */ 0x3AC81388UL, + /* 60F4 */ 0x0006209CUL, + /* 60F8 */ 0x00206100UL, + /* 60FC */ 0x208556B7UL, + 0x00036104UL, 0x0010F000UL, + /* 6108 */ 0x00003020UL, + /* 610C */ 0x0000BB88UL, + 0x00016120UL, 0x00000000UL, + 0x00077014UL, 0x000270FEUL, + /* 7018 */ 0x00001300UL, + /* 701C */ 0x850A0060UL, + /* 7020 */ 0x00000000UL, + /* 7024 */ 0x00000082UL, + /* 7028 */ 0x00000000UL, + /* 702C */ 0x000000D5UL, + 0x00027048UL, 0x0000383EUL, + /* 704C */ 0x000025BCUL, + 0x00037070UL, 0x00220103UL, + /* 7074 */ 0x0008300FUL, + /* 7078 */ 0x006D8480UL, + + 0xFFFFFFFFUL, +}; + +RAIL_ChannelConfigEntryAttr_t generated_entryAttr = { + { 0xFFFFFFFFUL } +}; + +const RAIL_ChannelConfigEntry_t generated_channels[] = { + { + .phyConfigDeltaAdd = NULL, + .baseFrequency = 904000000, + .channelSpacing = 2000000, + .physicalChannelOffset = 0, + .channelNumberStart = 0, + .channelNumberEnd = 20, + .maxPower = RAIL_TX_POWER_MAX, + .attr = &generated_entryAttr + }, +}; + +const RAIL_ChannelConfig_t generated_channelConfig = { + generated, + NULL, + generated_channels, + 1 +}; +const RAIL_ChannelConfig_t *channelConfigs[] = { + &generated_channelConfig, +}; + + +// +// | )/ ) Wireless +// \\ |//,' __ Application +// (")(_)-"()))=- Software +// (\\ Platform