cancel
Showing results for 
Search instead for 
Did you mean: 

Receiver unable to properly connect/sync with transmitter BIS and play selected audio streams.

jeevanmv1998
Associate II

hi

 

1. Your STM32WBA55G-DK1 with BLE_Audio_TMAP_Peripheral

  • The TMAP (Telephony and Media Audio Profile) example in the STM32 WBA SDK has different roles.

  • In your case, the BLE_Audio_TMAP_Peripheral project is designed as a TMAP Sink/Peripheral device (meaning it receives Auracast™ / BIS streams).

  • So your STM32WBA55G-DK1 is the Receiver (Sink).

2. Your nRF5340 Audio DK

  • You are running the nRF5340 Audio DK in “Broadcast Source / Transmitter” role.

  • That means it is sending audio over BIS (Broadcast Isochronous Streams).

  • In your logs:

    LE_AUDIO_EVT_STREAM_0
    LE_AUDIO_EVT_STREAM_1
    ...

    These indicate stream events per BIS index being transmitted.

3. BIS and Subgroups

  • You mentioned Number of BIS = 4, with 2 subgroups.
    Example breakdown:

    • Subgroup 1 → BIS 0 & BIS 1

    • Subgroup 2 → BIS 2 & BIS 3

  • The transmitter (nRF5340) is advertising 4 streams grouped into 2 subgroups.

  • The receiver (STM32WBA) must parse the BASE (Broadcast Audio Stream Endpoint) info and decide:

    • Which subgroup(s) it will sync to.

    • Which BIS index(es) it will actually receive/play.qqqqqqqqqqqqqqqqqqq.png

4. Receiver Role (Your STM32WBA)

  • It scans advertisements from the nRF5340 source.

  • Decodes the BASE → finds available subgroups and BIS indexes.

  • Selects BISes dynamically (you’ll need to implement Select_Suitable_BISes() correctly).

  • Then it synchronizes to the BIG (Broadcast Isochronous Group) and starts receiving audio.


:white_heavy_check_mark: So final answer:

  • STM32WBA55G-DK1 with BLE_Audio_TMAP_Peripheral → Sink/Peripheral (Receiver).

  • nRF5340 Audio DK → Source/Transmitter (Broadcaster).

  • The 4 BIS / 2 subgroups you see in logs are exactly the broadcast streams from nRF5340, which your STM32 board should choose and sync to for playback.


:backhand_index_pointing_right: Do you want me to show you the code changes needed on STM32 receiver side so it automatically picks one BIS (like BIS 0/1 for left/right channel), instead of just logging the broadcast info?

 

 

######################################################################

this is  receiver  side presently i am  try  to implement feature is   once  the receiver side  will syn to transmitter then i need to  select the bis audio  has  the  oled display menau  showing select audio then the receiver  side will  play  the audio 

 

 

  • Receiver side flow you want:

    • Receiver scans & syncs to a transmitter (BIG sync established).

    • Once synced, your OLED menu shows “Select Audio”.

    • User selects a BIS index from the OLED.

    • Receiver starts playing that audio.

  • Your issue right now:

    • You’re not sure what is blocking this behavior (sync is happening, but audio selection/playback isn’t working).

 

Where the issue could be

I’ll break it down step by step:

:small_blue_diamond: 1. BIG Sync Success, but BIS not selected

  • After CAP_Broadcast_StartBIGSync() succeeds, the receiver is synced to BIG, but not yet subscribed to BIS indexes.

  • You must explicitly pass the selected BIS indexes + selected_count to the sync API.

  • If you hardcoded BIS index earlier, but now you want dynamic user selection → you need to stop BIG sync, update BIS selection, and restart OR implement runtime BIS switching.

:small_blue_diamond: 2. OLED menu integration

  • If your OLED shows “Select Audio” before BIG Sync is fully complete, the BIS handle may not be valid yet.

  • Sequence should be:

    • CAP_BROADCAST_BIG_SYNC_EVT → only then show menu.

    • After user chooses → call API again with chosen BIS index.

:small_blue_diamond: 3. Audio path setup

  • Even if BIS subscription works, check if:

    • The audio buffer/decoder is correctly bound to that BIS index.

    • PCM pipeline is reconfigured when switching BIS (some stacks only configure once).

