Bluetooth: Host: Add conversion macros from ms to various units

Add conversion macros from milliseconds to various units.
The purpose of these macros is to make it more clear/easier
for users to set and read values using milliseconds rather
than the various BT units which may be in 0.625, 1.25 or 10ms
units.

This is especially useful when comparing related values using
different units, such as advertising interval (0.625ms units)
and periodic advertising interval units (1.25ms units).

Users will have to be aware that these macros can provide slightly
different values than what is provided, if the provided values
do not match the units.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-11-07 11:49:24 +01:00 committed by Anas Nashif
commit 8703381764
30 changed files with 539 additions and 99 deletions

View file

@ -0,0 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(bt_gap)
target_sources(testbinary
PRIVATE
src/main.c
)

View file

@ -0,0 +1,3 @@
CONFIG_ZTEST=y
CONFIG_BT=y

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/ztest.h>
#include <zephyr/ztest_test.h>
#include <zephyr/ztest_assert.h>
ZTEST_SUITE(gap_test_suite, NULL, NULL, NULL, NULL, NULL);
static ZTEST(gap_test_suite, test_bt_gap_conversion_macros)
{
zassert_equal(BT_GAP_ADV_INTERVAL_TO_US(0x0020U), 20000U);
zassert_equal(BT_GAP_ADV_INTERVAL_TO_US(0x0021U), 20625U);
zassert_equal(BT_GAP_ADV_INTERVAL_TO_US(0x0022U), 21250U);
zassert_equal(BT_GAP_ADV_INTERVAL_TO_MS(0x0020U), 20U);
/* Round down expected from 20.625 */
zassert_equal(BT_GAP_ADV_INTERVAL_TO_MS(0x0021U), 20U);
/* Round down expected from 21.250 */
zassert_equal(BT_GAP_ADV_INTERVAL_TO_MS(0x0022U), 21U);
zassert_equal(BT_GAP_ISO_INTERVAL_TO_US(0x0004U), 5000U);
zassert_equal(BT_GAP_ISO_INTERVAL_TO_US(0x0005U), 6250U);
zassert_equal(BT_GAP_ISO_INTERVAL_TO_US(0x0006U), 7500U);
zassert_equal(BT_GAP_ISO_INTERVAL_TO_MS(0x0004U), 5U);
/* Round down expected from 6.25 */
zassert_equal(BT_GAP_ISO_INTERVAL_TO_MS(0x0005U), 6U);
/* Round down expected from 7.50 */
zassert_equal(BT_GAP_ISO_INTERVAL_TO_MS(0x0006U), 7U);
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_US(0x0008U), 10000U);
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_US(0x0009U), 11250U);
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_US(0x000aU), 12500U);
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_MS(0x0008U), 10U);
/* Round down expected from 11.25 */
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_MS(0x0009U), 11U);
/* Round down expected from 12.50 */
zassert_equal(BT_GAP_PER_ADV_INTERVAL_TO_MS(0x000aU), 12U);
zassert_equal(BT_GAP_US_TO_ADV_INTERVAL(20000U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_US_TO_ADV_INTERVAL(21000U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_US_TO_ADV_INTERVAL(22000U), 0x0023U);
zassert_equal(BT_GAP_MS_TO_ADV_INTERVAL(20U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_MS_TO_ADV_INTERVAL(21U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_MS_TO_ADV_INTERVAL(22U), 0x0023U);
zassert_equal(BT_GAP_US_TO_PER_ADV_INTERVAL(10000U), 0x0008U);
/* Round down expected from 8.8 */
zassert_equal(BT_GAP_US_TO_PER_ADV_INTERVAL(11000U), 0x0008U);
/* Round down expected from 9.6 */
zassert_equal(BT_GAP_US_TO_PER_ADV_INTERVAL(12000U), 0x0009U);
zassert_equal(BT_GAP_MS_TO_PER_ADV_INTERVAL(10U), 0x0008U);
/* Round down expected from 8.8 */
zassert_equal(BT_GAP_MS_TO_PER_ADV_INTERVAL(11U), 0x0008U);
/* Round down expected from 9.6 */
zassert_equal(BT_GAP_MS_TO_PER_ADV_INTERVAL(12U), 0x0009U);
zassert_equal(BT_GAP_MS_TO_PER_ADV_SYNC_TIMEOUT(4000U), 0x0190U);
/* Round down expected from 400.5 */
zassert_equal(BT_GAP_MS_TO_PER_ADV_SYNC_TIMEOUT(4005U), 0x0190U);
zassert_equal(BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(4000000U), 0x0190U);
/* Round down expected from 400.5 */
zassert_equal(BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(4005000U), 0x0190U);
zassert_equal(BT_GAP_US_TO_SCAN_INTERVAL(20000U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_US_TO_SCAN_INTERVAL(21000U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_US_TO_SCAN_INTERVAL(22000U), 0x0023U);
zassert_equal(BT_GAP_MS_TO_SCAN_INTERVAL(20U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_MS_TO_SCAN_INTERVAL(21U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_MS_TO_SCAN_INTERVAL(22U), 0x0023U);
zassert_equal(BT_GAP_US_TO_SCAN_WINDOW(20000U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_US_TO_SCAN_WINDOW(21000U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_US_TO_SCAN_WINDOW(22000U), 0x0023U);
zassert_equal(BT_GAP_MS_TO_SCAN_WINDOW(20U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_MS_TO_SCAN_WINDOW(21U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_MS_TO_SCAN_WINDOW(22U), 0x0023U);
zassert_equal(BT_GAP_US_TO_CONN_INTERVAL(10000U), 0x0008U);
/* Round down expected from 8.8 */
zassert_equal(BT_GAP_US_TO_CONN_INTERVAL(11000U), 0x0008U);
/* Round down expected from 9.6 */
zassert_equal(BT_GAP_US_TO_CONN_INTERVAL(12000U), 0x0009U);
zassert_equal(BT_GAP_MS_TO_CONN_INTERVAL(10U), 0x0008U);
/* Round down expected from 8.8 */
zassert_equal(BT_GAP_MS_TO_CONN_INTERVAL(11U), 0x0008U);
/* Round down expected from 9.6 */
zassert_equal(BT_GAP_MS_TO_CONN_INTERVAL(12U), 0x0009U);
zassert_equal(BT_GAP_MS_TO_CONN_TIMEOUT(4000U), 0x0190U);
/* Round down expected from 400.5 */
zassert_equal(BT_GAP_MS_TO_CONN_TIMEOUT(4005U), 0x0190U);
zassert_equal(BT_GAP_US_TO_CONN_TIMEOUT(4000000U), 0x0190U);
/* Round down expected from 400.5 */
zassert_equal(BT_GAP_US_TO_CONN_TIMEOUT(4005000U), 0x0190U);
zassert_equal(BT_GAP_US_TO_CONN_EVENT_LEN(20000U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_US_TO_CONN_EVENT_LEN(21000U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_US_TO_CONN_EVENT_LEN(22000U), 0x0023U);
zassert_equal(BT_GAP_MS_TO_CONN_EVENT_LEN(20U), 0x0020U);
/* Round down expected from 33.60 */
zassert_equal(BT_GAP_MS_TO_CONN_EVENT_LEN(21U), 0x0021U);
/* Round down expected from 35.20 */
zassert_equal(BT_GAP_MS_TO_CONN_EVENT_LEN(22U), 0x0023U);
}

View file

@ -0,0 +1,7 @@
common:
tags:
- bluetooth
- host
tests:
bluetooth.gap.test:
type: unit

View file

@ -13,6 +13,7 @@
#include <zephyr/kernel.h>
#include <zephyr/sys/ring_buffer.h>
#include <zephyr/bluetooth/audio/audio.h>
#include <zephyr/bluetooth/gap.h>
#include "bap_endpoint.h"
#include <zephyr/logging/log.h>
@ -1261,8 +1262,9 @@ static void bap_broadcast_assistant_scan_cb(const struct bt_le_scan_recv_info *i
char le_addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
LOG_DBG("[DEVICE]: %s, broadcast_id 0x%06X, interval (ms) %u), SID 0x%x, RSSI %i", le_addr,
broadcast_id, BT_GAP_PER_ADV_INTERVAL_TO_MS(info->interval), info->sid, info->rssi);
LOG_DBG("[DEVICE]: %s, broadcast_id 0x%06X, interval (ms) %u (0x%04x)), SID 0x%x, RSSI %i",
le_addr, broadcast_id, BT_GAP_PER_ADV_INTERVAL_TO_MS(info->interval),
info->interval, info->sid, info->rssi);
}
static void bap_broadcast_assistant_recv_state_cb(struct bt_conn *conn, int err,

View file

@ -989,7 +989,8 @@ static uint8_t connect(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
const struct bt_le_conn_param *conn_param =
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN, 0, 400);
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN, 0,
BT_GAP_MS_TO_CONN_TIMEOUT(4000));
const struct btp_gap_connect_cmd *cp = cmd;
int err;

View file

@ -607,10 +607,10 @@ static void cap_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type
return;
}
err = bt_conn_le_create(
addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN, 0, 400),
&connected_conns[connected_conn_cnt]);
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN,
0, BT_GAP_MS_TO_CONN_TIMEOUT(4000)),
&connected_conns[connected_conn_cnt]);
if (err) {
FAIL("Could not connect to peer: %d", err);
}

View file

@ -38,14 +38,13 @@
* required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the
* Broadcast ISO radio events.
*/
#define BT_LE_EXT_ADV_CUSTOM \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, \
0x0080, 0x0080, NULL)
#define BT_LE_EXT_ADV_CUSTOM \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, BT_GAP_MS_TO_ADV_INTERVAL(80), \
BT_GAP_MS_TO_ADV_INTERVAL(80), NULL)
#define BT_LE_PER_ADV_CUSTOM \
BT_LE_PER_ADV_PARAM(0x0048, \
0x0048, \
BT_LE_PER_ADV_OPT_NONE)
#define BT_LE_PER_ADV_CUSTOM \
BT_LE_PER_ADV_PARAM(BT_GAP_MS_TO_PER_ADV_INTERVAL(90), BT_GAP_MS_TO_PER_ADV_INTERVAL(90), \
BT_LE_PER_ADV_OPT_NONE)
#define BROADCAST_STREMT_CNT CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT
#define BROADCAST_ENQUEUE_COUNT 2U

View file

@ -438,10 +438,10 @@ static void cap_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type
return;
}
err = bt_conn_le_create(
addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN, 0, 400),
&connected_conns[connected_conn_cnt]);
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN,
0, BT_GAP_MS_TO_CONN_TIMEOUT(4000)),
&connected_conns[connected_conn_cnt]);
if (err) {
FAIL("Could not connect to peer: %d", err);
}

View file

@ -231,12 +231,13 @@ uint16_t interval_to_sync_timeout(uint16_t pa_interval)
/* Use maximum value to maximize chance of success */
pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT;
} else {
uint32_t interval_ms;
uint32_t interval_us;
uint32_t timeout;
/* Add retries and convert to unit in 10's of ms */
interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval);
timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10;
interval_us = BT_GAP_PER_ADV_INTERVAL_TO_US(pa_interval);
timeout = BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(interval_us) *
PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO;
/* Enforce restraints */
pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);

View file

@ -44,14 +44,13 @@
* required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the
* Broadcast ISO radio events.
*/
#define BT_LE_EXT_ADV_CUSTOM \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, \
0x0080, 0x0080, NULL)
#define BT_LE_EXT_ADV_CUSTOM \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, BT_GAP_MS_TO_ADV_INTERVAL(80), \
BT_GAP_MS_TO_ADV_INTERVAL(80), NULL)
#define BT_LE_PER_ADV_CUSTOM \
BT_LE_PER_ADV_PARAM(0x0048, \
0x0048, \
BT_LE_PER_ADV_OPT_NONE)
#define BT_LE_PER_ADV_CUSTOM \
BT_LE_PER_ADV_PARAM(BT_GAP_MS_TO_PER_ADV_INTERVAL(90), BT_GAP_MS_TO_PER_ADV_INTERVAL(90), \
BT_LE_PER_ADV_OPT_NONE)
#define UNICAST_SINK_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0)
#define UNICAST_SRC_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0)
@ -546,10 +545,10 @@ static void gmap_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t typ
return;
}
err = bt_conn_le_create(
addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN, 0, 400),
&connected_conns[connected_conn_cnt]);
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MIN,
0, BT_GAP_MS_TO_CONN_TIMEOUT(4000)),
&connected_conns[connected_conn_cnt]);
if (err) {
FAIL("Could not connect to peer: %d", err);
}

