diff --git a/nrf_802154/driver/include/nrf_802154_types.h b/nrf_802154/driver/include/nrf_802154_types.h index cd7332e8dc..076f8f4487 100644 --- a/nrf_802154/driver/include/nrf_802154_types.h +++ b/nrf_802154/driver/include/nrf_802154_types.h @@ -481,13 +481,22 @@ typedef struct } data; // !< Result values that are valid only for successful operations. } nrf_802154_transmit_done_metadata_t; +/** + * @brief Represents components of tx_power to be applied for stages on transmit path. + */ +typedef struct +{ + nrf_radio_txpower_t radio_tx_power; // !< TX power to be applied to the RADIO peripheral. + int8_t fem_gain; // !< Gain of the Front-End Module in dB. +} nrf_802154_tx_power_split_t; + /** * @brief Structure that holds transmission parameters. */ typedef struct { nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted. - int8_t tx_power; // !< Power to be used when transmitting the frame. + nrf_802154_tx_power_split_t tx_power; // !< Power to be used when transmitting the frame, split into components to be applied on each stage on transmit path. bool cca; // !< If the driver is to perform CCA procedure before transmission. bool immediate; // !< If true, the driver schedules transmission immediately or never. If false, the transmission may be postponed // until its preconditions are met. diff --git a/nrf_802154/driver/src/fal/nrf_802154_fal.c b/nrf_802154/driver/src/fal/nrf_802154_fal.c deleted file mode 100644 index c057ab42ce..0000000000 --- a/nrf_802154/driver/src/fal/nrf_802154_fal.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017 - 2022, Nordic Semiconductor ASA - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * 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 contains implementation of the nRF 802.15.4 FEM abstraction layer. - * - */ - -#include - -#include "nrf_802154_fal.h" - -int8_t nrf_802154_fal_tx_power_get(const uint8_t channel, const int8_t power) -{ - (void)channel; - - return power; -} diff --git a/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c b/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c index a5d6a7901e..452a817e61 100644 --- a/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c +++ b/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c @@ -77,7 +77,7 @@ static uint8_t m_be; ///< Backoff exponent, static uint8_t * mp_data; ///< Pointer to a buffer containing PHR and PSDU of the frame being transmitted. static nrf_802154_transmitted_frame_props_t m_data_props; ///< Structure containing detailed properties of data in buffer. -static int8_t m_tx_power; ///< Power in dBm to be used when transmitting the frame. +static nrf_802154_tx_power_split_t m_tx_power; ///< Power to be used when transmitting the frame split into components. static csma_ca_state_t m_state; ///< The current state of the CSMA-CA procedure. /** @@ -363,9 +363,9 @@ bool nrf_802154_csma_ca_start(uint8_t * p_d m_data_props = p_metadata->frame_props; m_nb = 0; m_be = nrf_802154_pib_csmaca_min_be_get(); - m_tx_power = - nrf_802154_tx_power_convert_metadata_to_raw_value(nrf_802154_pib_channel_get(), - p_metadata->tx_power); + (void)nrf_802154_tx_power_convert_metadata_to_tx_power_split(nrf_802154_pib_channel_get(), + p_metadata->tx_power, + &m_tx_power); random_backoff_start(); diff --git a/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c b/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c index 3f86a6819b..a832db77e2 100644 --- a/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c +++ b/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c @@ -772,9 +772,9 @@ bool nrf_802154_delayed_trx_transmit(uint8_t * p p_dly_tx_data->tx.p_data = p_data; p_dly_tx_data->tx.params.frame_props = p_metadata->frame_props; - p_dly_tx_data->tx.params.tx_power = nrf_802154_tx_power_convert_metadata_to_raw_value( - p_metadata->channel, - p_metadata->tx_power); + (void)nrf_802154_tx_power_convert_metadata_to_tx_power_split(p_metadata->channel, + p_metadata->tx_power, + &p_dly_tx_data->tx.params.tx_power); p_dly_tx_data->tx.params.cca = p_metadata->cca; p_dly_tx_data->tx.params.immediate = true; p_dly_tx_data->tx.channel = p_metadata->channel; diff --git a/nrf_802154/driver/src/nrf_802154.c b/nrf_802154/driver/src/nrf_802154.c index eb6481cdd6..5135cc7b5b 100644 --- a/nrf_802154/driver/src/nrf_802154.c +++ b/nrf_802154/driver/src/nrf_802154.c @@ -157,7 +157,11 @@ void nrf_802154_tx_power_set(int8_t power) int8_t nrf_802154_tx_power_get(void) { - return nrf_802154_tx_power_constrained_pib_power_get(); + nrf_802154_tx_power_split_t split_power = {0}; + + (void)nrf_802154_tx_power_split_pib_power_get(&split_power); + + return split_power.fem_gain + split_power.radio_tx_power; } bool nrf_802154_coex_rx_request_mode_set(nrf_802154_coex_rx_request_mode_t mode) @@ -491,13 +495,15 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, nrf_802154_transmit_params_t params = { .frame_props = p_metadata->frame_props, - .tx_power = nrf_802154_tx_power_convert_metadata_to_raw_value( - nrf_802154_pib_channel_get(), - p_metadata->tx_power), - .cca = p_metadata->cca, - .immediate = false + .tx_power = {0}, + .cca = p_metadata->cca, + .immediate = false }; + (void)nrf_802154_tx_power_convert_metadata_to_tx_power_split(nrf_802154_pib_channel_get(), + p_metadata->tx_power, + ¶ms.tx_power); + result = are_frame_properties_valid(¶ms.frame_props); if (result) { @@ -537,13 +543,15 @@ bool nrf_802154_transmit(const uint8_t * p_data, nrf_802154_transmit_params_t params = { .frame_props = p_metadata->frame_props, - .tx_power = nrf_802154_tx_power_convert_metadata_to_raw_value( - nrf_802154_pib_channel_get(), - p_metadata->tx_power), - .cca = p_metadata->cca, - .immediate = false + .tx_power = {0}, + .cca = p_metadata->cca, + .immediate = false }; + (void)nrf_802154_tx_power_convert_metadata_to_tx_power_split(nrf_802154_pib_channel_get(), + p_metadata->tx_power, + ¶ms.tx_power); + result = are_frame_properties_valid(¶ms.frame_props); if (result) { diff --git a/nrf_802154/driver/src/nrf_802154_core.c b/nrf_802154/driver/src/nrf_802154_core.c index df853c5cd0..7b942577a7 100644 --- a/nrf_802154/driver/src/nrf_802154_core.c +++ b/nrf_802154/driver/src/nrf_802154_core.c @@ -115,13 +115,13 @@ static rx_buffer_t * const mp_current_rx_buffer = &nrf_802154_rx_buffers[0]; #endif -static uint8_t * mp_ack; ///< Pointer to Ack frame buffer. -static uint8_t * mp_tx_data; ///< Pointer to the data to transmit. -static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us]. -static uint8_t m_ed_result; ///< Result of the current energy detection procedure. -static uint8_t m_last_lqi; ///< LQI of the last received non-ACK frame, corrected for the temperature. -static int8_t m_last_rssi; ///< RSSI of the last received non-ACK frame, corrected for the temperature. -static int8_t m_tx_power; ///< Power in dBm to be used to transmit the current frame. +static uint8_t * mp_ack; ///< Pointer to Ack frame buffer. +static uint8_t * mp_tx_data; ///< Pointer to the data to transmit. +static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us]. +static uint8_t m_ed_result; ///< Result of the current energy detection procedure. +static uint8_t m_last_lqi; ///< LQI of the last received non-ACK frame, corrected for the temperature. +static nrf_802154_tx_power_split_t m_tx_power; ///< Power to be used to transmit the current frame split into components. +static int8_t m_last_rssi; ///< RSSI of the last received non-ACK frame, corrected for the temperature. static nrf_802154_frame_parser_data_t m_current_rx_frame_data; ///< RX frame parser data. @@ -1025,9 +1025,13 @@ static void rx_init(void) nrf_802154_trx_receive_buffer_set(rx_buffer_get()); + nrf_802154_tx_power_split_t split_power = {0}; + + (void)nrf_802154_tx_power_split_pib_power_get(&split_power); + nrf_802154_trx_receive_frame(BCC_INIT / 8U, m_trx_receive_frame_notifications_mask, - nrf_802154_tx_power_constrained_pib_power_get()); + &split_power); #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get(); @@ -1089,7 +1093,7 @@ static bool tx_init(const uint8_t * p_data, bool cca) m_flags.tx_with_cca = cca; nrf_802154_trx_transmit_frame(nrf_802154_tx_work_buffer_get(p_data), cca, - m_tx_power, + &m_tx_power, m_trx_transmit_frame_notifications_mask); return true; @@ -1153,8 +1157,11 @@ static void continuous_carrier_init(void) { return; } + nrf_802154_tx_power_split_t split_power = {0}; - nrf_802154_trx_continuous_carrier(nrf_802154_tx_power_constrained_pib_power_get()); + (void)nrf_802154_tx_power_split_pib_power_get(&split_power); + + nrf_802154_trx_continuous_carrier(&split_power); } /** Initialize Modulated Carrier operation. */ @@ -1170,7 +1177,11 @@ static void modulated_carrier_init(const uint8_t * p_data) return; } - nrf_802154_trx_modulated_carrier(p_data, nrf_802154_tx_power_constrained_pib_power_get()); + nrf_802154_tx_power_split_t split_power = {0}; + + (void)nrf_802154_tx_power_split_pib_power_get(&split_power); + + nrf_802154_trx_modulated_carrier(p_data, &split_power); } #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED @@ -1897,9 +1908,14 @@ void nrf_802154_trx_receive_frame_crcerror(void) // We don't change receive buffer, receive will go to the same that was already used #if !NRF_802154_DISABLE_BCC_MATCHING request_preconditions_for_state(m_state); + + nrf_802154_tx_power_split_t split_power = {0}; + + (void)nrf_802154_tx_power_split_pib_power_get(&split_power); + nrf_802154_trx_receive_frame(BCC_INIT / 8U, m_trx_receive_frame_notifications_mask, - nrf_802154_tx_power_constrained_pib_power_get()); + &split_power); #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get(); diff --git a/nrf_802154/driver/src/nrf_802154_trx.c b/nrf_802154/driver/src/nrf_802154_trx.c index 167eec2e18..3a8d6ff8c4 100644 --- a/nrf_802154/driver/src/nrf_802154_trx.c +++ b/nrf_802154/driver/src/nrf_802154_trx.c @@ -41,7 +41,6 @@ #include "nrf_802154_config.h" #include "nrf_802154_const.h" -#include "nrf_802154_types.h" #include "nrf_802154_peripherals.h" #include "nrf_802154_pib.h" #include "nrf_802154_rssi.h" @@ -321,8 +320,9 @@ static void fem_for_lna_reset(void) * * @note This function must be called before ramp up PPIs are configured. */ -static void fem_for_pa_set(void) +static void fem_for_pa_set(int8_t gain) { + (void)mpsl_fem_pa_gain_set(gain); if (mpsl_fem_pa_configuration_set(&m_activate_tx_cc0, NULL) == 0) { nrf_timer_shorts_enable(m_activate_tx_cc0.event.timer.p_timer_instance, @@ -347,10 +347,12 @@ static void fem_for_pa_reset(void) * * @note This function must be called before ramp up PPIs are configured. */ -static void fem_for_tx_set(bool cca) +static void fem_for_tx_set(bool cca, int8_t gain) { bool success; + (void)mpsl_fem_pa_gain_set(gain); + if (cca) { bool pa_set = false; @@ -909,7 +911,7 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer) void nrf_802154_trx_receive_frame(uint8_t bcc, nrf_802154_trx_receive_notifications_t notifications_mask, - int8_t ack_tx_power) + const nrf_802154_tx_power_split_t * p_ack_tx_power) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -928,7 +930,7 @@ void nrf_802154_trx_receive_frame(uint8_t bcc, m_flags.rssi_settled = false; - nrf_radio_txpower_set(NRF_RADIO, (nrf_radio_txpower_t)ack_tx_power); + nrf_radio_txpower_set(NRF_RADIO, p_ack_tx_power->radio_tx_power); if (mp_receive_buffer != NULL) { @@ -1014,6 +1016,9 @@ void nrf_802154_trx_receive_frame(uint8_t bcc, nrf_timer_cc_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, delta_time); } + // Set FEM PA gain for ACK transmission + mpsl_fem_pa_gain_set(p_ack_tx_power->fem_gain); + m_timer_value_on_radio_end_event = delta_time; // Select antenna @@ -1140,7 +1145,7 @@ bool nrf_802154_trx_rssi_sample_is_available(void) void nrf_802154_trx_transmit_frame(const void * p_transmit_buffer, bool cca, - int8_t tx_power, + const nrf_802154_tx_power_split_t * p_tx_power, nrf_802154_trx_transmit_notifications_t notifications_mask) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -1153,7 +1158,8 @@ void nrf_802154_trx_transmit_frame(const void * p_tra m_trx_state = TRX_STATE_TXFRAME; m_transmit_with_cca = cca; - nrf_radio_txpower_set(NRF_RADIO, (nrf_radio_txpower_t)tx_power); + nrf_radio_txpower_set(NRF_RADIO, p_tx_power->radio_tx_power); + nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer); // Set shorts @@ -1197,7 +1203,7 @@ void nrf_802154_trx_transmit_frame(const void * p_tra nrf_radio_int_enable(NRF_RADIO, ints_to_enable); - fem_for_tx_set(cca); + fem_for_tx_set(cca, p_tx_power->fem_gain); nrf_802154_trx_antenna_update(); nrf_802154_trx_ppi_for_ramp_up_set(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN, false); @@ -1769,7 +1775,7 @@ static void standalone_cca_abort(void) #if NRF_802154_CARRIER_FUNCTIONS_ENABLED -void nrf_802154_trx_continuous_carrier(int8_t tx_power) +void nrf_802154_trx_continuous_carrier(const nrf_802154_tx_power_split_t * p_tx_power) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -1778,10 +1784,10 @@ void nrf_802154_trx_continuous_carrier(int8_t tx_power) m_trx_state = TRX_STATE_CONTINUOUS_CARRIER; // Set Tx Power - nrf_radio_txpower_set(NRF_RADIO, (nrf_radio_txpower_t)tx_power); + nrf_radio_txpower_set(NRF_RADIO, p_tx_power->radio_tx_power); // Set FEM - fem_for_pa_set(); + fem_for_pa_set(p_tx_power->fem_gain); // Select antenna nrf_802154_trx_antenna_update(); @@ -1824,7 +1830,8 @@ static void continuous_carrier_abort(void) nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } -void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, int8_t tx_power) +void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, + const nrf_802154_tx_power_split_t * p_tx_power) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -1834,7 +1841,7 @@ void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, int8_t tx_ m_trx_state = TRX_STATE_MODULATED_CARRIER; // Set Tx Power - nrf_radio_txpower_set(NRF_RADIO, (nrf_radio_txpower_t)tx_power); + nrf_radio_txpower_set(NRF_RADIO, p_tx_power->radio_tx_power); // Set Tx buffer nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer); @@ -1843,7 +1850,7 @@ void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, int8_t tx_ nrf_radio_shorts_set(NRF_RADIO, SHORTS_MOD_CARRIER); // Set FEM - fem_for_pa_set(); + fem_for_pa_set(p_tx_power->fem_gain); // Select antenna nrf_802154_trx_antenna_update(); diff --git a/nrf_802154/driver/src/nrf_802154_trx.h b/nrf_802154/driver/src/nrf_802154_trx.h index 235309cce5..10a212ba12 100644 --- a/nrf_802154/driver/src/nrf_802154_trx.h +++ b/nrf_802154/driver/src/nrf_802154_trx.h @@ -47,6 +47,7 @@ #include "nrf_802154_config.h" #include "nrf_802154_sl_types.h" +#include "nrf_802154_types.h" #ifdef __cplusplus extern "C" { @@ -208,11 +209,11 @@ void nrf_802154_trx_cca_configuration_update(void); * @param[in] notifications_mask Selects additional notifications generated during a frame reception. * It is bitwise combination of @ref nrf_802154_trx_receive_notifications_t values. * When NRF_802154_DISABLE_BCC_MATCHING != 0, flag @ref TRX_RECEIVE_NOTIFICATION_PRESTARTED is forbidden. - * @param[in] ack_tx_power Selects the power which should be used to transmitted an ACK if required. + * @param[in] p_ack_tx_power Selects the power which should be used to transmitted an ACK if required. */ void nrf_802154_trx_receive_frame(uint8_t bcc, nrf_802154_trx_receive_notifications_t notifications_mask, - int8_t ack_tx_power); + const nrf_802154_tx_power_split_t * p_ack_tx_power); /**@brief Puts the trx module into receive ACK mode. * @@ -340,14 +341,14 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer); * @param cca Selects if CCA procedure should be performed prior to * real transmission. If false no cca will be performed. * If true, cca will be performed. - * @param tx_power Transmit power in dBm. + * @param p_tx_power Transmit power in dBm. * @param notifications_mask Selects additional notifications generated during a frame transmission. * It is bitwise combination of @ref nrf_802154_trx_transmit_notifications_t values. * @note To transmit ack after frame is received use @ref nrf_802154_trx_transmit_ack. */ void nrf_802154_trx_transmit_frame(const void * p_transmit_buffer, bool cca, - int8_t tx_power, + const nrf_802154_tx_power_split_t * p_tx_power, nrf_802154_trx_transmit_notifications_t notifications_mask); /**@brief Puts the trx module into transmit ACK mode. @@ -390,12 +391,12 @@ void nrf_802154_trx_standalone_cca(void); /**@brief Starts generating continuous carrier. * - * @param[in] tx_power Transmit power in dBm. + * @param[in] p_tx_power Transmit power in dBm. * * Generation of a continuous carrier generates no handlers. It may be terminated by a call to * @ref nrf_802154_trx_abort or @ref nrf_802154_trx_disable. */ -void nrf_802154_trx_continuous_carrier(int8_t tx_power); +void nrf_802154_trx_continuous_carrier(const nrf_802154_tx_power_split_t * p_tx_power); /**@brief Restarts generating continuous carrier * @@ -410,9 +411,10 @@ void nrf_802154_trx_continuous_carrier_restart(void); /**@brief Starts generating modulated carrier with given buffer. * * @param[in] p_transmit_buffer Pointer to a buffer used for modulating the carrier wave. - * @param[in] tx_power Transmit power in dBm. + * @param[in] p_tx_power Transmit power in dBm. */ -void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, int8_t tx_power); +void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer, + const nrf_802154_tx_power_split_t * p_tx_power); /** @brief Restarts generating modulated carrier.*/ void nrf_802154_trx_modulated_carrier_restart(void); diff --git a/nrf_802154/driver/src/nrf_802154_tx_power.c b/nrf_802154/driver/src/nrf_802154_tx_power.c index e1881f6ca9..971543a4b3 100644 --- a/nrf_802154/driver/src/nrf_802154_tx_power.c +++ b/nrf_802154/driver/src/nrf_802154_tx_power.c @@ -35,7 +35,7 @@ #include "nrf_802154_tx_power.h" #include "nrf_802154_pib.h" #include "nrf_802154_utils.h" -#include "fal/nrf_802154_fal.h" +#include "nrf_802154_fal.h" /** * Converts TX power integer values to RADIO TX power allowed values. @@ -98,38 +98,60 @@ static nrf_radio_txpower_t to_radio_tx_power_convert(int8_t integer_tx_power) } /** - * Converts TX power integer values to RADIO TX power allowed values, constrained by the allowed TX power allowed for - * a specific channel. + * Constrains the TX power by the maximum allowed TX power allowed for a specific channel, splits it into + * components to be applied on each stage of the transmit path and for the TX power applied to the RADIO peripheral + * converts the integer value to a RADIO TX power allowed value. * - * @param[in] channel The channel based on which the power should be constrained - * @param[in] tx_power Unconstrained TX power integer value. + * @param[in] channel The channel based on which the power should be constrained + * @param[in] tx_power Unconstrained TX power integer value. + * @param[out] split_power Pointer to the structure holding TX power split into constrained and converted components. * - * @retval RADIO TX power allowed and constrained value. + * @retval true Calculation performed successfully. + * @retval false Given @p power cannot be achieved. If requested value is too high + * the @p p_tx_power_split will be set to a value representing maximum + * achievable power. If the requested value is too low, the + * @p p_tx_power_split will be set to a value representing minimum + * achievable power. */ -static nrf_radio_txpower_t constrain_and_convert_tx_power(uint8_t channel, int8_t tx_power) +static bool constrain_split_and_convert_tx_power( + uint8_t channel, + int8_t tx_power, + nrf_802154_tx_power_split_t * const split_power) { - int8_t constrained_power = nrf_802154_fal_tx_power_get(channel, tx_power); + int32_t ret = 0; + nrf_802154_fal_tx_power_split_t fal_split_power = {0}; - return to_radio_tx_power_convert(constrained_power); + ret = nrf_802154_fal_tx_power_split(channel, tx_power, &fal_split_power); + + split_power->fem_gain = fal_split_power.fem_gain; + split_power->radio_tx_power = to_radio_tx_power_convert(fal_split_power.radio_tx_power); + + return (0 == ret); } -nrf_radio_txpower_t nrf_802154_tx_power_convert_metadata_to_raw_value( - uint8_t channel, - nrf_802154_tx_power_metadata_t tx_power) +bool nrf_802154_tx_power_convert_metadata_to_tx_power_split( + uint8_t channel, + nrf_802154_tx_power_metadata_t tx_power, + nrf_802154_tx_power_split_t * const p_tx_power_split) { int8_t power_unconstrained = tx_power.use_metadata_value ? tx_power.power : nrf_802154_pib_tx_power_get(); - return constrain_and_convert_tx_power(channel, power_unconstrained); + return constrain_split_and_convert_tx_power(channel, power_unconstrained, p_tx_power_split); } -nrf_radio_txpower_t nrf_802154_tx_power_constrained_pib_power_get(void) +bool nrf_802154_tx_power_split_pib_power_get(nrf_802154_tx_power_split_t * const p_split_power) { - return constrain_and_convert_tx_power(nrf_802154_pib_channel_get(), - nrf_802154_pib_tx_power_get()); + return constrain_split_and_convert_tx_power(nrf_802154_pib_channel_get(), + nrf_802154_pib_tx_power_get(), + p_split_power); } -nrf_radio_txpower_t nrf_802154_tx_power_constrained_pib_power_for_channel_get(uint8_t channel) +bool nrf_802154_tx_power_split_pib_power_for_channel_get( + uint8_t channel, + nrf_802154_tx_power_split_t * const p_split_power) { - return constrain_and_convert_tx_power(channel, nrf_802154_pib_tx_power_get()); + return constrain_split_and_convert_tx_power(channel, + nrf_802154_pib_tx_power_get(), + p_split_power); } diff --git a/nrf_802154/driver/src/nrf_802154_tx_power.h b/nrf_802154/driver/src/nrf_802154_tx_power.h index b175e86d25..1116c1ae27 100644 --- a/nrf_802154/driver/src/nrf_802154_tx_power.h +++ b/nrf_802154/driver/src/nrf_802154_tx_power.h @@ -39,37 +39,63 @@ #include "nrf_802154.h" -/**@brief Convert tx_power value passed through metadata to a raw value in dBm used by the core module. +/**@brief Convert tx_power value passed through metadata to raw components in dBms to be applied + * on each stage of the transmit path. - * This function also ensures that the value meets the constraints for the current channel. + * This function also ensures that the values meet the constraints for the given channel. * - * @param[in] channel The channel to be used for transmission - * @param[in] tx_power The value passed to the transmit metadata. + * @param[in] channel The channel to be used for transmission + * @param[in] tx_power The value passed to the transmit metadata. + * @param[out] p_tx_power_split Pointer to the structure holding TX power split into raw components in dBm. * - * @retval Returns the power in dBm which will be used to transmit the frame. + * @retval true Calculation performed successfully. + * @retval false Given @p tx_power cannot be achieved. If requested value is too high + * the @p p_tx_power_split will be set to a value representing maximum + * achievable power. If the requested value is too low, the + * @p p_tx_power_split will be set to a value representing minimum + * achievable power. * */ -nrf_radio_txpower_t nrf_802154_tx_power_convert_metadata_to_raw_value( - uint8_t channel, - nrf_802154_tx_power_metadata_t tx_power); +bool nrf_802154_tx_power_convert_metadata_to_tx_power_split( + uint8_t channel, + nrf_802154_tx_power_metadata_t tx_power, + nrf_802154_tx_power_split_t * const p_tx_power_split); -/**@brief Get the transmit power stored in PIB after applying the power constraints for the current channel. +/**@brief Get the transmit power stored in PIB after applying the power constraints for the current channel and splitting + * into components to be applied on each stage of the transmit path. * * The current channel is acquired from PIB. * - * @retval Returns the constrained power in dBm which will be used to transmit the frame. + * @param[out] p_split_power Pointer to the structure holding TX power split into components in dBm. + * + * @retval true Calculation performed successfully. + * @retval false cannot be achieved. If requested value is too high + * Current power set in PIB the @p p_split_power will be set to a value representing maximum + * achievable power. If the requested value is too low, the + * @p p_split_power will be set to a value representing minimum + * achievable power. + * */ -nrf_radio_txpower_t nrf_802154_tx_power_constrained_pib_power_get(void); +bool nrf_802154_tx_power_split_pib_power_get(nrf_802154_tx_power_split_t * const p_split_power); -/**@brief Get the transmit power stored in PIB after applying the power constraints for the given channel. +/**@brief Get the transmit power stored in PIB after applying the power constraints for the given channel and splitting + * into components to be applied on each stage of the transmit path. * - * @param[in] channel The channel based on which the power should be constrained + * @param[in] channel The channel based on which the power should be constrained + * @param[out] p_split_power Pointer to the structure holding TX power split into components in dBm. * - * @retval Returns the power in dBm which will be used to transmit the frame. + * @retval true Calculation performed successfully. + * @retval false Current power set in PIB cannot be achieved. If requested value is too high + * the @p p_split_power will be set to a value representing maximum + * achievable power. If the requested value is too low, the + * @p p_split_power will be set to a value representing minimum + * achievable power. * */ -nrf_radio_txpower_t nrf_802154_tx_power_constrained_pib_power_for_channel_get(uint8_t channel); +bool nrf_802154_tx_power_split_pib_power_for_channel_get( + uint8_t channel, + nrf_802154_tx_power_split_t * const p_split_power); /** *@} diff --git a/nrf_802154/driver/src/fal/nrf_802154_fal.h b/nrf_802154/sl/include/nrf_802154_fal.h similarity index 68% rename from nrf_802154/driver/src/fal/nrf_802154_fal.h rename to nrf_802154/sl/include/nrf_802154_fal.h index d2a8914e30..5ef1a33623 100644 --- a/nrf_802154/driver/src/fal/nrf_802154_fal.h +++ b/nrf_802154/sl/include/nrf_802154_fal.h @@ -46,6 +46,15 @@ extern "C" { #endif +/** + * @brief Represents components of tx_power to be applied for stages on transmit path. + */ +typedef struct +{ + int8_t radio_tx_power; // !< TX power in dBm to be applied to the RADIO peripheral. + int8_t fem_gain; // !< Gain of the Front-End Module in dB. +} nrf_802154_fal_tx_power_split_t; + /** * @brief Returns 'power' value. * @@ -58,6 +67,20 @@ extern "C" { */ int8_t nrf_802154_fal_tx_power_get(const uint8_t channel, const int8_t power); +/** @brief Splits transmit power value into components to be applied on each stage on the transmit path. + * + * @note This is a stub implementation used when MPSL is not linked. + * + * @param[in] channel Ignored. + * @param[in] power TX power in dBm requested for transmission on air. + * @param[out] p_tx_power_split Components of tx_power to be applied for stages on transmit path. + * + * @returns Always 0. + */ +int32_t nrf_802154_fal_tx_power_split(const uint8_t channel, + const int8_t power, + nrf_802154_fal_tx_power_split_t * const p_tx_power_split); + #ifdef __cplusplus } #endif diff --git a/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h b/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h index 17a919bbf7..8748edb608 100644 --- a/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h +++ b/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h @@ -103,6 +103,19 @@ typedef struct #endif } mpsl_fem_event_t; +/** TX power, dBm. */ +typedef int8_t mpsl_tx_power_t; + +/** @brief Represents components of tx_power to be applied for stages on transmit path. */ +typedef struct +{ + /** TX power to be applied to the RADIO peripheral. */ + mpsl_tx_power_t radio_tx_power; + + /** Gain of the Front-End Module in dB. */ + int8_t fem_gain; +} mpsl_tx_power_split_t; + /** @brief Disable Front End Module. * * Some Front End Module devices can be explicitly disabled after PA and LNA activities are @@ -292,6 +305,38 @@ int32_t mpsl_fem_abort_clear(void); */ void mpsl_fem_cleanup(void); +/** @brief Splits transmit power value into components to be applied on each stage on transmit path. + * + * @note If the exact value of @p power cannot be achieved, this function attempts to use less + * power to not exceed constraint. However, if @p power is lower than the minimum achievable power, + * or larger than the maximum achievable power, the function returns failure. + * + * @param[in] power TX power requested for transmission on air. + * @param[out] p_tx_power_split Components of tx_power to be applied for stages on transmit path. + * + * @retval 0 Calculation performed successfully. + * @retval - ::NRF_EINVAL Given @p power cannot be achieved. If requested value is too high + * the @p p_tx_power_split will be set to a value representing maximum + * achievable power. If the requested value is too low, the + * @p p_tx_power_split will be set to a value representing minimum + * achievable power. + */ +int32_t mpsl_fem_tx_power_split(const mpsl_tx_power_t power, + mpsl_tx_power_split_t *const p_tx_power_split); + +/** @brief Sets PA gain. + * + * @note The gain set by this function will be applied to radio transmissions + * following the call. If the function is called during radio transmission + * or during ramp-up for transmission it is unspecified if the gain is applied. + * + * @param[in] gain Gain in dB to be set. + * + * @retval 0 Gain has been set successfully. + * @retval -NRF_EINVAL Gain could not be set. Provided @p gain is invalid. + */ +int32_t mpsl_fem_pa_gain_set(int8_t gain); + /** @brief Checks if the PA signaling is configured and enabled, and gets * the configured gain in dB. * diff --git a/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c b/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c index f98c161ef8..2cd7b522ca 100644 --- a/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c +++ b/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c @@ -37,6 +37,8 @@ #include #include +#include "nrf_802154_fal.h" + #include "protocol/mpsl_fem_protocol_api.h" #ifdef __cplusplus @@ -110,6 +112,22 @@ void mpsl_fem_cleanup(void) // Intentionally empty } +int32_t mpsl_fem_tx_power_split(const mpsl_tx_power_t power, + mpsl_tx_power_split_t * const p_tx_power_split) +{ + p_tx_power_split->radio_tx_power = power; + p_tx_power_split->fem_gain = 0; + + return 0; +} + +int32_t mpsl_fem_pa_gain_set(int8_t gain) +{ + (void)gain; + + return 0; +} + void mpsl_fem_pa_is_configured(int8_t * const p_gain) { (void)p_gain; @@ -138,6 +156,18 @@ int8_t nrf_802154_fal_tx_power_get(const uint8_t channel, const int8_t power) return power; } +int32_t nrf_802154_fal_tx_power_split(const uint8_t channel, + const int8_t power, + nrf_802154_fal_tx_power_split_t * const p_tx_power_split) +{ + (void)channel; + + p_tx_power_split->radio_tx_power = power; + p_tx_power_split->fem_gain = 0; + + return 0; +} + #ifdef __cplusplus } #endif