:small_blue_diamond: 4. Encryption/Broadcast Code mismatch

  • If transmitter uses encryption (BAP_BROADCAST_ENCRYPTION enabled) → your receiver must provide the same broadcast code.

  • Wrong code = you’ll sync to BIG, but BIS data won’t decrypt → looks like “no audio”.

 

 

=== Available Languages ===
[0] Subgroup 0 → Language: eng (BIS count: 2)
[1] Subgroup 1 → Language: chi (BIS count: 2)

Select language index: 0
Selected subgroup 0 → BIS count: 2
BIS[0] = 0x01
BIS[1] = 0x02
Success: CAP_Broadcast_StartBIGSync() with 2 BIS

 

 

i am implementation for oled  display to  select the audio  showing  display 

Got it :white_heavy_check_mark:
I’ve gone carefully through your logs and the issue is very clear:

  • Static BIS selection works fine (you hardcode bis_indexes[0] = 0x01; bis_indexes[1] = 0x02;)

  • Dynamic BIS selection is failing: after PA sync, your code doesn’t parse the BASE → subgroup → BIS correctly, so the receiver never proceeds to BIG sync & playback.

  • You want the receiver side to:

    1. Parse the transmitter’s BASE (languages, subgroups, BIS indexes)

    2. Show them on OLED menu (eng/chi etc.)

    3. Allow joystick navigation and selection

    4. Auto-select after 2s if user doesn’t choose

    5. Pass chosen subgroup + BIS indexes dynamically to CAP_Broadcast_StartBIGSync()

    6. Establish BIG sync → Setup codec → Play audio


:magnifying_glass_tilted_right: Why it is “stuck” at PA sync

From your logs:

CAP Event : 0x19 == CAP_BROADCAST_PA_SYNC_ESTABLISHED_EVT
- SyncHandle : 0x00
PA sync established - preparing for language selection


Media(2).jpeg

➡ At this point your code should immediately parse BASE report (CAP Event 0x1A) and show menu.
But currently your implementation only logs PA sync and doesn’t trigger menu + subgroup/BIS parsing.
That’s why it hangs.


:white_heavy_check_mark: Correct Flow for Dynamic BIS Selection (Receiver Side)

  1. Receive PA sync event

    • Trigger Start BASE parsing (CAP_Broadcast_ParseBASEReport()).

    • Extract number of subgroups and BIS per subgroup.

  2. Display Menu (OLED)

    • For each subgroup: map language metadata (0x656e67 = “eng”, 0x636869 = “chi”)

    • Show:

      [0] English (BIS 1,2)
      [1] Chinese (BIS 3,4)
    • Wait joystick input (up/down/select).

  3. Auto-selection Fallback

    • If no joystick press in 2 sec → auto-select subgroup 0 (default language).

  4. Prepare BIS Index Array

    uint8_t bis_indexes[2]; bis_indexes[0] = 0x01;//chosen->pBIS[0].BIS_Index; bis_indexes[1] = 0x02;//chosen->pBIS[1].BIS_Index;



    it was  hard coded bis  selection only in static wise  not  dynamic selection 
  5. Start BIG Sync

    CAP_Broadcast_StartBIGSync(sync_handle, num_bis, bis_indexes);
  6. On BIG_SYNC_ESTABLISHED_EVT (0x1C)

    • Setup ISO data path

    • Start codec

    • Begin playback


 


:white_heavy_check_mark: Key Guarantees in this Implementation

  • Menu appears right after PA sync (0x19 event).

  • Dynamic parsing of BIS indexes from BASE, no hardcoding.

  • Auto-selection prevents deadlock if user doesn’t select.

  • BIG sync + ISO datapath start automatically after selection.

  • Logs for each step → easy debugging.


:backhand_index_pointing_right: Now, I need to confirm from you:
Do you want me to write the full integrated code (including OLED + joystick handling + auto-select timer) for your STM32WBA tmap_app.c, or just the dynamic BIS parsing + selection module so you can hook it into your existing menu system?

11 REPLIES 11
TPITEL
ST Employee

Hi Jeevan,

Just to clarify the situation:

  • You're using a nrf53840 Audio DK as a Broadcast Source with 2 subgroups, 2 BIS per subgroup
  • You try to synchronize to the Broadcast Source with a STM32WBA55G-DK1 with the TMAP_Peripheral app
  • The synchronization stops at "Synchronizing PA" step

