samples: bluetooth: Add peripheral PAST sample
Adds a sample of using (in this case subscribing) to periodic advertising sync transfer (PAST). Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
d0ce9bb877
commit
bfa7315649
5 changed files with 216 additions and 0 deletions
7
samples/bluetooth/peripheral_past/CMakeLists.txt
Normal file
7
samples/bluetooth/peripheral_past/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13.1)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(peripheral_past)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
27
samples/bluetooth/peripheral_past/README.rst
Normal file
27
samples/bluetooth/peripheral_past/README.rst
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
.. _bluetooth-peripheral-past-sample:
|
||||||
|
|
||||||
|
Bluetooth: Periodic Advertising Synchronization Transfer
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
A simple application demonstrating the BLE Periodic Advertising Synchronization
|
||||||
|
Transfer (PAST) functionality as the receiver.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
************
|
||||||
|
|
||||||
|
* A board with BLE 5.1 support
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
********************
|
||||||
|
|
||||||
|
This sample can be found under :zephyr_file:`samples/bluetooth/peripheral_past`
|
||||||
|
in the Zephyr tree.
|
||||||
|
|
||||||
|
Use the sample found under :zephyr_file:`samples/bluetooth/central_past` on
|
||||||
|
another board that will connect to this and transfer a periodic advertisement
|
||||||
|
sync.
|
||||||
|
|
||||||
|
See :ref:`bluetooth samples section <bluetooth-samples>` for details.
|
7
samples/bluetooth/peripheral_past/prj.conf
Normal file
7
samples/bluetooth/peripheral_past/prj.conf
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
CONFIG_BT=y
|
||||||
|
CONFIG_BT_BROADCASTER=y
|
||||||
|
CONFIG_BT_OBSERVER=y
|
||||||
|
CONFIG_BT_EXT_ADV=y
|
||||||
|
CONFIG_BT_PER_ADV_SYNC=y
|
||||||
|
CONFIG_BT_DEBUG_LOG=y
|
||||||
|
CONFIG_BT_DEVICE_NAME="Peripheral PAST"
|
7
samples/bluetooth/peripheral_past/sample.yaml
Normal file
7
samples/bluetooth/peripheral_past/sample.yaml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
sample:
|
||||||
|
name: Bluetooth Peripheral Periodic Advertising Synchronization Transfer (PAST)
|
||||||
|
tests:
|
||||||
|
sample.bluetooth.peripheral_past:
|
||||||
|
harness: bluetooth
|
||||||
|
platform_allow: qemu_cortex_m3 qemu_x86 nrf52_bsim
|
||||||
|
tags: bluetooth
|
168
samples/bluetooth/peripheral_past/src/main.c
Normal file
168
samples/bluetooth/peripheral_past/src/main.c
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <devicetree.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
#include <bluetooth/bluetooth.h>
|
||||||
|
#include <bluetooth/conn.h>
|
||||||
|
|
||||||
|
static struct bt_conn *default_conn;
|
||||||
|
|
||||||
|
static K_SEM_DEFINE(sem_per_sync, 0, 1);
|
||||||
|
static K_SEM_DEFINE(sem_per_sync_lost, 0, 1);
|
||||||
|
|
||||||
|
static void sync_cb(struct bt_le_per_adv_sync *sync,
|
||||||
|
struct bt_le_per_adv_sync_synced_info *info)
|
||||||
|
{
|
||||||
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
char past_peer_addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
if (!info->conn) {
|
||||||
|
printk("Sync not from PAST\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(info->conn), past_peer_addr,
|
||||||
|
sizeof(past_peer_addr));
|
||||||
|
|
||||||
|
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s synced, Interval 0x%04x (%u ms). PAST peer %s\n",
|
||||||
|
bt_le_per_adv_sync_get_index(sync), le_addr, info->interval,
|
||||||
|
info->interval * 5 / 4, past_peer_addr);
|
||||||
|
|
||||||
|
k_sem_give(&sem_per_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_cb(struct bt_le_per_adv_sync *sync,
|
||||||
|
const struct bt_le_per_adv_sync_term_info *info)
|
||||||
|
{
|
||||||
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||||
|
|
||||||
|
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated\n",
|
||||||
|
bt_le_per_adv_sync_get_index(sync), le_addr);
|
||||||
|
|
||||||
|
k_sem_give(&sem_per_sync_lost);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_cb(struct bt_le_per_adv_sync *sync,
|
||||||
|
const struct bt_le_per_adv_sync_recv_info *info,
|
||||||
|
struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
char data_str[129];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
|
||||||
|
bin2hex(buf->data, buf->len, data_str, sizeof(data_str));
|
||||||
|
|
||||||
|
printk("PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, RSSI %i, CTE %u, data length %u, "
|
||||||
|
"data: %s\n", bt_le_per_adv_sync_get_index(sync), le_addr,
|
||||||
|
info->tx_power, info->rssi, info->cte_type, buf->len, data_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_le_per_adv_sync_cb sync_callbacks = {
|
||||||
|
.synced = sync_cb,
|
||||||
|
.term = term_cb,
|
||||||
|
.recv = recv_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
static void connected(struct bt_conn *conn, uint8_t err)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (default_conn == NULL) {
|
||||||
|
default_conn = conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn != default_conn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Connected: %s\n", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
if (conn != default_conn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
|
||||||
|
|
||||||
|
bt_conn_unref(default_conn);
|
||||||
|
default_conn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_conn_cb conn_callbacks = {
|
||||||
|
.connected = connected,
|
||||||
|
.disconnected = disconnected,
|
||||||
|
};
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
struct bt_le_per_adv_sync_transfer_param past_param;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
printk("Starting Peripheral Periodic Advertising Synchronization Transfer (PAST) Demo\n");
|
||||||
|
|
||||||
|
/* Initialize the Bluetooth Subsystem */
|
||||||
|
err = bt_enable(NULL);
|
||||||
|
if (err) {
|
||||||
|
printk("Bluetooth init failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Connection callbacks register...");
|
||||||
|
bt_conn_cb_register(&conn_callbacks);
|
||||||
|
printk("Success\n");
|
||||||
|
|
||||||
|
printk("Periodic Advertising callbacks register...");
|
||||||
|
bt_le_per_adv_sync_cb_register(&sync_callbacks);
|
||||||
|
printk("Success.\n");
|
||||||
|
|
||||||
|
printk("Subscribing to periodic advertising sync transfers\n");
|
||||||
|
past_param.skip = 1;
|
||||||
|
past_param.timeout = 1000; /* 10 seconds */
|
||||||
|
err = bt_le_per_adv_sync_transfer_subscribe(NULL /* any peer */,
|
||||||
|
&past_param);
|
||||||
|
if (err) {
|
||||||
|
printk("PAST subscribe failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, NULL, 0, NULL, 0);
|
||||||
|
if (err) {
|
||||||
|
printk("Advertising failed to start (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
printk("Waiting for periodic sync...\n");
|
||||||
|
err = k_sem_take(&sem_per_sync, K_FOREVER);
|
||||||
|
if (err) {
|
||||||
|
printk("failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printk("Periodic sync established.\n");
|
||||||
|
|
||||||
|
printk("Waiting for periodic sync lost...\n");
|
||||||
|
err = k_sem_take(&sem_per_sync_lost, K_FOREVER);
|
||||||
|
if (err) {
|
||||||
|
printk("failed (err %d)\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printk("Periodic sync lost.\n");
|
||||||
|
} while (true);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue