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 /**
36  * @brief 802.15.4 antenna diversity module.
37  */
38 
39 #ifndef NRF_802154_SL_ANT_DIV_H
40 #define NRF_802154_SL_ANT_DIV_H
41 
42 #include <stdint.h>
43 #include <stdbool.h>
44 
45 #include "nrfx.h"
46 
47 /**
48  * @brief RSSI measurement results.
49  */
50 #define NRF_802154_SL_ANT_DIV_RSSI_INVALID           INT8_MAX
51 
52 /**
53  * @brief Priority of TIMER IRQ.
54  */
55 #define NRF_802154_SL_ANT_DIV_IRQ_PRIORITY           1
56 
57 /**
58  * @brief Recommended value of time in microseconds between consecutive antenna switches.
59  *
60  * When antenna diversity interface operates in @ref NRF_802154_SL_ANT_DIV_MODE_AUTO mode,
61  * the antenna is toggled periodically in order to maximize the chance of receiving a frame
62  * preamble. The time between consecutive antenna toggles is configured through
63  * @ref nrf_802154_sl_ant_div_cfg_set function. The value specified by this macro is the
64  * recommended value of @p toggle_time parameter that should be set if no particular reasons
65  * for a different configuration exist.
66  */
67 #define NRF_802154_SL_ANT_DIV_DEFAULT_TOGGLE_TIME_US 40
68 
69 /**
70  * @brief Mode of the antenna diversity module.
71  *
72  * Possible values:
73  * - @ref NRF_802154_SL_ANT_DIV_MODE_DISABLED,
74  * - @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL,
75  * - @ref NRF_802154_SL_ANT_DIV_MODE_AUTO
76  */
77 typedef uint8_t nrf_802154_sl_ant_div_mode_t;
78 
79 #define NRF_802154_SL_ANT_DIV_MODE_DISABLED 0x00 // !< Antenna diversity is disabled - Antenna will not be controlled by sl_ant_div module. While in this mode, current antenna is unspecified.
80 #define NRF_802154_SL_ANT_DIV_MODE_MANUAL   0x01 // !< Antenna is selected manually
81 #define NRF_802154_SL_ANT_DIV_MODE_AUTO     0x02 // !< Antenna is selected automatically based on RSSI - not supported for transmission.
82 
83 /**
84  * @brief Available antennas
85  *
86  * Possible values:
87  * - @ref NRF_802154_SL_ANT_DIV_ANTENNA_1,
88  * - @ref NRF_802154_SL_ANT_DIV_ANTENNA_2,
89  * - @ref NRF_802154_SL_ANT_DIV_ANTENNA_NONE
90  */
91 typedef uint8_t nrf_802154_sl_ant_div_antenna_t;
92 
93 #define NRF_802154_SL_ANT_DIV_ANTENNA_1    0x00 // !< First antenna
94 #define NRF_802154_SL_ANT_DIV_ANTENNA_2    0x01 // !< Second antenna
95 #define NRF_802154_SL_ANT_DIV_ANTENNA_NONE 0x02 // !< Used to indicate that antenna for the last reception was not selected via antenna diversity algorithm.
96 
97 /**
98  * @brief Types of operations supported by antenna diversity module.
99  *
100  * Possible values:
101  * - @ref NRF_802154_SL_ANT_DIV_OP_RX,
102  * - @ref NRF_802154_SL_ANT_DIV_OP_TX
103  */
104 typedef uint8_t nrf_802154_sl_ant_div_op_t;
105 
106 #define NRF_802154_SL_ANT_DIV_OP_RX 0x00 // !< RX-related operations
107 #define NRF_802154_SL_ANT_DIV_OP_TX 0x01 // !< TX-related operations
108 
109 /**
110  * @brief Configuration of the antenna diversity module.
111  *
112  * The following configuration parameters are to be set before
113  * @ref nrf_802154_sl_ant_div_init is called.
114  */
115 typedef struct
116 {
117     /**
118      * @brief Pin used for antenna selection.
119      */
120     uint8_t ant_sel_pin;
121 
122     /**
123      * @brief Time in microseconds between antenna switches in @ref NRF_802154_SL_ANT_DIV_MODE_AUTO.
124      */
125     uint8_t toggle_time;
126 
127     /**
128      * @brief PPI channel instance used to connect TIMER event with antenna toggling task.
129      *
130      * Antenna diversity interface claims exclusive access to the provided PPI channel.
131      */
132     uint8_t ppi_ch;
133 
134     /**
135      * @brief GPIOTE channel instance used to toggle antenna when triggered with PPI.
136      *
137      * Antenna diversity interface claims exclusive access to the provided GPIOTE channel.
138      */
139     uint8_t gpiote_ch;
140 
141     /**
142      * @brief Timer instance used to measure time between consecutive antenna toggles.
143      *
144      * Antenna diversity interface claims exclusive access to the provided TIMER peripheral.
145      */
146     NRF_TIMER_Type * p_timer;
147 } nrf_802154_sl_ant_div_cfg_t;
148 
149 /**
150  * @}
151  * @defgroup nrf_802154_ant_div_cfg Antenna diversity configuration
152  * @{
153  */
154 
155 /**
156  * @brief Configures the antenna diversity interface.
157  *
158  * @note This function must be called before @ref nrf_802154_sl_ant_div_init
159  * and can only be called once.
160  *
161  * @param[in] p_cfg  Antenna diversity interface configuration.
162  */
163 void nrf_802154_sl_ant_div_cfg_set(const nrf_802154_sl_ant_div_cfg_t * p_cfg);
164 
165 /**
166  * @brief Gets the antenna diversity interface configuration.
167  *
168  * @param[out] p_cfg  Antenna diversity interface configuration.
169  *
170  * @retval true  The configuration was retrieved successfully.
171  * @retval false The configuration could not be retrieved.
172  */
173 bool nrf_802154_sl_ant_div_cfg_get(nrf_802154_sl_ant_div_cfg_t * p_cfg);
174 
175 /**
176  * @brief Sets the antenna diversity mode.
177  *
178  * @param[in] op   Type of antenna diversity operations the mode should be changed for.
179  * @param[in] mode Antenna diversity mode to be set.
180  *
181  * @retval true  Antenna diversity mode set successfully.
182  * @retval false Invalid antenna diversity mode or operation type passed as arguments.
183  */
184 bool nrf_802154_sl_ant_div_cfg_mode_set(nrf_802154_sl_ant_div_op_t   op,
185                                         nrf_802154_sl_ant_div_mode_t mode);
186 
187 /**
188  * @brief Gets the antenna diversity mode.
189  *
190  * @param[in] op  Type of antenna diversity operations the mode should be retrieved for.
191  *
192  * @return Current antenna diversity mode.
193  */
194 nrf_802154_sl_ant_div_mode_t nrf_802154_sl_ant_div_cfg_mode_get(nrf_802154_sl_ant_div_op_t op);
195 
196 /**
197  * @brief Selects antenna to be used in @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL mode.
198  *
199  * @note Takes effect only if antenna diversity mode is set to
200  * @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. See @ref nrf_802154_sl_ant_div_mode_set.
201  *
202  * @param[in] op       Type of antenna diversity operations the antenna should be changed for.
203  * @param[in] antenna  Antenna to be selected.
204  *
205  * @retval true  Antenna selected successfully.
206  * @retval false Invalid antenna or operation type passed as arguments.
207  */
208 bool nrf_802154_sl_ant_div_cfg_antenna_set(nrf_802154_sl_ant_div_op_t      op,
209                                            nrf_802154_sl_ant_div_antenna_t antenna);
210 
211 /**
212  * @brief Reads the currently used antenna.
213  *
214  * @note The antenna read by this function is currently used antenna only if antenna diversity
215  * mode is set to @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, currently used antenna
216  * may be different. @sa nrf_802154_sl_ant_div_mode_set
217  *
218  * @param[in] op       Type of antenna diversity operations the antenna should be retrieved for.
219  *
220  * @return Currently selected antenna.
221  */
222 nrf_802154_sl_ant_div_antenna_t nrf_802154_sl_ant_div_cfg_antenna_get(
223     nrf_802154_sl_ant_div_op_t op);
224 
225 /**
226  * @}
227  * @defgroup nrf_802154_ant_div Antenna diversity API
228  * @{
229  */
230 
231 /**
232  * @brief Initializes antenna diversity module.
233  *
234  * @note Before this function is called, antenna diversity interface must be configured with
235  * @ref nrf_802154_sl_ant_div_cfg_set.
236  *
237  * @retval true   Initialization was successful.
238  * @retval false  Initialization could not be performed due to unconfigured interface.
239  */
240 bool nrf_802154_sl_ant_div_init(void);
241 
242 /**
243  * @brief Selects an antenna to use.
244  *
245  * This function has no effect if called when antenna diversity module is toggling antenna, i.e.:
246  *  - @ref NRF_802154_SL_ANT_DIV_MODE_AUTO is set
247  *  - receiver is turned on
248  *  - no PPDU is currently being received
249  *
250  * @param[in] antenna  Antenna to be used.
251  *
252  * @retval true  Antenna switched successfully.
253  * @retval false Invalid antenna passed to the function.
254  */
255 bool nrf_802154_sl_ant_div_antenna_set(nrf_802154_sl_ant_div_antenna_t antenna);
256 
257 /**
258  * @brief Gets currently used antenna.
259  *
260  * @retval NRF_802154_SL_ANT_DIV_ANTENNA_1     If antenna 1 is used.
261  * @retval NRF_802154_SL_ANT_DIV_ANTENNA_2     If antenna 2 is used.
262  * @retval NRF_802154_SL_ANT_DIV_ANTENNA_NONE  If the antenna diversity interface is not configured.
263  */
264 nrf_802154_sl_ant_div_antenna_t nrf_802154_sl_ant_div_antenna_get(void);
265 
266 /**
267  * @brief Gets which antenna was selected as best for the last reception.
268  *
269  * @note In three cases @ref NRF_802154_SL_ANT_DIV_ANTENNA_NONE may be returned:
270  *  - No frame was received yet.
271  *  - Last frame was received with antenna diversity auto mode disabled.
272  *  - RSSI measurements didn't have enough time to finish during last frame reception
273  *    and it is unspecified which antenna was selected.
274  *
275  * @return Antenna selected during last successful reception in automatic mode.
276  */
277 nrf_802154_sl_ant_div_antenna_t nrf_802154_sl_ant_div_last_rx_best_antenna_get(void);
278 
279 /**
280  * @brief Handles TIMER IRQ of the antenna diversity interface.
281  *
282  * This function should be called when the timer instance provided to the antenna diversity
283  * interface reports an interrupt.
284  */
285 void nrf_802154_sl_ant_div_timer_irq_handle(void);
286 
287 /**
288  * @}
289  * @defgroup nrf_802154_ant_div_callout Antenna diversity callouts
290  * @{
291  */
292 
293 /**
294  * @brief Callout for RSSI measurement.
295  *
296  * RSSI needs to be settled already after enabling RX or switching antenna.
297  *
298  * @note This function must be called from critical section.
299  *
300  * @return Corrected measured RSSI value.
301  */
302 extern int8_t nrf_802154_sl_ant_div_rssi_measure_get(void);
303 
304 /**
305  * @}
306  * @defgroup nrf_802154_ant_div_notification Antenna diversity notifications
307  * @{
308  */
309 
310 /**
311  * @brief Notification to be called when antenna diversity auto mode is enabled.
312  */
313 void nrf_802154_sl_ant_div_rx_auto_mode_enable_notify(void);
314 
315 /**
316  * @brief Notification to be called when antenna diversity auto mode is disabled.
317  */
318 void nrf_802154_sl_ant_div_rx_auto_mode_disable_notify(void);
319 
320 /**
321  * @brief Notification to be called when radio rx is started.
322  */
323 void nrf_802154_sl_ant_div_rx_started_notify(void);
324 
325 /**
326  * @brief Notification to be called when radio rx is aborted.
327  */
328 void nrf_802154_sl_ant_div_rx_aborted_notify(void);
329 
330 /**
331  * @brief Notification to be called when preamble is detected.
332  */
333 void nrf_802154_sl_ant_div_rx_preamble_detected_notify(void);
334 
335 /**
336  * @brief Notification to be called when frame start is detected during reception.
337  *
338  * @retval true  RSSI measurements have finished and currently selected antenna is optimal for reception.
339  * @retval false RSSI measurements have not yet finished and currently selected antenna is random.
340  */
341 bool nrf_802154_sl_ant_div_rx_frame_started_notify(void);
342 
343 /**
344  * @brief Notification to be called when frame is received successfully.
345  */
346 void nrf_802154_sl_ant_div_rx_frame_received_notify(void);
347 
348 /**
349  * @brief Notification to be called when timeout expires after preamble detection.
350  */
351 void nrf_802154_sl_ant_div_rx_preamble_timeout_notify(void);
352 
353 /**
354  * @brief Notification to be called when energy detection procedure is requested.
355  *
356  * This notification will update the antenna and inform the caller for how long the energy
357  * detection operation should be scheduled. This notification should also be called
358  * after @ref nrf_802154_sl_ant_div_energy_detection_finished_notify requests repeating
359  * the energy detection procedure. In that case, p_ed_time value must be set to 0
360  * when passed to the function.
361  *
362  * @param[inout] p_ed_time Time of the energy detection procedure requested. Value will be updated with time for
363  *                         energy detection procedure on the current antenna.
364  */
365 void nrf_802154_sl_ant_div_energy_detection_requested_notify(uint32_t * p_ed_time);
366 
367 /**
368  * @brief Notification to be called when energy detection procedure is finished.
369  * This notification checks whether the procedure should be repeated on the second antenna.
370  *
371  * @retval true  Energy detection should be repeated, antenna diversity module will switch the antenna when it is started.
372  * @retval false Energy detection is finished, the result can be reported as normally.
373  */
374 bool nrf_802154_sl_ant_div_energy_detection_finished_notify(void);
375 
376 /**
377  * @brief Notification to be called when energy detection procedure is aborted.
378  */
379 void nrf_802154_sl_ant_div_energy_detection_aborted_notify(void);
380 
381 /**
382  * @brief Notification to be called when txack operation is requested.
383  */
384 void nrf_802154_sl_ant_div_txack_notify(void);
385 
386 #endif // NRF_802154_SL_ANT_DIV_H
387