Does this summarize your issue ?

If so, could you provide the full logs of the TMAP_Peripheral app when the problem occur ? Did you try to synchronize to the Broadcast Source with another nrf5340 Audio DK to ensure that the Broadcast Source is operational ?

Best Regards,

Tom.

Post edited by ST moderator to be inline with the community rules especially with the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code

Hi,


Here’s a refined project summary that clearly explains your work and the BIS (Broadcast Isochronous Stream) part with English + Chinese subgroups:


Project Summary – BLE Audio Broadcast with Multi-Language BIS

  • Transmitter (nRF5340 Audio DK): Implemented BLE Audio Auracast Broadcast Source, configured with 2 subgroups, each carrying a BIS (Broadcast Isochronous Stream) — one for English and one for Chinese audio.

  • Receiver (STM32WBA55G-DK1): Developed TMAP Sink application to scan, synchronize, and subscribe to broadcast streams dynamically.

  • Dynamic BIS Handling: Integrated logic for dynamic BIS scanning, synchronization, and stream selection, enabling receiver-side choice of language stream.

  • User Interface: Designed OLED display + joystick-based menu for language selection (English/Chinese) and audio stream control.

  • End-to-End Demonstration: Successfully demonstrated real-time BLE Audio playback across Tx–Rx platforms, showing multi-language broadcast working via Auracast.

System Flow:
nRF5340 Audio DK (Tx: English + Chinese BIS) → Auracast Broadcast → STM32WBA55G (Rx) → OLED menu (Language Select) → Audio Out


:backhand_index_pointing_right: Since you mentioned logs are showing 2 subgroups with BIS streams, I can also create a block diagram that shows:

  • Broadcast Source with Subgroup1 (English BIS), Subgroup2 (Chinese BIS)

  • Receiver with BIS scanning + synchronization

  • User selection on OLED → playback.

This  logs  related  to  Transmitter  side/source

--- 5 messages dropped ---                                                      
-- [00:00:47.523,559] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_1
--- 6 messages dropped ---                                                      
-- [00:00:47.542,541] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_0
--- 7 messages dropped ---                                                      
-- [00:00:47.562,530] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_0
--- 6 messages dropped ---                                                      
-- [00:00:47.580,993] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_1
--- 5 messages dropped ---                                                      
-- [00:00:47.593,566] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_1
--- 6 messages dropped ---                                                      
-- [00:00:47.612,548] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_0
--- 7 messages dropped ---                                                      
-- [00:00:47.632,537] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_0
--- 6 messages dropped ---                                                      
-- [00:00:47.650,970] <dbg> main: le_audio_msg_sub_thread: LE_AUDIO_EVT_STREAM_1

 

  Receiver  side for  static


Current Behavior (Hardcoded BIS)

  • On receiving a BIGINFO report, your sink app checks available subgroups.

  • You manually hardcoded BIS indexes (0x03, 0x04 for English OR 0x01, 0x02 for Chinese).

  • Only one subgroup (one language) can be synced at a time.

  • This works fine → only one audio stream (English or Chinese) plays at once.


Key Points in Your Code

  1. Subgroup selection (language choice):

    uint8_t chosen_subgroup = APP_SelectLanguage(TMAPAPP_Context.BSNK.base_group.NumSubgroups);
    BAP_BASE_Subgroup_t *chosen = &TMAPAPP_Context.BSNK.base_subgroups[chosen_subgroup];

    → You already have a mechanism to ask/select which subgroup (language) to use.

  2. BIS Index assignment (currently hardcoded):

    uint8_t bis_indexes[2];
    bis_indexes[0] = 0x03;  // English BIS
    bis_indexes[1] = 0x04;  // English BIS

    OR

    uint8_t bis_indexes[2];
    bis_indexes[0] = 0x01;  // Chinese BIS
    bis_indexes[1] = 0x02;  // Chinese BIS

    → This is where you hardcode either English or Chinese.

  3. Start BIG Sync:

    status = CAP_Broadcast_StartBIGSync(
        BIG_HANDLE,
        data->SyncHandle,
        bis_indexes,
        2u, // stereo (2 BIS)
        &(TMAPAPP_Context.BSNK.base_group),
        0u,
        BAP_BROADCAST_ENCRYPTION,
        aAPP_BroadcastCode,
        BIG_MSE,
        BIG_SYNC_TIMEOUT
    );

    → Works fine once you fix BIS indexes manually.