View file

@ -14,6 +14,7 @@
#include <zephyr/bluetooth/audio/media_proxy.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/hci_types.h>
#include <zephyr/bluetooth/services/ots.h>
#include <zephyr/kernel.h>
@ -2462,7 +2463,10 @@ void test_main(void)
bt_addr_le_to_str(bt_conn_get_dst(default_conn), addr, sizeof(addr));
printk("Connected: %s\n", addr);
bt_conn_le_param_update(default_conn, BT_LE_CONN_PARAM(0x06U, 0x10U, 0U, 400U));
bt_conn_le_param_update(default_conn,
BT_LE_CONN_PARAM(BT_GAP_US_TO_CONN_INTERVAL(7500),
BT_GAP_US_TO_CONN_INTERVAL(20000), 0U,
BT_GAP_MS_TO_CONN_TIMEOUT(4000U)));
WAIT_FOR_FLAG(flag_conn_updated);
test_discover();

View file

@ -4,11 +4,14 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "common.h"
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/iso.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
#include "babblekit/flags.h"
#include "babblekit/sync.h"
@ -176,18 +179,18 @@ static void init(void)
static uint16_t interval_to_sync_timeout(uint16_t pa_interval)
{
uint32_t interval_ms;
uint16_t pa_timeout;
uint32_t interval_us;
uint32_t timeout;
/* Add retries and convert to unit in 10's of ms */
interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval);
timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10U;
interval_us = BT_GAP_PER_ADV_INTERVAL_TO_US(pa_interval);
timeout =
BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(interval_us) * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO;
/* Enforce restraints */
pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT);
return pa_timeout;
return timeout;
}
static void scan_and_sync_pa(struct bt_le_per_adv_sync **out_sync)

