1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5  */
6 
7 /**
8  * @file mpsl_fem_protocol_api.h
9  *
10  * @defgroup mpsl_fem MPSL Protocol interface for Power Amplifier (PA) and Low Noise Amplifier (LNA).
11  * @ingroup  mpsl
12  *
13  * This module provides the interface for the protocols to use PA, LNA, or both
14  * in the radio transmission and the radio reception. Refer to the README.rst
15  * for the details.
16  *
17  * @{
18  */
19 
20 #ifndef MPSL_FEM_PROTOCOL_API_H__
21 #define MPSL_FEM_PROTOCOL_API_H__
22 
23 #include <stdint.h>
24 #include <stdbool.h>
25 
26 #include <nrf.h>
27 #include "nrf_errno.h"
28 
29 /** @brief PA and LNA functionality types. */
30 typedef enum
31 {
32     MPSL_FEM_PA  = 1 << 0,                     /**< PA Functionality. */
33     MPSL_FEM_LNA = 1 << 1,                     /**< LNA Functionality. */
34     MPSL_FEM_ALL = MPSL_FEM_PA | MPSL_FEM_LNA  /**< Both PA and LNA Functionalities. */
35 } mpsl_fem_functionality_t;
36 
37 /** @brief PA and LNA activation event types. */
38 typedef enum
39 {
40     MPSL_FEM_EVENT_TYPE_TIMER,                 /**< Timer Event type. */
41     MPSL_FEM_EVENT_TYPE_GENERIC                /**< Generic Event type. */
42 } mpsl_fem_event_type_t;
43 
44 /** @brief Type representing a multiple-subscribable hardware event.
45  *
46  *  For nRF52 series this is an address of an event within a peripheral. This
47  *  event can be written to @c EEP register of a PPI channel, to make the
48  *  PPI channel be driven by the event. For nRF52 series an event can be
49  *  published to multiple PPI channels by hardware design, which makes it possible
50  *  for multiple tasks to subscribe to it.
51  *
52  *  For nRF53 series this is a number of a DPPI channel which is configured
53  *  in such a way that certain event publishes to the DPPI channel and the
54  *  DPPI channel is enabled. Ensuring above is responsibility of an user
55  *  of the provided API. Multiple tasks can then subscribe to the DPPI channel
56  *  (by hardware design) thus indirectly to the event.
57  */
58 typedef uint32_t mpsl_subscribable_hw_event_t;
59 
60 /** @brief MPSL Front End Module event. */
61 typedef struct
62 {
63     /** Type of event source. */
64     mpsl_fem_event_type_t      type;
65     /** Implementation of the event. */
66     union
67     {
68         /** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_TIMER. */
69         struct
70         {
71             /** Pointer to a 1-us resolution timer instance. */
72             NRF_TIMER_Type *   p_timer_instance;
73 
74             /** Counter period parameters */
75             struct
76             {
77                 /** Timer value when the Front End Module can start preparing PA/LNA. */
78                 uint32_t       start;
79                 /** Timer value at which the PA/LNA have to be prepared. Radio operation shall start at this point. */
80                 uint32_t       end;
81               /** Time interval in which the timer should start and end. */
82             } counter_period;
83 
84             /** Mask of the compare channels that can be used by the Front End Module to schedule its own tasks. */
85             uint8_t            compare_channel_mask;
86           /** Event generated by the timer, used in case of type equal to @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER. */
87         } timer;
88 
89         /** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_GENERIC. */
90         struct
91         {
92             /** Event triggerring required FEM operation. */
93             mpsl_subscribable_hw_event_t event;
94           /** Generic event, used in case of type equal to @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_GENERIC. */
95         } generic;
96     } event;
97 
98 #if defined(NRF52_SERIES)
99     /** False to ignore the PPI channel below and use the one set by application. True to use the PPI channel below. */
100     bool                       override_ppi;
101     /** PPI channel to be used for this event. */
102     uint8_t                    ppi_ch_id;
103 #endif
104 } mpsl_fem_event_t;
105 
106 /** TX power, dBm. */
107 typedef int8_t mpsl_tx_power_t;
108 
109 /**
110  * @brief Represents data needed to set the FEM gain.
111  */
112 typedef struct
113 {
114     int8_t  gain_db;         // !< Gain in dB.
115     uint8_t private_setting; // !< Setting of the Front-End Module. The interpretation of this field is specific
116                              // for a given Front-End Module implementation.
117 } mpsl_fem_gain_t;
118 
119 /** @brief Represents components of tx_power to be applied for stages on transmit path. */
120 typedef struct
121 {
122     /** TX power to be applied to the RADIO peripheral. */
123     mpsl_tx_power_t radio_tx_power;
124 
125     /** Data needed to set the FEM gain. */
126     mpsl_fem_gain_t fem;
127 } mpsl_tx_power_split_t;
128 
129 /** @brief Disable Front End Module.
130  *
131  * Some Front End Module devices can be explicitly disabled after PA and LNA activities are
132  * finished to preserve power.
133  *
134  * This function is intended to disable Front End Module shortly after radio operations are
135  * finished and the protocol does not expect more radio activities in short future, or passes
136  * radio control to other protocols in the system.
137  *
138  * Front End Module disabling process is synchronous and immediate.
139  *
140  * @retval 0
141  * @retval -NRF_EPERM    FEM is configured to enable PA or LNA.
142  */
143 int32_t mpsl_fem_disable(void);
144 
145 /** @brief Sets up PA using the provided events for the upcoming radio transmission.
146  *
147  * Multiple configurations can be provided by repeating calls to this function
148  * (that is, you can set the activate and the deactivate events in multiple calls,
149  * and the configuration is preserved between calls).
150  *
151  * The order of calls of this function and its `lna` counterpart must match the
152  * order of radio operations.
153  * I.e. if you want to listen first and then send the frame, you need first to
154  * issue @ref mpsl_fem_lna_configuration_set and only after @ref mpsl_fem_pa_configuration_set.
155  *
156  * If a @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER timer event is
157  * provided, the PA will be configured to activate or deactivate at the
158  * application-configured time gap before the timer instance reaches the given
159  * register_value. The time gap is set via the corresponding configuration setter
160  * of the selected Front End Module.
161  *
162  * If a @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_GENERIC event is provided,
163  * the PA will be configured to activate or deactivate when an event occurs.
164  *
165  * The function sets up the PPIs and the GPIOTE channel to activate PA for the
166  * upcoming radio transmission. The PA pin will be active until deactivated,
167  * which can happen either by encountering a configured deactivation event or by
168  * using @ref mpsl_fem_deactivate_now.
169  *
170  * @param[in] p_activate_event   Pointer to the activation event structure.
171  * @param[in] p_deactivate_event Pointer to the deactivation event structure.
172  *
173  * @pre To activate PA, the corresponding configuration setter of the selected
174  * Front End Module must have been called first.
175  *
176  * @note If a timer event is provided, the caller of this function is responsible
177  * for starting the timer and configuring its shorts.
178  * Moreover, the caller is responsible for stopping the timer no earlier than
179  * the compare channel of the lowest ID among the provided ones does expire.
180  *
181  * @note The activation event can be only of type
182  * @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER.
183  * Using other activation event type leads to undefined module behavior.
184  *
185  * @retval   0             PA activation setup is successful.
186  * @retval   -NRF_EPERM    PA is currently disabled.
187  * @retval   -NRF_EINVAL   PA activation setup could not be performed due to
188  *                         invalid or missing configuration parameters
189  *                         in p_activate_event or p_deactivate_event, or both.
190  */
191 int32_t mpsl_fem_pa_configuration_set(const mpsl_fem_event_t * const p_activate_event,
192                                       const mpsl_fem_event_t * const p_deactivate_event);
193 
194 /** @brief Clears up the configuration provided by the @ref mpsl_fem_pa_configuration_set function.
195  *
196  * @retval   0             PA activation setup purge is successful.
197  * @retval   -NRF_EPERM    PA is currently disabled.
198  */
199 int32_t mpsl_fem_pa_configuration_clear(void);
200 
201 /** @brief Sets up LNA using the provided event for the upcoming radio reception.
202  *
203  * Multiple configurations can be provided by repeating calls to this function
204  * (that is, you can set the activate and the deactivate event in multiple calls,
205  * and the configuration is preserved between calls).
206  *
207  * The order of calls of this function and its `pa` counterpart must match the
208  * order of radio operations. I.e. if you want to listen first and then send the
209  * frame, you need first to issue @ref mpsl_fem_lna_configuration_set and only
210  * after @ref mpsl_fem_pa_configuration_set.
211  *
212  * If a @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER timer event is
213  * provided, the LNA will be configured to activate or deactivate at the
214  * application-configured time gap before the timer instance reaches the given
215  * register_value. The time gap is set via the corresponding configuration setter
216  * of the selected Front End Module.
217  *
218  * If a @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_GENERIC event is provided,
219  * the LNA will be configured to activate or deactivate when an event occurs.
220  *
221  * The function sets up the PPIs and the GPIOTE channel to activate LNA for the
222  * upcoming radio transmission. The LNA pin will be active until deactivated,
223  * which can happen either by encountering a configured deactivation event or by
224  * using @ref mpsl_fem_deactivate_now.
225  *
226  * @param[in] p_activate_event   Pointer to the activation event structure.
227  * @param[in] p_deactivate_event Pointer to the deactivation event structure.
228  *
229  * @pre To activate LNA, the corresponding configuration setter of the selected
230  * Front End Module must have been called first.
231  *
232  * @note If a timer event is provided, the caller of this function is responsible
233  * for starting the timer and configuring its shorts.
234  * Moreover, the caller is responsible for stopping the timer no earlier than
235  * the compare channel of the lowest ID among the provided ones does expire.
236  *
237  * @note The activation event can be only of type
238  * @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_TIMER. Using other activation
239  * event type leads to undefined module behavior.
240  *
241  * @retval   0             LNA activation setup is successful.
242  * @retval   -NRF_EPERM    LNA is currently disabled.
243  * @retval   -NRF_EINVAL   LNA activation setup could not be performed due to
244  *                         invalid or missing configuration parameters
245  *                         in p_activate_event or p_deactivate_event, or both.
246  */
247 int32_t mpsl_fem_lna_configuration_set(const mpsl_fem_event_t * const p_activate_event,
248                                        const mpsl_fem_event_t * const p_deactivate_event);
249 
250 /** @brief Clears up the configuration provided by the @ref mpsl_fem_lna_configuration_set function.
251  *
252  * @retval   0             LNA activate setup purge is successful.
253  * @retval   -NRF_EPERM    LNA is currently disabled.
254  */
255 int32_t mpsl_fem_lna_configuration_clear(void);
256 
257 /** @brief Deactivates PA/LNA with immediate effect.
258  *
259  *  Deactivates PA/LNA with immediate effect - contrary to
260  *  @ref mpsl_fem_lna_configuration_clear or @ref mpsl_fem_pa_configuration_clear,
261  *  which both just set up the infrastructure for events which shall disable the PA/LNA.
262  *
263  * @param[in] type Whether to deactivate imeediately PA, LNA, or both (see @ref mpsl_fem_functionality_t).
264  */
265 void mpsl_fem_deactivate_now(mpsl_fem_functionality_t type);
266 
267 /** @brief Instruct Front End Module to disable PA and LNA as soon as possible
268  *  using the group following the event.
269  *
270  * @param[in] event       An event which is triggered when the abort condition occurs.
271  *                        (See doc for @ref mpsl_subscribable_hw_event_t type.)
272  * @param[in] group       (D)PPI Group which shall be disabled when the abort event is triggered.
273  *
274  * @retval   0            Setting of the abort sequence path is successful.
275  * @retval   -NRF_EPERM   Setting of the abort sequence path could not be performed.
276  */
277 int32_t mpsl_fem_abort_set(mpsl_subscribable_hw_event_t event, uint32_t group);
278 
279 /** @brief Adds one more PPI channel to the PPI Group prepared by the
280  *  @ref mpsl_fem_abort_set function.
281  *
282  * @param[in] channel_to_add (D)PPI channel to add to the (D)PPI group.
283  * @param[in] group          The said PPI group.
284  *
285  * @retval    0              Setting of the abort sequence path is successful.
286  * @retval    -NRF_EPERM     Setting of the abort sequence path could not be performed.
287  */
288 int32_t mpsl_fem_abort_extend(uint32_t channel_to_add, uint32_t group);
289 
290 /** @brief Removes one PPI channel from the PPI Group prepared by the
291  *  @ref mpsl_fem_abort_set function.
292  *
293  * @param[in] channel_to_remove (D)PPI channel to remove from the (D)PPI group.
294  * @param[in] group             The said PPI group.
295  *
296  * @retval   0                  Setting of the abort sequence path is successful.
297  * @retval   -NRF_EPERM         Setting of the abort sequence path could not be performed.
298  */
299 int32_t mpsl_fem_abort_reduce(uint32_t channel_to_remove, uint32_t group);
300 
301 /** @brief Clears up the configuration provided by the @ref mpsl_fem_abort_set
302  *  function.
303  *
304  * @retval   0          Clearing of the abort sequence path is successful.
305  * @retval   -NRF_EPERM Clearing was not done - the possible reason is that there was nothing to clear.
306  */
307 int32_t mpsl_fem_abort_clear(void);
308 
309 /** @brief Cleans up the configured PA/LNA hardware resources.
310  *
311  *  The function resets the hardware that has been set up for the PA/LNA
312  *  activation. The PA and LNA module control configuration parameters
313  *  are not deleted.
314  *  The function is intended to be called after the radio DISABLED signal.
315  */
316 void mpsl_fem_cleanup(void);
317 
318 /** @brief Splits transmit power value into components to be applied on each stage on transmit path.
319  *
320  * @note If the exact value of @p power cannot be achieved, this function attempts to use less
321  * power to not exceed constraint.
322  *
323  * @param[in]  power            TX power requested for transmission on air.
324  * @param[out] p_tx_power_split Components of tx_power to be applied for stages on transmit path.
325  *                              If requested @p power is too high, the split will be set to
326  *                              a value representing maximum achievable power. If the requested
327  *                              @p power is too low, the split will be set to a value representing
328  *                              minimum achievable power.
329  */
330 void mpsl_fem_tx_power_split(const mpsl_tx_power_t power,
331                              mpsl_tx_power_split_t *const p_tx_power_split);
332 
333 /** @brief Sets PA gain.
334  *
335  * @note The gain set by this function will be applied to radio transmissions
336  * following the call. If the function is called during radio transmission
337  * or during ramp-up for transmission it is unspecified if the gain is applied.
338  *
339  * @param[in] gain Gain in dB to be set.
340  *
341  * @retval   0             Gain has been set successfully.
342  * @retval   -NRF_EINVAL   Gain could not be set. Provided @p gain is invalid.
343  */
344 int32_t mpsl_fem_pa_gain_set(const mpsl_fem_gain_t * p_gain);
345 
346 /** @brief Checks if the PA signaling is configured and enabled, and gets
347  *  the configured gain in dB.
348  *
349  * @param[out] p_gain The configured gain in dB if PA is configured and enabled.
350  *                    If there is no PA present or the PA does not affect
351  *                    the signal gain, returns 0 dB.
352  */
353 void mpsl_fem_pa_is_configured(int8_t * const p_gain);
354 
355 /** @brief Prepares the Front End Module to switch to the Power Down state.
356  *
357  *  @deprecated This function is deprecated. Use @ref mpsl_fem_disable instead.
358  *
359  *  This function makes sure the Front End Module shall be switched off in the
360  *  appropriate time, using the hardware timer and its compare channel.
361  *  The timer is owned by the protocol and must be started by the protocol.
362  *  The timer stops after matching the provided compare channel (the call sets the short).
363  *
364  * @param[in] p_instance      Timer instance that is used to schedule the transition to the Power Down state.
365  * @param[in] compare_channel Compare channel to hold a value for the timer.
366  * @param[in] ppi_id          ID of the PPI channel used to switch to the Power Down state.
367  * @param[in] event_addr      Address of the event which shall trigger the Timer start.
368  *
369  * @retval true               Whether the scheduling of the transition was successful.
370  * @retval false              Whether the scheduling of the transition was not successful.
371  */
372 bool mpsl_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
373                                 uint32_t         compare_channel,
374                                 uint32_t         ppi_id,
375                                 uint32_t         event_addr);
376 
377 #endif // MPSL_FEM_PROTOCOL_API_H__
378 
379 /**@} */
380