Что мы знаем про BLE 5.3? Это технология беспроводной передачи сжатого звука. Появилась в июле 2021 года. В 2022 появились образцы чипов с реализацией этой технологии. Например SoC nrf5340 от Nordic Semiconductor. Также есть открытые примеры сборок прошивок для передачи звука по BLE-Audio.

Вот ключевые атрибуты технологии BLE Audio:

1--Gateway передает пакеты с временными отметками.

2--Есть режим передачи данных с установкой соединения и без установки соединения

3--Предусмотрена ретрансляция данных

4--Аудиоданные по самому BLE передаются в сжатом виде (encoded audio data). Сжатием занимается программный кодек LC3

5--Частота дискретизации настаивается в интервале 8kHz.....48kHz

6--Битовая скорость 16kBit/s....320kBit/s на канал

7--Возможна двунаправленная передача аудио данных

8--Предусмотрено шифрование аудио трафика

9--Gateway может передавать 2 независимых аудиопотока одновременно (Connected Isochronous Stream (CIS).

Программный кодек LC3 для сжатия звука проприетарный. Цена на него исходники не известна. Однако его предварительно скомпилированная библиотека присутствует в исходниках NRF5 SDK версии 2.1.0.

Аппаратная часть

Есть по меньшей мере две отладочные платы для этой технологии: nRF5340-DK($66.01) nRF5340-ADK($224.03).

nrf5340-ADK ($224.03)
nrf5340-ADK ($224.03)

и nrf5340-DK.

nrf5340-DK($66.01)
nrf5340-DK($66.01)

Сам исходный звук можно брать, например, из USB из NetTop-PC. Вот возможная схема прототипа для отладки.

Топология BLE сети для отладки
Топология BLE сети для отладки

Чтобы работать с SDK от вендора надо ориентироваться в следующих программных технологиях

Технология

Назначение

DeviceTree

Способ передачи аппаратных конфигов сборке

Kconfig

Способ передачи программных конфигов сборке

GDB

Пошаговый отладчик из консоли

DTS

DeviceTree Specification

GCC

Компилятор. Генератор машинного кода (бинаря)

GIT

система контроля версий исходников

west

Утилита для обновления 4х репозиториев (RTOS, Bootloader, HAL, SDK)

Ninja

Утилита для выбора файлов, которые будут переданы компилятору

CMake

Способ авто генерации скриптов для сборки (Ninja, make, IDExml)

nrfx

HAL для nrf микроконтроллеров

VS Code

Какой-то хипстерский текстовый редактор.

MCUboot

Исходники загрузчика

Zephyr RTOS

Операционная система реального времени для MCU(шек)

У Nordic Semiconductor существует пример BLE 5.3 основанный на Zephyr RTOS для микроконтроллера nrf5340. Их пример расположен в папке

C:\ncs\v2.1.0\nrf\applications\nrf5340_audio

и предназначен для парочки плат с названием nrf5340-ADK. В принципе, некоторыми усилиями пример для nrf5340-ADK можно адаптировать для более дешевых плат nrf5340-DK.

Зафиксируем несколько определений.

Понятие

Перевод

Определение

GateWay 

шлюз

Устройство которое транслирует звук в BLE

HeadSet

гарнитура

Устройство которое принимает звук из BLE

В BLE 5.3 два режима CIS и BIS.

Режим

Направления

данных

Соединение

с GateWay 

channels

CIS

двунаправленный

есть

2

BIS

однонаправленный

нет

?

Примеры BLE Audio от вендора основаны на Zephyr RTOS. Поэтому если вы хотите использовать BLE Audio, то тут без вариантов Вам придется разбираться с Zephyr Project.

GateWay в режиме (I2S->BLE 5.3) 

Вот так выглядел прототип GateWay. Плата NRF5340-DK брала звук из I2S от модуля BT1026 и транслировала этот звук в BLE 5.3.

Прототип BLE 5.3 GateWay устройства
Прототип BLE 5.3 GateWay устройства

Про то что такое BT1026 есть отдельный текст https://habr.com/ru/articles/700102/

Чтобы собрать передатчик BLE Audio трафика надо собрать прошивку класса GateWay. В прошивке GateWay есть вот такие потоки

#

Thread name

priority

Stack size

1

ENCODER

-2

6752

2

AUDIO DATAPATH

-1

4096

3

BT RX

-8

2048

4

BT TX

-9

1024

5

syswork

-1

4096

6

shell_rtt

14

8192

7

loggong

14

2048

8

idle

15

2048

9

main

10

8192

Скорее всего вы захотите добавить свой собственный функционал рядом с BLE 5.3. Тогда Вам придется добавить custom поток с наименьшим приоритетом. В Zephyr в значении приоритета, чем выше число, тем меньше приоритет потока.

Код BlueTooth очень чувствителен к жесткому реальному времени. Если вы поставите слишком высокий приоритет вашего custom потока, то в принимаемом звуке Вы будете слышать щелчки. Это значит, что аудио данные теряются.

Gateway обрабатывает данные в приложении. Звуковые данные попадают в модуль синхронизации. Звуковые данные сжимаются LC3 кодеком. Сжатые данные посылаются в Bluetooth LE Host. Bluetooth LE Host отправляет сжатые аудиоданные в подсистему LE Audio Controller Subsystem для nRF53 в сетевом ядре микроконтроллера. Подсистема перенаправляет аудиоданные на аппаратное радио и отправляет их на устройства гарнитуры в соответствии со спецификациями LE Audio.

Gateway может принимать звуковые данные не только из USB, но и из I2S. В случае когда исходные аудио-данные извлекаются из I2S, то нужна фаза синхронизации. Этот модуль гарантирует, что звук воспроизводится одновременно с правильной скоростью.

Synchronization module работает в отдельном потоке. После извлечения звуковых данных полученных из I2S пакеты посылаются в поток сжатия в файле streamctrl.c

Обзор модуля синхронизации

Модуль синхронизации реализован в файле audio_datapath.c. Для синхронизации звука он выполняет следующие типы настроек:

Перевод

Действие

компенсация представления

Presentation compensation

компенсация дрейфа

Drift compensation

Компенсация представления заставляет все гарнитуры воспроизводить звук одновременно синхронно, даже если пакеты, содержащие аудио кадры, не принимаются одновременно на разных гарнитурах. На практике он перемещает блоки аудиоданных в FIFO вперед или назад на несколько блоков, добавляя при необходимости блоки тишины.

Компенсация дрейфа регулирует частоту звуковых часов, чтобы регулировать скорость воспроизведения звука. Это требуется в режиме connected isochronous stream (CIS), где gateway (шлюз) и headsets  должны синхронизировать воспроизведение звука, чтобы обеспечить воспроизведение звука True Wireless Stereo (TWS). Таким образом, компенсация дрейфа обеспечивает как большие настройки в начале, так и непрерывные небольшие настройки синхронизации звука. Компенсация дрейфа противодействует любому дрейфу, вызванному различиями в частотах кварцевых генераторов, используемых в наборах для разработки. В отладочных платах используются кварцевые генераторы для генерации стабильной тактовой частоты тактирования микроконтроллера. В данном случае это X1 32MHz. Однако частота этих кристаллов всегда немного различается. Благодаря компенсации дрейфа интерфейс I2S на headset(ах) работает так же быстро, как прием пакетов Bluetooth. Это предотвращает переполнение или недополнение I2S как в режиме CIS, так и в режиме BIS.

На следующем рисунке показан обзор модуля синхронизации.

Обзор модуля аудио синхронизации nRF5340
Обзор модуля аудио синхронизации nRF5340

Оба метода синхронизации используют эталонные временные метки SDU (sdu_ref) в качестве эталонной переменной. Если устройство является шлюзом, который использует I2S в качестве источника звука, а поток является однонаправленным (от шлюза к гарнитурам), sdu_ref постоянно извлекается из LE Audio Controller Subsystem для nRF5340 на шлюзе. Извлечение происходит внутри функции отправки файлов le_audio_cis_gateway.c и le_audio_bis_gateway.c. Затем значения sdu_ref отправляются в модуль синхронизации шлюза и используются для компенсации дрейфа.

Поскольку nRF5340 является двухъядерным SoC, то обоим ядрам (App Core, Net Core) требуется одинаковая концепция времени, каждое ядро запускает автономный аппаратный таймер в бесконечном цикле. Эти два аппаратных таймера сбрасываются одновременно и работают от одного и того же источника частоты. Это означает, что два таймера всегда должны показывать одни и те же числовые значения для одних и тех же моментов времени.
Net core nRF5340, на котором работает LE controller для nRF53, использует свой аппаратный таймер для генерации временной метки sdu_ref для каждого полученного аудио пакета. App core , работающее с аудио приложением nRF5340, использует свой отдельный аппаратный таймер для генерации cur_time и frame_start_ts.

После декомпрессии аудиоданные делятся на более мелкие блоки и добавляются в FIFO. Затем эти блоки непрерывно передаются в I2S, блок за блоком.

На следующем рисунке показаны методы компенсации модуля синхронизации.

Конечный автомат nRF5340 Audio для механизма компенсации
Конечный автомат nRF5340 Audio для механизма компенсации

На компенсацию представления (presentation compensation ) могут повлиять следующие внешние факторы:

-- Компенсация дрейфа должна быть синхронизирована с заблокированным состоянием (DRIFT_STATE_LOCKED), прежде чем можно будет начать компенсацию презентации. Эта компенсация дрейфа регулирует частоту звуковых часов, указывая, что звук воспроизводится с правильной скоростью. Когда компенсация дрейфа не находится в заблокированном состоянии, компенсация представления не выходит из состояния инициализации (PRES_STATE_INIT). Кроме того, если компенсация дрейфа теряет синхронизацию, выходя из DRIFT_STATE_LOCKED, компенсация презентации возвращается в PRES_STATE_INIT.

-- При воспроизведении аудио ожидается, что новый аудиокадр будет получен в каждом интервале соединения ISO. Если этого не происходит, возможно, гарнитура (headset) потеряла связь со шлюзом (gateway). Когда соединение восстанавливается, приложение получает sdu_ref, не следующий за ранее полученным sdu_ref. Затем компенсация презентации помещается в состояние PRES_STATE_WAIT, чтобы гарантировать, что звук все еще в синхронизации.

Когда и дрейф, и компенсация представления находятся в заблокированном состоянии (DRIFT_STATE_LOCKED и PRES_STATE_LOCKED), загорается светодиод 2.

Какой путь проходят данные в модуле синхронизации?

Полученные аудиоданные из I2S идут по следующему пути:

Порядок

Действие

1

LE Audio Controller Subsystem для nRF53, работающая на сетевом ядре, получает сжатые аудиоданные.

2

Подсистема контроллера отправляет аудиоданные на хост Zephyr Bluetooth LE аналогично примеру Bluetooth: HCI RPMsg. Это межпроцессорный переход.

3

Хост отправляет данные в модуль управления потоком streamctrl.c

4

Данные отправляются в буфер FIFO.

5

Данные отправляются из буфера FIFO в модуль синхронизации audio_datapath.c. Модуль audio_datapath.c выполняет аудиосинхронизацию на основе эталонных временных меток SDU. Каждый пакет, отправленный со шлюза, получает уникальную временную метку SDU. Эти метки времени генерируются на контроллерах гарнитуры (в ядре сети). Это позволяет создавать наушники True Wireless Stereo (TWS), в которых звук синхронизируется в режиме CIS. Он также синхронизирует скорость интерфейса I2S со скоростью отправки и получения пакетов Bluetooth.

6

Модуль audio_datapath.c отправляет сжатые аудиоданные в аудиодекодер LC3 для декодирования.

7

Аудио декодер распаковывает данные и отправляет несжатые сырые аудиоданные (PCM) обратно в модуль audio_datapath.c.

8

Модуль audio_datapath.c непрерывно передает несжатые аудиоданные (PCM семплы) аппаратному кодеку.

9

Аппаратный кодек (DAC) получает несжатые аудиоданные через интерфейс I2S и выполняет цифро-аналоговое преобразование (DAC) в аналоговый аудиосигнал.


HeadSet (BLE 5.3->I2S)

Вот так выглядел прототип HeadSet устройства. Звук принимался от BLE 5.3 и воспроизводился через усилитель D класса MAX98357A через 4 Оммный звукоизлучатель.

прототип HeadSet устройства
прототип HeadSet устройства

На стороне HeadSet прошивки вертятся вот эти потоки.

#

Name

priority

stack size

1

AUDIO DATAPATH

4

4096

2

BT RX

-8

2048

3

BT TX

-9

1024

4

sysworkq

-1

4096

5

BT_LW_WQ

10

1304

6

shell_rtt

14

8192

7

shell_uart

14

8192

8

logging

14

2048

9

idle

15

320

10

main

10

4096

Как собрать сборку из сорцов?

Чтобы собрать передатчик BLE Audio трафика (gateway) надо собрать прошивку класса gateway. Для этого надо передать системе сборки макроопределение CONFIG_AUDIO_DEV=2. Скрипт сначала вызывает конфигуратор сборки Cmake затем сам сборщик ninjia.

echo off
cls
set CUR_DIR=%~dp0
echo Cur Dir: [%CUR_DIR%]

call clean.bat

set BOARD=nrf5340dk_nrf5340_cpuapp
set SDK_PROJECT_DIR=%NRF_SDK_DIR%/nrf/applications/nrf5340_dk_audio_w
echo Sdk Project Dir:[%SDK_PROJECT_DIR%]
echo Project Dir:[%PROJECT_DIR%]

set BUILD_DIR=%SDK_PROJECT_DIR%/build/gateway_app
set ARTEFACT_DIR=%CUR_DIR%build
echo BUILD_DIR_=%BUILD_DIR%

cd %SDK_PROJECT_DIR%

cmake %CMAKE_OP% -B%BUILD_DIR% -DBOARD=%BOARD% -GNinja -DCONFIG_AUDIO_DEV=2 -DCONF_FILE="i2s_ble.conf" 
ninja -C %BUILD_DIR%

cd %CUR_DIR%

Net Core

Прошивка для Net core одинаковая как для GateWay так и для HeadSet. Бинарь этой прошивки поставляет сам Vendor (Nordic Semiconductor). Артефакт называется ble5-ctr-rpmsg_3303.hex и лежит в папке C:\ncs\v2.1.0\nrf\applications\nrf5340_dk_audio\bin\

Отладка
Как обычно при отладке прошивки мы первым делом смотрим и анализируем лог загрузки микроконтроллера. Вот лог загрузки gateway

Hidden text


->
->*** Booting Zephyr OS build v3.1.99-ncs1 ***
0.305 :I [?] Init Writer OK0.308 :I [?] Init Log OK
0.311 :I [GPIO] Init
0.314 :I [?] Init Gpio OK
0.318 :I [?] Init Pre OK
0.321 :I [?] Init Clk OK
0.324 :I [SYS] PowerInit..
0.327 :I [?] Init PwrSys OK
0.331 :I [SYS] InitHwConnectivity
0.335 :I [SYS] WireConnectivityInit
0.339 :I [UART] Init..
0.342 :I [UART] Cnt: 2
0.345 :I [UART] 0 Init
0.348 :I [UART] 0 Device found!
Init_UART0
0.353 :I [UART] 0 InitOk!
0.356 :I [UART] 2 Init
0.359 :I [UART] 2 Device found!
0.364 :I [UART] 2 InitOk!
0.367 :I [?] Init UART OK
0.371 :I [I2S] Init Cnt 1
0.468 :I [?] Init I2S OK
0.471 :I [?] Init WireCon OK
0.474 :I [SYS] InitWireLessConnectivity
0.479 :I [?] Init WireLessCon OK
0.483 :I [?] Init HwCon OK
0.486 :I [SYS] StorageHwInit
0.490 :I [?] Init StorageHw OK
0.494 :I [?] Init HW OK
0.497 :I [?] Init Time OK
0.500 :I [SYS] ProtocolsInit
0.504 :I [?] Init Protocol OK
0.507 :I [SYS] TaskInit
0.510 :I [SYS] TaskCnt 2
0.514 :I [SYS] Task ID:0
0.517 :I [SYS] Task ID:1
0.520 :I [?] Init task OK
0.523 :I [SYS] StorageSwInit
0.527 :I [?] Init StorageSw OK
0.531 :I [SYS] SwConnectivityInit
0.535 :I [CLI] All 63 CommandsUnique
0.540 :I [CLI] AllCommandsUnique!
0.544 :I [?] Init Cli OK
0.547 :I [?] Init ConSw OK
0.550 :I [SYS] InitMultimedia
0.554 :I [BT1026] Init
0.557 :I [BT1026] Set I2S config 1
RegVal: 0x01 0b0000_0001
5-6 resolution: 0=16 bit
3-4 format: 0
2 sample_rate: 0=48000
1 role: 0=Master
0 status: 1=On
0.573 :I [?] Init BT1026 OK
0.576 :I [?] Init multimedia OK
0.580 :I [SuperLoop] Init
0.584 :I [?] Init SuperCycle OK
0.587 :I [?] Init SW OK
0.591 :I [?] Init board OK
0.594 :I [?] Init SYS OK
0.597 :I [SYS] init [OK!]
GW [00:00:00.300,079] audio_sync_timer: Audio sync timer initialized
GW [00:00:00.300,811] nrf5340dk_nrf5340_cpuapp: remoteproc_mgr_boot: Network MCU released.
GW [00:00:00.305,084] main: nRF5340 APP core started
GW [00:00:00.601,013] main: InitRes: 1=Ok
GW [00:00:00.601,165] fw_info:
nRF5340 nRF5340 DK cpuapp
NCS Version: 2.1.0
GW [00:00:00.601,165] fw_info: ------- DEBUG BUILD -------
GW [00:00:00.601,165] fw_info:
Compiled for GATEWAY device
GW [00:00:00.601,165] ble: init core
GW [00:00:00.601,196] ble: Failed to create ID
GW [00:00:00.604,217] fs_nvs: 6 Sectors of 4096 bytes
GW [00:00:00.604,217] fs_nvs: alloc wra: 0, f70
GW [00:00:00.604,217] fs_nvs: data wra: 0, 124
GW [00:00:00.613,830] bt_hci_core: Controller to host flow control not support0.706 :I [SYS] StreamCtrlStart
0.710 :I [BLE] Enable
0.713 :I [BLE] Init
0.715 :I [BLE] BT_AUDIO_UNICAST_CLIENT_ASE_SNK_CNT 2
0.721 :I [BLE] initialized:0
ed0.725 :I [BLE] StartScan
0m
GW [00.730 :I [SYS] StartSurepCycle
0:00:00.616,790] bt_hci_core: No ID address. App must call settings_load()
GW [00:00:00.616,790] ble: Bluetooth initialized
GW [00:00:00.616,851] ble: MAC: 00:00:00:00:00:00 (public)
GW [00:00:00.617,401] ble: Controller version: 3303
GW [00:00:00.621,002] main: Clearing all bonds
GW [00:00:00.705,322] audio_system: AudioSysInit
GW [00:00:00.730,834] cis_gateway: Scanning successfully started

->GW [00:00:01.282,562] cis_gateway: Connected: 4E:80:31:F3:BC:B9 (random)
GW [00:00:01.282,562] cis_gateway: Connected: 4E:80:31:F3:BC:B9 (random)
->3.584 :I [BLE] StartScan
GW [00:00:03.587,921] cis_gateway: Scanning successfully started
GW [00:00:03.587,921] cis_gateway: Scanning successfully started
->7.990 :E [BT1026] LackOfLink 7256 ms 5000 ms
GW [00:00:07.984,222] cis_gateway: Stream 0x2000a610 started
GW [00:00:08.005,279] audio_datapath: I2S RX overrun. Single msg
GW [00:00:08.007,263] audio_datapath: I2S RX continuing stream
GW [00:00:08.011,260] audio_datapath: I2S RX overrun. Single msg
GW [00:00:08.012,847] bt_hci_core: opcode 0x2061 status 0x0c
GW [00:00:08.013,275] audio_datapath: I2S RX continuing stream
GW [00:00:08.022,277] audio_datapath: Drft comp state: CALIB
GW [00:00:08.122,283] audio_datapath: Drft comp state: OFFSET
GW [00:00:08.222,290] audio_datapath: Drft comp state: LOCKED
GW [00:00:07.984,222] cis_gateway: Stream 0x2000a610 started
GW [00:00:08.005,279] audio_datapath: I2S RX overrun. Single msg
GW [00:00:08.007,263] audio_datapath: I2S RX continuing stream
GW [00:00:08.011,260] audio_datapath: I2S RX overrun. Single msg
GW [00:00:08.012,847] bt_hci_core: opcode 0x2061 status 0x0c
GW [00:00:08.013,275] audio_datapath: I2S RX continuing stream
GW [00:00:08.022,277] audio_datapath: Drft comp state: CALIB


Лог загрузки устройства headset

Hidden text

->
->*** Booting Zephyr OS build v3.1.99-ncs1 ***
0.260 :I [?] Init Writer OK0.263 :I [?] Init Log OK
0.266 :I [GPIO] Init
0.269 :I [GPIO] TotalPins: 8
0.273 :I [GPIO] SetDirOk Pad:P0.28 Io
0.277 :I [GPIO] SetDirOk Pad:P0.29 Io
0.282 :I [GPIO] SetDirOk Pad:P0.30 Io
0.286 :I [GPIO] SetDirOk Pad:P0.31 Io
0.290 :I [GPIO] SetDirOk Pad:P0.20 Out
0.295 :I [GPIO] SetDirOk Pad:P0.22 In
0.299 :I [GPIO] SetDirOk Pad:P1.3 Out
0.303 :I [GPIO] SetDirOk Pad:P1.2 InOd
0.308 :I [?] Init Gpio OK
0.311 :I [?] Init Pre OK
0.314 :I [?] Init Clk OK
0.318 :I [SYS] PowerInit..
0.321 :I [?] Init PwrSys OK
0.324 :I [SYS] InitHwConnectivity
0.328 :I [SYS] WireConnectivityInit
0.333 :I [UART] Init..
0.336 :I [UART] Cnt: 1
0.339 :I [UART] 0 Init
0.342 :I [UART] 0 Device found!
Init_UART0
0.347 :I [UART] 0 InitOk!
0.350 :I [?] Init UART OK
0.353 :I [I2C] Init
0.356 :I [I2C] 1 Init
0.359 :I [I2C] Init 1 I2Cs
0.362 :I [?] Init I2C OK
0.366 :I [?] Init WireCon OK
0.369 :I [SYS] InitWireLessConnectivity
0.374 :I [?] Init WireLessCon OK
0.378 :I [?] Init HwCon OK
0.381 :I [SYS] StorageHwInit
0.385 :I [?] Init StorageHw OK
0.388 :I [?] Init HW OK
0.391 :I [?] Init Time OK
0.395 :I [HEAP] Init
0.398 :I [?] Init Heap OK
0.401 :I [DAC] Init 1
0.404 :I [DAC] Init 2
0.407 :I [DAC] Init 3
0.410 :I [?] Init DACsw OK
0.413 :I [SYS] ProtocolsInit
0.417 :I [?] Init Protocol OK
0.420 :I [SYS] StorageSwInit
0.424 :I [?] Init StorageSw OK
0.428 :I [SYS] SwConnectivityInit
0.432 :I [CLI] All 47 CommandsUnique
0.436 :I [CLI] AllCommandsUnique!
0.440 :I [?] Init Cli OK
0.443 :I [?] Init ConSw OK
0.447 :I [SYS] InitMultimedia
0.450 :D [WM8731] Spot 10 CfgRegs
-- [00:00:00.255,187] audio_sync_timer: Audio sync timer initialized
-- [00:00:00.255,889] nrf5340dk_nrf5340_cpuapp: remoteproc_mgr_boot: Ne rk MCU released.
-- [00:00:00.260,131] main: nRF5340 APP core started
2.608 :I [?] Init WM8731 OK
2.611 :I [?] Init multimedia OK
2.615 :I [SuperLoop] Init
2.618 :I [?] Init SuperCycle OK
2.622 :I [?] Init SW OK
2.625 :I [?] Init board OK
2.629 :I [?] Init SYS OK
2.632 :I [SYS] init [OK!]
HL [00:00:02.635,711] main: InitRes: 1=Ok
HL [00:00:02.635,864] fw_info:
nRF5340 nRF5340 DK cpuapp
NCS Version: 2.1.0
HL [00:00:02.635,864] fw_info: ------- DEBUG BUILD -------
HL [00:00:02.635,864] fw_info:
HEADSET defaulting to AUDIO_CH_L
HL [00:00:02.635,864] fw_info:
HEADSET left device
HL [00:00:02.635,894] ble: init core
HL [00:00:02.635,894] ble: Failed to create ID
HL [00:00:02.639,038] fs_nvs: 6 Sectors of 4096 bytes
HL [00:00:02.639,068] fs_nvs: alloc wra: 0, f98
HL [00:00:02.639,068] fs_nvs: data wra: 0, 5c
HL [00:00:02.648,742] bt_hci_core: Controller to host flow control not ported
HL [00:00:02.651,733] bt_hci_core: No ID address. App must call setting oad()
HL [00:00:02.651,733] 2.740 :I [SYS] StreamCtrlStart
2.746 :I [SYS] StartSurepCycle
ble: Bluetooth initialized
HL [00:00:02.651,794] ble: MAC: 00:00:00:00:00:00 (public)
HL [00:00:02.652,374] ble: Controller version: 3303
HL [00:00:02.740,112] audio_system: AudioSysInit
HL [00:00:02.748,382] cis_headset: Regular advertising started
HL [00:00:02.635,711] main: InitRes: 1=Ok
HL [00:00:02.635,864] fw_info:
nRF5340 nRF5340 DK cpuapp
NCS Version: 2.1.0
Cmake run : Mon Jan 23 13:47:23 2023
HL [00:00:02.635,864] fw_info: ------- DEBUG BUILD -------
HL [00:00:02.635,864] fw_info:
HEADSET defaulting to AUDIO_CH_L
HL [00:00:02.635,864] fw_info:
HEADSET left device
HL [00:00:02.635,894] ble: init core
HL [00:00:02.635,894] ble: Failed to create ID
HL [00:00:02.639,038] fs_nvs: 6 Sectors of 4096 bytes
HL [00:00:02.639,068] fs_nvs: alloc wra: 0, f98
HL [00:00:02.639,068] fs_nvs: data wra: 0, 5c
HL [00:00:02.648,742] bt_hci_core: Controller to host flow control not ported
HL [00:00:02.651,733] bt_hci_core: No ID address. App must call setting oad()
HL [00:00:02.651,733] ble: Bluetooth initialized
HL [00:00:02.651,794] ble: MAC: 00:00:00:00:00:00 (public)
HL [00:00:02.652,374] ble: Controller version: 3303
HL [00:00:02.740,112] audio_system: AudioSysInit
HL [00:00:02.748,382] cis_headset: Regular advertising started
->HL [00:00:03.900,970] cis_headset: Connected: 7D:32:A4:77:BB:8A (rand
HL [00:00:03.900,970] cis_headset: Connected: 7D:32:A4:77:BB:8A (random
HL [00:00:47.601,806] cis_headset: Disconnected: 7D:32:A4:77:BB:8A (ran dom) (reason 0x08)
HL [00:00:47.603,179] cis_headset: Regular advertising started
HL [00:00:47.813,476] cis_headset: Connected: 7D:A1:F6:47:F9:D0 (random )
HL [00:00:47.601,806] cis_headset: Disconnected: 7D:32:A4:77:BB:8A (ran dom) (reason 0x08)
HL [00:00:47.603,179] cis_headset: Regular advertising started
HL [00:00:47.813,476] cis_headset: Connected: 7D:A1:F6:47:F9:D0 (random )
->HL [00:01:36.014,404] cis_headset: Disconnected: 7D:A1:F6:47:F9:D0 (r andom) (reason 0x08)
HL [00:01:36.015,777] cis_headset: Regular advertising started
HL [00:01:36.231,872] cis_headset: Connected: 78:C5:58:66:A4:70 (random )
HL [00:01:36.014,404] cis_headset: Disconnected: 7D:A1:F6:47:F9:D0 (ran dom) (reason 0x08)
HL [00:01:36.015,777] cis_headset: Regular advertising started
HL [00:01:36.231,872] cis_headset: Connected: 78:C5:58:66:A4:70 (random )
->HL [00:01:41.034,545] cis_headset: Codec config for LC3:
HL [00:01:41.034,545] cis_headset: Frequency: 48000 Hz
HL [00:01:41.034,545] cis_headset: Frame Duration: 10000 us
HL [00:01:41.034,576] cis_headset: Channel allocation: 0x1
HL [00:01:41.034,576] cis_headset: Octets per frame: 120 (96000 kbps)
HL [00:01:41.034,576] cis_headset: Frames per SDU: 1
HL [00:01:41.034,637] bt_gatt: Device is not subscribed to characterist ic
HL [00:01:41.133,239] bt_gatt: Device is not subscribed to characterist ic
HL [00:01:41.348,022] audio_datapath: I2S RX overrun. Single msg
HL [00:01:41.034,545] cis_headset: Codec config for LC3:
HL [00:01:41.034,545] cis_headset: Frequency: 48000 Hz
HL [00:01:41.034,545] cis_headset: Frame Duration: 10000 us
HL [00:01:41.034,576] cis_headset: Channel allocation: 0x1
HL [00:01:41.034,576] cis_headset: Octets per frame: 120 (96000 kbps)
HL [00:01:41.034,576] cis_headset: Frames per SDU: 1
HL [00:01:41.034,637] bt_gatt: Device is not subscribed to characterist ic
HL [00:01:41.133,239] bt_gatt: Device is not subscribed to characterist ic
HL [00:01:41.348,022] audio_datapath: I2S RX overrun. Single msg
->HL [00:01:42.965,972] audio_datapath: Drft comp state: CALIB
HL [00:01:42.967,956] audio_datapath: Data received, total underruns: 1 627
HL [00:01:43.065,979] audio_datapath: Drft comp state: OFFSET
HL [00:01:43.525,390] audio_datapath: Drft comp state: LOCKED
HL [00:01:43.535,064] audio_datapath: Pres comp state: MEAS
HL [00:01:43.645,050] audio_datapath: Pres comp state: WAIT
HL [00:01:43.745,056] audio_datapath: Pres comp state: INIT
HL [00:01:43.755,065] audio_datapath: Pres comp state: MEAS


При успешном подключении по BLE 5.3 Gateway прошивка пишет вот это сообщение в UART TUI. Вот полный лог успешного соединения на стороне gateway устройства.

лог успешного соединения при на стороне gateway устройства.
лог успешного соединения при на стороне gateway устройства.
лог успешного соединения при на стороне gateway устройства.

Сразу после этого можно услышать музыку в наушниках на headset устройстве. Это лог успешной загрузки Ble 5.3 headset устройства

Идеи проектов на основе BLE 5.3:

--Можно сделать рацию по BLE Audio (CIS режим).

--Можно сделать беспроводные наушники/громкоговорители по BLE Audio. Не надо прокладывать электропроводку.

--Можно сделать широковещательную передачу звуковых данных бесчисленному количеству потребителей (BIS режим). Например в лекционных аудиториях, музеях, аэропортах и т п.

Итоги

Удалось научиться собирать прошивки с использованием стандарта беспроводной передачи аудиоданных BLE 5.3 (широковещательное аудио). Удалось научиться добавлять сustom (ный) функционал в виде отдельного bare-bone потока. При передаче 16bit, 48kHz звука по BLE 5.3 звук на слух чисты и понятный. BLE 5.3 в самом деле позволяет реализовать широковещательную трансляцию звука.

Словарь

Акроним

Расшифровка

LC3

Low Complexity Communication codec

SDK

Software Development Kit

HCI

Host Controller Interface

I2S

Inter-IC Sound

PCM

Pulse-code modulation

TWS

True Wireless Stereo

DAC

Digital-to-analog converter

FOTA 

Firmware Over-The-Air

DFU

device firmware update

RPM

Remote Processor Messaging

SDU 

S???? Data Unit

SoC 

System on a chip

BLE

Bluetooth Low Energy

ISO

isochronous channels

BIS

broadcast isochronous stream

CIS

connected isochronous stream

GNU

GNU’s Not UNIX

GCC

GNU Compiler Collection

HAL

hardware abstraction layer

SBC

SubBand Codec

LE

Low Energy

Links/URLs

nRF5340 Audio configuration and testing https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/applications/nrf5340_audio/README.html#nrf53-audio-app

nRF5340 Audio overview and firmware architecture https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/applications/nrf5340_audio/doc/firmware_architecture.html

Основа BlueTooth колонки https://habr.com/ru/articles/700102/

Low Complexity Communication Codec (LC3) https://github.com/google/liblc3

Комментарии (2)


  1. Pitkin_zadov
    25.12.2023 15:01

    1. aabzel Автор
      25.12.2023 15:01

      Это не то. Нужны именно реализации функций API. Например LC3DecodeSessionData