Why only static selection works now?

  • You’re not yet parsing BIS indexes dynamically from the subgroup (chosen->pBIS[x].BIS_Index).

  • Instead, you hardcoded fixed values (0x01/0x02 or 0x03/0x04).

  • That’s why it only plays one hardcoded language at a time.


:white_heavy_check_mark: So right now:

  • Your receiver supports only static (hardcoded) BIS selection.

  • It works fine for one subgroup (English or Chinese).

  • But dynamic user-based selection from logs (pBIS array) is not implemented yet.

 

this is the code

this  is the code  for  hardcoded for  this

case CAP_BROADCAST_BIGINFO_REPORT_EVT:
{
if ((TMAPAPP_Context.BSNK.BIGSyncState == APP_BIG_SYNC_STATE_IDLE) &&
(TMAPAPP_Context.BroadcastMode == APP_BROADCAST_MODE_SINK_ONLY))
{
uint8_t status;
BAP_BIGInfo_Report_Data_t *data = (BAP_BIGInfo_Report_Data_t *) pNotification->pInfo;

LOG_INFO_APP(">>== CAP_BROADCAST_BIGINFO_REPORT_EVT\r\n");
LOG_INFO_APP(" Subgroups available: %d\r\n",
TMAPAPP_Context.BSNK.base_group.NumSubgroups);

/* ==========================
* Step 1: Ask user which subgroup (language) to use
* ========================== */
uint8_t chosen_subgroup = APP_SelectLanguage(TMAPAPP_Context.BSNK.base_group.NumSubgroups);

/* ==========================
* Step 2: Extract BIS indexes from chosen subgroup
* ========================== */
BAP_BASE_Subgroup_t *chosen = &TMAPAPP_Context.BSNK.base_subgroups[chosen_subgroup];

if (chosen->NumBISes < 2)
{
LOG_INFO_APP(" Error: subgroup has less than 2 BIS\r\n");
break;
}

uint8_t bis_indexes[2];
bis_indexes[0] = 0x03;//chosen->pBIS[0].BIS_Index;
bis_indexes[1] = 0x04;//chosen->pBIS[1].BIS_Index;



//uint8_t bis_indexes[2];
//bis_indexes[0] = 0x01;//chosen->pBIS[0].BIS_Index;
//bis_indexes[1] = 0x02;//chosen->pBIS[1].BIS_Index;

LOG_INFO_APP(" Selected subgroup %d with BIS indexes: 0x%02X, 0x%02X\r\n",
chosen_subgroup, bis_indexes[0], bis_indexes[1]);

/* ==========================
* Step 3: Start BIG Sync
* ========================== */
LOG_INFO_APP(" CAP_Broadcast_StartBIGSync() function for 2 BISes\r\n");

status = CAP_Broadcast_StartBIGSync(BIG_HANDLE,
data->SyncHandle,
bis_indexes,
2u, // stereo always 2
&(TMAPAPP_Context.BSNK.base_group),
0u,
BAP_BROADCAST_ENCRYPTION,
aAPP_BroadcastCode,
BIG_MSE,
BIG_SYNC_TIMEOUT);

if (status != BLE_STATUS_SUCCESS)
{
LOG_INFO_APP(" Fail : CAP_Broadcast_StartBIGSync() result: 0x%02X\r\n", status);
}
else
{
LOG_INFO_APP(" Success: CAP_Broadcast_StartBIGSync()\r\n");
TMAPAPP_Context.BSNK.BIGSyncState = APP_BIG_SYNC_STATE_SYNCHRONIZING;
Menu_SetBISSyncPage();
}
}
break;
}

logs

