1use procmacros::BuilderLite;
2
3use super::*;
4use crate::{
5 ble::InvalidConfigError,
6 hal::{interrupt, peripherals::BT},
7 interrupt_dispatch::Handler,
8 sys::include::esp_bt_controller_config_t,
9};
10
11static ISR_INTERRUPT_4: Handler = Handler::new();
12static ISR_INTERRUPT_7: Handler = Handler::new();
13
14#[derive(Default, Clone, Copy, Eq, PartialEq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub enum TxPower {
18 N15,
20 N12,
22 N9,
24 N6,
26 N3,
28 N0,
30 P3,
32 P6,
34 #[default]
36 P9,
37 P12,
39 P15,
41 P18,
43 P20,
45}
46
47#[allow(dead_code)]
48impl TxPower {
49 fn idx(self) -> esp_power_level_t {
50 match self {
51 Self::N15 => esp_power_level_t_ESP_PWR_LVL_N15,
52 Self::N12 => esp_power_level_t_ESP_PWR_LVL_N12,
53 Self::N9 => esp_power_level_t_ESP_PWR_LVL_N9,
54 Self::N6 => esp_power_level_t_ESP_PWR_LVL_N6,
55 Self::N3 => esp_power_level_t_ESP_PWR_LVL_N3,
56 Self::N0 => esp_power_level_t_ESP_PWR_LVL_N0,
57 Self::P3 => esp_power_level_t_ESP_PWR_LVL_P3,
58 Self::P6 => esp_power_level_t_ESP_PWR_LVL_P6,
59 Self::P9 => esp_power_level_t_ESP_PWR_LVL_P9,
60 Self::P12 => esp_power_level_t_ESP_PWR_LVL_P12,
61 Self::P15 => esp_power_level_t_ESP_PWR_LVL_P15,
62 Self::P18 => esp_power_level_t_ESP_PWR_LVL_P18,
63 Self::P20 => esp_power_level_t_ESP_PWR_LVL_P20,
64 }
65 }
66
67 fn dbm(self) -> i8 {
68 match self {
69 Self::N15 => -15,
70 Self::N12 => -12,
71 Self::N9 => -9,
72 Self::N6 => -6,
73 Self::N3 => -3,
74 Self::N0 => 0,
75 Self::P3 => 3,
76 Self::P6 => 6,
77 Self::P9 => 9,
78 Self::P12 => 12,
79 Self::P15 => 15,
80 Self::P18 => 18,
81 Self::P20 => 20,
82 }
83 }
84}
85
86#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
88#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89pub struct Config {
90 task_priority: u8,
92
93 task_stack_size: u16,
95
96 max_connections: u16,
100
101 qa_test_mode: bool,
103
104 bqb_test: bool,
106
107 ll_resolv_list_size: u16,
109
110 ll_sync_list_cnt: u8,
114
115 ll_sync_cnt: u8,
119
120 ll_rsp_dup_list_count: u16,
124
125 ll_adv_dup_list_count: u16,
129
130 verify_access_address: bool,
137
138 channel_assessment: bool,
140
141 default_tx_power: TxPower,
143
144 hci_high_buffer_count: u16,
146
147 hci_low_buffer_count: u16,
149
150 whitelist_size: u8,
152
153 acl_buf_size: u16,
155
156 acl_buf_count: u16,
158
159 hci_evt_buf_size: u16,
161
162 multi_adv_instances: u16,
164
165 ext_adv_max_size: u16,
169
170 dis_scan_backoff: bool,
172
173 scan_backoff_max: u16,
179
180 cca: bool,
182
183 cca_threshold: u8,
192
193 data_length_zero_aux: bool,
195
196 disconnect_llcp_conn_update: bool,
198
199 disconnect_llcp_chan_map_update: bool,
201
202 disconnect_llcp_phy_update: bool,
204}
205
206impl Default for Config {
207 fn default() -> Self {
208 Self {
209 task_priority: crate::preempt::max_task_priority()
210 .saturating_sub(2)
211 .min(255) as u8,
212 task_stack_size: 4096,
213 max_connections: 2,
214 qa_test_mode: false,
215 bqb_test: false,
216 ll_resolv_list_size: 4,
217 ll_sync_list_cnt: 5,
218 ll_sync_cnt: 0,
219 ll_rsp_dup_list_count: 20,
220 ll_adv_dup_list_count: 20,
221 default_tx_power: TxPower::default(),
222 hci_high_buffer_count: 30,
223 hci_low_buffer_count: 8,
224 whitelist_size: 12,
225 acl_buf_size: 255,
226 acl_buf_count: 24,
227 hci_evt_buf_size: 70,
228 multi_adv_instances: 1,
229 ext_adv_max_size: 31,
230 dis_scan_backoff: false,
231 scan_backoff_max: 256,
232 verify_access_address: false,
233 disconnect_llcp_conn_update: false,
234 disconnect_llcp_chan_map_update: false,
235 disconnect_llcp_phy_update: false,
236 cca_threshold: 65,
237 cca: false,
238 channel_assessment: false,
239 data_length_zero_aux: false,
240 }
241 }
242}
243
244impl Config {
245 pub(crate) fn validate(&self) -> Result<(), InvalidConfigError> {
246 crate::ble::validate_range!(
247 self,
248 task_priority,
249 0,
250 crate::preempt::max_task_priority().min(255) as u8
251 );
252 crate::ble::validate_range!(self, max_connections, 1, 70);
253 crate::ble::validate_range!(self, ll_sync_cnt, 0, 3);
254 crate::ble::validate_range!(self, ll_sync_list_cnt, 1, 5);
255 crate::ble::validate_range!(self, ll_rsp_dup_list_count, 1, 100);
256 crate::ble::validate_range!(self, ll_adv_dup_list_count, 1, 100);
257 crate::ble::validate_range!(self, whitelist_size, 1, 31);
258 crate::ble::validate_range!(self, multi_adv_instances, 0, 4);
259 crate::ble::validate_range!(self, ext_adv_max_size, 0, 1650);
260 crate::ble::validate_range!(self, scan_backoff_max, 1, 256);
261 crate::ble::validate_range!(self, cca_threshold, 20, 100);
262 Ok(())
263 }
264}
265
266pub(crate) fn create_ble_config(config: &Config) -> esp_bt_controller_config_t {
267 esp_bt_controller_config_t {
270 config_version: CONFIG_VERSION,
271 ble_ll_resolv_list_size: config.ll_resolv_list_size,
272 ble_hci_evt_hi_buf_count: config.hci_high_buffer_count,
273 ble_hci_evt_lo_buf_count: config.hci_low_buffer_count,
274 ble_ll_sync_list_cnt: config.ll_sync_list_cnt,
275 ble_ll_sync_cnt: config.ll_sync_cnt,
276 ble_ll_rsp_dup_list_count: config.ll_rsp_dup_list_count,
277 ble_ll_adv_dup_list_count: config.ll_adv_dup_list_count,
278 ble_ll_tx_pwr_dbm: config.default_tx_power.dbm() as u8,
279 rtc_freq: 32000,
280 ble_ll_sca: 60,
281 ble_ll_scan_phy_number: 2,
282 ble_ll_conn_def_auth_pyld_tmo: 3000,
283 ble_ll_jitter_usecs: 16,
284 ble_ll_sched_max_adv_pdu_usecs: 376,
285 ble_ll_sched_direct_adv_max_usecs: 502,
286 ble_ll_sched_adv_max_usecs: 852,
287 ble_scan_rsp_data_max_len: 31,
288 ble_ll_cfg_num_hci_cmd_pkts: 1,
289 ble_ll_ctrl_proc_timeout_ms: 40000,
290 nimble_max_connections: config.max_connections,
291 ble_whitelist_size: config.whitelist_size,
292 ble_acl_buf_size: config.acl_buf_size,
293 ble_acl_buf_count: config.acl_buf_count,
294 ble_hci_evt_buf_size: config.hci_evt_buf_size,
295 ble_multi_adv_instances: config.multi_adv_instances,
296 ble_ext_adv_max_size: config.ext_adv_max_size,
297 controller_task_stack_size: config.task_stack_size,
298 controller_task_prio: config.task_priority,
299 controller_run_cpu: 0,
300 enable_qa_test: config.qa_test_mode as u8,
301 enable_bqb_test: config.bqb_test as u8,
302 enable_tx_cca: config.cca as u8,
303 cca_rssi_thresh: (256 - config.cca_threshold as u32) as u8,
304 sleep_en: 0,
305 coex_phy_coded_tx_rx_time_limit: 0,
306 dis_scan_backoff: config.dis_scan_backoff as u8,
307 ble_scan_classify_filter_enable: 1,
308 cca_drop_mode: 0, cca_low_tx_pwr: 0, main_xtal_freq: 40,
311 ignore_wl_for_direct_adv: 0,
312 cpu_freq_mhz: 160,
313 enable_pcl: 0, version_num: esp_hal::efuse::minor_chip_version() as u32,
315 csa2_select: 1,
316 enable_csr: 0,
317 ble_aa_check: config.verify_access_address as u8,
318 ble_llcp_disc_flag: config.disconnect_llcp_conn_update as u8
319 | ((config.disconnect_llcp_chan_map_update as u8) << 1)
320 | ((config.disconnect_llcp_phy_update as u8) << 2),
321 scan_backoff_upperlimitmax: config.scan_backoff_max,
322 ble_chan_ass_en: config.channel_assessment as u8,
323 ble_data_lenth_zero_aux: config.data_length_zero_aux as u8,
324 vhci_enabled: 1,
325 ptr_check_enabled: 0,
326 ble_adv_tx_options: 0,
327 skip_unnecessary_checks_en: 0,
328 fast_conn_data_tx_en: 0,
329 ch39_txpwr: 9,
330 adv_rsv_cnt: 1,
331 conn_rsv_cnt: 2,
332 priority_level_cfg: 1 << 4 | 1 << 2,
333 slv_fst_rx_lat_en: 0,
334 dl_itvl_phy_sync_en: 0,
335 scan_allow_adi_filter: 0,
336 config_magic: CONFIG_MAGIC,
337 }
338}
339
340pub(crate) fn bt_periph_module_enable() {
341 crate::radio_clocks::clocks_ll::enable_bt(true);
342}
343
344pub(crate) fn disable_sleep_mode() {
345 }
347
348pub(super) unsafe extern "C" fn esp_intr_alloc(
349 source: u32,
350 flags: u32,
351 handler: *mut c_void,
352 arg: *mut c_void,
353 ret_handle: *mut *mut c_void,
354) -> i32 {
355 trace!(
356 "esp_intr_alloc {} {} {:?} {:?} {:?}",
357 source, flags, handler, arg, ret_handle
358 );
359
360 match source {
361 4 => unsafe {
362 ISR_INTERRUPT_4.set(handler, arg);
363 BT::steal().enable_mac_interrupt(interrupt::Priority::Priority1);
364 },
365 7 => unsafe {
366 ISR_INTERRUPT_7.set(handler, arg);
367 BT::steal().enable_lp_timer_interrupt(interrupt::Priority::Priority1);
368 },
369 _ => panic!("Unexpected interrupt source {}", source),
370 }
371
372 0
373}
374
375pub(super) fn ble_rtc_clk_init() {
376 crate::radio_clocks::clocks_ll::ble_rtc_clk_init();
377}
378
379pub(super) unsafe extern "C" fn reset_modem(_mdl_opts: u8, _start: u8) {
380 todo!()
381}
382
383#[unsafe(no_mangle)]
384#[crate::hal::ram]
385extern "C" fn LP_TIMER() {
386 ISR_INTERRUPT_7.dispatch();
387}
388
389#[unsafe(no_mangle)]
390#[crate::hal::ram]
391extern "C" fn BT_MAC() {
392 ISR_INTERRUPT_4.dispatch();
393}
394
395pub(crate) fn shutdown_ble_isr() {
396 unsafe {
397 BT::steal().disable_lp_timer_interrupt_on_all_cores();
398 BT::steal().disable_mac_interrupt_on_all_cores();
399 }
400}