1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  *  SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/types.h>
8 #include <stddef.h>
9 #include <errno.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/printk.h>
12 
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/direction.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/sys/util.h>
17 
18 /* Length of CTE in unit of 8[us] */
19 #define CTE_LEN (0x14U)
20 /* Number of CTE send in single periodic advertising train */
21 #define PER_ADV_EVENT_CTE_COUNT 5
22 
23 static void adv_sent_cb(struct bt_le_ext_adv *adv,
24 			struct bt_le_ext_adv_sent_info *info);
25 
26 static struct bt_le_ext_adv_cb adv_callbacks = {
27 	.sent = adv_sent_cb,
28 };
29 
30 static struct bt_le_ext_adv *adv_set;
31 
32 static struct bt_le_adv_param param =
33 		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_EXT_ADV |
34 				     BT_LE_ADV_OPT_USE_IDENTITY,
35 				     BT_GAP_ADV_FAST_INT_MIN_2,
36 				     BT_GAP_ADV_FAST_INT_MAX_2,
37 				     NULL);
38 
39 static struct bt_le_ext_adv_start_param ext_adv_start_param = {
40 	.timeout = 0,
41 	.num_events = 0,
42 };
43 
44 static struct bt_le_per_adv_param per_adv_param = {
45 	.interval_min = BT_GAP_PER_ADV_SLOW_INT_MIN,
46 	.interval_max = BT_GAP_PER_ADV_SLOW_INT_MAX,
47 	.options = BT_LE_ADV_OPT_USE_TX_POWER,
48 };
49 
50 #if defined(CONFIG_BT_DF_CTE_TX_AOD)
51 static uint8_t ant_patterns[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA };
52 #endif /* CONFIG_BT_DF_CTE_TX_AOD */
53 
54 struct bt_df_adv_cte_tx_param cte_params = { .cte_len = CTE_LEN,
55 					     .cte_count = PER_ADV_EVENT_CTE_COUNT,
56 #if defined(CONFIG_BT_DF_CTE_TX_AOD)
57 					     .cte_type = BT_DF_CTE_TYPE_AOD_2US,
58 					     .num_ant_ids = ARRAY_SIZE(ant_patterns),
59 					     .ant_ids = ant_patterns
60 #else
61 					     .cte_type = BT_DF_CTE_TYPE_AOA,
62 					     .num_ant_ids = 0,
63 					     .ant_ids = NULL
64 #endif /* CONFIG_BT_DF_CTE_TX_AOD */
65 };
66 
67 static const struct bt_data ad[] = {
68 	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
69 };
70 
adv_sent_cb(struct bt_le_ext_adv * adv,struct bt_le_ext_adv_sent_info * info)71 static void adv_sent_cb(struct bt_le_ext_adv *adv,
72 			struct bt_le_ext_adv_sent_info *info)
73 {
74 	printk("Advertiser[%d] %p sent %d\n", bt_le_ext_adv_get_index(adv),
75 	       adv, info->num_sent);
76 }
77 
main(void)78 int main(void)
79 {
80 	char addr_s[BT_ADDR_LE_STR_LEN];
81 	struct bt_le_oob oob_local;
82 	int err;
83 
84 	printk("Starting Direction Finding periodic advertising Beacon Demo\n");
85 
86 	/* Initialize the Bluetooth Subsystem */
87 	printk("Bluetooth initialization...");
88 	err = bt_enable(NULL);
89 	if (err) {
90 		printk("failed (err %d)\n", err);
91 		return 0;
92 	}
93 	printk("success\n");
94 
95 	printk("Advertising set create...");
96 	err = bt_le_ext_adv_create(&param, &adv_callbacks, &adv_set);
97 	if (err) {
98 		printk("failed (err %d)\n", err);
99 		return 0;
100 	}
101 	printk("success\n");
102 
103 	err = bt_le_ext_adv_set_data(adv_set, ad, ARRAY_SIZE(ad), NULL, 0);
104 	if (err) {
105 		printk("failed (err %d)\n", err);
106 		return 0;
107 	}
108 
109 	printk("Update CTE params...");
110 	err = bt_df_set_adv_cte_tx_param(adv_set, &cte_params);
111 	if (err) {
112 		printk("failed (err %d)\n", err);
113 		return 0;
114 	}
115 	printk("success\n");
116 
117 	printk("Periodic advertising params set...");
118 	err = bt_le_per_adv_set_param(adv_set, &per_adv_param);
119 	if (err) {
120 		printk("failed (err %d)\n", err);
121 		return 0;
122 	}
123 	printk("success\n");
124 
125 	printk("Enable CTE...");
126 	err = bt_df_adv_cte_tx_enable(adv_set);
127 	if (err) {
128 		printk("failed (err %d)\n", err);
129 		return 0;
130 	}
131 	printk("success\n");
132 
133 	printk("Periodic advertising enable...");
134 	err = bt_le_per_adv_start(adv_set);
135 	if (err) {
136 		printk("failed (err %d)\n", err);
137 		return 0;
138 	}
139 	printk("success\n");
140 
141 	printk("Extended advertising enable...");
142 	err = bt_le_ext_adv_start(adv_set, &ext_adv_start_param);
143 	if (err) {
144 		printk("failed (err %d)\n", err);
145 		return 0;
146 	}
147 	printk("success\n");
148 
149 	printk("Get extended advertising address...");
150 	err = bt_le_ext_adv_oob_get_local(adv_set, &oob_local);
151 	if (err) {
152 		printk("failed (err %d)\n", err);
153 		return 0;
154 	}
155 	printk("success\n");
156 
157 	bt_addr_le_to_str(&oob_local.addr, addr_s, sizeof(addr_s));
158 
159 	printk("Started extended advertising as %s\n", addr_s);
160 	return 0;
161 }
162