preseny iwhat exctally getting logs i am sharing and need prefect impneation i need code has above infomation CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
[APP_MENU_CONF] Selected device 0
==>> Starting Broadcasting DiscoveryDevice with Source 25:E0:2D:52:D2:FC
Success: CAP_Broadcast_StartPASync() function
PBPAPP_SyncToPA() returns status 0x00
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 25:E0:2D:52:D2:FC
CAP Event : 0x19
>>== CAP_BROADCAST_PA_SYNC_ESTABLISHED_EVT
- SyncHandle : 0x00
Success: CAP_Broadcast_StopAdvReportParsing() function
Success: aci_gap_terminate_gap_proc() function
>>== ACI_GAP_PROC_COMPLETE_VSEVT_CODE
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
==>> Start BAP BSNK Parse BASE Group INFO
Payload Len role : 0x66
Presentation_delay: 0x00009c40
Num_subgroups : 0x02
BAP_BSNK_ParseBASESubgroup INFO Number :0
Codec ID : 0x00000000
Codec specific config length : 16 bytes
Length: 0x02
Type: 0x01
Value: 0x05
Length: 0x02
Type: 0x02
Value: 0x01
Length: 0x05
Type: 0x03
Value: 0x03000000
Length: 0x03
Type: 0x04
Value: 0x3c00
Metadata length : 9 bytes
Length: 0x03
Type: 0x02
Value: 0x0400
Length: 0x04
Type: 0x04
Value: 0x656e67
Num_BIS : 2
BIS INDEX : 0x01
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x01000000
Audio Channels Allocation Configuration : 0x00000001
Number of Audio Channels 1
BIS INDEX : 0x02
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x02000000
Audio Channels Allocation Configuration : 0x00000002
Number of Audio Channels 1
BAP_BSNK_ParseBASESubgroup INFO Number :1
Codec ID : 0x00000000
Codec specific config length : 16 bytes
Length: 0x02
Type: 0x01
Value: 0x05
Length: 0x02
Type: 0x02
Value: 0x01
Length: 0x05
Type: 0x03
Value: 0x03000000
Length: 0x03
Type: 0x04
Value: 0x3c00
Metadata length : 9 bytes
Length: 0x03
Type: 0x02
Value: 0x0400
Length: 0x04
Type: 0x04
Value: 0x636869
Num_BIS : 2
BIS INDEX : 0x03
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x01000000
Audio Channels Allocation Configuration : 0x00000001
Number of Audio Channels 1
BIS INDEX : 0x04
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x02000000
Audio Channels Allocation Configuration : 0x00000002
Number of Audio Channels 1
==>> End Start BAP BSNK Parse BASE Group INFO
==>> Audio Clock with Sample Frequency Type 0x05 Initialization
Audio Clock Initialization
RCC AS is now properly initialized
CAP Event : 0x1B
>>== CAP_BROADCAST_BIGINFO_REPORT_EVT
Subgroups available: 2

=== Available Languages ===
[0] Subgroup 0 → Language: eng (BIS count: 2)
[1] Subgroup 1 → Language: chi (BIS count: 2)
Select language index: Selected subgroup 0 with BIS indexes: 0x01, 0x02
CAP_Broadcast_StartBIGSync() function for 2 BISes
Success: CAP_Broadcast_StartBIGSync()
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
CAP Event : 0x1B
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
CAP Event : 0x1B
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
CAP Event : 0x1B
>>== ISOCHRONOUS_GROUP_EVENT
- Opcode: 0x001D
- big_handle: 0x00
- iso_interval: 0x0008
==>> AUDIO_RegisterGroup()
CAP Event : 0x1C
>>== CAP_BROADCAST_BIG_SYNC_ESTABLISHED_EVT
- Status = 0x00
- BIG_Handle = 0x00
- Num BISes = 2
Success: CAP_Broadcast_StopPASync() function
==>> Start APP_BroadcastSetupAudio function
Controller delay chosen to 39990 us
Expecting application to respect the delay of 10 us
==>> CODEC Configure Data Path with following parameters:
Direction : 1
Data Path ID : 0x01
Sample Depth : 16
Decimation : 2
==>> CODEC_ConfigureDataPath() : Success
==>> CODEC Setup ISO Data Path for CIS Connection Handle 0x000B
==>> CODEC_SetupIsoDataPath() : Success
==>> CODEC Setup ISO Data Path for CIS Connection Handle 0x000C
==>> CODEC_SetupIsoDataPath() : Success
CAP Event : 0x1F
>>== CAP_BROADCAST_AUDIO_UP_EVT
Success: CAP_Broadcast_SetupAudioDataPath() function
==>> End APP_BroadcastSetupAudio function
[APP_MENU_CONF] Volume+
CAP Event : 0x3E
Volume Control Meta Event 0x00 is received on ConnHandle 0x0000:
Updated Volume State :
Volume Setting : 138
Mute : 0
Change Counter : 1
VCP_RENDER_SetAbsVolume() with volume 138 returns status 0x00
[APP_MENU_CONF] Volume+
CAP Event : 0x3E
Volume Control Meta Event 0x00 is received on ConnHandle 0x0000:
Updated Volume State :
Volume Setting : 148
Mute : 0
Change Counter : 2
VCP_RENDER_SetAbsVolume() with volume 148 returns status 0x00
[APP_MENU_CONF] Volume-
CAP Event : 0x3E
Volume Control Meta Event 0x00 is received on ConnHandle 0x0000:
Updated Volume State :
Volume Setting : 138
Mute : 0
Change Counter : 3
VCP_RENDER_SetAbsVolume() with volume 138 returns status 0x00
[APP_MENU_CONF] Volume Mute
CAP Event : 0x3E
Volume Control Meta Event 0x00 is received on ConnHandle 0x0000:
Updated Volume State :
Volume Setting : 138
Mute : 1
Change Counter : 4
VCP_RENDER_SetMuteState() returns status 0x00

 

