1 /*
2  * Copyright (c) 2020 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include <nrfx.h>
36 #include "nrf_errno.h"
37 #include <stdbool.h>
38 #include <stdint.h>
39 
40 #include "nrf_802154_fal.h"
41 #include "nrf_802154_types.h"
42 
43 #include "protocol/mpsl_fem_protocol_api.h"
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /**@brief Macro to get the number of elements in an array.
50  *
51  * @param[in] X   Array.
52  */
53 #define NUMELTS(X) (sizeof((X)) / sizeof(X[0]))
54 
55 /**
56  * Converts TX power integer values to RADIO TX power allowed values.
57  *
58  * @param[in]  integer_tx_power  TX power integer value.
59  *
60  * @retval     RADIO TX power allowed value.
61  */
to_radio_tx_power_convert(int8_t integer_tx_power)62 static nrf_radio_txpower_t to_radio_tx_power_convert(int8_t integer_tx_power)
63 {
64     static const nrf_radio_txpower_t allowed_values[] =
65     {
66 #if defined(RADIO_TXPOWER_TXPOWER_Neg40dBm)
67         NRF_RADIO_TXPOWER_NEG40DBM, /**< -40 dBm. */
68 #endif
69         NRF_RADIO_TXPOWER_NEG20DBM, /**< -20 dBm. */
70         NRF_RADIO_TXPOWER_NEG16DBM, /**< -16 dBm. */
71         NRF_RADIO_TXPOWER_NEG12DBM, /**< -12 dBm. */
72         NRF_RADIO_TXPOWER_NEG8DBM,  /**< -8 dBm. */
73         NRF_RADIO_TXPOWER_NEG4DBM,  /**< -4 dBm. */
74         NRF_RADIO_TXPOWER_0DBM,     /**< 0 dBm. */
75 #if defined(RADIO_TXPOWER_TXPOWER_Pos2dBm)
76         NRF_RADIO_TXPOWER_POS2DBM,  /**< 2 dBm. */
77 #endif
78 #if defined(RADIO_TXPOWER_TXPOWER_Pos3dBm)
79         NRF_RADIO_TXPOWER_POS3DBM,  /**< 3 dBm. */
80 #endif
81 #if defined(RADIO_TXPOWER_TXPOWER_Pos4dBm)
82         NRF_RADIO_TXPOWER_POS4DBM,  /**< 4 dBm. */
83 #endif
84 #if defined(RADIO_TXPOWER_TXPOWER_Pos5dBm)
85         NRF_RADIO_TXPOWER_POS5DBM,  /**< 5 dBm. */
86 #endif
87 #if defined(RADIO_TXPOWER_TXPOWER_Pos6dBm)
88         NRF_RADIO_TXPOWER_POS6DBM,  /**< 6 dBm. */
89 #endif
90 #if defined(RADIO_TXPOWER_TXPOWER_Pos7dBm)
91         NRF_RADIO_TXPOWER_POS7DBM,  /**< 7 dBm. */
92 #endif
93 #if defined(RADIO_TXPOWER_TXPOWER_Pos8dBm)
94         NRF_RADIO_TXPOWER_POS8DBM,  /**< 8 dBm. */
95 #endif
96     };
97 
98     for (uint32_t i = NUMELTS(allowed_values) - 1; i > 0; i--)
99     {
100         if (integer_tx_power >= (int8_t)allowed_values[i])
101         {
102             return allowed_values[i];
103         }
104     }
105 
106     return allowed_values[0];
107 }
108 
mpsl_fem_disable(void)109 int32_t mpsl_fem_disable(void)
110 {
111     return 0;
112 }
113 
mpsl_fem_pa_configuration_set(const mpsl_fem_event_t * const p_activate_event,const mpsl_fem_event_t * const p_deactivate_event)114 int32_t mpsl_fem_pa_configuration_set(const mpsl_fem_event_t * const p_activate_event,
115                                       const mpsl_fem_event_t * const p_deactivate_event)
116 {
117     (void)p_activate_event;
118     (void)p_deactivate_event;
119 
120     return -NRF_EPERM;
121 }
122 
mpsl_fem_pa_configuration_clear(void)123 int32_t mpsl_fem_pa_configuration_clear(void)
124 {
125     return -NRF_EPERM;
126 }
127 
mpsl_fem_lna_configuration_set(const mpsl_fem_event_t * const p_activate_event,const mpsl_fem_event_t * const p_deactivate_event)128 int32_t mpsl_fem_lna_configuration_set(const mpsl_fem_event_t * const p_activate_event,
129                                        const mpsl_fem_event_t * const p_deactivate_event)
130 {
131     (void)p_activate_event;
132     (void)p_deactivate_event;
133 
134     return -NRF_EPERM;
135 }
136 
mpsl_fem_lna_configuration_clear(void)137 int32_t mpsl_fem_lna_configuration_clear(void)
138 {
139     return -NRF_EPERM;
140 }
141 
mpsl_fem_deactivate_now(mpsl_fem_functionality_t type)142 void mpsl_fem_deactivate_now(mpsl_fem_functionality_t type)
143 {
144     (void)type;
145 }
146 
mpsl_fem_abort_set(uint32_t event,uint32_t group)147 int32_t mpsl_fem_abort_set(uint32_t event, uint32_t group)
148 {
149     return -NRF_EPERM;
150 }
151 
mpsl_fem_abort_extend(uint32_t channel_to_add,uint32_t group)152 int32_t mpsl_fem_abort_extend(uint32_t channel_to_add, uint32_t group)
153 {
154     (void)channel_to_add;
155     (void)group;
156     return 0;
157 }
158 
mpsl_fem_abort_reduce(uint32_t channel_to_remove,uint32_t group)159 int32_t mpsl_fem_abort_reduce(uint32_t channel_to_remove, uint32_t group)
160 {
161     (void)channel_to_remove;
162     (void)group;
163     return 0;
164 }
165 
mpsl_fem_abort_clear(void)166 int32_t mpsl_fem_abort_clear(void)
167 {
168     return -NRF_EPERM;
169 }
170 
mpsl_fem_cleanup(void)171 void mpsl_fem_cleanup(void)
172 {
173     // Intentionally empty
174 }
175 
mpsl_fem_tx_power_split(const mpsl_tx_power_t power,mpsl_tx_power_split_t * const p_tx_power_split)176 void mpsl_fem_tx_power_split(const mpsl_tx_power_t         power,
177                              mpsl_tx_power_split_t * const p_tx_power_split)
178 {
179     p_tx_power_split->radio_tx_power      = to_radio_tx_power_convert(power);
180     p_tx_power_split->fem.gain_db         = 0;
181     p_tx_power_split->fem.private_setting = 0;
182 }
183 
mpsl_fem_pa_gain_set(const mpsl_fem_gain_t * p_gain)184 int32_t mpsl_fem_pa_gain_set(const mpsl_fem_gain_t * p_gain)
185 {
186     (void)p_gain;
187 
188     return 0;
189 }
190 
mpsl_fem_pa_is_configured(int8_t * const p_gain)191 void mpsl_fem_pa_is_configured(int8_t * const p_gain)
192 {
193     (void)p_gain;
194 }
195 
mpsl_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,uint32_t compare_channel,uint32_t ppi_id,uint32_t event_addr)196 bool mpsl_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
197                                 uint32_t         compare_channel,
198                                 uint32_t         ppi_id,
199                                 uint32_t         event_addr)
200 {
201     (void)p_instance;
202     (void)compare_channel;
203     (void)ppi_id;
204 
205     return false;
206 }
207 
mpsl_fem_device_config_254_apply_get(void)208 bool mpsl_fem_device_config_254_apply_get(void)
209 {
210     return false;
211 }
212 
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)213 int8_t nrf_802154_fal_tx_power_split(const uint8_t                           channel,
214                                      const int8_t                            power,
215                                      nrf_802154_fal_tx_power_split_t * const p_tx_power_split)
216 {
217     (void)channel;
218 
219     p_tx_power_split->radio_tx_power      = to_radio_tx_power_convert(power);
220     p_tx_power_split->fem.gain_db         = 0;
221     p_tx_power_split->fem.private_setting = 0;
222 
223     return p_tx_power_split->radio_tx_power;
224 }
225 
226 #ifdef __cplusplus
227 }
228 #endif
229