diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 6ebceeed58..cfec804eaf 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -359,7 +359,7 @@ Central Role A central device can connect to peripherals that it has discovered using the observer role (see :meth:`gap_scan`) or with a known address. -.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, /) +.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, min_conn_interval_us=None, max_conn_interval_us=None, /) Connect to a peripheral. @@ -367,6 +367,15 @@ A central device can connect to peripherals that it has discovered using the obs On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. + The device will wait up to *scan_duration_ms* to receive an advertising + payload from the device. + + The connection interval can be configured in **micro**\ seconds using either + or both of *min_conn_interval_us* and *max_conn_interval_us*. Otherwise a + default interval will be chosen, typically between 30000 and 50000 + microseconds. A shorter interval will increase throughput, at the expense + of power usage. + Peripheral Role --------------- diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index 4e81e21fe2..cd2ba83d53 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -1265,13 +1265,13 @@ int mp_bluetooth_gap_scan_stop(void) { return 0; } -int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us) { DEBUG_printf("mp_bluetooth_gap_peripheral_connect\n"); uint16_t conn_scan_interval = 60000 / 625; uint16_t conn_scan_window = 30000 / 625; - uint16_t conn_interval_min = 10000 / 1250; - uint16_t conn_interval_max = 30000 / 1250; + uint16_t conn_interval_min = (min_conn_interval_us ? min_conn_interval_us : 10000) / 1250; + uint16_t conn_interval_max = (max_conn_interval_us ? max_conn_interval_us : 30000) / 1250; uint16_t conn_latency = 4; uint16_t supervision_timeout = duration_ms / 10; // default = 720 uint16_t min_ce_length = 10000 / 625; diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index cb153f70e9..e3d64b81f1 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -637,14 +637,22 @@ STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(MP_ERROR_TEXT("invalid addr")); } mp_int_t scan_duration_ms = MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS; - if (n_args == 4) { + mp_int_t min_conn_interval_us = 0; + mp_int_t max_conn_interval_us = 0; + if (n_args >= 4 && args[3] != mp_const_none) { scan_duration_ms = mp_obj_get_int(args[3]); } + if (n_args >= 5 && args[4] != mp_const_none) { + min_conn_interval_us = mp_obj_get_int(args[4]); + } + if (n_args >= 6 && args[5] != mp_const_none) { + max_conn_interval_us = mp_obj_get_int(args[5]); + } - int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms); + int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms, min_conn_interval_us, max_conn_interval_us); return bluetooth_handle_errno(err); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 6, bluetooth_ble_gap_connect); STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { // Default is indefinite scan, with the NimBLE "background scan" interval and window. diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 43519e5941..fe41fd5143 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -370,7 +370,7 @@ int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_ int mp_bluetooth_gap_scan_stop(void); // Connect to a found peripheral. -int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms); +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us); #endif #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index e4b4cb68af..6ac31fd4bd 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -1202,7 +1202,7 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { return commmon_gap_event_cb(event, arg); } -int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us) { DEBUG_printf("mp_bluetooth_gap_peripheral_connect\n"); if (!mp_bluetooth_is_active()) { return ERRNO_BLUETOOTH_NOT_ACTIVE; @@ -1211,12 +1211,14 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, mp_bluetooth_gap_scan_stop(); } - // TODO: This is the same as ble_gap_conn_params_dflt (i.e. passing NULL). - STATIC const struct ble_gap_conn_params params = { + uint16_t conn_interval_min = min_conn_interval_us ? min_conn_interval_us / BLE_HCI_CONN_ITVL : BLE_GAP_INITIAL_CONN_ITVL_MIN; + uint16_t conn_interval_max = max_conn_interval_us ? max_conn_interval_us / BLE_HCI_CONN_ITVL : BLE_GAP_INITIAL_CONN_ITVL_MAX; + + const struct ble_gap_conn_params params = { .scan_itvl = 0x0010, .scan_window = 0x0010, - .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN, - .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX, + .itvl_min = conn_interval_min, + .itvl_max = conn_interval_max, .latency = BLE_GAP_INITIAL_CONN_LATENCY, .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT, .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN, diff --git a/ports/zephyr/modbluetooth_zephyr.c b/ports/zephyr/modbluetooth_zephyr.c index 5753d71476..f4b6f35590 100644 --- a/ports/zephyr/modbluetooth_zephyr.c +++ b/ports/zephyr/modbluetooth_zephyr.c @@ -400,7 +400,7 @@ int mp_bluetooth_gap_scan_stop(void) { return bt_err_to_errno(err); } -int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms, int32_t min_conn_interval_us, int32_t max_conn_interval_us) { DEBUG_printf("mp_bluetooth_gap_peripheral_connect\n"); if (!mp_bluetooth_is_active()) { return ERRNO_BLUETOOTH_NOT_ACTIVE;