Dynamic bis selection   related  to 

Project Summary – BLE Audio Broadcast with Multi-Language BIS

  • Transmitter (nRF5340 Audio DK): Implemented BLE Audio Auracast Broadcast Source, configured with 2 subgroups, each carrying a BIS (Broadcast Isochronous Stream) — one for English and one for Chinese audio.

  • Receiver (STM32WBA55G-DK1): Developed TMAP Sink application to scan, synchronize, and subscribe to broadcast streams dynamically.

  • Dynamic BIS Handling: Integrated logic for dynamic BIS scanning, synchronization, and stream selection, enabling receiver-side choice of language stream.

  • User Interface: Designed OLED display + joystick-based menu for language selection (English/Chinese) and audio stream control.

  • End-to-End Demonstration: Successfully demonstrated real-time BLE Audio playback across Tx–Rx platforms, showing multi-language broadcast working via Auracast.

Feature: Dynamic BIS Selection with OLED & Joystick

1. What the feature does

  • When the receiver (STM32WBA55G-DK1) synchronizes with the transmitter (nRF5340 Audio DK):

    • The OLED shows a menu of available BIS indexes (audio streams).

    • Using the joystick, the user can navigate and select which BIS audio to play.

    • Once selected, the receiver syncs to the chosen BIS and plays the audio.


2. Core Workflow

  1. Transmitter broadcasts BIG with multiple BIS indexes.

  2. Receiver discovers BIG → gets BIS list.

  3. Menu on OLED shows BIS indexes dynamically.

  4. Joystick input updates selected BIS index.

  5. Receiver calls CAP_Broadcast_StartBIGSync() with the selected BIS index.

  6. Audio starts streaming from the chosen BIS.

 

 

 

4. OLED + Joystick Integration

  • OLED:

    • Used to render BIS menu with highlighted current selection.

    • Shows “Now Playing: BIS X” after selection.

  • Joystick:

    • Provides menu navigation.

    • Event mapping:

      • UP/DOWN → change highlighted BIS.

      • OK → confirm BIS.

      • BACK → return to main menu.

files changed  code here has  per  my requirement

  • tmap_app.c/h = BLE Audio logic + BIS sync function updates.

  • app_menu_cfg.c/h = Menu tree config for OLED (BIS entries).

  • app_menu.c/h = UI drawing + joystick handling.

now  i am sharing  logs:

CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 1C:6E:B4:16:9F:40
[APP_MENU_CONF] Selected device 0
==>> Starting Broadcasting DiscoveryDevice with Source 1C:6E:B4:16:9F:40
Success: CAP_Broadcast_StartPASync() function
PBPAPP_SyncToPA() returns status 0x00
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 1C:6E:B4:16:9F:40
CAP Event : 0x18
>>== CAP_BROADCAST_SOURCE_ADV_REPORT_EVT
- Broadcasting Device with address 1C:6E:B4:16:9F:40
CAP Event : 0x19
>>== CAP_BROADCAST_PA_SYNC_ESTABLISHED_EVT
- SyncHandle : 0x00
Success: CAP_Broadcast_StopAdvReportParsing() function
Success: aci_gap_terminate_gap_proc() function
>>== ACI_GAP_PROC_COMPLETE_VSEVT_CODE
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
==>> Start BAP BSNK Parse BASE Group INFO
Payload Len role : 0x66
Presentation_delay: 0x00009c40
Num_subgroups : 0x02
BAP_BSNK_ParseBASESubgroup INFO Number :0
Codec ID : 0x00000000
Codec specific config length : 16 bytes
Length: 0x02
Type: 0x01
Value: 0x05
Length: 0x02
Type: 0x02
Value: 0x01
Length: 0x05
Type: 0x03
Value: 0x03000000
Length: 0x03
Type: 0x04
Value: 0x3c00
Metadata length : 9 bytes
Length: 0x03
Type: 0x02
Value: 0x0400
Length: 0x04
Type: 0x04
Value: 0x656e67
Num_BIS : 2
BIS INDEX : 0x01
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x01000000
Audio Channels Allocation Configuration : 0x00000001
Number of Audio Channels 1
BIS INDEX : 0x02
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x02000000
Audio Channels Allocation Configuration : 0x00000002
Number of Audio Channels 1
BAP_BSNK_ParseBASESubgroup INFO Number :1
Codec ID : 0x00000000
Codec specific config length : 16 bytes
Length: 0x02
Type: 0x01
Value: 0x05
Length: 0x02
Type: 0x02
Value: 0x01
Length: 0x05
Type: 0x03
Value: 0x03000000
Length: 0x03
Type: 0x04
Value: 0x3c00
Metadata length : 9 bytes
Length: 0x03
Type: 0x02
Value: 0x0400
Length: 0x04
Type: 0x04
Value: 0x636869
Num_BIS : 2
BIS INDEX : 0x03
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x01000000
Audio Channels Allocation Configuration : 0x00000001
Number of Audio Channels 1
BIS INDEX : 0x04
Codec specific config length : 6 bytes
Length: 0x05
Type: 0x03
Value: 0x02000000
Audio Channels Allocation Configuration : 0x00000002
Number of Audio Channels 1
==>> End Start BAP BSNK Parse BASE Group INFO
==>> Audio Clock with Sample Frequency Type 0x05 Initialization
Audio Clock Initialization
RCC AS is now properly initialized
CAP Event : 0x1B
>>== CAP_BROADCAST_BIGINFO_REPORT_EVT
Subgroups available: 2

=== Available Languages ===
[0] Subgroup 0 → Language: eng (BIS count: 2)
[1] Subgroup 1 → Language: chi (BIS count: 2)
Select language index: Selected subgroup 0 with BIS indexes: 0x01, 0x02
CAP_Broadcast_StartBIGSync() function for 2 BISes
Success: CAP_Broadcast_StartBIGSync()
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
CAP Event : 0x1B
CAP Event : 0x1A
>>== CAP_BROADCAST_BASE_REPORT_EVT
CAP Event : 0x1B
>>== ISOCHRONOUS_GROUP_EVENT
- Opcode: 0x001D
- big_handle: 0x00
- iso_interval: 0x0008
==>> AUDIO_RegisterGroup()
CAP Event : 0x1C
>>== CAP_BROADCAST_BIG_SYNC_ESTABLISHED_EVT
- Status = 0x00
- BIG_Handle = 0x00
- Num BISes = 2
Success: CAP_Broadcast_StopPASync() function
==>> Start APP_BroadcastSetupAudio function
Controller delay chosen to 39990 us
Expecting application to respect the delay of 10 us
==>> CODEC Configure Data Path with following parameters:
Direction : 1
Data Path ID : 0x01
Sample Depth : 16
Decimation : 2
==>> CODEC_ConfigureDataPath() : Success
==>> CODEC Setup ISO Data Path for CIS Connection Handle 0x000B
==>> CODEC_SetupIsoDataPath() : Success
==>> CODEC Setup ISO Data Path for CIS Connection Handle 0x000C
==>> CODEC_SetupIsoDataPath() : Success
CAP Event : 0x1F
>>== CAP_BROADCAST_AUDIO_UP_EVT
Success: CAP_Broadcast_SetupAudioDataPath() function
==>> End APP_BroadcastSetupAudio function

 

