Skip to content

Commit

Permalink
samples: bluetooth: Add Channel Sounding Reflector with RRSP sample
Browse files Browse the repository at this point in the history
This sample can be used to set up a Channel Sounding Reflector with
the GATT Ranging Responder service.
A Channel Sounding Initiator with Ranging Requestor can connect to this
sample to receive CS Ranging Data and perform distance estimation.

Signed-off-by: Aleksandar Stanoev <[email protected]>
  • Loading branch information
alexstanoev-nordic committed Nov 14, 2024
1 parent 4239811 commit d9e2653
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@
/samples/bluetooth/central_nfc_pairing/ @nrfconnect/ncs-si-muffin
/samples/bluetooth/central_smp_client/ @nrfconnect/ncs-si-muffin
/samples/bluetooth/central_uart/ @nrfconnect/ncs-si-muffin
/samples/bluetooth/channel_sounding_ras/ @nrfconnect/ncs-dragoon
/samples/bluetooth/conn_time_sync/ @nrfconnect/ncs-dragoon
/samples/bluetooth/direction_finding_central/ @nrfconnect/ncs-dragoon
/samples/bluetooth/direction_finding_connectionless_rx/ @nrfconnect/ncs-dragoon
Expand Down
15 changes: 15 additions & 0 deletions samples/bluetooth/channel_sounding_ras/reflector/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(channel_sounding_ras_reflector)

# NORDIC SDK APP START
target_sources(app PRIVATE
src/main.c
)
# NORDIC SDK APP END
79 changes: 79 additions & 0 deletions samples/bluetooth/channel_sounding_ras/reflector/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.. _channel_sounding_ras_reflector:

Bluetooth: Channel Sounding Reflector with Ranging Responder
############################################################

.. contents::
:local:
:depth: 2

This sample demonstrates how to use the ranging service to provide ranging data to a client.

Requirements
************

The sample supports the following development kits:

.. table-from-sample-yaml::

The sample also requires a device running a Channel Sounding Initiator with Ranging Requestor to connect to.

Overview
********

The sample demonstrates a basic Bluetooth® Low Energy Peripheral role functionality that exposes the GATT Ranging Responder Service and configures the Channel Sounding reflector role.
When Channel Sounding Ranging Data is generated by the controller, it will be automatically stored by the Ranging Service, and can be queried at any time by the Ranging Requestor.
The Channel Sounding Ranging Data can then be used by the peer device to perform distance estimation.

User interface
**************

The sample does not require user input and will advertise using the GATT Ranging Service UUID.
The first LED on the development kit will be lit when a connection has been established.

Building and running
********************
.. |sample path| replace:: :file:`samples/bluetooth/channel_sounding_ras/reflector`

.. include:: /includes/build_and_run.txt

Testing
=======

After programming the sample to your development kit, you can test it by connecting to another development kit with a Channel Sounding Initiator role with Ranging Requestor.

1. |connect_terminal_specific|
#. Reset the kit.
#. Program the other kit with the Channel Sounding Initiator with Ranging Requestor sample.
#. Wait until the advertiser is detected by the Central.
In the terminal window, check for information similar to the following::

Connected to xx.xx.xx.xx.xx.xx (random) (err 0x00)
Pairing completed: xx.xx.xx.xx.xx.xx (random), bonded: 1
CS capability exchange completed.
CS config creation complete. ID: 0
CS security enabled.
CS procedures enabled.

Dependencies
************

This sample uses the following |NCS| libraries:

* :ref:`dk_buttons_and_leds_readme`
* :file:`include/bluetooth/services/ras.h`

This sample uses the following Zephyr libraries:

* :file:`include/sys/printk.h`
* :file:`include/zephyr/types.h`
* :ref:`zephyr:kernel_api`:

* :file:`include/kernel.h`

* :ref:`zephyr:bluetooth_api`:

* :file:`include/bluetooth/bluetooth.h`
* :file:`include/bluetooth/conn.h`
* :file:`include/bluetooth/uuid.h`
* :file:`include/bluetooth/cs.h`
25 changes: 25 additions & 0 deletions samples/bluetooth/channel_sounding_ras/reflector/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_DK_LIBRARY=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_SMP=y
CONFIG_BT_DEVICE_NAME="Nordic CS Reflector"
CONFIG_BT_MAX_CONN=1

