8 Commits

Author SHA1 Message Date
pstruebi 766498be5a Add todos 2025-01-05 17:45:00 +01:00
pstruebi 9ea485abc0 Add todo list 2024-12-19 16:45:06 +01:00
pstruebi 1b12e5151d make 4 broadcasters with 16kHz work 2024-12-18 16:53:55 +01:00
pstruebi 4d6e6b8962 Add initial support for up to 5BIG 2024-12-18 10:26:55 +01:00
pstruebi bcb2bf3694 improve config procedure 2024-12-17 13:00:31 +01:00
pstruebi 2120f9b188 Implement the ability to broadcast a file only once 2024-12-12 19:22:14 +01:00
pstruebi a70bf09bfa Add broadcaster with python 2024-12-05 18:07:05 +01:00
pstruebi 9647a07598 Implement usb mass storge device in project 2024-11-27 18:05:28 +01:00
11 changed files with 658 additions and 51 deletions
+2
View File
@@ -1,3 +1,5 @@
*.pyc
# editors
*.swp
*~
+6
View File
@@ -0,0 +1,6 @@
{
"files.associations": {
"broadcast_source.h": "c",
"bit": "c"
}
}
+2
View File
@@ -16,6 +16,8 @@ zephyr_library_include_directories(app PRIVATE
${ZEPHYR_NRF_MODULE_DIR}/applications/nrf5340_audio/src/modules
${ZEPHYR_NRF_MODULE_DIR}/applications/nrf5340_audio/src/utils/macros
)
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
add_subdirectory(${ZEPHYR_NRF_MODULE_DIR}/applications/nrf5340_audio/src/bluetooth bluetooth_build)
+75
View File
@@ -11,6 +11,81 @@ rsource "${ZEPHYR_NRF_MODULE_DIR}/applications/nrf5340_audio/src/utils/Kconfig"
#----------------------------------------------------------------------------#
# USB mass storage device
menu "MSC sample options"
config APP_WIPE_STORAGE
bool "Option to clear the flash area before mounting"
help
Use this to force an existing file system to be created.
choice
prompt "Storage and file system type used by the application"
default APP_MSC_STORAGE_NONE
help
Specify the type of storage and file system.
config APP_MSC_STORAGE_NONE
bool "Use RAM disk as block device"
config APP_MSC_STORAGE_RAM
bool "Use RAM disk and FAT file system"
imply FILE_SYSTEM
imply FAT_FILESYSTEM_ELM
config APP_MSC_STORAGE_FLASH_FATFS
bool "Use FLASH disk and FAT file system"
imply DISK_DRIVER_FLASH
imply FILE_SYSTEM
imply FAT_FILESYSTEM_ELM
config APP_MSC_STORAGE_FLASH_LITTLEFS
bool "Use FLASH disk and LittleFS"
imply DISK_DRIVER_FLASH
imply FILE_SYSTEM
imply FILE_SYSTEM_LITTLEFS
config APP_MSC_STORAGE_SDCARD
bool "Use SDHC and FAT file system"
imply DISK_DRIVER_SDMMC
imply FILE_SYSTEM
imply FAT_FILESYSTEM_ELM
endchoice
config MASS_STORAGE_DISK_NAME
default "NAND" if DISK_DRIVER_FLASH
default "RAM" if DISK_DRIVER_RAM
default "SD" if DISK_DRIVER_SDMMC
if DISK_DRIVER_FLASH
config FLASH_MAP
default y
config FLASH_PAGE_LAYOUT
default y
config FLASH_LOG_LEVEL
default 3
if NORDIC_QSPI_NOR
config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE
default 4096
endif # NORDIC_QSPI_NOR
endif # DISK_DRIVER_FLASH
endmenu
# Source common USB sample options used to initialize new experimental USB
# device stack. The scope of these options is limited to USB samples in project
# tree, you cannot use them in your own application.
source "samples/subsys/usb/common/Kconfig.sample_usbd"
# Auraconfig
config TRANSPORT_BIS
bool "Use BIS (Broadcast Isochronous Stream)"
+11
View File
@@ -0,0 +1,11 @@
nac preset 24_2_1 0
nac file select left-channel_24kHz_left_48kbps_10ms.lc3 0 0 0
nac file select left-channel_24kHz_left_48kbps_10ms.lc3 0 0 1
nac broadcast_name broadcast1 0
nac preset 24_2_1 1
nac file select right-channel_24kHz_left_48kbps_10ms.lc3 1 0 0
nac file select right-channel_24kHz_left_48kbps_10ms.lc3 1 0 1
nac broadcast_name broadcast2 1
nac start
+29
View File
@@ -0,0 +1,29 @@
from config_broadcaster import write_to_serial_read_respone
import time
if __name__ == "__main__":
serial_port = "/dev/ttyACM0"
broadcast_config = {
"broadcast1": "left24kHz_48kbps.lc3",
"broadcast2": "right-channel_24kHz_left_48kbps_10ms.lc3"
}
broadcast_ch = 0
file = "announcement_de.lc3"
ret = write_to_serial_read_respone(serial_port, f"nac file stream_close {broadcast_ch} 0 0", timeout=0.1)
print("\n".join(ret))
ret = write_to_serial_read_respone(serial_port, f"nac file select_play_once {file} {broadcast_ch} 0 0", timeout=0.1)
print("\n".join(ret))
time.sleep(1)
broadcast_ch = 1
file = "announcement_en.lc3"
ret = write_to_serial_read_respone(serial_port, f"nac stream_close {broadcast_ch} 0 0", timeout=0.1)
print("\n".join(ret))
ret = write_to_serial_read_respone(serial_port, f"nac file select_play_once {file} {broadcast_ch} 0 0", timeout=0.1)
print("\n".join(ret))
+105
View File
@@ -0,0 +1,105 @@
import serial
import time
def write_to_serial_read_respone(port, cmd, timeout = 2):
# Initialize serial connection
ser = serial.Serial(timeout = timeout)
ser.port = port
ser.baudrate = 115200
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
try:
# Try to open the serial connection
#if not ser.is_open:
ser.open()
# Send string to serial port and get response
command = f"{cmd.strip()}\r\n"
ser.write(command.encode())
time.sleep(1) # wait a bit for response
readlines = []
for _ in range(20):
line = ser.readline().decode('utf-8').strip()
if not line:
ser.close()
break
else:
readlines.append(line)
except serial.SerialException as e:
print(f"Error communicating with serial port: {e}")
finally:
# Close serial connection before returning
if ser.is_open:
ser.close()
return readlines
def gen_broadcast_config_cmd(preset, broadcast_config: dict):
"""
Writes broadcaster configuration to the given serial port.
Args:
serial_port (str): Device path of the serial port (e.g., '/dev/ttyACM0')
preset (str): Preset string used in nac preset line
broadcast_names (list): List of names for each broadcast group
"""
cmds = []
for ch, file_name in broadcast_config.items():
cmds.append(f"nac preset {preset} {ch}")
cmds.append(f"nac broadcast_name broadcast{ch} {ch}")
cmds.append(f"nac file select {file_name} {ch} 0 0")
cmds.append(f"nac num_bises 1 {ch} 0")
return cmds
if __name__ == "__main__":
import subprocess
PORT = "/dev/ttyACM0"
SAMPLING_RATE_KHZ = 16
FRAME_DUR_MS = 10
PRESET = f'{SAMPLING_RATE_KHZ}_2_1'
if SAMPLING_RATE_KHZ == 8:
BITRATE_KBPS = 16
elif SAMPLING_RATE_KHZ == 16:
BITRATE_KBPS = 32
elif SAMPLING_RATE_KHZ == 24:
BITRATE_KBPS = 48
else:
raise NotImplemented()
# TODO: Advertising interval wird ungelmäßig bei mehr als 3 broadcasts 10ms -> 1s< bei 24kHz sampling rat. Wie ist die load ?
# TODO: stop the lc3 streamer, setup all files and then start the streamer, should work for up to 4 streams
broadcast_config = {
0: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_de.lc3",
1: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_en.lc3",
2: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_fr.lc3",
3: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_es.lc3",
#4: f"announcement_{SAMPLING_RATE_KHZ}_{FRAME_DUR_MS}_{BITRATE_KBPS}_it.lc3"
}
cmds = gen_broadcast_config_cmd(PRESET, broadcast_config)
subprocess.run(["nrfjprog", "--reset", "-s", "1050109484"], check=True)
time.sleep(2)
for cmd in cmds:
ret = write_to_serial_read_respone(PORT, cmd, timeout=0.1)
print("\n".join(ret))
time.sleep(1)
for i in broadcast_config.keys():
ret = write_to_serial_read_respone(PORT, f"nac start_idx {i}", timeout=0.1)
print("\n".join(ret))
time.sleep(0.2)
+20 -12
View File
@@ -3,7 +3,16 @@
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
# USB mass storage
CONFIG_APP_MSC_STORAGE_SDCARD=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr MSC sample"
CONFIG_USB_DEVICE_PID=0x0008
CONFIG_LOG=y
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y
CONFIG_USB_MASS_STORAGE=y
CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y
CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y
# General
CONFIG_REBOOT=y
@@ -15,9 +24,9 @@ CONFIG_THREAD_RUNTIME_STATS=y
CONFIG_MAIN_THREAD_PRIORITY=10
CONFIG_STACK_SENTINEL=y
CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=12000
CONFIG_MAIN_STACK_SIZE=18000
CONFIG_THREAD_NAME=y
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1200
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2000
# Uart driver
CONFIG_SERIAL=y
@@ -28,7 +37,7 @@ CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_LOG_TAG_MAX_LEN=2
CONFIG_LOG_TAG_DEFAULT="--"
CONFIG_LOG_BUFFER_SIZE=4096
CONFIG_LOG_BUFFER_SIZE=16384
CONFIG_USE_SEGGER_RTT=n
CONFIG_LOG_BACKEND_RTT=n
@@ -82,7 +91,6 @@ CONFIG_ADC=y
CONFIG_WATCHDOG=y
CONFIG_TASK_WDT=y
# Use this for debugging thread usage
#CONFIG_LOG_THREAD_ID_PREFIX=y
@@ -96,8 +104,8 @@ CONFIG_KERNEL_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_VT100_COMMANDS=y
CONFIG_SHELL_VT100_COLORS=y
CONFIG_SHELL_STACK_SIZE=8096
CONFIG_SHELL_CMD_BUFF_SIZE=128
CONFIG_SHELL_STACK_SIZE=16384
CONFIG_SHELL_CMD_BUFF_SIZE=512
## Reduce shell memory usage
CONFIG_SHELL_WILDCARD=n
CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT=n
@@ -125,16 +133,16 @@ CONFIG_BT_DEVICE_NAME_DYNAMIC=y
CONFIG_BT_CAP_INITIATOR=y
CONFIG_BT_ISO_BROADCASTER=y
CONFIG_BT_ISO_MAX_BIG=2
CONFIG_BT_ISO_MAX_BIG=5
CONFIG_BT_ISO_MAX_CHAN=8
# Should be twice that of BT_ISO_MAX_CHAN
CONFIG_BT_ISO_TX_BUF_COUNT=16
CONFIG_BT_BAP_BROADCAST_SOURCE=y
CONFIG_BT_BAP_BROADCAST_SRC_COUNT=2
CONFIG_BT_EXT_ADV_MAX_ADV_SET=2
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=4
CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=8
CONFIG_BT_BAP_BROADCAST_SRC_COUNT=5
CONFIG_BT_EXT_ADV_MAX_ADV_SET=5
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1
CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=1
# Broadcasting Device - 0x0885
CONFIG_BT_DEVICE_APPEARANCE=2181
+6
View File
@@ -0,0 +1,6 @@
# TODO:
- stoppen von streams während advertising weiter läuft
- 16kHz mit 16kbps (nur 32 kbps möglich)
- cpu usage debuggen
- 5 streams oder mehr parallel
- mehr als 4 streams erzeugen file open error
+399 -36
View File
@@ -22,10 +22,57 @@
#include "sd_card.h"
#include "lc3_streamer.h"
#include "led.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main, CONFIG_MAIN_LOG_LEVEL);
#include <sample_usbd.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/usb/usbd.h>
#include <zephyr/usb/class/usbd_msc.h>
#include <zephyr/fs/fs.h>
#if CONFIG_FAT_FILESYSTEM_ELM
#include <ff.h>
#endif
#if !defined(CONFIG_DISK_DRIVER_FLASH) && \
!defined(CONFIG_DISK_DRIVER_RAM) && \
!defined(CONFIG_DISK_DRIVER_SDMMC)
#error No supported disk driver enabled
#endif
#define STORAGE_PARTITION storage_partition
#define STORAGE_PARTITION_ID FIXED_PARTITION_ID(STORAGE_PARTITION)
static struct fs_mount_t fs_mnt;
static int mount_app_fs(struct fs_mount_t *mnt)
{
int rc;
#if CONFIG_FAT_FILESYSTEM_ELM
static FATFS fat_fs;
mnt->type = FS_FATFS;
mnt->fs_data = &fat_fs;
if (IS_ENABLED(CONFIG_DISK_DRIVER_RAM)) {
mnt->mnt_point = "/RAM:";
} else if (IS_ENABLED(CONFIG_DISK_DRIVER_SDMMC)) {
mnt->mnt_point = "/SD:";
} else {
mnt->mnt_point = "/NAND:";
}
#elif CONFIG_FILE_SYSTEM_LITTLEFS
mnt->type = FS_LITTLEFS;
mnt->mnt_point = "/lfs";
mnt->fs_data = &storage;
#endif
rc = fs_mount(mnt);
return rc;
}
ZBUS_CHAN_DECLARE(bt_mgmt_chan);
ZBUS_CHAN_DECLARE(sdu_ref_chan);
ZBUS_CHAN_DECLARE(le_audio_chan);
@@ -44,11 +91,17 @@ struct bt_le_ext_adv *ext_adv;
#define EXT_ADV_UUID_BUF_SIZE (128)
NET_BUF_SIMPLE_DEFINE_STATIC(uuid_data0, EXT_ADV_UUID_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(uuid_data1, EXT_ADV_UUID_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(uuid_data2, EXT_ADV_UUID_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(uuid_data3, EXT_ADV_UUID_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(uuid_data4, EXT_ADV_UUID_BUF_SIZE);
/* Buffer for periodic advertising BASE data. */
#define BASE_DATA_BUF_SIZE (256)
NET_BUF_SIMPLE_DEFINE_STATIC(base_data0, BASE_DATA_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(base_data1, BASE_DATA_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(base_data2, BASE_DATA_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(base_data3, BASE_DATA_BUF_SIZE);
NET_BUF_SIMPLE_DEFINE_STATIC(base_data4, BASE_DATA_BUF_SIZE);
/* Extended advertising buffer. */
static struct bt_data ext_adv_buf[CONFIG_BT_ISO_MAX_BIG][CONFIG_EXT_ADV_BUF_MAX];
@@ -80,13 +133,28 @@ static struct broadcast_source_ext_adv_data ext_adv_data[] = {
.pba_buf = pba_data[0]},
{.uuid_buf = &uuid_data1,
.pba_metadata_vacant_cnt = BROADCAST_SOURCE_PBA_METADATA_VACANT,
.pba_buf = pba_data[1]}};
.pba_buf = pba_data[1]},
{.uuid_buf = &uuid_data2,
.pba_metadata_vacant_cnt = BROADCAST_SOURCE_PBA_METADATA_VACANT,
.pba_buf = pba_data[2]},
{.uuid_buf = &uuid_data3,
.pba_metadata_vacant_cnt = BROADCAST_SOURCE_PBA_METADATA_VACANT,
.pba_buf = pba_data[3]},
{.uuid_buf = &uuid_data1,
.pba_metadata_vacant_cnt = BROADCAST_SOURCE_PBA_METADATA_VACANT,
.pba_buf = pba_data[4]}
};
/**
* @brief Broadcast source static periodic advertising data.
*/
static struct broadcast_source_per_adv_data per_adv_data[] = {{.base_buf = &base_data0},
{.base_buf = &base_data1}};
static struct broadcast_source_per_adv_data per_adv_data[] = {
{.base_buf = &base_data0},
{.base_buf = &base_data1},
{.base_buf = &base_data2},
{.base_buf = &base_data3},
{.base_buf = &base_data4}
};
static struct broadcast_source_big broadcast_param[CONFIG_BT_ISO_MAX_BIG];
static struct subgroup_config subgroups[CONFIG_BT_ISO_MAX_BIG]
@@ -287,24 +355,33 @@ static void stream_frame_get_and_send(struct stream_index stream_idx)
ret = lc3_streamer_next_frame_get(
stream_file_idx, (const uint8_t **const)&(bis_info->frame_ptrs[stream_idx.lvl3]));
if (ret == -ENODATA) {
LOG_WRN("No more frames to read");
ret = lc3_streamer_stream_close(stream_file_idx);
if (ret) {
LOG_ERR("Failed to close stream: %d", ret);
}
bis_info->lc3_streamer_idx[stream_idx.lvl3] = LC3_STREAMER_INDEX_UNUSED;
return;
} else if (ret == -ENOMSG) {
LOG_DBG("Frame from SD card not ready for stream %d, using zero packet",
stream_idx.lvl3);
bis_info->frame_ptrs[stream_idx.lvl3] = NULL;
} else if (ret) {
LOG_ERR("Failed to get next frame: %d", ret);
return;
if (ret != 0){
bis_info->frame_ptrs[stream_idx.lvl3] = NULL; // use zero packet
//ret = lc3_streamer_stream_close(stream_file_idx);
// if (ret) {
// LOG_ERR("Failed to close stream: %d", ret);
// }
}
// if (ret == -ENODATA) {
// LOG_WRN("No more frames to read");
// ret = lc3_streamer_stream_close(stream_file_idx);
// if (ret) {
// LOG_ERR("Failed to close stream: %d", ret);
// }
// bis_info->lc3_streamer_idx[stream_idx.lvl3] = LC3_STREAMER_INDEX_UNUSED;
// return;
// } else if (ret == -ENOMSG) {
// LOG_DBG("Frame from SD card not ready for stream %d, using zero packet",
// stream_idx.lvl3);
// bis_info->frame_ptrs[stream_idx.lvl3] = NULL;
// } else if (ret) {
// LOG_ERR("Failed to get next frame: %d", ret);
// return;
// }
bis_info->frame_loaded[stream_idx.lvl3] = true;
@@ -490,13 +567,16 @@ static int ext_adv_populate(uint8_t big_index, struct broadcast_source_ext_adv_d
ext_adv_buf[ext_adv_buf_cnt].data = ext_adv_data->uuid_buf->data;
ext_adv_buf_cnt++;
ret = bt_mgmt_manufacturer_uuid_populate(ext_adv_data->uuid_buf,
CONFIG_BT_DEVICE_MANUFACTURER_ID);
if (ret) {
LOG_ERR("Failed to add adv data with manufacturer ID: %d", ret);
return ret;
}
//TODO: populating the manufacturer id fails with crash for more than 2 big
// LOG_INF("populating manufacurer id for %d", big_index);
// ret = bt_mgmt_manufacturer_uuid_populate(ext_adv_data->uuid_buf,
// CONFIG_BT_DEVICE_MANUFACTURER_ID);
// if (ret) {
// LOG_ERR("Failed to add adv data with manufacturer ID: %d", ret);
// return ret;
// }
LOG_INF("Populating ext adv broadcast source %d", big_index);
ret = broadcast_source_ext_adv_populate(big_index, broadcast_param[big_index].fixed_id,
broadcast_param[big_index].broadcast_id,
ext_adv_data, &ext_adv_buf[ext_adv_buf_cnt],
@@ -511,7 +591,7 @@ static int ext_adv_populate(uint8_t big_index, struct broadcast_source_ext_adv_d
/* Add the number of UUIDs */
ext_adv_buf[0].data_len = ext_adv_data->uuid_buf->len;
LOG_DBG("Size of adv data: %d, num_elements: %d", sizeof(struct bt_data) * ext_adv_buf_cnt,
LOG_INF("Size of adv data: %d, num_elements: %d", sizeof(struct bt_data) * ext_adv_buf_cnt,
ext_adv_buf_cnt);
*ext_adv_count = ext_adv_buf_cnt;
@@ -560,7 +640,7 @@ static int per_adv_populate(uint8_t big_index, struct broadcast_source_per_adv_d
static void broadcast_create(uint8_t big_index)
{
if (big_index >= CONFIG_BT_ISO_MAX_BIG) {
LOG_ERR("BIG index out of range");
LOG_ERR("BIG index %d out of range", big_index);
return;
}
@@ -654,7 +734,7 @@ int main(void)
{
int ret;
LOG_DBG("Main started");
LOG_INF("Main started");
ret = nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1);
ret -= NRFX_ERROR_BASE_NUM;
@@ -689,14 +769,15 @@ int main(void)
}
}
ret = zbus_subscribers_create();
ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads");
if (sd_card_present) {
ret = sd_card_toc_gen();
ERR_CHK_MSG(ret, "Failed to generate SD card table");
}
ret = zbus_subscribers_create();
ERR_CHK_MSG(ret, "Failed to create zbus subscriber threads");
return 0;
}
@@ -874,6 +955,18 @@ static void nrf_auraconfig_print(const struct shell *shell, uint8_t group_index)
}
}
static int cmd_usb_mass_enable(const struct shell *shell, size_t argc, char **argv)
{
int ret;
ret = usb_enable(NULL);
if (ret != 0) {
LOG_ERR("Failed to enable USB");
return -1;
}
LOG_INF("The device is put in USB mass storage mode.\n");
return 0;
}
static int cmd_list(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
@@ -892,12 +985,15 @@ static int adv_create_and_start(const struct shell *shell, uint8_t big_index)
size_t ext_adv_buf_cnt = 0;
size_t per_adv_buf_cnt = 0;
LOG_INF("Starting Ext Advertising for big %d", big_index);
if (big_index >= CONFIG_BT_ISO_MAX_BIG) {
shell_error(shell, "BIG index out of range");
return -EINVAL;
}
LOG_INF("Starting Ext Advertising for big %d", big_index);
if (broadcast_param[big_index].broadcast_name[0] == '\0') {
/* Name not set, using default */
size_t brdcst_name_size = sizeof(CONFIG_BT_AUDIO_BROADCAST_NAME) - 1;
@@ -931,6 +1027,7 @@ static int adv_create_and_start(const struct shell *shell, uint8_t big_index)
bt_set_name(broadcast_param[big_index].adv_name);
LOG_INF("Populating Ext Advertising for big %d", big_index);
/* Get advertising set for BIG0 */
ret = ext_adv_populate(big_index, &ext_adv_data[big_index], ext_adv_buf[big_index],
ARRAY_SIZE(ext_adv_buf[big_index]), &ext_adv_buf_cnt);
@@ -938,6 +1035,7 @@ static int adv_create_and_start(const struct shell *shell, uint8_t big_index)
return ret;
}
LOG_INF("Populating periodic Advertising for big %d", big_index);
ret = per_adv_populate(big_index, &per_adv_data[big_index], &per_adv_buf[big_index], 1,
&per_adv_buf_cnt);
if (ret) {
@@ -945,6 +1043,7 @@ static int adv_create_and_start(const struct shell *shell, uint8_t big_index)
}
/* Start broadcaster */
LOG_INF("Starting the Advertiser for big %d", big_index);
ret = bt_mgmt_adv_start(big_index, ext_adv_buf[big_index], ext_adv_buf_cnt,
&per_adv_buf[big_index], per_adv_buf_cnt, false);
if (ret) {
@@ -1053,12 +1152,13 @@ static int big_enable(const struct shell *shell, uint8_t big_index)
return ret;
}
LOG_INF("starting advertising for BIG %d", big_index);
ret = adv_create_and_start(shell, big_index);
if (ret) {
shell_error(shell, "Failed to start advertising for BIG%d: %d", big_index, ret);
return ret;
}
LOG_INF("Advertising started for BIG %d", big_index);
return 0;
}
@@ -1096,6 +1196,103 @@ static int cmd_start(const struct shell *shell, size_t argc, char **argv)
return 0;
}
static int cmd_start_idx(const struct shell *shell, size_t argc, char **argv)
{
int ret;
uint8_t big_index;
big_index = (uint8_t)atoi(argv[1]);
LOG_INF("Enable big %d", big_index);
ret = big_enable(shell, big_index);
if (ret) {
return ret;
}
led_blink(LED_APP_RGB, LED_COLOR_GREEN);
return 0;
}
static int enable_broadcast_source_only(const struct shell *shell, uint8_t big_index)
{
int ret;
if (big_index >= CONFIG_BT_ISO_MAX_BIG) {
return -EINVAL;
}
if ((broadcast_param[big_index].subgroups == NULL) ||
(broadcast_param[big_index].num_subgroups == 0)) {
LOG_ERR("No subgroups defined for BIG%d", big_index);
return -EINVAL;
}
if (broadcast_source_is_streaming(big_index)) {
LOG_WRN("BIG %d is already streaming", big_index);
/* Do not return error code as this might be called from a for-loop */
return 0;
}
ret = broadcast_source_enable(&broadcast_param[big_index], big_index);
if (ret) {
shell_error(shell, "Failed to enable broadcaster: %d", ret);
return ret;
}
return 0;
}
static int cmd_broadcast_source_enable(const struct shell *shell, size_t argc, char **argv)
{
int ret;
if (argc == 2) {
uint8_t big_index;
ret = argv_to_indexes(shell, argc, argv, &big_index, 1, NULL, 0);
if (ret) {
return ret;
}
ret = enable_broadcast_source_only(shell, big_index);
if (ret) {
return ret;
}
} else {
for (int i = 0; i < CONFIG_BT_ISO_MAX_BIG; i++) {
if (broadcast_param[i].subgroups != NULL ||
broadcast_param[i].num_subgroups > 0) {
ret = enable_broadcast_source_only(shell, i);
if (ret) {
return ret;
}
}
}
}
led_blink(LED_APP_RGB, LED_COLOR_GREEN);
return 0;
}
static int broadcaster_source_disable(const struct shell *shell, uint8_t big_index)
{
int ret;
if (!broadcast_source_is_streaming(big_index)) {
return 0;
}
ret = broadcast_source_disable(big_index);
if (ret) {
shell_error(shell, "Failed to stop broadcaster(s) %d", ret);
return ret;
}
return 0;
}
static int broadcaster_stop(const struct shell *shell, uint8_t big_index)
{
int ret;
@@ -1121,14 +1318,24 @@ static int broadcaster_stop(const struct shell *shell, uint8_t big_index)
shell_error(shell, "Failed to stop extended advertiser");
return ret;
}
if (big_index == 0) {
net_buf_simple_reset(&base_data0);
net_buf_simple_reset(&uuid_data0);
} else if (big_index == 1) {
net_buf_simple_reset(&base_data1);
net_buf_simple_reset(&uuid_data1);
} else {
} else if (big_index == 2) {
net_buf_simple_reset(&base_data2);
net_buf_simple_reset(&uuid_data2);
} else if (big_index == 3) {
net_buf_simple_reset(&base_data3);
net_buf_simple_reset(&uuid_data3);
} else if (big_index == 4) {
net_buf_simple_reset(&base_data4);
net_buf_simple_reset(&uuid_data4);
}
else {
LOG_ERR("Stopping the broadcast source failed, big index %d out of range", big_index);
shell_error(shell, "BIG index out of range");
return -EINVAL;
}
@@ -1146,6 +1353,38 @@ static int broadcaster_stop(const struct shell *shell, uint8_t big_index)
return 0;
}
static int cmd_broadcast_source_disable(const struct shell *shell, size_t argc, char **argv)
{
int ret;
if (argc == 2) {
uint8_t big_index;
ret = argv_to_indexes(shell, argc, argv, &big_index, 1, NULL, 0);
if (ret) {
return ret;
}
ret = broadcaster_source_disable(shell, big_index);
} else {
for (size_t i = 0; i < CONFIG_BT_ISO_MAX_BIG; i++) {
if (broadcast_param[i].subgroups != NULL) {
ret = broadcaster_source_disable(shell, i);
if (ret) {
return ret;
}
}
}
}
led_on(LED_APP_RGB, LED_COLOR_GREEN);
return 0;
}
static int cmd_stop(const struct shell *shell, size_t argc, char **argv)
{
int ret;
@@ -1780,7 +2019,120 @@ static int cmd_file_select(const struct shell *shell, size_t argc, char **argv)
ret = lc3_streamer_stream_register(
file_name, &lc3_stream_infos[big_index][sub_index].lc3_streamer_idx[bis_index],
true);
true); // TODO: set this to false and only loop once with a dedicated command
if (ret) {
shell_error(shell, "Failed to register stream: %d", ret);
return ret;
}
lc3_stream_infos[big_index][sub_index].frame_size =
broadcast_param[big_index].subgroups[sub_index].group_lc3_preset.qos.sdu;
return 0;
}
static int cmd_stream_close(const struct shell *shell, size_t argc, char **argv)
{
int ret;
uint8_t big_index;
uint8_t sub_index;
uint8_t bis_index;
ret = argv_to_indexes(shell, argc, argv, &big_index, 1, &sub_index, 2);
if (ret) {
shell_error(shell, "Failed to get indexes: %d", ret);
return ret;
}
bis_index = (uint8_t)atoi(argv[3]);
ret = lc3_streamer_stream_close(lc3_stream_infos[big_index][sub_index].lc3_streamer_idx[bis_index]);
}
static int cmd_file_select_play_once(const struct shell *shell, size_t argc, char **argv)
{
int ret;
uint8_t big_index;
uint8_t sub_index;
uint8_t bis_index;
if (!sd_card_present) {
shell_error(shell, "No SD card present: files cannot be selected");
return -EFAULT;
}
if (argc != 5) {
shell_error(shell,
"Usage: nac file select <file path> <BIG index> <subgroup index> "
"<BIS index>");
return -EINVAL;
}
ret = argv_to_indexes(shell, argc, argv, &big_index, 2, &sub_index, 3);
if (ret) {
shell_error(shell, "Failed to get indexes: %d", ret);
return ret;
}
// bis_index = (uint8_t)atoi(argv[4]);
// ret = lc3_streamer_stream_close(lc3_stream_infos[big_index][sub_index].lc3_streamer_idx[bis_index]);
// if (ret) {
// shell_error(shell, "Failed to close stream: %d", ret);
// return ret;
// }
if (!is_number(argv[4])) {
shell_error(shell, "BIS index must be a digit");
return -EINVAL;
}
bis_index = (uint8_t)atoi(argv[4]);
if ((bis_index >= CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) ||
(bis_index >= broadcast_param[big_index].subgroups[sub_index].num_bises)) {
shell_error(shell, "BIS index %d is out of range (max %d)", bis_index,
broadcast_param[big_index].subgroups[sub_index].num_bises - 1);
return -EINVAL;
}
char *file_name = argv[1];
LOG_DBG("Selecting file %s for stream big: %d sub: %d bis: %d", file_name, big_index,
sub_index, bis_index);
struct bt_audio_codec_cfg *codec_cfg =
&broadcast_param[big_index].subgroups[sub_index].group_lc3_preset.codec_cfg;
struct lc3_stream_cfg cfg;
ret = le_audio_freq_hz_get(codec_cfg, &cfg.sample_rate_hz);
if (ret) {
shell_error(shell, "Failed to get frequency: %d", ret);
return ret;
}
ret = le_audio_duration_us_get(codec_cfg, &cfg.frame_duration_us);
if (ret) {
shell_error(shell, "Failed to get frame duration: %d", ret);
}
ret = le_audio_bitrate_get(codec_cfg, &cfg.bit_rate_bps);
if (ret) {
shell_error(shell, "Failed to get bit rate: %d", ret);
}
/* Verify that the file header matches the stream configurationn */
/* NOTE: This will not abort the streamer if the file is not valid, only give a warning */
bool header_valid = lc3_streamer_file_compatible_check(file_name, &cfg);
if (!header_valid) {
shell_warn(shell, "File header verification failed. File may not be compatible "
"with stream config.");
}
ret = lc3_streamer_stream_register(
file_name, &lc3_stream_infos[big_index][sub_index].lc3_streamer_idx[bis_index],
false); // TODO: set this to false and only loop once with a dedicated command
if (ret) {
shell_error(shell, "Failed to register stream: %d", ret);
return ret;
@@ -2603,6 +2955,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_file_cmd,
/* 5 required arguments */
SHELL_CMD_ARG(select, &folder_names, "Select file on SD card",
cmd_file_select, 5, 0),
SHELL_CMD_ARG(select_play_once, &folder_names, "Select file on SD card",
cmd_file_select_play_once, 5, 0),
SHELL_CMD_ARG(stream_close, &folder_names, "Select file on SD card",
cmd_stream_close, 4, 0),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(
@@ -2617,6 +2973,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
configuration_cmd, SHELL_COND_CMD(CONFIG_SHELL, list, NULL, "List presets", cmd_list),
SHELL_COND_CMD(CONFIG_SHELL, start, NULL, "Start broadcaster", cmd_start),
SHELL_COND_CMD(CONFIG_SHELL, stop, NULL, "Stop broadcaster", cmd_stop),
SHELL_COND_CMD(CONFIG_SHELL, start_idx, NULL, "Start broadcaster with index", cmd_start_idx),
SHELL_COND_CMD(CONFIG_SHELL, source_disable, NULL, "Disable broadcast source", cmd_broadcast_source_disable),
SHELL_COND_CMD(CONFIG_SHELL, source_enable, NULL, "Enable broadcast source", cmd_broadcast_source_enable),
SHELL_COND_CMD(CONFIG_SHELL, stream_close, NULL, "Close lc3 stream", cmd_stream_close),
SHELL_COND_CMD(CONFIG_SHELL, en_usb_mass, NULL, "Enable usb mass storage device", cmd_usb_mass_enable),
SHELL_COND_CMD(CONFIG_SHELL, show, NULL, "Show current configuration", cmd_show),
SHELL_COND_CMD(CONFIG_SHELL, packing, NULL, "Set type of packing", cmd_packing),
SHELL_COND_CMD(CONFIG_SHELL, preset, NULL, "Set preset", cmd_preset),
+3 -3
View File
@@ -19,9 +19,9 @@ CONFIG_BT_ISO_BROADCASTER=y
CONFIG_BT_ISO_SYNC_RECEIVER=n
CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_ADV_SET=2
CONFIG_BT_EXT_ADV_MAX_ADV_SET=2
CONFIG_BT_CTLR_ADV_ISO_SET=2
CONFIG_BT_CTLR_ADV_SET=5
CONFIG_BT_EXT_ADV_MAX_ADV_SET=5
CONFIG_BT_CTLR_ADV_ISO_SET=5
CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT=8
CONFIG_BT_MAX_CONN=1