View file

@ -6,6 +6,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/gap.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
@ -14,6 +15,8 @@
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/iso.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys_clock.h>
#include "bs_types.h"
#include "bs_tracing.h"
@ -52,19 +55,20 @@ static bt_addr_le_t peer_addr;
#define ISO_LATENCY_MS DIV_ROUND_UP(ISO_INTERVAL_US, USEC_PER_MSEC)
#define ISO_LATENCY_FT_MS 20U
#define BT_CONN_US_TO_INTERVAL(t) ((uint16_t)((t) * 4U / 5U / USEC_PER_MSEC))
#if (CONFIG_BT_CTLR_CENTRAL_SPACING == 0)
#define CONN_INTERVAL_MIN BT_CONN_US_TO_INTERVAL(ISO_INTERVAL_US)
#define CONN_INTERVAL_MIN_US ISO_INTERVAL_US
#else /* CONFIG_BT_CTLR_CENTRAL_SPACING > 0 */
#define CONN_INTERVAL_MIN BT_CONN_US_TO_INTERVAL(ISO_INTERVAL_US * CONFIG_BT_MAX_CONN)
#define CONN_INTERVAL_MIN_US (ISO_INTERVAL_US * CONFIG_BT_MAX_CONN)
#endif /* CONFIG_BT_CTLR_CENTRAL_SPACING > 0 */
#define CONN_INTERVAL_MAX_US CONN_INTERVAL_MIN_US
#define CONN_INTERVAL_MAX CONN_INTERVAL_MIN
#define CONN_TIMEOUT MAX((BT_CONN_INTERVAL_TO_MS(CONN_INTERVAL_MAX) * 6U / 10U), 10U)
#define CONN_INTERVAL_MIN BT_GAP_US_TO_CONN_INTERVAL(CONN_INTERVAL_MIN_US)
#define CONN_INTERVAL_MAX BT_GAP_US_TO_CONN_INTERVAL(CONN_INTERVAL_MAX_US)
#define CONN_TIMEOUT \
MAX(BT_GAP_US_TO_CONN_TIMEOUT(CONN_INTERVAL_MAX_US * 6U), BT_GAP_MS_TO_CONN_TIMEOUT(100U))
#define ADV_INTERVAL_MIN 0x0020
#define ADV_INTERVAL_MAX 0x0020
#define ADV_INTERVAL_MIN BT_GAP_MS_TO_ADV_INTERVAL(20)
#define ADV_INTERVAL_MAX BT_GAP_MS_TO_ADV_INTERVAL(20)
#define BT_CONN_LE_CREATE_CONN_CUSTOM \
BT_CONN_LE_CREATE_PARAM(BT_CONN_LE_OPT_NONE, \