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 a 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 #ifdef PPI_PRESENT
59 typedef uint32_t mpsl_subscribable_hw_event_t;
60 #else
61 typedef uint8_t mpsl_subscribable_hw_event_t;
62 #endif
63 
64 /** @brief MPSL Front End Module event. */
65 typedef struct
66 {
67     /** Type of event source. */
68     mpsl_fem_event_type_t      type;
69     /** Implementation of the event. */
70     union
71     {
72         /** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_TIMER. */
73         struct
74         {
75             /** Pointer to a 1-us resolution timer instance. */
76             NRF_TIMER_Type *   p_timer_instance;
77 
78             /** Counter period parameters */
79             struct
80             {
81                 /** Timer value when the Front End Module can start preparing PA/LNA. */
82                 uint32_t       start;
83                 /** Timer value at which the PA/LNA have to be prepared. Radio operation shall start at this point. */
84                 uint32_t       end;
85               /** Time interval in which the timer should start and end. */
86             } counter_period;
87 
88             /** Mask of the compare channels that can be used by the Front End Module to schedule its own tasks. */
89             uint8_t            compare_channel_mask;
90           /** Event generated by the timer, used in case of type equal to @ref MPSL_FEM_EVENT_TYPE_TIMER. */
91         } timer;
92 
93         /** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_GENERIC. */
94         struct
95         {
96             /** Event triggering required FEM operation. */
97             mpsl_subscribable_hw_event_t event;
98           /** Generic event, used in case of type equal to @ref MPSL_FEM_EVENT_TYPE_GENERIC. */
99         } generic;
100     } event;
101 
102 #if defined(NRF52_SERIES)
103     /** False to ignore the PPI channel below and use the one set by application. True to use the PPI channel below. */
104     bool                       override_ppi;
105     /** PPI channel to be used for this event. */
106     uint8_t                    ppi_ch_id;
107 #endif
108 } mpsl_fem_event_t;
109 
110 /** TX power, dBm. */
111 typedef int8_t mpsl_tx_power_t;
112 
113 /** Type for PA power control to be applied to Front-End Module, depending on its type.
114  *
115  *  The meaning of this type is FEM type-specific.
116  */
117 typedef uint8_t mpsl_fem_pa_power_control_t;
118 
119 
120 /** @brief Represents components of tx_power to be applied for stages on transmit path. */
121 typedef struct
122 {
123     /** TX power to be applied to the RADIO peripheral. */
124     mpsl_tx_power_t radio_tx_power;
125 
126     /** FEM PA power control.*/
127     mpsl_fem_pa_power_control_t fem_pa_power_control;
128 } mpsl_tx_power_split_t;
129 
130 /** @brief PA setup is required before starting a transmission.
131  *
132  *  This flag applies to @ref mpsl_fem_caps_t::flags.
133  *
134  *  If it is set, then @ref mpsl_fem_pa_configuration_set must be called before transmission starts.
135  */
136 #define MPSL_FEM_CAPS_FLAG_PA_SETUP_REQUIRED  (1U << 0)
137 
138 /** @brief LNA setup is required before starting a reception.
139  *
140  *  This flag applies to @ref mpsl_fem_caps_t::flags.
141  *
142  *  If it is set, then @ref mpsl_fem_lna_configuration_set must be called before reception starts.
143  */
144 #define MPSL_FEM_CAPS_FLAG_LNA_SETUP_REQUIRED (1U << 1)
145 
146 /** @brief Structure representing capabilities and characteristics of the FEM in use. */
147 typedef struct
148 {
149     /** Flags informing about the FEM in use.
150      *
151      *  The following flags apply:
152      *  @ref MPSL_FEM_CAPS_FLAG_PA_SETUP_REQUIRED, @ref MPSL_FEM_CAPS_FLAG_LNA_SETUP_REQUIRED
153      */
154     uint32_t flags;
155 } mpsl_fem_caps_t;
156 
157 /** @brief Gets the capabilities of the FEM in use.
158  *
159  *  @param[out] p_caps  Pointer to the capabilities structure to be filled in.
160  */
161 void mpsl_fem_caps_get(mpsl_fem_caps_t * p_caps);
162 
163 /** @brief Enable Front End Module.
164  *
165  *  Some Front End Module devices should be explicitly enabled before they can be configured
166  *  for radio operation. This function is intended to enable Front End Module shortly before
167  *  radio operations are started.
168  *
169  *  After the Front End Module performed all it's operations complementary @ref mpsl_fem_disable
170  *  function should be called.
171  */
172 void mpsl_fem_enable(void);
173 
174 /** @brief Disable Front End Module.
175  *
176  * Some Front End Module devices can be explicitly disabled after PA and LNA activities are
177  * finished to preserve power.
178  *
179  * This function is intended to disable Front End Module shortly after radio operations are
180  * finished and the protocol does not expect more radio activities in short future, or passes
181  * radio control to other protocols in the system.
182  *
183  * Front End Module disabling process is synchronous and immediate.
184  *
185  * @retval 0
186  * @retval -NRF_EPERM    FEM is configured to enable PA or LNA.
187  */
188 int32_t mpsl_fem_disable(void);
189 
190 /** @brief Sets up PA using the provided events for the upcoming radio transmission.
191  *
192  * Multiple configurations can be provided by repeating calls to this function
193  * (that is, you can set the activate and the deactivate events in multiple calls,
194  * and the configuration is preserved between calls).
195  *
196  * The order of calls of this function and its `lna` counterpart must match the
197  * order of radio operations.
198  * I.e. if you want to listen first and then send the frame, you need first to
199  * issue @ref mpsl_fem_lna_configuration_set and only after @ref mpsl_fem_pa_configuration_set.
200  *
201  * If a @ref MPSL_FEM_EVENT_TYPE_TIMER timer event is
202  * provided, the PA will be configured to activate or deactivate at the
203  * application-configured time gap before the timer instance reaches the given
204  * register_value. The time gap is set via the corresponding configuration setter
205  * of the selected Front End Module.
206  *
207  * If a @ref MPSL_FEM_EVENT_TYPE_GENERIC event is provided,
208  * the PA will be configured to activate or deactivate when an event occurs.
209  *
210  * The function sets up the PPIs and the GPIOTE channel to activate PA for the
211  * upcoming radio transmission. The PA pin will be active until deactivated,
212  * which can happen either by encountering a configured deactivation event or by
213  * using @ref mpsl_fem_deactivate_now.
214  *
215  * @param[in] p_activate_event   Pointer to the activation event structure.
216  * @param[in] p_deactivate_event Pointer to the deactivation event structure.
217  *
218  * @pre To activate PA, the corresponding configuration setter of the selected
219  * Front End Module must have been called first.
220  *
221  * @note If a timer event is provided, the caller of this function is responsible
222  * for starting the timer and configuring its shorts.
223  * Moreover, the caller is responsible for stopping the timer no earlier than
224  * the compare channel of the lowest ID among the provided ones does expire.
225  *
226  * @note The activation event can be only of type
227  * @ref MPSL_FEM_EVENT_TYPE_TIMER.
228  * Using other activation event type leads to undefined module behavior.
229  *
230  * @retval   0             PA activation setup is successful.
231  * @retval   -NRF_EPERM    PA is currently disabled.
232  * @retval   -NRF_EINVAL   PA activation setup could not be performed due to
233  *                         invalid or missing configuration parameters
234  *                         in p_activate_event or p_deactivate_event, or both.
235  */
236 int32_t mpsl_fem_pa_configuration_set(const mpsl_fem_event_t * const p_activate_event,
237                                       const mpsl_fem_event_t * const p_deactivate_event);
238 
239 /** @brief Clears up the configuration provided by the @ref mpsl_fem_pa_configuration_set function.
240  *
241  * @retval   0             PA activation setup purge is successful.
242  * @retval   -NRF_EPERM    PA is currently disabled.
243  */
244 int32_t mpsl_fem_pa_configuration_clear(void);
245 
246 /** @brief Sets up LNA using the provided event for the upcoming radio reception.
247  *
248  * Multiple configurations can be provided by repeating calls to this function
249  * (that is, you can set the activate and the deactivate event in multiple calls,
250  * and the configuration is preserved between calls).
251  *
252  * The order of calls of this function and its `pa` counterpart must match the
253  * order of radio operations. I.e. if you want to listen first and then send the
254  * frame, you need first to issue @ref mpsl_fem_lna_configuration_set and only
255  * after @ref mpsl_fem_pa_configuration_set.
256  *
257  * If a @ref MPSL_FEM_EVENT_TYPE_TIMER timer event is
258  * provided, the LNA will be configured to activate or deactivate at the
259  * application-configured time gap before the timer instance reaches the given
260  * register_value. The time gap is set via the corresponding configuration setter
261  * of the selected Front End Module.
262  *
263  * If a @ref MPSL_FEM_EVENT_TYPE_GENERIC event is provided,
264  * the LNA will be configured to activate or deactivate when an event occurs.
265  *
266  * The function sets up the PPIs and the GPIOTE channel to activate LNA for the
267  * upcoming radio transmission. The LNA pin will be active until deactivated,
268  * which can happen either by encountering a configured deactivation event or by
269  * using @ref mpsl_fem_deactivate_now.
270  *
271  * @param[in] p_activate_event   Pointer to the activation event structure.
272  * @param[in] p_deactivate_event Pointer to the deactivation event structure.
273  *
274  * @pre To activate LNA, the corresponding configuration setter of the selected
275  * Front End Module must have been called first.
276  *
277  * @note If a timer event is provided, the caller of this function is responsible
278  * for starting the timer and configuring its shorts.
279  * Moreover, the caller is responsible for stopping the timer no earlier than
280  * the compare channel of the lowest ID among the provided ones does expire.
281  *
282  * @note The activation event can be only of type
283  * @ref MPSL_FEM_EVENT_TYPE_TIMER. Using other activation
284  * event type leads to undefined module behavior.
285  *
286  * @retval   0             LNA activation setup is successful.
287  * @retval   -NRF_EPERM    LNA is currently disabled.
288  * @retval   -NRF_EINVAL   LNA activation setup could not be performed due to
289  *                         invalid or missing configuration parameters
290  *                         in p_activate_event or p_deactivate_event, or both.
291  */
292 int32_t mpsl_fem_lna_configuration_set(const mpsl_fem_event_t * const p_activate_event,
293                                        const mpsl_fem_event_t * const p_deactivate_event);
294 
295 /** @brief Clears up the configuration provided by the @ref mpsl_fem_lna_configuration_set function.
296  *
297  * @retval   0             LNA activate setup purge is successful.
298  * @retval   -NRF_EPERM    LNA is currently disabled.
299  */
300 int32_t mpsl_fem_lna_configuration_clear(void);
301 
302 /** @brief Deactivates PA/LNA with immediate effect.
303  *
304  *  Deactivates PA/LNA with immediate effect - contrary to
305  *  @ref mpsl_fem_lna_configuration_clear or @ref mpsl_fem_pa_configuration_clear,
306  *  which both just set up the infrastructure for events which shall disable the PA/LNA.
307  *
308  * @param[in] type Whether to deactivate imeediately PA, LNA, or both (see @ref mpsl_fem_functionality_t).
309  */
310 void mpsl_fem_deactivate_now(mpsl_fem_functionality_t type);
311 
312 /** @brief Instruct Front End Module to disable PA and LNA as soon as possible
313  *  using the group following the event.
314  *
315  * @param[in] event       An event which is triggered when the abort condition occurs.
316  *                        (See doc for @ref mpsl_subscribable_hw_event_t type.)
317  * @param[in] group       (D)PPI Group which shall be disabled when the abort event is triggered.
318  *
319  * @retval   0            Setting of the abort sequence path is successful.
320  * @retval   -NRF_EPERM   Setting of the abort sequence path could not be performed.
321  */
322 int32_t mpsl_fem_abort_set(mpsl_subscribable_hw_event_t event, uint32_t group);
323 
324 /** @brief Adds one more PPI channel to the PPI Group prepared by the
325  *  @ref mpsl_fem_abort_set function.
326  *
327  * @param[in] channel_to_add (D)PPI channel to add to the (D)PPI group.
328  * @param[in] group          The said PPI group.
329  *
330  * @retval    0              Setting of the abort sequence path is successful.
331  * @retval    -NRF_EPERM     Setting of the abort sequence path could not be performed.
332  */
333 int32_t mpsl_fem_abort_extend(uint32_t channel_to_add, uint32_t group);
334 
335 /** @brief Removes one PPI channel from the PPI Group prepared by the
336  *  @ref mpsl_fem_abort_set function.
337  *
338  * @param[in] channel_to_remove (D)PPI channel to remove from the (D)PPI group.
339  * @param[in] group             The said PPI group.
340  *
341  * @retval   0                  Setting of the abort sequence path is successful.
342  * @retval   -NRF_EPERM         Setting of the abort sequence path could not be performed.
343  */
344 int32_t mpsl_fem_abort_reduce(uint32_t channel_to_remove, uint32_t group);
345 
346 /** @brief Clears up the configuration provided by the @ref mpsl_fem_abort_set
347  *  function.
348  *
349  * @retval   0          Clearing of the abort sequence path is successful.
350  * @retval   -NRF_EPERM Clearing was not done - the possible reason is that there was nothing to clear.
351  */
352 int32_t mpsl_fem_abort_clear(void);
353 
354 /** @brief Cleans up the configured PA/LNA hardware resources.
355  *
356  *  The function resets the hardware that has been set up for the PA/LNA
357  *  activation. The PA and LNA module control configuration parameters
358  *  are not deleted.
359  *  The function is intended to be called after the radio DISABLED signal.
360  */
361 void mpsl_fem_cleanup(void);
362 
363 /** @brief Splits transmit power value into components to be applied on each stage on transmit path.
364  *
365  * @note If the exact value of @p power cannot be achieved, this function attempts to either use
366  * available level lower than the requested level to not exceed constraint, or use the lowest
367  * available level greater than the requested level, depending on @p tx_power_ceiling.
368  *
369  * @param[in]  power                TX power requested for transmission on air.
370  * @param[out] p_tx_power_split     Components of tx_power to be applied for stages on transmit path.
371  *                                  If requested @p power is too high, the split will be set to
372  *                                  a value representing maximum achievable power. If the requested
373  *                                  @p power is too low, the split will be set to a value representing
374  *                                  minimum achievable power.
375  * @param[in]  freq_mhz             Frequency in MHz to calculate the split for.
376  * @param[in]  tx_power_ceiling     Flag to get ceiling or floor of requested transmit power level.
377  *
378  * @return  The power in dBm that will be achieved if values returned through @p p_tx_power_split
379  *          are applied.
380  */
381 int8_t mpsl_fem_tx_power_split(const mpsl_tx_power_t         power,
382                                mpsl_tx_power_split_t * const p_tx_power_split,
383                                uint16_t                      freq_mhz,
384                                bool                          tx_power_ceiling);
385 
386 /** @brief Sets the PA power control.
387  *
388  * Setting the PA power control informs the FEM implementation how the PA is to be controlled
389  * before the next transmission.
390  *
391  * The PA power control set by this function is to be applied to control signals or
392  * parameters. What signals and parameters are controlled and how does it happen depends on
393  * implementation of given FEM. The meaning of @p pa_power_control parameter is
394  * fully FEM type-dependent. For FEM type-independent protocol implementation please
395  * use the function @ref mpsl_fem_tx_power_split and provide outcome of this function
396  * returned by the parameter @c p_tx_power_split to the call to @ref mpsl_fem_pa_power_control_set.
397  * For applications intended for testing the FEM itself when @ref mpsl_fem_tx_power_split is not used
398  * you must make the @p pa_power_control parameter on your own.
399  *
400  * @note The PA power control set by this function will be applied to radio transmissions
401  * following the call. If the function is called during radio transmission
402  * or during ramp-up for transmission it is unspecified if the control is applied.
403  *
404  * @param[in] pa_power_control  PA power control to be applied to the FEM.
405  *
406  * @retval   0             PA power control has been applied successfully.
407  * @retval   -NRF_EINVAL   PA power control could not be applied. Provided @p pa_power_control is invalid.
408  */
409 int32_t mpsl_fem_pa_power_control_set(mpsl_fem_pa_power_control_t pa_power_control);
410 
411 /** @brief Prepares the Front End Module to switch to the Power Down state.
412  *
413  *  @deprecated This function is deprecated. Use @ref mpsl_fem_disable instead.
414  *
415  *  This function makes sure the Front End Module shall be switched off in the
416  *  appropriate time, using the hardware timer and its compare channel.
417  *  The timer is owned by the protocol and must be started by the protocol.
418  *  The timer stops after matching the provided compare channel (the call sets the short).
419  *
420  * @param[in] p_instance      Timer instance that is used to schedule the transition to the Power Down state.
421  * @param[in] compare_channel Compare channel to hold a value for the timer.
422  * @param[in] ppi_id          ID of the PPI channel used to switch to the Power Down state.
423  * @param[in] event_addr      Address of the event which shall trigger the Timer start.
424  *
425  * @retval true               Whether the scheduling of the transition was successful.
426  * @retval false              Whether the scheduling of the transition was not successful.
427  */
428 bool mpsl_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
429                                 uint32_t         compare_channel,
430                                 uint32_t         ppi_id,
431                                 uint32_t         event_addr);
432 
433 #endif // MPSL_FEM_PROTOCOL_API_H__
434 
435 /**@} */
436