regrads,

JEEVAN MV

Hi Jeevan,

I understand your project but I still don't understand what's the blocking point.

According to you logs, the app successfully synchronizes to your broadcast source and should be receiving the audio. Are you sure your nrf5340 is actually broadcasting audio over the first 2 BIS ? What do you see on the OLED screen of the STM32WBA DK ?

Regards,

Tom.

 

 

Can we implement OLED display + joystick for audio selection, sync, and play?

 

The STM32WBA55G DK has enough resources (OLED + joystick + BLE stack) to handle dynamic BIS selection at runtime.
But your current problem is you are stuck at PA sync, so the flow never reaches the audio selection menu.

Media(2).jpeg

1. What you see on OLED right now

  • When the receiver DK (STM32WBA55G) is scanning and trying to sync with the transmitter (nRF5340 Audio DK),
    the OLED shows:

    Synchronizing PA... not  process  to  next step  for process
  • (A) Sync stuck at PA

    • The receiver is able to detect advertisements from the transmitter, but it gets stuck at Periodic Advertisement (PA) sync.

  • (B) UI (OLED + joystick) integration

    • You are trying to let the user choose between 2 BIS audio streams (example: English / Chinese).

    • You already updated:

      • tmap_app.c/h → to call BIS sync logic.

      • app_menu_cfg.c/h → added BIS entries (English, Chinese).

      • app_menu.c/h → joystick handling + OLED drawing.

    • But right now, the UI is not linked properly with BIS sync logic: i  write 

 

3. Typical expected flow (working case)

Here’s how it should work on OLED if things are correct:

  1. Receiver scanning

    Found Broadcast Source
    Synchronizing PA...                   actually  i am  struck in
  2. Once PA sync is successful:
    1. Select Audio:
      -> English
      Chinese
      (Joystick to move, press to select)
  3. After selection:
    1. Syncing BIS: English
  4. Once BIS sync complete:

                   Playing: English

 


Do you want me to map these functions to actual files (tmap_app.c/h, app_menu.c/h, app_menu_cfg.c/h) so you’ll know which function belongs where in your project? are any other  files need to  change we  need  to work  on it ?

Functionality File Functions / Notes

BLE & Audio Coretmap_app.c/hInit, PA sync, BIG sync, Audio Start/Stop, Event handlers
Menu / OLED / Joystickapp_menu.c/hMenu init, display sources, handle input, select BIS
Menu Configurationapp_menu_cfg.c/hStatic menu items, mapping, labels, constants
   
   
   

 

 

The screen says that you are stuck at the Periodic Advertising Synchronization step but according to your logs that is incorrect. In your logs you can see  "Success: CAP_Broadcast_StartBIGSync()" which in the original source code of the app would be followed by "Menu_SetBISSyncPage" that would update the screen to the next step. Is this function actually called in your project ?

Everything in the log is fine so I would say this is probably a display issue.

Regards,

Tom.

Hi Tom,

Can you please suggest me where to call "Menu_SetBISSyncPage" this function?

My nRF board is broadcasting successfully. But I got blocked at this stage.

Regards,
Jeevan

Menu_SetBISSyncPage permits to display the menu page "Synchronizing BIS" so it should be called at the moment the app starts synchronizing to the BIS which is right after the call to CAP_Broadcast_StartBIGSync. You can check the base TMAP_Peripheral application as an example.

Regards,

Tom.

Got it. But my problem is It should display the Languages(BIS's) before synchronizing to the BIS. So that user can select the language, according to the selected language receiver can sync to that BIS. It is working fine if I gave the BIS's statically. How can I add the language menu on the display? to select by the user.

Regards,
Jeevan

You would need to understand and edit the app_menu_cfg.c file, which contains the user menu displayed on the LCD. You need to create a new page of type LIST, populate it with the languages available from your stream and assign actions to it. You can check how it is done for the p_broadcast_menu which is populated by the Broadcast Sources scanned and initiate synchronization when selecting an entry.

By the way, we are currently in the process of publishing a Github repository with 2 projects that fit your needs: a PBP Source with multiple languages and a TMAP Peripheral that synchronizes to one language and allows to switch between available languages. It should be available in a few weeks if you can wait until then.

Regards,

Tom.