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 14, 2024
1 parent c50777a commit 6a4da5d
Show file tree
Hide file tree
Showing 30 changed files with 540 additions and 100 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
217 changes: 215 additions & 2 deletions include/zephyr/bluetooth/gap.h
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,225 @@ 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 microseconds
*
* Value range of @p _interval is @ref BT_LE_ADV_INTERVAL_MIN to @ref BT_LE_ADV_INTERVAL_MAX
*/
#define BT_GAP_ADV_INTERVAL_TO_US(_interval) ((uint32_t)((_interval) * 625U))

/**
* @brief Convert periodic advertising interval (N * 0.625 ms) to milliseconds
*
* Value range of @p _interval is @ref BT_LE_ADV_INTERVAL_MIN to @ref BT_LE_ADV_INTERVAL_MAX
*
* @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) (BT_GAP_ADV_INTERVAL_TO_US(_interval) / USEC_PER_MSEC)

/**
* @brief Convert isochronous interval (N * 1.25 ms) to microseconds
*
* Value range of @p _interval is @ref BT_HCI_ISO_INTERVAL_MIN to @ref BT_HCI_ISO_INTERVAL_MAX
*/
#define BT_GAP_ISO_INTERVAL_TO_US(_interval) ((uint32_t)((_interval) * 1250U))

/**
* @brief Convert isochronous interval (N * 1.25 ms) to milliseconds
*
* Value range of @p _interval is @ref BT_HCI_ISO_INTERVAL_MIN to @ref BT_HCI_ISO_INTERVAL_MAX
*
* @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) (BT_GAP_ISO_INTERVAL_TO_US(_interval) / USEC_PER_MSEC)

/** @brief Convert periodic advertising interval (N * 1.25 ms) to microseconds *
*
* Value range of @p _interval is @ref BT_HCI_LE_PER_ADV_INTERVAL_MIN to @ref
* BT_HCI_LE_PER_ADV_INTERVAL_MAX
*/
#define BT_GAP_PER_ADV_INTERVAL_TO_US(_interval) ((uint32_t)((_interval) * 1250U))

/**
* @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) \
(BT_GAP_PER_ADV_INTERVAL_TO_US(_interval) / USEC_PER_MSEC)

/**
* @brief Convert microseconds to advertising interval units (0.625 ms)
*
* Value range of @p _interval is 20000 to 1024000
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_ADV_INTERVAL(21000) will become 20625 microseconds
*/
#define BT_GAP_US_TO_ADV_INTERVAL(_interval) ((uint16_t)((_interval) / 625U))

/**
* @brief Convert milliseconds to advertising interval units (0.625 ms)
*
* Value range of @p _interval is 20 to 1024
*
* @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) \
(BT_GAP_US_TO_ADV_INTERVAL((_interval) * USEC_PER_MSEC))

/**
* @brief Convert microseconds to periodic advertising interval units (1.25 ms)
*
* Value range of @p _interval is 7500 to 81918750
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_PER_ADV_INTERVAL(11000) will become 10000 microseconds
*/
#define BT_GAP_US_TO_PER_ADV_INTERVAL(_interval) ((uint16_t)((_interval) / 1250U))

/**
* @brief Convert milliseconds to periodic advertising interval units (1.25 ms)
*
* Value range of @p _interval is 7.5 to 81918.75
*
* @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) \
(BT_GAP_US_TO_PER_ADV_INTERVAL((_interval) * USEC_PER_MSEC))

/**
* @brief Convert milliseconds to periodic advertising sync timeout units (10 ms)
*
* Value range of @p _timeout is 100 to 163840
*
* @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 microseconds to periodic advertising sync timeout units (10 ms)
*
* Value range of @p _timeout is 100000 to 163840000
*
* @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(4005000) will become 4000000 microseconds
*/
#define BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(_timeout) \
(BT_GAP_MS_TO_PER_ADV_SYNC_TIMEOUT((_timeout) / USEC_PER_MSEC))

/**
* @brief Convert microseconds to scan interval units (0.625 ms)
*
* Value range of @p _interval is 2500 to 40959375 if @kconfig{CONFIG_BT_EXT_ADV} else
* 2500 to 10240000
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_SCAN_INTERVAL(21000) will become 20625 microseconds
*/
#define BT_GAP_US_TO_SCAN_INTERVAL(_interval) ((uint16_t)((_interval) / 625U))

/**
* @brief Convert milliseconds to scan interval units (0.625 ms)
*
* Value range of @p _interval is 2.5 to 40959.375 if @kconfig{CONFIG_BT_EXT_ADV} else
* 2500 to 10240
*
* @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) \
(BT_GAP_US_TO_SCAN_INTERVAL((_interval) * USEC_PER_MSEC))

/**
* @brief Convert microseconds to scan window units (0.625 ms)
*
* Value range of @p _window is 2500 to 40959375 if @kconfig{CONFIG_BT_EXT_ADV} else
* 2500 to 10240000
*
* @note If @p _window is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_SCAN_WINDOW(21000) will become 20625 microseconds
*/
#define BT_GAP_US_TO_SCAN_WINDOW(_window) ((uint16_t)((_window) / 625U))

