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_peripheral.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_periph_init(void)39 int lll_periph_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_periph_reset(void)51 int lll_periph_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_periph_prepare(void * param)63 void lll_periph_prepare(void *param)
64 {
65 struct lll_prepare_param *p;
66 struct lll_conn *lll;
67 int err;
68
69 err = lll_clk_on();
70 LL_ASSERT(!err || err == -EINPROGRESS);
71
72 p = param;
73
74 lll = p->param;
75
76 /* Accumulate window widening */
77 lll->periph.window_widening_prepare_us +=
78 lll->periph.window_widening_periodic_us * (p->lazy + 1);
79 if (lll->periph.window_widening_prepare_us >
80 lll->periph.window_widening_max_us) {
81 lll->periph.window_widening_prepare_us =
82 lll->periph.window_widening_max_us;
83 }
84
85 /* Invoke common pipeline handling of prepare */
86 err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
87 LL_ASSERT(!err || err == -EINPROGRESS);
88 }
89
init_reset(void)90 static int init_reset(void)
91 {
92 return 0;
93 }
94
prepare_cb(struct lll_prepare_param * p)95 static int prepare_cb(struct lll_prepare_param *p)
96 {
97 uint32_t ticks_at_event;
98 uint32_t ticks_at_start;
99 uint16_t event_counter;
100 uint32_t remainder_us;
101 uint8_t data_chan_use;
102 struct lll_conn *lll;
103 struct ull_hdr *ull;
104 uint32_t remainder;
105 uint32_t hcto;
106
107 DEBUG_RADIO_START_S(1);
108
109 lll = p->param;
110
111 /* Reset connection event global variables */
112 lll_conn_prepare_reset();
113
114 /* Calculate the current event latency */
115 lll->latency_event = lll->latency_prepare + p->lazy;
116
117 /* Calculate the current event counter value */
118 event_counter = lll->event_counter + lll->latency_event;
119
120 /* Update event counter to next value */
121 lll->event_counter = (event_counter + 1);
122
123 /* Reset accumulated latencies */
124 lll->latency_prepare = 0;
125
126 if (lll->data_chan_sel) {
127 #if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
128 data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
129 &lll->data_chan_map[0],
130 lll->data_chan_count);
131 #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
132 data_chan_use = 0;
133 LL_ASSERT(0);
134 #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
135 } else {
136 data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
137 lll->data_chan_hop,
138 lll->latency_event,
139 &lll->data_chan_map[0],
140 lll->data_chan_count);
141 }
142
143 /* current window widening */
144 lll->periph.window_widening_event_us +=
145 lll->periph.window_widening_prepare_us;
146 lll->periph.window_widening_prepare_us = 0;
147 if (lll->periph.window_widening_event_us >
148 lll->periph.window_widening_max_us) {
149 lll->periph.window_widening_event_us =
150 lll->periph.window_widening_max_us;
151 }
152
153 /* current window size */
154 lll->periph.window_size_event_us +=
155 lll->periph.window_size_prepare_us;
156 lll->periph.window_size_prepare_us = 0;
157
158 /* Start setting up Radio h/w */
159 radio_reset();
160 /* TODO: other Tx Power settings */
161 radio_tx_power_set(RADIO_TXP_DEFAULT);
162
163 lll_conn_rx_pkt_set(lll);
164
165 radio_aa_set(lll->access_addr);
166 radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
167 (((uint32_t)lll->crc_init[2] << 16) |
168 ((uint32_t)lll->crc_init[1] << 8) |
169 ((uint32_t)lll->crc_init[0])));
170
171 lll_chan_set(data_chan_use);
172
173 radio_isr_set(lll_conn_isr_rx, lll);
174
175 radio_tmr_tifs_set(EVENT_IFS_US);
176
177 #if defined(CONFIG_BT_CTLR_PHY)
178 radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx,
179 lll->phy_flags);
180 #else /* !CONFIG_BT_CTLR_PHY */
181 radio_switch_complete_and_tx(0, 0, 0, 0);
182 #endif /* !CONFIG_BT_CTLR_PHY */
183
184 ticks_at_event = p->ticks_at_expire;
185 ull = HDR_LLL2ULL(lll);
186 ticks_at_event += lll_event_offset_get(ull);
187
188 ticks_at_start = ticks_at_event;
189 ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
190
191 remainder = p->remainder;
192 remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
193
194 radio_tmr_aa_capture();
195 radio_tmr_aa_save(0);
196
197 hcto = remainder_us + EVENT_JITTER_US + (EVENT_JITTER_US << 2) +
198 (lll->periph.window_widening_event_us << 1) +
199 lll->periph.window_size_event_us;
200
201 #if defined(CONFIG_BT_CTLR_PHY)
202 hcto += radio_rx_ready_delay_get(lll->phy_rx, 1);
203 hcto += addr_us_get(lll->phy_rx);
204 hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
205 #else /* !CONFIG_BT_CTLR_PHY */
206 hcto += radio_rx_ready_delay_get(0, 0);
207 hcto += addr_us_get(0);
208 hcto += radio_rx_chain_delay_get(0, 0);
209 #endif /* !CONFIG_BT_CTLR_PHY */
210
211 radio_tmr_hcto_configure(hcto);
212
213 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
214 radio_gpio_lna_setup();
215
216 #if defined(CONFIG_BT_CTLR_PHY)
217 radio_gpio_pa_lna_enable(remainder_us +
218 radio_rx_ready_delay_get(lll->phy_rx, 1) -
219 HAL_RADIO_GPIO_LNA_OFFSET);
220 #else /* !CONFIG_BT_CTLR_PHY */
221 radio_gpio_pa_lna_enable(remainder_us +
222 radio_rx_ready_delay_get(0, 0) -
223 HAL_RADIO_GPIO_LNA_OFFSET);
224 #endif /* !CONFIG_BT_CTLR_PHY */
225 #endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
226
227 #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
228 defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
229 radio_tmr_end_capture();
230 #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
231
232 #if defined(CONFIG_BT_CTLR_CONN_RSSI)
233 radio_rssi_measure();
234 #endif /* CONFIG_BT_CTLR_CONN_RSSI */
235
236 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
237 (EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
238 /* check if preempt to start has changed */
239 if (lll_preempt_calc(ull, (TICKER_ID_CONN_BASE + lll->handle),
240 ticks_at_event)) {
241 radio_isr_set(lll_conn_isr_abort, lll);
242 radio_disable();
243 } else
244 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
245 {
246 uint32_t ret;
247
248 ret = lll_prepare_done(lll);
249 LL_ASSERT(!ret);
250 }
251
252 DEBUG_RADIO_START_S(1);
253
254 return 0;
255 }
256