1 /*
2  * Copyright (c) 2018-2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <stddef.h>
9 
10 #include <zephyr/toolchain.h>
11 
12 #include <zephyr/sys/util.h>
13 #include <zephyr/sys/byteorder.h>
14 
15 #include "hal/ccm.h"
16 #include "hal/radio.h"
17 #include "hal/radio_df.h"
18 #include "hal/ticker.h"
19 
20 #include "util/util.h"
21 #include "util/memq.h"
22 #include "util/dbuf.h"
23 
24 #include "pdu_df.h"
25 #include "pdu_vendor.h"
26 #include "pdu.h"
27 
28 #include "lll.h"
29 #include "lll_vendor.h"
30 #include "lll_clock.h"
31 #include "lll_df_types.h"
32 #include "lll_conn.h"
33 #include "lll_central.h"
34 #include "lll_chan.h"
35 
36 #include "lll_internal.h"
37 #include "lll_df_internal.h"
38 #include "lll_tim_internal.h"
39 
40 #include <soc.h>
41 #include "hal/debug.h"
42 
43 static int init_reset(void);
44 static int prepare_cb(struct lll_prepare_param *p);
45 
lll_central_init(void)46 int lll_central_init(void)
47 {
48 	int err;
49 
50 	err = init_reset();
51 	if (err) {
52 		return err;
53 	}
54 
55 	return 0;
56 }
57 
lll_central_reset(void)58 int lll_central_reset(void)
59 {
60 	int err;
61 
62 	err = init_reset();
63 	if (err) {
64 		return err;
65 	}
66 
67 	return 0;
68 }
69 
lll_central_prepare(void * param)70 void lll_central_prepare(void *param)
71 {
72 	int err;
73 
74 	err = lll_hfclock_on();
75 	LL_ASSERT(err >= 0);
76 
77 	/* Invoke common pipeline handling of prepare */
78 	err = lll_prepare(lll_conn_central_is_abort_cb, lll_conn_abort_cb,
79 			  prepare_cb, 0, param);
80 	LL_ASSERT(!err || err == -EINPROGRESS);
81 }
82 
init_reset(void)83 static int init_reset(void)
84 {
85 	return 0;
86 }
87 
prepare_cb(struct lll_prepare_param * p)88 static int prepare_cb(struct lll_prepare_param *p)
89 {
90 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
91 	struct lll_df_conn_rx_params *df_rx_params;
92 	struct lll_df_conn_rx_cfg *df_rx_cfg;
93 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
94 	struct pdu_data *pdu_data_tx;
95 	uint32_t ticks_at_event;
96 	uint32_t ticks_at_start;
97 	uint16_t event_counter;
98 	uint32_t remainder_us;
99 	uint8_t data_chan_use;
100 	struct lll_conn *lll;
101 	struct ull_hdr *ull;
102 	uint32_t remainder;
103 	uint8_t cte_len;
104 	uint32_t ret;
105 
106 	DEBUG_RADIO_START_M(1);
107 
108 	lll = p->param;
109 
110 	/* Check if stopped (on disconnection between prepare and pre-empt)
111 	 */
112 	if (unlikely(lll->handle == 0xFFFF)) {
113 		radio_isr_set(lll_isr_early_abort, lll);
114 		radio_disable();
115 
116 		return 0;
117 	}
118 
119 	/* Reset connection event global variables */
120 	lll_conn_prepare_reset();
121 
122 	/* Calculate the current event latency */
123 	lll->lazy_prepare = p->lazy;
124 	lll->latency_event = lll->latency_prepare + lll->lazy_prepare;
125 
126 	/* Calculate the current event counter value */
127 	event_counter = lll->event_counter + lll->latency_event;
128 
129 	/* Update event counter to next value */
130 	lll->event_counter = (event_counter + 1);
131 
132 	/* Reset accumulated latencies */
133 	lll->latency_prepare = 0;
134 
135 	if (lll->data_chan_sel) {
136 #if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
137 		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
138 					       &lll->data_chan_map[0],
139 					       lll->data_chan_count);
140 #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
141 		data_chan_use = 0;
142 		LL_ASSERT(0);
143 #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
144 	} else {
145 		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
146 					       lll->data_chan_hop,
147 					       lll->latency_event,
148 					       &lll->data_chan_map[0],
149 					       lll->data_chan_count);
150 	}
151 
152 	/* Prepare the Tx PDU */
153 	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
154 	pdu_data_tx->sn = lll->sn;
155 	pdu_data_tx->nesn = lll->nesn;
156 
157 	/* Start setting up of Radio h/w */
158 	radio_reset();
159 
160 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX)
161 	if (pdu_data_tx->cp) {
162 		cte_len = CTE_LEN_US(pdu_data_tx->octet3.cte_info.time);
163 
164 		lll_df_cte_tx_configure(pdu_data_tx->octet3.cte_info.type,
165 					pdu_data_tx->octet3.cte_info.time,
166 					lll->df_tx_cfg.ant_sw_len,
167 					lll->df_tx_cfg.ant_ids);
168 	} else
169 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_TX */
170 	{
171 		cte_len = 0U;
172 	}
173 
174 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
175 	radio_tx_power_set(lll->tx_pwr_lvl);
176 #else
177 	radio_tx_power_set(RADIO_TXP_DEFAULT);
178 #endif
179 
180 	radio_aa_set(lll->access_addr);
181 	radio_crc_configure(PDU_CRC_POLYNOMIAL,
182 					sys_get_le24(lll->crc_init));
183 	lll_chan_set(data_chan_use);
184 
185 	lll_conn_tx_pkt_set(lll, pdu_data_tx);
186 
187 	radio_isr_set(lll_conn_isr_tx, lll);
188 
189 	radio_tmr_tifs_set(lll->tifs_rx_us);
190 
191 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
192 	/* If CTE RX is enabled and the PHY is not CODED, store channel used for
193 	 * the connection event to report it with collected IQ samples.
194 	 * The configuration of the CTE receive may not change during the event,
195 	 * so config buffer is swapped in prepare and used in IRS handers.
196 	 */
197 	if (lll->phy_rx != PHY_CODED) {
198 		df_rx_cfg = &lll->df_rx_cfg;
199 		df_rx_params = dbuf_latest_get(&df_rx_cfg->hdr, NULL);
200 
201 		if (df_rx_params->is_enabled == true) {
202 			lll->df_rx_cfg.chan = data_chan_use;
203 		}
204 	}
205 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
206 
207 #if defined(CONFIG_BT_CTLR_PHY)
208 	radio_switch_complete_and_rx(lll->phy_rx);
209 #else /* !CONFIG_BT_CTLR_PHY */
210 	radio_switch_complete_and_rx(0);
211 #endif /* !CONFIG_BT_CTLR_PHY */
212 
213 	ticks_at_event = p->ticks_at_expire;
214 	ull = HDR_LLL2ULL(lll);
215 	ticks_at_event += lll_event_offset_get(ull);
216 
217 	ticks_at_start = ticks_at_event;
218 	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
219 
220 	remainder = p->remainder;
221 	remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
222 
223 	/* capture end of Tx-ed PDU, used to calculate HCTO. */
224 	radio_tmr_end_capture();
225 
226 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
227 	radio_gpio_pa_setup();
228 
229 #if defined(CONFIG_BT_CTLR_PHY)
230 	radio_gpio_pa_lna_enable(remainder_us +
231 				 radio_tx_ready_delay_get(lll->phy_tx,
232 							  lll->phy_flags) -
233 				 HAL_RADIO_GPIO_PA_OFFSET);
234 #else /* !CONFIG_BT_CTLR_PHY */
235 	radio_gpio_pa_lna_enable(remainder_us +
236 				 radio_tx_ready_delay_get(0, 0) -
237 				 HAL_RADIO_GPIO_PA_OFFSET);
238 #endif /* !CONFIG_BT_CTLR_PHY */
239 #else /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
240 	ARG_UNUSED(remainder_us);
241 #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
242 
243 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
244 	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
245 	uint32_t overhead;
246 
247 	overhead = lll_preempt_calc(ull, (TICKER_ID_CONN_BASE + lll->handle), ticks_at_event);
248 	/* check if preempt to start has changed */
249 	if (overhead) {
250 		LL_ASSERT_OVERHEAD(overhead);
251 
252 		radio_isr_set(lll_isr_abort, lll);
253 		radio_disable();
254 
255 		return -ECANCELED;
256 	}
257 #endif /* !CONFIG_BT_CTLR_XTAL_ADVANCED */
258 
259 	ret = lll_prepare_done(lll);
260 	LL_ASSERT(!ret);
261 
262 	DEBUG_RADIO_START_M(1);
263 
264 	return 0;
265 }
266