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