# The Ranging Profile recommends a MTU of at least 247 octets.
CONFIG_BT_L2CAP_TX_MTU=498
CONFIG_BT_BUF_ACL_TX_SIZE=502
CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_CTLR_PHY_2M=y

CONFIG_BT_CHANNEL_SOUNDING=y
CONFIG_BT_RAS=y
CONFIG_BT_RAS_RRSP=y
12 changes: 12 additions & 0 deletions samples/bluetooth/channel_sounding_ras/reflector/sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
sample:
description: Bluetooth Low Energy Channel Sounding Reflector with Ranging Service Responder
name: Bluetooth LE Channel Sounding Reflector with RRSP
tests:
sample.bluetooth.channel_sounding_ras.reflector:
sysbuild: true
build_only: true
integration_platforms:
- nrf54l15dk/nrf54l15/cpuapp
platform_allow:
- nrf54l15dk/nrf54l15/cpuapp
tags: bluetooth ci_build sysbuild
167 changes: 167 additions & 0 deletions samples/bluetooth/channel_sounding_ras/reflector/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/** @file
* @brief Channel Sounding Reflector with Ranging Responder sample
*/

#include <zephyr/sys/printk.h>
#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/cs.h>
#include <bluetooth/services/ras.h>

#include <dk_buttons_and_leds.h>

#define CON_STATUS_LED DK_LED1

static K_SEM_DEFINE(sem_connected, 0, 1);

static struct bt_conn *connection;

static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_RANGING_SERVICE_VAL)),
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

static void pairing_complete(struct bt_conn *conn, bool bonded)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
}

static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

printk("Pairing failed conn: %s, reason %d %s\n", addr, reason,
bt_security_err_to_str(reason));
}

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {.pairing_complete = pairing_complete,
.pairing_failed = pairing_failed};

static void connected_cb(struct bt_conn *conn, uint8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];

(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Connected to %s (err 0x%02X)\n", addr, err);

if (err) {
bt_conn_unref(conn);
connection = NULL;
}

connection = bt_conn_ref(conn);

k_sem_give(&sem_connected);

dk_set_led_on(CON_STATUS_LED);
}

static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02X)\n", reason);

bt_conn_unref(conn);
connection = NULL;

dk_set_led_off(CON_STATUS_LED);
}

static void remote_capabilities_cb(struct bt_conn *conn, struct bt_conn_le_cs_capabilities *params)
{
ARG_UNUSED(conn);
ARG_UNUSED(params);
printk("CS capability exchange completed.\n");
}

static void config_created_cb(struct bt_conn *conn, struct bt_conn_le_cs_config *config)
{
ARG_UNUSED(conn);
printk("CS config creation complete. ID: %d\n", config->id);
}

static void security_enabled_cb(struct bt_conn *conn)
{
ARG_UNUSED(conn);
printk("CS security enabled.\n");
}

static void procedure_enabled_cb(struct bt_conn *conn,
struct bt_conn_le_cs_procedure_enable_complete *params)
{
ARG_UNUSED(conn);
if (params->state == 1) {
printk("CS procedures enabled.\n");
} else {
printk("CS procedures disabled.\n");
}
}

BT_CONN_CB_DEFINE(conn_cb) = {
.connected = connected_cb,
.disconnected = disconnected_cb,
.le_cs_remote_capabilities_available = remote_capabilities_cb,
.le_cs_config_created = config_created_cb,
.le_cs_security_enabled = security_enabled_cb,
.le_cs_procedure_enabled = procedure_enabled_cb,
};

int main(void)
{
int err;

printk("Starting Channel Sounding Reflector Sample\n");

dk_leds_init();

err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
if (err) {
printk("Failed to register authorization info callbacks.\n");
return 0;
}

err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0;
}

err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return 0;
}

while (true) {
k_sem_take(&sem_connected, K_FOREVER);

const struct bt_le_cs_set_default_settings_param default_settings = {
.enable_initiator_role = false,
.enable_reflector_role = true,
.cs_sync_antenna_selection = BT_LE_CS_ANTENNA_SELECTION_OPT_REPETITIVE,
.max_tx_power = BT_HCI_OP_LE_CS_MAX_MAX_TX_POWER,
};

err = bt_le_cs_set_default_settings(connection, &default_settings);
if (err) {
printk("Failed to configure default CS settings (err %d)\n", err);
}
}

return 0;
}

0 comments on commit d9e2653

Please sign in to comment.