1515#include "radio_df.h"
1616#include "radio_internal.h"
1717
18- /* @brief Minimum antennas number required if antenna switching is enabled */
19- #define DF_ANT_NUM_MIN 2
20- /* @brief Value that used to check if PDU antenna pattern is not set */
21- #define DF_PDU_ANT_NOT_SET 0xFF
22- /* @brief Value to set antenna GPIO pin as not connected */
23- #define DF_GPIO_PIN_NOT_SET 0xFF
24- /* @brief Number of PSEL_DFEGPIO registers in Radio peripheral */
25- #define DF_PSEL_GPIO_NUM 8
26- /* @brief Maximum index number related with count of PSEL_DFEGPIO registers in
27- * Radio peripheral. It is used in macros only e.g. UTIL_LISTIFY that
28- * evaluate indices in an inclusive way.
18+ /* Devicetree node identifier for the radio node. */
19+ #define RADIO_NODE DT_NODELABEL(radio)
20+
21+ /* Value to set for unconnected antenna GPIO pins. */
22+ #define DFE_PSEL_NOT_SET 0xFF
23+ /* Number of PSEL_DFEGPIO[n] registers in the radio peripheral. */
24+ #define MAX_DFE_GPIO 8
25+ /* Run a macro 'fn' on each available DFE GPIO index, from 0 to
26+ * MAX_DFE_GPIO-1, with the given parenthesized separator.
2927 */
30- #define DF_PSEL_GPIO_NUM_MAX_IDX 7
28+ #define FOR_EACH_DFE_GPIO (fn , sep ) \
29+ FOR_EACH(fn, sep, 0, 1, 2, 3, 4, 5, 6, 7)
3130
32- /* @brief Direction Finding antenna matrix configuration */
31+ /* Direction Finding antenna matrix configuration */
3332struct df_ant_cfg {
3433 uint8_t ant_num ;
3534 /* Selection of GPIOs to be used to switch antennas by Radio */
36- uint8_t dfe_gpio [DF_PSEL_GPIO_NUM ];
35+ uint8_t dfe_gpio [MAX_DFE_GPIO ];
3736};
3837
39- #define RADIO DT_NODELABEL(radio)
40- #define DFE_GPIO_PSEL (idx ) \
41- COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
42- (NRF_DT_GPIOS_TO_PSEL(RADIO, dfegpio##idx##_gpios)), \
43- (DF_GPIO_PIN_NOT_SET))
38+ #define DFE_GPIO_PSEL (idx ) \
39+ NRF_DT_GPIOS_TO_PSEL_OR(RADIO_NODE, dfegpio##idx##_gpios, \
40+ DFE_PSEL_NOT_SET)
4441
4542#define DFE_GPIO_PIN_DISCONNECT (RADIO_PSEL_DFEGPIO_CONNECT_Disconnected << \
4643 RADIO_PSEL_DFEGPIO_CONNECT_Pos)
4744
48- #define COUNT_GPIO (idx , _ ) + DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios)
49- #define DFE_GPIO_NUM (UTIL_LISTIFY(DF_PSEL_GPIO_NUM, COUNT_GPIO, _))
45+ #define HAS_DFE_GPIO (idx ) DT_NODE_HAS_PROP(RADIO_NODE, dfegpio##idx##_gpios)
5046
51- /* DFE_GPIO_NUM_IS_ZERO is required to correctly compile COND_CODE_1 in
52- * DFE_GPIO_ALLOWED_ANT_NUM macro. DFE_GPIO_NUM does not expand to literal 1
53- * So it is not possible to use it as a conditional in COND_CODE_1 argument.
47+ /* The number of dfegpio[n]-gpios properties which are set. */
48+ #define DFE_GPIO_NUM (FOR_EACH_DFE_GPIO(HAS_DFE_GPIO, (+)))
49+
50+ /* The minimum number of antennas required to enable antenna switching. */
51+ #define MIN_ANTENNA_NUM 2
52+
53+ /* The maximum number of antennas supported by the number of
54+ * dfegpio[n]-gpios properties which are set.
5455 */
5556#if (DFE_GPIO_NUM > 0 )
56- #define DFE_GPIO_NUM_IS_ZERO 1
57+ #define MAX_ANTENNA_NUM BIT(DFE_GPIO_NUM)
5758#else
58- #define DFE_GPIO_NUM_IS_ZERO EMPTY
59+ #define MAX_ANTENNA_NUM 0
5960#endif
6061
61- #define DFE_GPIO_ALLOWED_ANT_NUM COND_CODE_1(DFE_GPIO_NUM_IS_ZERO, \
62- (BIT(DFE_GPIO_NUM)), (0))
62+ /* PDU_ANTENNA is defined outside of the #if block below because
63+ * radio_df_pdu_antenna_switch_pattern_get() can get called even when
64+ * the preprocessor condition being tested is 0. In this case, we use
65+ * the default value of 0.
66+ */
67+ #define PDU_ANTENNA DT_PROP_OR(RADIO_NODE, dfe_pdu_antenna, 0)
68+
69+ uint8_t radio_df_pdu_antenna_switch_pattern_get (void )
70+ {
71+ return PDU_ANTENNA ;
72+ }
6373
6474#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX ) || \
6575 defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX )
6676
67- /* Check if there is enough pins configured to represent each pattern
68- * for given antennas number.
77+ /*
78+ * Check that we have an antenna switch pattern for the DFE idle
79+ * state. (In DFE idle state, the radio peripheral transmits or
80+ * receives PDUs.)
6981 */
70- BUILD_ASSERT (( DT_PROP ( RADIO , dfe_antenna_num ) <= DFE_GPIO_ALLOWED_ANT_NUM ), "Insufficient "
71- "number of GPIO pins configured." );
72- BUILD_ASSERT (( DT_PROP ( RADIO , dfe_antenna_num ) >= DF_ANT_NUM_MIN ), "Insufficient "
73- "number of antennas provided." );
74- BUILD_ASSERT (! IS_ENABLED ( CONFIG_BT_CTLR_DF_INIT_ANT_SEL_GPIOS ) ||
75- ( DT_PROP ( RADIO , dfe_pdu_antenna ) != DF_PDU_ANT_NOT_SET ), "Missing "
76- "antenna pattern used to select antenna for PDU Tx ." );
77-
78- /* Check if dfegpio#-gios property has flag cell set to zero */
79- #define DFE_GPIO_PIN_FLAGS ( idx ) (DT_GPIO_FLAGS(RADIO, dfegpio##idx##_gpios))
80- #define DFE_GPIO_PIN_IS_FLAG_ZERO ( idx ) \
81- COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
82- (BUILD_ASSERT((DFE_GPIO_PIN_FLAGS(idx) == 0), \
83- "Flags value of GPIO pin property must be" \
84- "zero.")), \
85- (EMPTY))
86-
87- #define DFE_GPIO_PIN_LIST ( idx , _ ) idx ,
88- FOR_EACH ( DFE_GPIO_PIN_IS_FLAG_ZERO , (;) ,
89- UTIL_LISTIFY ( DF_PSEL_GPIO_NUM_MAX_IDX , DFE_GPIO_PIN_LIST ))
90-
91- #if DT_NODE_HAS_STATUS ( RADIO , okay )
92- const static struct df_ant_cfg ant_cfg = {
93- . ant_num = DT_PROP ( RADIO , dfe_antenna_num ),
94- . dfe_gpio = {
95- FOR_EACH ( DFE_GPIO_PSEL , (,),
96- UTIL_LISTIFY ( DF_PSEL_GPIO_NUM_MAX_IDX , DFE_GPIO_PIN_LIST ))
82+
83+ #define HAS_PDU_ANTENNA DT_NODE_HAS_PROP(RADIO_NODE, dfe_pdu_antenna)
84+
85+ BUILD_ASSERT ( HAS_PDU_ANTENNA ,
86+ "Missing antenna pattern used to select antenna for PDU Tx "
87+ "during the DFE Idle state. "
88+ "Set the dfe-pdu- antenna devicetree property ." );
89+
90+ void radio_df_ant_switch_pattern_set ( const uint8_t * patterns , uint8_t len )
91+ {
92+ /* SWITCHPATTERN is like a moving pointer to an underlying buffer.
93+ * Each write stores a value and moves the pointer to new free position.
94+ * When read it returns number of stored elements since last write to
95+ * CLEARPATTERN. There is no need to use a subscript operator.
96+ *
97+ * Some storage entries in the buffer has special purpose for DFE
98+ * extension in radio:
99+ * - SWITCHPATTERN[0] for idle period (PDU Tx/Rx) ,
100+ * - SWITCHPATTERN[1] for guard and reference period ,
101+ * - SWITCHPATTERN[2] and following for switch-sampling slots.
102+ * Due to that in SWITCHPATTER[0] there is stored a pattern provided by
103+ * DTS property dfe_pdu_antenna. This limits number of supported antenna
104+ * switch patterns by one.
105+ */
106+ NRF_RADIO -> SWITCHPATTERN = PDU_ANTENNA ;
107+ for ( uint8_t idx = 0 ; idx < len ; ++ idx ) {
108+ NRF_RADIO -> SWITCHPATTERN = patterns [ idx ];
97109 }
110+ }
111+
112+ /*
113+ * Check that the number of antennas has been set, and that enough
114+ * pins are configured to represent each pattern for the given number
115+ * of antennas.
116+ */
117+
118+ #define HAS_ANTENNA_NUM DT_NODE_HAS_PROP(RADIO_NODE, dfe_antenna_num)
119+
120+ BUILD_ASSERT (HAS_ANTENNA_NUM ,
121+ "You must set the dfe-antenna-num property in the radio node "
122+ "to enable antenna switching." );
123+
124+ #define ANTENNA_NUM DT_PROP_OR(RADIO_NODE, dfe_antenna_num, 0)
125+
126+ BUILD_ASSERT (!HAS_ANTENNA_NUM || (ANTENNA_NUM <= MAX_ANTENNA_NUM ),
127+ "Insufficient number of GPIO pins configured. "
128+ "Set more dfegpio[n]-gpios properties." );
129+ BUILD_ASSERT (!HAS_ANTENNA_NUM || (ANTENNA_NUM >= MIN_ANTENNA_NUM ),
130+ "Insufficient number of antennas provided. "
131+ "Increase the dfe-antenna-num property." );
132+
133+ /*
134+ * Check that each dfegpio[n]-gpios property has a zero flags cell.
135+ */
136+
137+ #define ASSERT_DFE_GPIO_FLAGS_ARE_ZERO (idx ) \
138+ BUILD_ASSERT(DT_GPIO_FLAGS(RADIO_NODE, dfegpio##idx##_gpios) == 0, \
139+ "The flags cell in each dfegpio[n]-gpios " \
140+ "property must be zero.")
141+
142+ FOR_EACH_DFE_GPIO (ASSERT_DFE_GPIO_FLAGS_ARE_ZERO , (;));
143+
144+ /* Stores the dfegpio[n]-gpios property values.
145+ */
146+ const static struct df_ant_cfg ant_cfg = {
147+ .ant_num = ANTENNA_NUM ,
148+ .dfe_gpio = { FOR_EACH_DFE_GPIO (DFE_GPIO_PSEL , (,)) }
98149};
99- #else
100- #error "DF antenna switching feature requires dfe_antenna_num to be enabled in DTS"
101- #endif
102150
103151/* @brief Function configures Radio with information about GPIO pins that may be
104152 * used to drive antenna switching during CTE Tx/RX.
@@ -111,10 +159,10 @@ void radio_df_ant_switching_pin_sel_cfg(void)
111159{
112160 uint8_t pin_sel ;
113161
114- for (uint8_t idx = 0 ; idx < DF_PSEL_GPIO_NUM ; ++ idx ) {
162+ for (uint8_t idx = 0 ; idx < MAX_DFE_GPIO ; ++ idx ) {
115163 pin_sel = ant_cfg .dfe_gpio [idx ];
116164
117- if (pin_sel != DF_GPIO_PIN_NOT_SET ) {
165+ if (pin_sel != DFE_PSEL_NOT_SET ) {
118166 nrf_radio_dfe_pattern_pin_set (NRF_RADIO ,
119167 pin_sel ,
120168 idx );
@@ -141,12 +189,12 @@ void radio_df_ant_switching_gpios_cfg(void)
141189{
142190 uint8_t pin_sel ;
143191
144- for (uint8_t idx = 0 ; idx < DF_PSEL_GPIO_NUM ; ++ idx ) {
192+ for (uint8_t idx = 0 ; idx < MAX_DFE_GPIO ; ++ idx ) {
145193 pin_sel = ant_cfg .dfe_gpio [idx ];
146- if (pin_sel != DF_GPIO_PIN_NOT_SET ) {
194+ if (pin_sel != DFE_PSEL_NOT_SET ) {
147195 nrf_gpio_cfg_output (pin_sel );
148196
149- if (BIT (idx ) & DT_PROP ( RADIO , dfe_pdu_antenna ) ) {
197+ if (BIT (idx ) & PDU_ANTENNA ) {
150198 nrf_gpio_pin_set (pin_sel );
151199 } else {
152200 nrf_gpio_pin_clear (pin_sel );
@@ -316,33 +364,6 @@ void radio_df_ant_switch_pattern_clear(void)
316364 NRF_RADIO -> CLEARPATTERN = RADIO_CLEARPATTERN_CLEARPATTERN_Clear ;
317365}
318366
319- void radio_df_ant_switch_pattern_set (const uint8_t * patterns , uint8_t len )
320- {
321- /* SWITCHPATTERN is like a moving pointer to underlying buffer.
322- * Each write stores a value and moves the pointer to new free position.
323- * When read it returns number of stored elements since last write to
324- * CLEARPATTERN. There is no need to use subscript operator.
325- *
326- * Some storage entries in the buffer has special purpose for DFE
327- * extension in radio:
328- * - SWITCHPATTERN[0] for idle period (PDU Tx/Rx),
329- * - SWITCHPATTERN[1] for guard and reference period,
330- * - SWITCHPATTERN[2] and following for switch-sampling slots.
331- * Due to that in SWITCHPATTER[0] there is stored a pattern provided by
332- * DTS property dfe_pdu_antenna. This limits number of supported antenna
333- * switch patterns by one.
334- */
335- NRF_RADIO -> SWITCHPATTERN = DT_PROP (RADIO , dfe_pdu_antenna );
336- for (uint8_t idx = 0 ; idx < len ; ++ idx ) {
337- NRF_RADIO -> SWITCHPATTERN = patterns [idx ];
338- }
339- }
340-
341- uint8_t radio_df_pdu_antenna_switch_pattern_get (void )
342- {
343- return DT_PROP (RADIO , dfe_pdu_antenna );
344- }
345-
346367void radio_df_reset (void )
347368{
348369 radio_df_mode_set (RADIO_DFEMODE_DFEOPMODE_Disabled );
0 commit comments