1 /*
2  * Copyright (c) 2018-2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 
9 #include <zephyr/toolchain.h>
10 #include <zephyr/types.h>
11 #include <zephyr/sys/util.h>
12 
13 #include "hal/ccm.h"
14 #include "hal/radio.h"
15 #include "hal/ticker.h"
16 
17 #include "util/util.h"
18 #include "util/memq.h"
19 
20 #include "pdu_vendor.h"
21 #include "pdu.h"
22 
23 #include "lll.h"
24 #include "lll_vendor.h"
25 #include "lll_df_types.h"
26 #include "lll_conn.h"
27 #include "lll_central.h"
28 #include "lll_chan.h"
29 
30 #include "lll_internal.h"
31 #include "lll_tim_internal.h"
32 
33 #include <soc.h>
34 #include "hal/debug.h"
35 
36 static int init_reset(void);
37 static int prepare_cb(struct lll_prepare_param *p);
38 
lll_central_init(void)39 int lll_central_init(void)
40 {
41 	int err;
42 
43 	err = init_reset();
44 	if (err) {
45 		return err;
46 	}
47 
48 	return 0;
49 }
50 
lll_central_reset(void)51 int lll_central_reset(void)
52 {
53 	int err;
54 
55 	err = init_reset();
56 	if (err) {
57 		return err;
58 	}
59 
60 	return 0;
61 }
62 
lll_central_prepare(void * param)63 void lll_central_prepare(void *param)
64 {
65 	int err;
66 
67 	err = lll_clk_on();
68 	LL_ASSERT(!err || err == -EINPROGRESS);
69 
70 	/* Invoke common pipeline handling of prepare */
71 	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0,
72 			  param);
73 	LL_ASSERT(!err || err == -EINPROGRESS);
74 }
75 
init_reset(void)76 static int init_reset(void)
77 {
78 	return 0;
79 }
80 
prepare_cb(struct lll_prepare_param * p)81 static int prepare_cb(struct lll_prepare_param *p)
82 {
83 	struct pdu_data *pdu_data_tx;
84 	uint32_t ticks_at_event;
85 	uint32_t ticks_at_start;
86 	uint16_t event_counter;
87 	uint32_t remainder_us;
88 	uint8_t data_chan_use;
89 	struct lll_conn *lll;
90 	struct ull_hdr *ull;
91 	uint32_t remainder;
92 
93 	DEBUG_RADIO_START_M(1);
94 
95 	lll = p->param;
96 
97 	/* Reset connection event global variables */
98 	lll_conn_prepare_reset();
99 
100 	/* Calculate the current event latency */
101 	lll->latency_event = lll->latency_prepare + p->lazy;
102 
103 	/* Calculate the current event counter value */
104 	event_counter = lll->event_counter + lll->latency_event;
105 
106 	/* Update event counter to next value */
107 	lll->event_counter = (event_counter + 1);
108 
109 	/* Reset accumulated latencies */
110 	lll->latency_prepare = 0;
111 
112 	if (lll->data_chan_sel) {
113 #if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
114 		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
115 					       &lll->data_chan_map[0],
116 					       lll->data_chan_count);
117 #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
118 		data_chan_use = 0;
119 		LL_ASSERT(0);
120 #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
121 	} else {
122 		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
123 					       lll->data_chan_hop,
124 					       lll->latency_event,
125 					       &lll->data_chan_map[0],
126 					       lll->data_chan_count);
127 	}
128 
129 	/* Prepare the Tx PDU */
130 	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
131 	pdu_data_tx->sn = lll->sn;
132 	pdu_data_tx->nesn = lll->nesn;
133 
134 	/* Start setting up of Radio h/w */
135 	radio_reset();
136 	/* TODO: other Tx Power settings */
137 	radio_tx_power_set(RADIO_TXP_DEFAULT);
138 	radio_aa_set(lll->access_addr);
139 	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
140 			    (((uint32_t)lll->crc_init[2] << 16) |
141 			     ((uint32_t)lll->crc_init[1] << 8) |
142 			     ((uint32_t)lll->crc_init[0])));
143 	lll_chan_set(data_chan_use);
144 
145 	/* setup the radio tx packet buffer */
146 	lll_conn_tx_pkt_set(lll, pdu_data_tx);
147 
148 	radio_isr_set(lll_conn_isr_tx, lll);
149 
150 	radio_tmr_tifs_set(EVENT_IFS_US);
151 
152 #if defined(CONFIG_BT_CTLR_PHY)
153 	radio_switch_complete_and_rx(lll->phy_rx);
154 #else /* !CONFIG_BT_CTLR_PHY */
155 	radio_switch_complete_and_rx(0);
156 #endif /* !CONFIG_BT_CTLR_PHY */
157 
158 	ticks_at_event = p->ticks_at_expire;
159 	ull = HDR_LLL2ULL(lll);
160 	ticks_at_event += lll_event_offset_get(ull);
161 
162 	ticks_at_start = ticks_at_event;
163 	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
164 
165 	remainder = p->remainder;
166 	remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
167 
168 	/* capture end of Tx-ed PDU, used to calculate HCTO. */
169 	radio_tmr_end_capture();
170 
171 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
172 	radio_gpio_pa_setup();
173 
174 #if defined(CONFIG_BT_CTLR_PHY)
175 	radio_gpio_pa_lna_enable(remainder_us +
176 				 radio_tx_ready_delay_get(lll->phy_tx,
177 							  lll->phy_flags) -
178 				 HAL_RADIO_GPIO_PA_OFFSET);
179 #else /* !CONFIG_BT_CTLR_PHY */
180 	radio_gpio_pa_lna_enable(remainder_us +
181 				 radio_tx_ready_delay_get(0, 0) -
182 				 HAL_RADIO_GPIO_PA_OFFSET);
183 #endif /* !CONFIG_BT_CTLR_PHY */
184 #else /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
185 	ARG_UNUSED(remainder_us);
186 #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
187 
188 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
189 	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
190 	/* check if preempt to start has changed */
191 	if (lll_preempt_calc(ull, (TICKER_ID_CONN_BASE + lll->handle),
192 			     ticks_at_event)) {
193 		radio_isr_set(lll_conn_isr_abort, lll);
194 		radio_disable();
195 	} else
196 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
197 	{
198 		uint32_t ret;
199 
200 		ret = lll_prepare_done(lll);
201 		LL_ASSERT(!ret);
202 	}
203 
204 	DEBUG_RADIO_START_M(1);
205 
206 	return 0;
207 }
208