From 75c5fbd1c9152da5699bb35c2aae55365ff8c143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Mi=C5=9B?= Date: Wed, 6 Sep 2017 18:55:47 +0200 Subject: [PATCH] [nRF52840] front end module support (#2175) --- examples/platforms/nrf52840/Makefile.am | 9 + examples/platforms/nrf52840/fem.c | 65 ++ examples/platforms/nrf52840/platform-fem.h | 108 ++++ .../drivers/radio/fem/nrf_fem_control_api.h | 182 ++++++ .../radio/fem/nrf_fem_control_common.c | 220 +++++++ .../radio/fem/nrf_fem_control_config.h | 69 ++ .../radio/fem/nrf_fem_control_direct.c | 91 +++ .../radio/fem/nrf_fem_control_internal.h | 82 +++ .../radio/fem/nrf_fem_control_softdevice.c | 78 +++ .../drivers/radio/nrf_drv_radio802154.c | 51 ++ .../drivers/radio/nrf_drv_radio802154.h | 62 ++ .../radio/nrf_drv_radio802154_config.h | 2 +- .../drivers/radio/nrf_drv_radio802154_fsm.c | 71 ++- .../NordicSemiconductor/hal/nrf_gpio.h | 38 +- .../NordicSemiconductor/hal/nrf_gpiote.h | 33 +- third_party/NordicSemiconductor/hal/nrf_ppi.h | 32 +- .../NordicSemiconductor/hal/nrf_radio.h | 10 + .../NordicSemiconductor/hal/nrf_timer.h | 589 ++++++++++++++++++ 18 files changed, 1704 insertions(+), 88 deletions(-) create mode 100644 examples/platforms/nrf52840/fem.c create mode 100644 examples/platforms/nrf52840/platform-fem.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h create mode 100644 third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c create mode 100644 third_party/NordicSemiconductor/hal/nrf_timer.h diff --git a/examples/platforms/nrf52840/Makefile.am b/examples/platforms/nrf52840/Makefile.am index 96db19c2c..e0e719fdc 100644 --- a/examples/platforms/nrf52840/Makefile.am +++ b/examples/platforms/nrf52840/Makefile.am @@ -37,6 +37,7 @@ lib_LIBRARIES COMMONCPPFLAGS = \ -DCONFIG_GPIO_AS_PINRESET \ -DNRF52840_XXAA \ + -DENABLE_FEM=1 \ -I$(top_srcdir)/include \ -I$(top_srcdir)/examples/platforms \ -I$(top_srcdir)/src/core \ @@ -53,12 +54,14 @@ COMMONCPPFLAGS PLATFORM_COMMON_SOURCES = \ alarm.c \ + fem.c \ flash.c \ logging.c \ misc.c \ platform.c \ uart.c \ platform-config.h \ + platform-fem.h \ platform-nrf5.h \ radio.c \ random.c \ @@ -70,6 +73,7 @@ SINGLEPHY_SOURCES @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_direct.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_direct.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c \ $(NULL) @@ -85,6 +89,7 @@ SOFTDEVICE_SOURCES @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_priority_drop_swi.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request_swi.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c \ $(NULL) @@ -120,6 +125,7 @@ NORDICSEMI_SOURCES @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_pib.c \ @top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.c \ + @top_builddir@/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c \ @top_builddir@/third_party/NordicSemiconductor/segger_rtt/SEGGER_RTT.c \ @top_builddir@/third_party/NordicSemiconductor/segger_rtt/SEGGER_RTT_Conf.h \ @top_builddir@/third_party/NordicSemiconductor/device/gcc_startup_nrf52840.S \ @@ -190,6 +196,9 @@ noinst_HEADERS $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_procedures_duration.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_request.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_rx_buffer.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h \ + $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h \ $(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h \ diff --git a/examples/platforms/nrf52840/fem.c b/examples/platforms/nrf52840/fem.c new file mode 100644 index 000000000..578d400cd --- /dev/null +++ b/examples/platforms/nrf52840/fem.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 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 implements the OpenThread FEM helper functions. + * + */ + +#include +#include + +#include +#include + +#include "platform-fem.h" + +#define ENABLE_FEM 1 +#include + +void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig) +{ + nrf_drv_radio802154_fem_control_cfg_t cfg; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.pa_cfg.enable = aConfig->mPaCfg.mEnable; + cfg.pa_cfg.active_high = aConfig->mPaCfg.mActiveHigh; + cfg.pa_cfg.gpio_pin = aConfig->mPaCfg.mGpioPin; + cfg.lna_cfg.enable = aConfig->mLnaCfg.mEnable; + cfg.lna_cfg.active_high = aConfig->mLnaCfg.mActiveHigh; + cfg.lna_cfg.gpio_pin = aConfig->mLnaCfg.mGpioPin; + cfg.ppi_ch_id_clr = aConfig->mPpiChIdClr; + cfg.ppi_ch_id_set = aConfig->mPpiChIdSet; + cfg.radio_ppi_grp = aConfig->mRadioPpiGrp; + cfg.timer_ppi_grp = aConfig->mTimerPpiGrp; + cfg.gpiote_ch_id = aConfig->mGpioteChId; + + nrf_drv_radio802154_fem_control_cfg_set(&cfg); +} diff --git a/examples/platforms/nrf52840/platform-fem.h b/examples/platforms/nrf52840/platform-fem.h new file mode 100644 index 000000000..78c9dff0b --- /dev/null +++ b/examples/platforms/nrf52840/platform-fem.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017, 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 front end module platform-specific functions. + * + */ + +#ifndef PLATFORM_FEM_H_ +#define PLATFORM_FEM_H_ + +#include + + +#define PLATFORM_FEM_DEFAULT_PA_PIN 26 /**< Default Power Amplifier pin. */ +#define PLATFORM_FEM_DEFAULT_LNA_PIN 27 /**< Default Low Noise Amplifier pin. */ +#define PLATFORM_FEM_DEFAULT_SET_PPI_CHANNEL 18 /**< Default PPI channel for pin setting. */ +#define PLATFORM_FEM_DEFAULT_CLR_PPI_CHANNEL 19 /**< Default PPI channel for pin clearing. */ +#define PLATFORM_FEM_DEFAULT_TIMER_MATCH_PPI_GROUP 4 /**< Default PPI channel group used to disable timer match PPI. */ +#define PLATFORM_FEM_DEFAULT_RADIO_DISABLED_PPI_GROUP 5 /**< Default PPI channel group used to disable radio disabled PPI. */ +#define PLATFORM_FEM_DEFAULT_GPIOTE_CHANNEL 7 /**< Default GPIOTE channel for FEM control. */ + +#define PLATFORM_FEM_DEFAULT_CONFIG \ + ((PlatformFemConfigParams) { \ + .mPaCfg = { \ + .mEnable = 1, \ + .mActiveHigh = 1, \ + .mGpioPin = PLATFORM_FEM_DEFAULT_PA_PIN, \ + }, \ + .mLnaCfg = { \ + .mEnable = 1, \ + .mActiveHigh = 1, \ + .mGpioPin = PLATFORM_FEM_DEFAULT_LNA_PIN, \ + }, \ + .mPpiChIdClr = PLATFORM_FEM_DEFAULT_CLR_PPI_CHANNEL, \ + .mPpiChIdSet = PLATFORM_FEM_DEFAULT_SET_PPI_CHANNEL, \ + .mTimerPpiGrp = PLATFORM_FEM_DEFAULT_TIMER_MATCH_PPI_GROUP, \ + .mRadioPpiGrp = PLATFORM_FEM_DEFAULT_RADIO_DISABLED_PPI_GROUP, \ + .mGpioteChId = PLATFORM_FEM_DEFAULT_GPIOTE_CHANNEL, \ + }) + + +/** + * @brief Configuration parameters for the PA and LNA. + */ +typedef struct +{ + uint8_t mEnable : 1; /**< Enable toggling for this amplifier */ + uint8_t mActiveHigh : 1; /**< Set the pin to be active high */ + uint8_t mGpioPin : 6; /**< The GPIO pin to toggle for this amplifier */ +} PlatformFemConfigPaLna; + +/** + * @brief PA & LNA GPIO toggle configuration + * + * This option configures the nRF 802.15.4 radio driver to toggle pins when the radio + * is active for use with a power amplifier and/or a low noise amplifier. + * + * Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided + * by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled. + * + * @note Changing this configuration while the radio is in use may have undefined + * consequences and must be avoided by the application. + */ +typedef struct +{ + PlatformFemConfigPaLna mPaCfg; /**< Power Amplifier configuration */ + PlatformFemConfigPaLna mLnaCfg; /**< Low Noise Amplifier configuration */ + uint8_t mPpiChIdSet; /**< PPI channel used for radio pin setting */ + uint8_t mPpiChIdClr; /**< PPI channel used for radio pin clearing */ + uint8_t mTimerPpiGrp; /**< PPI group used for disabling timer match PPI. */ + uint8_t mRadioPpiGrp; /**< PPI group used for disabling radio disabled PPI. */ + uint8_t mGpioteChId; /**< GPIOTE channel used for radio pin toggling */ +} PlatformFemConfigParams; + +/** + * Function used to set parameters of FEM. + * + */ +void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig); + +#endif // PLATFORM_FEM_H_ diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h new file mode 100644 index 000000000..40c042468 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_api.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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. + * + */ + +/** + * @brief Front End Module control for the nRF 802.15.4 radio driver. + * + */ + +#ifndef NRF_FEM_CONTROL_API_H_ +#define NRF_FEM_CONTROL_API_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @section Resource configuration. + */ + +/** Default Power Amplifier pin. */ +#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 26 + +/** Default Low Noise Amplifier pin. */ +#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 27 + +/** Default PPI channel for pin setting. */ +#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 18 + +/** Default PPI channel for pin clearing. */ +#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 19 + +/** Default PPI channel group used to disable timer match PPI. */ +#define NRF_FEM_CONTROL_DEFAULT_TIMER_MATCH_PPI_GROUP 4 + +/** Default PPI channel group used to disable radio disabled PPI. */ +#define NRF_FEM_CONTROL_DEFAULT_RADIO_DISABLED_PPI_GROUP 5 + +/** Default GPIOTE channel for FEM control. */ +#define NRF_FEM_CONTROL_DEFAULT_GPIOTE_CHANNEL 7 + +#if ENABLE_FEM + +/** + * @brief Configuration parameters for the PA and LNA. + */ +typedef struct +{ + uint8_t enable :1; /**< Enable toggling for this amplifier */ + uint8_t active_high :1; /**< Set the pin to be active high */ + uint8_t gpio_pin :6; /**< The GPIO pin to toggle for this amplifier */ +} nrf_fem_control_pa_lna_cfg_t; + +/** + * @brief PA & LNA GPIO toggle configuration + * + * This option configures the nRF 802.15.4 radio driver to toggle pins when the radio + * is active for use with a power amplifier and/or a low noise amplifier. + * + * Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided + * by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled. + * + * @note Changing this configuration while the radio is in use may have undefined + * consequences and must be avoided by the application. + */ +typedef struct +{ + nrf_fem_control_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */ + nrf_fem_control_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */ + uint8_t ppi_ch_id_set; /**< PPI channel used for radio pin setting */ + uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */ + uint8_t timer_ppi_grp; /**< PPI group used for disabling timer match PPI. */ + uint8_t radio_ppi_grp; /**< PPI group used for disabling radio disabled PPI. */ + uint8_t gpiote_ch_id; /**< GPIOTE channel used for radio pin toggling */ +} nrf_fem_control_cfg_t; + +/**@brief Set PA & LNA GPIO toggle configuration. + * + * @note This function shall not be called when radio is in use. + * + * @param[in] p_cfg A pointer to the PA & LNA GPIO toggle configuration. + * + */ +void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg); + +/**@brief Get PA & LNA GPIO toggle configuration. + * + * @param[out] p_cfg A pointer to the structure for the PA & LNA GPIO toggle configuration. + * + */ +void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg); + +/**@brief Activate FEM controller. + * + * This function should be called when radio wakes up. + */ +void nrf_fem_control_activate(void); + +/**@brief De-activate FEM controller. + * + * This function should be called when radio goes to sleep. + */ +void nrf_fem_control_deactivate(void); + +/**@brief Latch current time in FEM controller. + * + * This function stores current time to enable precise time measurement and mitigate impact of code + * execution time. It should be called before triggering RXEN or TXEN task, and calling + * @ref nrf_fem_control_pa_set or @ref nrf_fem_control_lna_set funcitons. + */ +void nrf_fem_control_time_latch(void); + +/**@brief Activate Power Amplifier (TX) pin of the Front End Module. + * + * @param[in] shorts_used Information if this operation is related to a task triggered by a short. + * + * This function will set up a timer to activate the pin 5 +/- 2.5 us before radio READY event is generated. + * It will also set up a PPI to deactivate the pin on radio DISABLED event. + * + * @note This function shall always be called after @ref nrf_fem_control_time_latch function was called, + * to enable precise time measurement. + * */ +void nrf_fem_control_pa_set(bool shorts_used); + +/**@brief Activate Low Noise Amplifier (RX) pin of the Front End Module. + * + * @param[in] shorts_used Information if this operation is related to a task triggered by a short. + * + * This function will set up a timer to activate the pin 5 +/- 2.5 us before radio READY event is generated. + * It will also set up a PPI to deactivate the pin on radio DISABLED event. + * + * @note This function shall always be called after @ref nrf_fem_control_time_latch function was called, + * to enable precise time measurement. + * */ +void nrf_fem_control_lna_set(bool shorts_used); + +#else // ENABLE_FEM + +#define nrf_fem_control_cfg_set(...) +#define nrf_fem_control_cfg_get(...) +#define nrf_fem_control_activate(...) +#define nrf_fem_control_deactivate(...) +#define nrf_fem_control_time_latch(...) +#define nrf_fem_control_pa_set(...) +#define nrf_fem_control_lna_set(...) + +#endif // ENABLE_FEM + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FEM_CONTROL_API_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c new file mode 100644 index 000000000..40cc8f53d --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_common.c @@ -0,0 +1,220 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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 implements common function for Front End Module control of the nRF 802.15.4 radio driver. + * + */ + +#include "nrf_fem_control_api.h" + +#include "compiler_abstraction.h" +#include "nrf_fem_control_config.h" +#include "nrf_fem_control_internal.h" +#include "nrf.h" +#include "hal/nrf_gpio.h" +#include "hal/nrf_gpiote.h" +#include "hal/nrf_ppi.h" +#include "hal/nrf_radio.h" + +static nrf_fem_control_cfg_t m_nrf_fem_control_cfg; /**< FEM controller configuration. */ +static volatile uint32_t m_time_latch; /**< Recently latched timer value. */ + +/** + * @section GPIO control. + */ + +/** Initialize GPIO according to configuration provided. */ +static void gpio_init(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable) + { + nrf_gpio_cfg_output(m_nrf_fem_control_cfg.pa_cfg.gpio_pin); + nrf_gpio_pin_write(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, + !m_nrf_fem_control_cfg.pa_cfg.active_high); + } + + if (m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_gpio_cfg_output(m_nrf_fem_control_cfg.lna_cfg.gpio_pin); + nrf_gpio_pin_write(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, + !m_nrf_fem_control_cfg.lna_cfg.active_high); + } +} + +/** Configure GPIOTE task. */ +__STATIC_INLINE void gpiote_configure(uint8_t pin, nrf_gpiote_outinit_t init_val) +{ + nrf_gpiote_task_configure(m_nrf_fem_control_cfg.gpiote_ch_id, + pin, + NRF_GPIOTE_POLARITY_TOGGLE, + init_val); + + nrf_gpiote_task_enable(m_nrf_fem_control_cfg.gpiote_ch_id); +} + +/** + * @section PPI control. + */ + +/** Initialize PPI according to configuration provided. */ +static void ppi_init(void) +{ + nrf_ppi_channel_include_in_group(m_nrf_fem_control_cfg.ppi_ch_id_set, + m_nrf_fem_control_cfg.timer_ppi_grp); + nrf_ppi_channel_include_in_group(m_nrf_fem_control_cfg.ppi_ch_id_clr, + m_nrf_fem_control_cfg.radio_ppi_grp); + + nrf_ppi_channel_and_fork_endpoint_setup( + m_nrf_fem_control_cfg.ppi_ch_id_set, + (uint32_t)(&NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_FEM]), + (uint32_t)(&NRF_GPIOTE->TASKS_OUT[m_nrf_fem_control_cfg.gpiote_ch_id]), + (uint32_t)(&NRF_PPI->TASKS_CHG[m_nrf_fem_control_cfg.timer_ppi_grp].DIS)); + + // Workaround for FTPAN-114, disable PPI to prevent second radio DISABLED event trigger. + nrf_ppi_channel_and_fork_endpoint_setup( + m_nrf_fem_control_cfg.ppi_ch_id_clr, + (uint32_t)(&NRF_RADIO->EVENTS_DISABLED), + (uint32_t)(&NRF_GPIOTE->TASKS_OUT[m_nrf_fem_control_cfg.gpiote_ch_id]), + (uint32_t)(&NRF_PPI->TASKS_CHG[m_nrf_fem_control_cfg.radio_ppi_grp].DIS)); +} + +/** Enable PPI. */ +__STATIC_INLINE void ppi_enable(void) +{ + NRF_PPI->CHENSET = (1 << m_nrf_fem_control_cfg.ppi_ch_id_set) | + (1 << m_nrf_fem_control_cfg.ppi_ch_id_clr); +} + +/** Disable PPI. */ +__STATIC_INLINE void ppi_disable(void) +{ + NRF_PPI->CHENCLR = (1 << m_nrf_fem_control_cfg.ppi_ch_id_set) | + (1 << m_nrf_fem_control_cfg.ppi_ch_id_clr); +} + +/** + * @section FEM API functions. + */ + +void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg) +{ + m_nrf_fem_control_cfg = *p_cfg; + + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + gpio_init(); + ppi_init(); + nrf_fem_control_timer_init(); + } + else + { + nrf_fem_control_timer_deinit(); + } +} + +void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg) +{ + *p_cfg = m_nrf_fem_control_cfg; +} + +void nrf_fem_control_activate(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_fem_control_timer_start(); + } +} + +void nrf_fem_control_deactivate(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + nrf_fem_control_timer_stop(); + nrf_gpiote_task_disable(m_nrf_fem_control_cfg.gpiote_ch_id); + ppi_disable(); + } +} + +void nrf_fem_control_time_latch(void) +{ + if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable) + { + m_time_latch = nrf_fem_control_timer_time_get(); + } +} + +void nrf_fem_control_pa_set(bool shorts_used) +{ + uint32_t target_time; + + if (m_nrf_fem_control_cfg.pa_cfg.enable) + { + gpiote_configure(m_nrf_fem_control_cfg.pa_cfg.gpio_pin, + !m_nrf_fem_control_cfg.pa_cfg.active_high); + ppi_enable(); + + uint32_t tifs = nrf_radio_ifs_get(); + + target_time = tifs <= NRF_FEM_RADIO_TX_STARTUP_LATENCY_US ? + m_time_latch + NRF_FEM_RADIO_TX_STARTUP_LATENCY_US - NRF_FEM_PA_TIME_IN_ADVANCE : + m_time_latch + tifs - NRF_FEM_RADIO_TIFS_DRIFT_US - NRF_FEM_PA_TIME_IN_ADVANCE; + + if (shorts_used) + { + target_time -= nrf_fem_control_irq_delay_get(); + } + + nrf_fem_control_timer_set(target_time); + } +} + +void nrf_fem_control_lna_set(bool shorts_used) +{ + uint32_t target_time; + + if (m_nrf_fem_control_cfg.lna_cfg.enable) + { + gpiote_configure(m_nrf_fem_control_cfg.lna_cfg.gpio_pin, + !m_nrf_fem_control_cfg.lna_cfg.active_high); + ppi_enable(); + + target_time = m_time_latch + NRF_FEM_RADIO_RX_STARTUP_LATENCY_US - + NRF_FEM_LNA_TIME_IN_ADVANCE; + + if (shorts_used) + { + target_time -= nrf_fem_control_irq_delay_get(); + } + + nrf_fem_control_timer_set(target_time); + } +} diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h new file mode 100644 index 000000000..7546c9006 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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. + * + */ + +#ifndef NRF_FEM_CONTROL_CONFIG_H_ +#define NRF_FEM_CONTROL_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @section Timings. + */ + +/** Time in us when PA GPIO is activated before radio is ready for transmission. */ +#define NRF_FEM_PA_TIME_IN_ADVANCE 5 + +/** Time in us when LNA GPIO is activated before radio is ready for reception. */ +#define NRF_FEM_LNA_TIME_IN_ADVANCE 5 + +#ifdef NRF52840_XXAA + +/** Radio ramp-up time in TX mode, in us. */ +#define NRF_FEM_RADIO_TX_STARTUP_LATENCY_US 129 + +/** Radio ramp-up time in RX mode, in us. */ +#define NRF_FEM_RADIO_RX_STARTUP_LATENCY_US 129 + +/** Tifs drift measured, in us. */ +#define NRF_FEM_RADIO_TIFS_DRIFT_US 20 + +#else + +#error "Device not supported." + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FEM_CONTROL_CONFIG_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c new file mode 100644 index 000000000..33086a319 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_direct.c @@ -0,0 +1,91 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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 implements internal functions of Front End Module control for standalone version of + * the nRF 802.15.4 radio driver. + * + */ + +#include "nrf_fem_control_internal.h" + +#include "hal/nrf_timer.h" + +static bool m_timer_started = false; /**< Information if timer is running. */ + +void nrf_fem_control_timer_start(void) +{ + if (!m_timer_started) + { + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_START); + + m_timer_started = true; + } +} + +void nrf_fem_control_timer_stop(void) +{ + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); + + m_timer_started = false; +} + +void nrf_fem_control_timer_set(uint32_t target) +{ + nrf_timer_cc_write(NRF_TIMER0, TIMER_CC_FEM, target); +} + +uint32_t nrf_fem_control_timer_time_get(void) +{ + NRF_TIMER0->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1; + return NRF_TIMER0->CC[TIMER_CC_CAPTURE]; +} + +void nrf_fem_control_timer_init(void) +{ + nrf_fem_control_timer_stop(); + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); + + nrf_timer_mode_set(NRF_TIMER0, NRF_TIMER_MODE_TIMER); + nrf_timer_bit_width_set(NRF_TIMER0, NRF_TIMER_BIT_WIDTH_32); + nrf_timer_frequency_set(NRF_TIMER0, NRF_TIMER_FREQ_1MHz); +} + +void nrf_fem_control_timer_deinit(void) +{ + nrf_fem_control_timer_stop(); + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); +} + +uint32_t nrf_fem_control_irq_delay_get(void) +{ + return 0; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h new file mode 100644 index 000000000..464184757 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_internal.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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. + * + */ + +/** + * @brief Front End Module control internal functions. + * + */ + +#ifndef NRF_FEM_CONTROL_INTERNAL_H_ +#define NRF_FEM_CONTROL_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_fem_control_api.h" + +#define TIMER_CC_FEM 3 /**< Compare channel used by the module. */ +#define TIMER_CC_CAPTURE 2 /**< Compare channel used for time capture. */ + +/**@brief Start timer used by the module. */ +void nrf_fem_control_timer_start(void); + +/**@brief Stop timer used by the module. */ +void nrf_fem_control_timer_stop(void); + +/**@brief Set timer CC target value. + * + * @param[in] target Traget time. + */ +void nrf_fem_control_timer_set(uint32_t target); + +/**@brief Get current time from the timer. + * + * @retval Current timer time. + */ +uint32_t nrf_fem_control_timer_time_get(void); + +/**@brief Initialize timer. */ +void nrf_fem_control_timer_init(void); + +/**@brief De-initialize timer. */ +void nrf_fem_control_timer_deinit(void); + +/**@brief Get configuration specific irq entry delay. + * + * @retval Delay value. + */ +uint32_t nrf_fem_control_irq_delay_get(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FEM_CONTROL_INTERNAL_H_ */ diff --git a/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c new file mode 100644 index 000000000..821be2fa1 --- /dev/null +++ b/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_softdevice.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2017, Nordic Semiconductor ASA + * 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 Nordic Semiconductor ASA 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 implements internal functions of Front End Module control for + * nRF 802.15.4 radio driver working with SoftDevice RAAL. + * + */ + +#include "nrf_fem_control_internal.h" + +#include "hal/nrf_timer.h" + +#define SOFTDEVICE_IRQ_ENTRY_DELAY 4UL /**< An IRQ entry delay when using SoftDevice. */ + +void nrf_fem_control_timer_start(void) +{ + // Intentionally empty. In this configuration timer is controlled by RAAL. +} + +void nrf_fem_control_timer_stop(void) +{ + // Intentionally empty. In this configuration timer is controlled by RAAL. +} + +void nrf_fem_control_timer_set(uint32_t target) +{ + nrf_timer_cc_write(NRF_TIMER0, TIMER_CC_FEM, target); +} + +uint32_t nrf_fem_control_timer_time_get(void) +{ + NRF_TIMER0->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1; + return NRF_TIMER0->CC[TIMER_CC_CAPTURE]; +} + +void nrf_fem_control_timer_init(void) +{ + // Intentionally empty. In this configuration timer is controlled by RAAL. +} + +void nrf_fem_control_timer_deinit(void) +{ + // Intentionally empty. In this configuration timer is controlled by RAAL. +} + +uint32_t nrf_fem_control_irq_delay_get(void) +{ + return SOFTDEVICE_IRQ_ENTRY_DELAY; +} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c index 13b53c737..f6a2f81a6 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c @@ -57,6 +57,10 @@ #include +#if ENABLE_FEM +#include "fem/nrf_fem_control_api.h" +#endif + #define RAW_LENGTH_OFFSET 0 #define RAW_PAYLOAD_OFFSET 1 @@ -134,6 +138,18 @@ void nrf_drv_radio802154_irq_handler(void) } #endif // !RADIO_INTERNAL_IRQ_HANDLING +#if ENABLE_FEM +void nrf_drv_radio802154_fem_control_cfg_set(const nrf_drv_radio802154_fem_control_cfg_t * p_cfg) +{ + nrf_fem_control_cfg_set(p_cfg); +} + +void nrf_drv_radio802154_fem_control_cfg_get(nrf_drv_radio802154_fem_control_cfg_t * p_cfg) +{ + nrf_fem_control_cfg_get(p_cfg); +} +#endif + nrf_drv_radio802154_state_t nrf_drv_radio802154_state_get(void) { switch (nrf_drv_radio802154_fsm_state_get()) @@ -299,6 +315,41 @@ int8_t nrf_drv_radio802154_rssi_last_get(void) return - (int8_t)minus_dbm; } +int8_t nrf_drv_radio802154_rssi_corrected_get(int8_t rssi, int8_t temp) +{ + if (temp <= -30) + { + return rssi + 3; + } + + if (temp <= -10) + { + return rssi + 2; + } + + if (temp <= 10) + { + return rssi + 1; + } + + if (temp <= 30) + { + return rssi; + } + + if (temp <= 50) + { + return rssi - 1; + } + + if (temp <= 70) + { + return rssi - 2; + } + + return rssi - 3; +} + bool nrf_drv_radio802154_promiscuous_get(void) { return nrf_drv_radio802154_pib_promiscuous_get(); diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h index c8ccb13c9..f007c2a61 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h @@ -42,6 +42,10 @@ #include "nrf_drv_radio802154_config.h" #include "hal/nrf_radio.h" +#if ENABLE_FEM +#include "fem/nrf_fem_control_api.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -132,6 +136,54 @@ void nrf_drv_radio802154_tx_power_set(int8_t power); */ int8_t nrf_drv_radio802154_tx_power_get(void); +/** + * @section Front-end module management. + */ + +#if ENABLE_FEM + +typedef nrf_fem_control_cfg_t nrf_drv_radio802154_fem_control_cfg_t; + +#define NRF_DRV_RADIO802154_FEM_DEFAULT_SETTINGS \ + ((nrf_drv_radio802154_fem_control_cfg_t) { \ + .pa_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \ + }, \ + .lna_cfg = { \ + .enable = 1, \ + .active_high = 1, \ + .gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \ + }, \ + .ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \ + .ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \ + .radio_ppi_grp = NRF_FEM_CONTROL_DEFAULT_TIMER_MATCH_PPI_GROUP, \ + .timer_ppi_grp = NRF_FEM_CONTROL_DEFAULT_RADIO_DISABLED_PPI_GROUP, \ + .gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_GPIOTE_CHANNEL, \ + }) + +/** + * @brief Set PA & LNA GPIO toggle configuration. + * + * @note This function shall not be called when radio is in use. + * + * @param[in] p_cfg A pointer to the PA & LNA GPIO toggle configuration. + * + */ +void nrf_drv_radio802154_fem_control_cfg_set(const nrf_drv_radio802154_fem_control_cfg_t * p_cfg); + +/** + * @brief Get PA & LNA GPIO toggle configuration. + * + * @param[out] p_cfg A pointer to the structure for the PA & LNA GPIO toggle configuration. + * + */ +void nrf_drv_radio802154_fem_control_cfg_get(nrf_drv_radio802154_fem_control_cfg_t * p_cfg); + +#endif // ENABLE_FEM + + /** * @section Setting addresses and Pan Id of this device. */ @@ -526,6 +578,16 @@ void nrf_drv_radio802154_rssi_measure(void); */ int8_t nrf_drv_radio802154_rssi_last_get(void); +/** + * @brief Adjust given RSSI measurement using a temperature correction factor. + * + * @param[in] rssi Measured RSSI value [dBm]. + * @param[in] temp Temperature value when RSSI sample took place [C]. + * + * @returns RSSI [dBm] corrected by a temperature factor (Errata 153). + */ +int8_t nrf_drv_radio802154_rssi_corrected_get(int8_t rssi, int8_t temp); + /** * @section Promiscuous mode. diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h index 64c5168e5..21b9024e5 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_config.h @@ -142,7 +142,7 @@ extern "C" { * Priority of software interrupt used to call notification from 802.15.4 driver. * */ -#define RADIO_NOTIFICATION_SWI_PRIORITY 6 +#define RADIO_NOTIFICATION_SWI_PRIORITY 5 /** *@} diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c index 432ac75f3..dd4fb9502 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c @@ -51,6 +51,7 @@ #include "nrf_drv_radio802154_priority_drop.h" #include "nrf_drv_radio802154_procedures_duration.h" #include "nrf_drv_radio802154_rx_buffer.h" +#include "fem/nrf_fem_control_api.h" #include "hal/nrf_radio.h" #include "raal/nrf_raal_api.h" @@ -190,6 +191,15 @@ static inline void state_set(radio_state_t state) { m_state = state; + if (m_state == RADIO_STATE_SLEEP) + { + nrf_fem_control_deactivate(); + } + else + { + nrf_fem_control_activate(); + } + nrf_drv_radio802154_log(EVENT_SET_STATE, (uint32_t)state); } @@ -260,6 +270,22 @@ static void cca_configuration_update(void) nrf_radio_cca_corr_counter_set(cca_cfg.corr_limit); } +/** Trigger RX task. */ +static void rx_enable(void) +{ + nrf_fem_control_time_latch(); + nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + nrf_fem_control_lna_set(false); +} + +/** Trigger TX task. */ +static void tx_enable(void) +{ + nrf_fem_control_time_latch(); + nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN); + nrf_fem_control_pa_set(false); +} + /*************************************************************************************************** * @section Radio parameters calculators **************************************************************************************************/ @@ -600,6 +626,7 @@ void nrf_raal_timeslot_ended(void) irq_deinit(); nrf_radio_reset(); + nrf_fem_control_deactivate(); switch (m_state) { @@ -1029,7 +1056,7 @@ static inline void irq_disabled_state_waiting_rx_frame(void) assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + rx_enable(); mutex_unlock(); rx_buffer_in_use_set(nrf_drv_radio802154_rx_buffer_free_find()); @@ -1074,6 +1101,12 @@ static inline void irq_disabled_state_tx_ack(void) auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); } + else + { + // nrf_fem_control_time_latch was called at the beginning of the irq handler, + // to capture the time as close to short occurence as possible + nrf_fem_control_pa_set(true); + } } /** This event is generated before CCA procedure starts. @@ -1084,7 +1117,8 @@ static inline void irq_disabled_state_cca_before_tx(void) { assert(nrf_radio_shorts_get() == SHORTS_IDLE); assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + + rx_enable(); } /** This event is generated before transmission of a frame starts. @@ -1096,7 +1130,8 @@ static inline void irq_disabled_state_tx_frame(void) if (nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED) { shorts_tx_frame_set(); - nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN); + + tx_enable(); } assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME); @@ -1110,7 +1145,8 @@ static inline void irq_disabled_state_rx_ack(void) { assert(nrf_radio_shorts_get() == SHORTS_IDLE); assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + + rx_enable(); if (mp_current_rx_buffer == NULL || (!mp_current_rx_buffer->free)) { @@ -1127,7 +1163,8 @@ static inline void irq_disabled_state_ed(void) { assert(nrf_radio_shorts_get() == SHORTS_IDLE); assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + + rx_enable(); } /** This event is generated before stand-alone CCA procedure. @@ -1138,7 +1175,8 @@ static inline void irq_disabled_state_cca(void) { assert(nrf_radio_shorts_get() == SHORTS_IDLE); assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN); + + rx_enable(); } /** This event is generated before continuous-carrier procedure is started. @@ -1150,7 +1188,8 @@ static inline void irq_disabled_state_continuous_carrier(void) { assert(nrf_radio_shorts_get() == SHORTS_IDLE); assert(nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED); - nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN); + + tx_enable(); } /** This event is generated when receiver is ready to start receiving a frame. @@ -1328,6 +1367,8 @@ static inline void irq_edend(void) /// Handler of radio interrupts. static inline void irq_handler(void) { + nrf_fem_control_time_latch(); + nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_IRQ_HANDLER); if (nrf_radio_event_get(NRF_RADIO_EVENT_FRAMESTART)) @@ -1551,6 +1592,10 @@ static inline void irq_handler(void) case RADIO_STATE_TX_FRAME: #if !RADIO_SHORT_CCAIDLE_TXEN irq_ccaidle_state_tx_frame(); +#else + // nrf_fem_control_time_latch was called at the beginning of the irq handler, + // to capture the time as close to short occurence as possible + nrf_fem_control_pa_set(true); #endif break; @@ -1558,6 +1603,13 @@ static inline void irq_handler(void) irq_ccaidle_state_cca(); break; +#if RADIO_SHORT_CCAIDLE_TXEN + case RADIO_STATE_WAITING_RX_FRAME: + case RADIO_STATE_RX_ACK: + // If CCAIDLE->TXEN short is enabled, this event may be handled after event END. + break; +#endif + case RADIO_STATE_WAITING_TIMESLOT: // Exit as soon as possible when waiting for timeslot. break; @@ -1626,6 +1678,11 @@ static inline void tx_procedure_abort(radio_state_t state) state_set(state); + // Stop CCA and clear result. CCA may be performed regardless disabled receiver. + nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTOP); + nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE); + nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY); + switch (nrf_radio_state_get()) { case NRF_RADIO_STATE_TX_DISABLE: diff --git a/third_party/NordicSemiconductor/hal/nrf_gpio.h b/third_party/NordicSemiconductor/hal/nrf_gpio.h index 2fb7b2dde..7fb8d7886 100644 --- a/third_party/NordicSemiconductor/hal/nrf_gpio.h +++ b/third_party/NordicSemiconductor/hal/nrf_gpio.h @@ -1,39 +1,19 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA - * All rights reserved. +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * - * 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 Nordic Semiconductor ASA 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. + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. * */ - #ifndef NRF_GPIO_H__ #define NRF_GPIO_H__ #include "nrf.h" #include "nrf_peripherals.h" -#include "nrf_assert.h" #include #include @@ -452,7 +432,7 @@ __STATIC_INLINE void nrf_gpio_pin_latch_clear(uint32_t pin_number); */ __STATIC_INLINE NRF_GPIO_Type * nrf_gpio_pin_port_decode(uint32_t * p_pin) { - ASSERT(*p_pin < NUMBER_OF_PINS); + //ASSERT(*p_pin < NUMBER_OF_PINS); #if (GPIO_COUNT == 1) // The oldest definition case return NRF_GPIO; @@ -732,7 +712,7 @@ __STATIC_INLINE void nrf_gpio_ports_read(uint32_t start_port, uint32_t length, u { NRF_GPIO_Type * gpio_regs[GPIO_COUNT] = GPIO_REG_LIST; - ASSERT(start_port + length <= GPIO_COUNT); + //ASSERT(start_port + length <= GPIO_COUNT); uint32_t i; for (i = start_port; i < (start_port + length); i++) diff --git a/third_party/NordicSemiconductor/hal/nrf_gpiote.h b/third_party/NordicSemiconductor/hal/nrf_gpiote.h index ac23f4715..8f1dfb9a5 100644 --- a/third_party/NordicSemiconductor/hal/nrf_gpiote.h +++ b/third_party/NordicSemiconductor/hal/nrf_gpiote.h @@ -1,33 +1,14 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA - * All rights reserved. +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * - * 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 Nordic Semiconductor ASA 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. + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. * */ - #ifndef NRF_GPIOTE_H__ #define NRF_GPIOTE_H__ diff --git a/third_party/NordicSemiconductor/hal/nrf_ppi.h b/third_party/NordicSemiconductor/hal/nrf_ppi.h index c429a187a..d217d0a8e 100644 --- a/third_party/NordicSemiconductor/hal/nrf_ppi.h +++ b/third_party/NordicSemiconductor/hal/nrf_ppi.h @@ -1,30 +1,12 @@ -/* Copyright (c) 2016, Nordic Semiconductor ASA - * All rights reserved. +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * - * 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 Nordic Semiconductor ASA 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. + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. * */ diff --git a/third_party/NordicSemiconductor/hal/nrf_radio.h b/third_party/NordicSemiconductor/hal/nrf_radio.h index 3150f0ed1..7a500b130 100644 --- a/third_party/NordicSemiconductor/hal/nrf_radio.h +++ b/third_party/NordicSemiconductor/hal/nrf_radio.h @@ -593,6 +593,16 @@ __STATIC_INLINE void nrf_radio_ifs_set(uint32_t radio_ifs) NRF_RADIO->TIFS = radio_ifs; } +/** + * @brief Function for getting Inter Frame Spacing + * + * @return Current Inter Frame Spacing + */ +__STATIC_INLINE uint32_t nrf_radio_ifs_get(void) +{ + return NRF_RADIO->TIFS & RADIO_TIFS_TIFS_Msk; +} + /** * @brief Function for setting Bit counter compare. * diff --git a/third_party/NordicSemiconductor/hal/nrf_timer.h b/third_party/NordicSemiconductor/hal/nrf_timer.h new file mode 100644 index 000000000..942fbc6f9 --- /dev/null +++ b/third_party/NordicSemiconductor/hal/nrf_timer.h @@ -0,0 +1,589 @@ +/*$$$LICENCE_NORDIC_STANDARD<2014>$$$*/ +/** + * @defgroup nrf_timer_hal Timer HAL + * @{ + * @ingroup nrf_timer + * + * @brief Hardware access layer for accessing the timer peripheral. + */ + +#ifndef NRF_TIMER_H__ +#define NRF_TIMER_H__ + +#include +#include +#include + +#include "nrf_peripherals.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Macro for validating the correctness of the BIT_WIDTH setting. + */ + +#define TIMER_MAX_SIZE(id) CONCAT_3(TIMER, id, _MAX_SIZE) + +#define TIMER_BIT_WIDTH_MAX(id, bit_width) \ + (TIMER_MAX_SIZE(id) == 8 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) : \ + (TIMER_MAX_SIZE(id) == 16 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) : \ + (TIMER_MAX_SIZE(id) == 24 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_24) : \ + (TIMER_MAX_SIZE(id) == 32 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_24) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_32) : \ + false)))) + +#if TIMER_COUNT > 3 +#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_reg, bit_width) ( \ + ((p_reg == NRF_TIMER0) && (TIMER_BIT_WIDTH_MAX(0, bit_width))) \ + || ((p_reg == NRF_TIMER1) && (TIMER_BIT_WIDTH_MAX(1, bit_width))) \ + || ((p_reg == NRF_TIMER2) && (TIMER_BIT_WIDTH_MAX(2, bit_width))) \ + || ((p_reg == NRF_TIMER3) && (TIMER_BIT_WIDTH_MAX(3, bit_width))) \ + || ((p_reg == NRF_TIMER4) && (TIMER_BIT_WIDTH_MAX(4, bit_width))) ) + +#else +#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_reg, bit_width) ( \ + ((p_reg == NRF_TIMER0) && TIMER_BIT_WIDTH_MAX(0, bit_width)) \ + || ((p_reg == NRF_TIMER1) && TIMER_BIT_WIDTH_MAX(1, bit_width)) \ + || ((p_reg == NRF_TIMER2) && TIMER_BIT_WIDTH_MAX(2, bit_width)) ) + +#endif + +/** + * @brief Macro for getting the number of capture/compare channels available + * in a given timer instance. + */ +#define NRF_TIMER_CC_CHANNEL_COUNT(id) CONCAT_3(TIMER, id, _CC_NUM) + +/** + * @brief Timer tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_TIMER_TASK_START = offsetof(NRF_TIMER_Type, TASKS_START), ///< Task for starting the timer. + NRF_TIMER_TASK_STOP = offsetof(NRF_TIMER_Type, TASKS_STOP), ///< Task for stopping the timer. + NRF_TIMER_TASK_COUNT = offsetof(NRF_TIMER_Type, TASKS_COUNT), ///< Task for incrementing the timer (in counter mode). + NRF_TIMER_TASK_CLEAR = offsetof(NRF_TIMER_Type, TASKS_CLEAR), ///< Task for resetting the timer value. + NRF_TIMER_TASK_SHUTDOWN = offsetof(NRF_TIMER_Type, TASKS_SHUTDOWN), ///< Task for powering off the timer. + NRF_TIMER_TASK_CAPTURE0 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[0]), ///< Task for capturing the timer value on channel 0. + NRF_TIMER_TASK_CAPTURE1 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[1]), ///< Task for capturing the timer value on channel 1. + NRF_TIMER_TASK_CAPTURE2 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[2]), ///< Task for capturing the timer value on channel 2. + NRF_TIMER_TASK_CAPTURE3 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[3]), ///< Task for capturing the timer value on channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_TASK_CAPTURE4 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[4]), ///< Task for capturing the timer value on channel 4. + NRF_TIMER_TASK_CAPTURE5 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[5]), ///< Task for capturing the timer value on channel 5. +#endif + /*lint -restore*/ +} nrf_timer_task_t; + +/** + * @brief Timer events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TIMER_EVENT_COMPARE0 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[0]), ///< Event from compare channel 0. + NRF_TIMER_EVENT_COMPARE1 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[1]), ///< Event from compare channel 1. + NRF_TIMER_EVENT_COMPARE2 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[2]), ///< Event from compare channel 2. + NRF_TIMER_EVENT_COMPARE3 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[3]), ///< Event from compare channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_EVENT_COMPARE4 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[4]), ///< Event from compare channel 4. + NRF_TIMER_EVENT_COMPARE5 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[5]), ///< Event from compare channel 5. +#endif + /*lint -restore*/ +} nrf_timer_event_t; + +/** + * @brief Types of timer shortcuts. + */ +typedef enum +{ + NRF_TIMER_SHORT_COMPARE0_STOP_MASK = TIMER_SHORTS_COMPARE0_STOP_Msk, ///< Shortcut for stopping the timer based on compare 0. + NRF_TIMER_SHORT_COMPARE1_STOP_MASK = TIMER_SHORTS_COMPARE1_STOP_Msk, ///< Shortcut for stopping the timer based on compare 1. + NRF_TIMER_SHORT_COMPARE2_STOP_MASK = TIMER_SHORTS_COMPARE2_STOP_Msk, ///< Shortcut for stopping the timer based on compare 2. + NRF_TIMER_SHORT_COMPARE3_STOP_MASK = TIMER_SHORTS_COMPARE3_STOP_Msk, ///< Shortcut for stopping the timer based on compare 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_SHORT_COMPARE4_STOP_MASK = TIMER_SHORTS_COMPARE4_STOP_Msk, ///< Shortcut for stopping the timer based on compare 4. + NRF_TIMER_SHORT_COMPARE5_STOP_MASK = TIMER_SHORTS_COMPARE5_STOP_Msk, ///< Shortcut for stopping the timer based on compare 5. +#endif + NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK = TIMER_SHORTS_COMPARE0_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 0. + NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK = TIMER_SHORTS_COMPARE1_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 1. + NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK = TIMER_SHORTS_COMPARE2_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 2. + NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK = TIMER_SHORTS_COMPARE3_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK = TIMER_SHORTS_COMPARE4_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 4. + NRF_TIMER_SHORT_COMPARE5_CLEAR_MASK = TIMER_SHORTS_COMPARE5_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 5. +#endif +} nrf_timer_short_mask_t; + +/** + * @brief Timer modes. + */ +typedef enum +{ + NRF_TIMER_MODE_TIMER = TIMER_MODE_MODE_Timer, ///< Timer mode: timer. + NRF_TIMER_MODE_COUNTER = TIMER_MODE_MODE_Counter, ///< Timer mode: counter. +#if defined(TIMER_MODE_MODE_LowPowerCounter) || defined(__SDK_DOXYGEN__) + NRF_TIMER_MODE_LOW_POWER_COUNTER = TIMER_MODE_MODE_LowPowerCounter, ///< Timer mode: low-power counter. +#endif +} nrf_timer_mode_t; + +/** + * @brief Timer bit width. + */ +typedef enum +{ + NRF_TIMER_BIT_WIDTH_8 = TIMER_BITMODE_BITMODE_08Bit, ///< Timer bit width 8 bit. + NRF_TIMER_BIT_WIDTH_16 = TIMER_BITMODE_BITMODE_16Bit, ///< Timer bit width 16 bit. + NRF_TIMER_BIT_WIDTH_24 = TIMER_BITMODE_BITMODE_24Bit, ///< Timer bit width 24 bit. + NRF_TIMER_BIT_WIDTH_32 = TIMER_BITMODE_BITMODE_32Bit ///< Timer bit width 32 bit. +} nrf_timer_bit_width_t; + +/** + * @brief Timer prescalers. + */ +typedef enum +{ + NRF_TIMER_FREQ_16MHz = 0, ///< Timer frequency 16 MHz. + NRF_TIMER_FREQ_8MHz, ///< Timer frequency 8 MHz. + NRF_TIMER_FREQ_4MHz, ///< Timer frequency 4 MHz. + NRF_TIMER_FREQ_2MHz, ///< Timer frequency 2 MHz. + NRF_TIMER_FREQ_1MHz, ///< Timer frequency 1 MHz. + NRF_TIMER_FREQ_500kHz, ///< Timer frequency 500 kHz. + NRF_TIMER_FREQ_250kHz, ///< Timer frequency 250 kHz. + NRF_TIMER_FREQ_125kHz, ///< Timer frequency 125 kHz. + NRF_TIMER_FREQ_62500Hz, ///< Timer frequency 62500 Hz. + NRF_TIMER_FREQ_31250Hz ///< Timer frequency 31250 Hz. +} nrf_timer_frequency_t; + +/** + * @brief Timer capture/compare channels. + */ +typedef enum +{ + NRF_TIMER_CC_CHANNEL0 = 0, ///< Timer capture/compare channel 0. + NRF_TIMER_CC_CHANNEL1, ///< Timer capture/compare channel 1. + NRF_TIMER_CC_CHANNEL2, ///< Timer capture/compare channel 2. + NRF_TIMER_CC_CHANNEL3, ///< Timer capture/compare channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_CC_CHANNEL4, ///< Timer capture/compare channel 4. + NRF_TIMER_CC_CHANNEL5, ///< Timer capture/compare channel 5. +#endif +} nrf_timer_cc_channel_t; + +/** + * @brief Timer interrupts. + */ +typedef enum +{ + NRF_TIMER_INT_COMPARE0_MASK = TIMER_INTENSET_COMPARE0_Msk, ///< Timer interrupt from compare event on channel 0. + NRF_TIMER_INT_COMPARE1_MASK = TIMER_INTENSET_COMPARE1_Msk, ///< Timer interrupt from compare event on channel 1. + NRF_TIMER_INT_COMPARE2_MASK = TIMER_INTENSET_COMPARE2_Msk, ///< Timer interrupt from compare event on channel 2. + NRF_TIMER_INT_COMPARE3_MASK = TIMER_INTENSET_COMPARE3_Msk, ///< Timer interrupt from compare event on channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_INT_COMPARE4_MASK = TIMER_INTENSET_COMPARE4_Msk, ///< Timer interrupt from compare event on channel 4. + NRF_TIMER_INT_COMPARE5_MASK = TIMER_INTENSET_COMPARE5_Msk, ///< Timer interrupt from compare event on channel 5. +#endif +} nrf_timer_int_mask_t; + + +/** + * @brief Function for activating a specific timer task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task); + +/** + * @brief Function for getting the address of a specific timer task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task); + +/** + * @brief Function for clearing a specific timer event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for checking the state of a specific timer event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for getting the address of a specific timer event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_reg, + uint32_t timer_int); + +/** + * @brief Function for setting the timer mode. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] mode Timer mode. + */ +__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_reg, + nrf_timer_mode_t mode); + +/** + * @brief Function for retrieving the timer mode. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer mode. + */ +__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for setting the timer bit width. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] bit_width Timer bit width. + */ +__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_reg, + nrf_timer_bit_width_t bit_width); + +/** + * @brief Function for retrieving the timer bit width. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer bit width. + */ +__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for setting the timer frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency Timer frequency. + */ +__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_reg, + nrf_timer_frequency_t frequency); + +/** + * @brief Function for retrieving the timer frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer frequency. + */ +__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for writing the capture/compare register for a specified channel. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] cc_channel Requested capture/compare channel. + * @param[in] cc_value Value to write to the capture/compare register. + */ +__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value); + +/** + * @brief Function for retrieving the capture/compare value for a specified channel. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] cc_channel Requested capture/compare channel. + * + * @return Value from the requested capture/compare register. + */ +__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel); + +/** + * @brief Function for getting a specific timer capture task. + * + * @param[in] channel Capture channel. + * + * @return Capture task. + */ +__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel); + +/** + * @brief Function for getting a specific timer compare event. + * + * @param[in] channel Compare channel. + * + * @return Compare event. + */ +__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel); + +/** + * @brief Function for getting a specific timer compare interrupt. + * + * @param[in] channel Compare channel. + * + * @return Compare interrupt. + */ +__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel); + +/** + * @brief Function for calculating the number of timer ticks for a given time + * (in microseconds) and timer frequency. + * + * @param[in] time_us Time in microseconds. + * @param[in] frequency Timer frequency. + * + * @return Number of timer ticks. + */ +__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us, + nrf_timer_frequency_t frequency); + +/** + * @brief Function for calculating the number of timer ticks for a given time + * (in milliseconds) and timer frequency. + * + * @param[in] time_ms Time in milliseconds. + * @param[in] frequency Timer frequency. + * + * @return Number of timer ticks. + */ +__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms, + nrf_timer_frequency_t frequency); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask) +{ + p_reg->SHORTS |= timer_shorts_mask; +} + +__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask) +{ + p_reg->SHORTS &= ~(timer_shorts_mask); +} + +__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask) +{ + p_reg->INTENSET = timer_int_mask; +} + +__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask) +{ + p_reg->INTENCLR = timer_int_mask; +} + +__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_reg, + uint32_t timer_int) +{ + return (bool)(p_reg->INTENSET & timer_int); +} + +__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_reg, + nrf_timer_mode_t mode) +{ + p_reg->MODE = (p_reg->MODE & ~TIMER_MODE_MODE_Msk) | + ((mode << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk); +} + +__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_mode_t)(p_reg->MODE); +} + +__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_reg, + nrf_timer_bit_width_t bit_width) +{ + p_reg->BITMODE = (p_reg->BITMODE & ~TIMER_BITMODE_BITMODE_Msk) | + ((bit_width << TIMER_BITMODE_BITMODE_Pos) & + TIMER_BITMODE_BITMODE_Msk); +} + +__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_bit_width_t)(p_reg->BITMODE); +} + +__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_reg, + nrf_timer_frequency_t frequency) +{ + p_reg->PRESCALER = (p_reg->PRESCALER & ~TIMER_PRESCALER_PRESCALER_Msk) | + ((frequency << TIMER_PRESCALER_PRESCALER_Pos) & + TIMER_PRESCALER_PRESCALER_Msk); +} + +__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_frequency_t)(p_reg->PRESCALER); +} + +__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value) +{ + p_reg->CC[cc_channel] = cc_value; +} + +__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel) +{ + return (uint32_t)p_reg->CC[cc_channel]; +} + +__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel) +{ + return (nrf_timer_task_t) + ((uint32_t)NRF_TIMER_TASK_CAPTURE0 + (channel * sizeof(uint32_t))); +} + +__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel) +{ + return (nrf_timer_event_t) + ((uint32_t)NRF_TIMER_EVENT_COMPARE0 + (channel * sizeof(uint32_t))); +} + +__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel) +{ + return (nrf_timer_int_mask_t) + ((uint32_t)NRF_TIMER_INT_COMPARE0_MASK << channel); +} + +__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us, + nrf_timer_frequency_t frequency) +{ + // The "frequency" parameter here is actually the prescaler value, and the + // timer runs at the following frequency: f = 16 MHz / 2^prescaler. + uint32_t prescaler = (uint32_t)frequency; + return ((time_us * 16UL) >> prescaler); +} + +__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms, + nrf_timer_frequency_t frequency) +{ + // The "frequency" parameter here is actually the prescaler value, and the + // timer runs at the following frequency: f = 16000 kHz / 2^prescaler. + uint32_t prescaler = (uint32_t)frequency; + return ((time_ms * 16000UL) >> prescaler); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_TIMER_H__ + +/** @} */