/**
* @brief Convert milliseconds to scan window units (0.625 ms)
*
* Value range of @p _window is 2.5 to 40959.375 if @kconfig{CONFIG_BT_EXT_ADV} else
* 2500 to 10240
*
* @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) (BT_GAP_US_TO_SCAN_WINDOW((_window) * USEC_PER_MSEC))

/**
* @brief Convert microseconds to connection interval units (1.25 ms)
*
* Value range of @p _interval is 7500 to 4000000
*
* @note If @p _interval is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_CONN_INTERVAL(21000) will become 20000 microseconds
*/
#define BT_GAP_US_TO_CONN_INTERVAL(_interval) ((uint16_t)((_interval) / 1250U))

/**
* @brief Convert milliseconds to connection interval units (1.25 ms)
*
* Value range of @p _interval is 7.5 to 4000
*
* @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 milliseconds
*/
#define BT_GAP_MS_TO_CONN_INTERVAL(_interval) \
(BT_GAP_US_TO_CONN_INTERVAL((_interval) * USEC_PER_MSEC))

/**
* @brief Convert milliseconds to connection supervision timeout units (10 ms)
*
* Value range of @p _timeout is 100 to 32000
*
* @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 microseconds to connection supervision timeout units (10 ms)
* Value range of @p _timeout is 100000 to 32000000
*
* @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(4005000) will become 4000000 microseconds
*/
#define BT_GAP_US_TO_CONN_TIMEOUT(_timeout) (BT_GAP_MS_TO_CONN_TIMEOUT((_timeout) / USEC_PER_MSEC))

/**
* @brief Convert milliseconds to connection event length units (0.625)
*
* Value range of @p _event_len is 0 to 40959375
*
* @note If @p _event_len is not a multiple of the unit, it will round down to nearest.
* For example BT_GAP_US_TO_CONN_EVENT_LEN(21000) will become 20625 milliseconds
*/
#define BT_GAP_US_TO_CONN_EVENT_LEN(_event_len) ((uint16_t)((_event_len) / 625U))

/**
* @brief Convert milliseconds to connection event length units (0.625)
*
* Value range of @p _event_len is 0 to 40959.375
*
* @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) \
(BT_GAP_US_TO_CONN_EVENT_LEN((_event_len) * USEC_PER_MSEC))

/** Constant Tone Extension (CTE) types */
enum {
Expand Down
7 changes: 4 additions & 3 deletions samples/bluetooth/bap_broadcast_assistant/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,13 @@ static 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);
Expand Down
7 changes: 4 additions & 3 deletions samples/bluetooth/bap_broadcast_sink/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,12 +851,13 @@ static 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);
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
7 changes: 4 additions & 3 deletions samples/bluetooth/cap_acceptor/src/cap_acceptor_broadcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,13 @@ static 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);
Expand Down
26 changes: 22 additions & 4 deletions samples/bluetooth/central_past/src/main.c
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdint.h>

#include <zephyr/bluetooth/gap.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/util.h>

#define NAME_LEN 30

static bool per_adv_found;
static bt_addr_le_t per_addr;
static uint8_t per_sid;
static struct bt_conn *default_conn;
static uint32_t per_adv_interval_ms;
static uint16_t per_adv_sync_timeout;

static K_SEM_DEFINE(sem_conn, 0, 1);
static K_SEM_DEFINE(sem_conn_lost, 0, 1);
Expand Down Expand Up @@ -106,8 +110,22 @@ static void scan_recv(const struct bt_le_scan_recv_info *info,
} else {
/* If info->interval it is a periodic advertiser, mark for sync */
if (!per_adv_found && info->interval) {
uint32_t interval_us;
uint32_t timeout;

per_adv_found = true;
per_adv_interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(info->interval);

/* Add retries and convert to unit in 10's of ms */
interval_us = BT_GAP_PER_ADV_INTERVAL_TO_US(info->interval);

timeout = BT_GAP_US_TO_PER_ADV_SYNC_TIMEOUT(interval_us);

/* 10 attempts */
timeout *= 10;

/* Enforce restraints */
per_adv_sync_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT,
BT_GAP_PER_ADV_MAX_TIMEOUT);

per_sid = info->sid;
bt_addr_le_copy(&per_addr, info->addr);
Expand Down Expand Up @@ -296,7 +314,7 @@ int main(void)
sync_create_param.options = 0;
sync_create_param.sid = per_sid;
sync_create_param.skip = 0;
sync_create_param.timeout = per_adv_interval_ms * 10 / 10; /* 10 attempts */
sync_create_param.timeout = per_adv_sync_timeout;
err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
if (err != 0) {
printk("failed (err %d)\n", err);
Expand Down
Loading

0 comments on commit 6a4da5d

Please sign in to comment.