Skip to content

Commit

Permalink
Bluetooth: Host: Add conversion macros from ms to various units
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Thalley committed Nov 11, 2024
1 parent c50777a commit 491436e
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 45 deletions.
6 changes: 3 additions & 3 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ struct bt_le_conn_param {
* Latency: 0
* Timeout: 4 s
*/
#define BT_LE_CONN_PARAM_DEFAULT BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, \
BT_GAP_INIT_CONN_INT_MAX, \
0, 400)
#define BT_LE_CONN_PARAM_DEFAULT \
BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, BT_GAP_INIT_CONN_INT_MAX, 0, \
BT_GAP_MS_TO_CONN_TIMEOUT(4000))

/** Connection PHY information for LE connections */
struct bt_conn_le_phy_info {
Expand Down
85 changes: 83 additions & 2 deletions include/zephyr/bluetooth/gap.h
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,93 @@ enum {
/** Maximum Periodic Advertising Interval (N * 1.25 ms) */
#define BT_GAP_PER_ADV_MAX_INTERVAL 0xFFFF /* 81.91875 s */

/**
* @brief Convert periodic advertising interval (N * 0.625 ms) to milliseconds
*
* @note When intervals cannot be represented in milliseconds, this will round down.
* For example BT_GAP_ADV_INTERVAL_TO_MS(0x0021) will become 20 ms instead of 20.625 ms
*/
#define BT_GAP_ADV_INTERVAL_TO_MS(_interval) ((_interval) * 5U / 8U)

/**
* @brief Convert isochronous interval (N * 1.25 ms) to milliseconds
*
* @note When intervals cannot be represented in milliseconds, this will round down.
* For example BT_GAP_ISO_INTERVAL_TO_MS(0x0005) will become 6 ms instead of 6.25 ms
*/
#define BT_GAP_ISO_INTERVAL_TO_MS(_interval) ((_interval) * 5U / 4U)

/**
* @brief Convert periodic advertising interval (N * 1.25 ms) to milliseconds
*
* 5 / 4 represents 1.25 ms unit.
* @note When intervals cannot be represented in milliseconds, this will round down.
* For example BT_GAP_PER_ADV_INTERVAL_TO_MS(0x0009) will become 11 ms instead of 11.25 ms
*/
#define BT_GAP_PER_ADV_INTERVAL_TO_MS(_interval) ((_interval) * 5U / 4U)

/**
* @brief Convert milliseconds to advertising interval units (0.625 ms)
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_ADV_INTERVAL(21) will become 20.625 milliseconds
*/
#define BT_GAP_MS_TO_ADV_INTERVAL(_interval) ((uint16_t)((_interval) * 8U / 5U))

/**
* @brief Convert milliseconds to periodic advertising interval units (1.25 ms)
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_PER_ADV_INTERVAL(11) will become 10 milliseconds
*/
#define BT_GAP_MS_TO_PER_ADV_INTERVAL(_interval) ((uint16_t)((_interval) * 4U / 5U))

/**
* @brief Convert milliseconds to periodic advertising sync timeout units (10 ms)
*
* @note If @p _timeout is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_PER_ADV_SYNC_TIMEOUT(4005) will become 4000 milliseconds
*/
#define BT_GAP_MS_TO_PER_ADV_SYNC_TIMEOUT(_timeout) ((uint16_t)((_timeout) / 10U))

/**
* @brief Convert milliseconds to scan interval units (0.625 ms)
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_SCAN_INTERVAL(21) will become 20.625 milliseconds
*/
#define BT_GAP_MS_TO_SCAN_INTERVAL(_interval) ((uint16_t)((_interval) * 8U / 5U))

/**
* @brief Convert milliseconds to scan window units (0.625 ms)
*
* @note If @p _window is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_SCAN_WINDOW(21) will become 20.625 milliseconds
*/
#define BT_GAP_MS_TO_SCAN_WINDOW(_window) ((uint16_t)((_window) * 8U / 5U))

/**
* @brief Convert milliseconds to connection interval units (1.25 ms)
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_CONN_INTERVAL(21) will become 20.625 milliseconds
*/
#define BT_GAP_MS_TO_CONN_INTERVAL(_interval) ((uint16_t)((_interval) * 4U / 5U))

/**
* @brief Convert milliseconds to connection supervision timeout units (10 ms)
*
* @note If @p _timeout is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_CONN_TIMEOUT(4005) will become 4000 milliseconds
*/
#define BT_GAP_MS_TO_CONN_TIMEOUT(_timeout) ((uint16_t)((_timeout) / 10U))

/**
* @brief Convert milliseconds to connection event length units (0.625)
*
* @note If @p _event_len is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_MS_TO_CONN_EVENT_LEN(21) will become 20.625 milliseconds
*/
#define BT_GAP_PER_ADV_INTERVAL_TO_MS(interval) ((interval) * 5 / 4)
#define BT_GAP_MS_TO_CONN_EVENT_LEN(_event_len) ((uint16_t)((_event_len) * 8U / 5U))

/** Constant Tone Extension (CTE) types */
enum {
Expand Down
4 changes: 3 additions & 1 deletion samples/bluetooth/bap_broadcast_source/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ BUILD_ASSERT(strlen(CONFIG_BROADCAST_CODE) <= BT_ISO_BROADCAST_CODE_SIZE, "Inval
* And, for 10 ms ISO interval, can use 90 ms minus 10 ms ==> 80 ms advertising
* interval.
*/
#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)

/* When BROADCAST_ENQUEUE_COUNT > 1 we can enqueue enough buffers to ensure that
* the controller is never idle
Expand Down
5 changes: 3 additions & 2 deletions samples/bluetooth/hci_pwr_ctrl/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/bluetooth/gap.h>
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
Expand Down Expand Up @@ -42,8 +43,8 @@ static K_THREAD_STACK_DEFINE(pwr_thread_stack, 512);

static const int8_t txpower[DEVICE_BEACON_TXPOWER_NUM] = {4, 0, -3, -8,
-15, -18, -23, -30};
static const struct bt_le_adv_param *param =
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, 0x0020, 0x0020, NULL);
static const struct bt_le_adv_param *param = BT_LE_ADV_PARAM(
BT_LE_ADV_OPT_CONN, BT_GAP_MS_TO_ADV_INTERVAL(20), BT_GAP_MS_TO_ADV_INTERVAL(20), NULL);

static void read_conn_rssi(uint16_t handle, int8_t *rssi)
{
Expand Down
12 changes: 12 additions & 0 deletions tests/bluetooth/gap/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
3 changes: 3 additions & 0 deletions tests/bluetooth/gap/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CONFIG_ZTEST=y

CONFIG_BT=y
79 changes: 79 additions & 0 deletions tests/bluetooth/gap/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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_conversion_macros)
{
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_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_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_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_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_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_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_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_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);
}
7 changes: 7 additions & 0 deletions tests/bluetooth/gap/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
common:
tags:
- bluetooth
- host
tests:
bluetooth.gap.test:
type: unit
3 changes: 2 additions & 1 deletion tests/bluetooth/tester/src/btp_gap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
8 changes: 4 additions & 4 deletions tests/bsim/bluetooth/audio/src/cap_commander_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,10 +586,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);
}
Expand Down
15 changes: 7 additions & 8 deletions tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_PER_ADV_CUSTOM \
BT_LE_PER_ADV_PARAM(0x0048, \
0x0048, \
BT_LE_PER_ADV_OPT_NONE)
#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(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
Expand Down
8 changes: 4 additions & 4 deletions tests/bsim/bluetooth/audio/src/cap_initiator_unicast_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
21 changes: 10 additions & 11 deletions tests/bsim/bluetooth/audio/src/gmap_ugg_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down
6 changes: 5 additions & 1 deletion tests/bsim/bluetooth/audio/src/mcc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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_MS_TO_CONN_INTERVAL(7.5),
BT_GAP_MS_TO_CONN_INTERVAL(20), 0U,
BT_GAP_MS_TO_CONN_TIMEOUT(4000U)));
WAIT_FOR_FLAG(flag_conn_updated);

test_discover();
Expand Down
Loading

0 comments on commit 491436e

Please sign in to comment.