Skip to content

Commit 5a04e98

Browse files
koffesrlubos
authored andcommitted
Applications: nrf5340_audio: Timestamp and seq_num added
OCT-2864 Timestamps and sequence numbers are now used. Signed-off-by: Kristoffer Rist Skøien <[email protected]>
1 parent d59993d commit 5a04e98

File tree

2 files changed

+86
-63
lines changed

2 files changed

+86
-63
lines changed

applications/nrf5340_audio/src/audio/audio_datapath.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL);
4848
#define MAX_FIFO_SIZE (FIFO_NUM_BLKS * BLK_SIZE_SAMPLES(CONFIG_AUDIO_SAMPLE_RATE_HZ) * 2)
4949

5050
/* Number of audio blocks given a duration */
51-
#define NUM_BLKS(d) ((d) / BLK_PERIOD_US)
51+
#define NUM_BLKS(d) ((d) / BLK_PERIOD_US)
5252
/* Single audio block size in number of samples (stereo) */
53+
/* clang-format off */
5354
#define BLK_SIZE_SAMPLES(r) (((r)*BLK_PERIOD_US) / 1000000)
55+
/* clang-format on */
5456
/* Increment sample FIFO index by one block */
55-
#define NEXT_IDX(i) (((i) < (FIFO_NUM_BLKS - 1)) ? ((i) + 1) : 0)
57+
#define NEXT_IDX(i) (((i) < (FIFO_NUM_BLKS - 1)) ? ((i) + 1) : 0)
5658
/* Decrement sample FIFO index by one block */
57-
#define PREV_IDX(i) (((i) > 0) ? ((i)-1) : (FIFO_NUM_BLKS - 1))
59+
#define PREV_IDX(i) (((i) > 0) ? ((i)-1) : (FIFO_NUM_BLKS - 1))
5860

5961
#define NUM_BLKS_IN_FRAME NUM_BLKS(CONFIG_AUDIO_FRAME_DURATION_US)
6062
#define BLK_MONO_NUM_SAMPS BLK_SIZE_SAMPLES(CONFIG_AUDIO_SAMPLE_RATE_HZ)
@@ -72,17 +74,19 @@ LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL);
7274
#define APLL_FREQ_MIN 36834
7375
#define APLL_FREQ_MAX 42874
7476
/* Use nanoseconds to reduce rounding errors */
77+
/* clang-format off */
7578
#define APLL_FREQ_ADJ(t) (-((t)*1000) / 331)
79+
/* clang-format on */
7680

7781
#define DRIFT_MEAS_PERIOD_US 100000
7882
#define DRIFT_ERR_THRESH_LOCK 16
7983
#define DRIFT_ERR_THRESH_UNLOCK 32
8084
/* To get smaller corrections */
8185
#define DRIFT_REGULATOR_DIV_FACTOR 2
8286

83-
/* 4000 us to allow BLE transmission and (host -> HCI -> controller) */
84-
#define JUST_IN_TIME_US (CONFIG_AUDIO_FRAME_DURATION_US - 4000)
85-
#define JUST_IN_TIME_THRESHOLD_US 2000
87+
/* To allow BLE transmission and (host -> HCI -> controller) */
88+
#define JUST_IN_TIME_US (CONFIG_AUDIO_FRAME_DURATION_US - 2500)
89+
#define JUST_IN_TIME_THRESHOLD_US 1500
8690

8791
/* How often to print underrun warning */
8892
#define UNDERRUN_LOG_INTERVAL_BLKS 5000
@@ -785,14 +789,15 @@ static void audio_datapath_i2s_stop(void)
785789
*/
786790
static void audio_datapath_just_in_time_check_and_adjust(uint32_t sdu_ref_us)
787791
{
788-
static int32_t count;
789792
int ret;
793+
static int32_t count;
790794

791795
uint32_t curr_frame_ts = audio_sync_timer_capture();
792796
int diff = curr_frame_ts - sdu_ref_us;
793797

794798
if (count++ % 100 == 0) {
795-
LOG_DBG("Time from last anchor: %d", diff);
799+
LOG_DBG("Time from last anchor: %d us, time to next: %d us", diff,
800+
CONFIG_AUDIO_FRAME_DURATION_US - diff);
796801
}
797802

798803
if ((diff < (JUST_IN_TIME_US - JUST_IN_TIME_THRESHOLD_US)) ||
@@ -802,7 +807,7 @@ static void audio_datapath_just_in_time_check_and_adjust(uint32_t sdu_ref_us)
802807
LOG_WRN("Not able to drop FIFO RX block");
803808
return;
804809
}
805-
810+
LOG_DBG("Dropped block to align with connection interval");
806811
count = 0;
807812
}
808813
}
@@ -831,9 +836,7 @@ static void audio_datapath_sdu_ref_update(const struct zbus_channel *chan)
831836
ctrl_blk.previous_sdu_ref_us = sdu_ref_us;
832837

833838
if (adjust && sdu_ref_us != 0) {
834-
if (IS_ENABLED(CONFIG_BT_LL_ACS_NRF53)) {
835-
audio_datapath_just_in_time_check_and_adjust(sdu_ref_us);
836-
}
839+
audio_datapath_just_in_time_check_and_adjust(sdu_ref_us);
837840
}
838841
} else {
839842
LOG_WRN("Stream not startet - Can not update sdu_ref_us");

applications/nrf5340_audio/src/bluetooth/bt_stream/bt_le_audio_tx/bt_le_audio_tx.c

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,20 @@ struct bt_le_audio_tx_info {
5252
static bool initialized;
5353
static struct bt_le_audio_tx_info tx_info[SRC_STREAM_COUNT];
5454

55+
/**
56+
* @brief Sends audio data over a single BAP stream.
57+
*
58+
* @param data Audio data to send.
59+
* @param size Size of data.
60+
* @param bap_stream Pointer to BAP stream to use.
61+
* @param tx_info Pointer to tx_info struct.
62+
* @param ts_tx Timestamp to send. Note that for some controllers, BT_ISO_TIMESTAMP_NONE
63+
* is used. This timestamp is used to ensure that SDUs are sent in the same
64+
* connection interval.
65+
* @return 0 if successful, error otherwise.
66+
*/
5567
static int iso_stream_send(uint8_t const *const data, size_t size, struct bt_bap_stream *bap_stream,
56-
struct bt_le_audio_tx_info *tx_info)
68+
struct bt_le_audio_tx_info *tx_info, uint32_t ts_tx)
5769
{
5870
int ret;
5971
struct net_buf *buf;
@@ -93,9 +105,15 @@ static int iso_stream_send(uint8_t const *const data, size_t size, struct bt_bap
93105

94106
atomic_inc(&tx_info->iso_tx_pool_alloc);
95107

96-
ret = bt_bap_stream_send(bap_stream, buf, tx_info->iso_tx.seq_num, BT_ISO_TIMESTAMP_NONE);
108+
if (IS_ENABLED(CONFIG_BT_LL_ACS_NRF53)) {
109+
ret = bt_bap_stream_send(bap_stream, buf, tx_info->iso_tx.seq_num,
110+
BT_ISO_TIMESTAMP_NONE);
111+
} else {
112+
ret = bt_bap_stream_send(bap_stream, buf, tx_info->iso_tx.seq_num, ts_tx);
113+
}
114+
97115
if (ret < 0) {
98-
LOG_WRN("Failed to send audio data: %d", ret);
116+
LOG_WRN("Failed to send audio data: %d stream %p", ret, bap_stream);
99117
net_buf_unref(buf);
100118
atomic_dec(&tx_info->iso_tx_pool_alloc);
101119
} else {
@@ -109,9 +127,6 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
109127
uint8_t streams_to_tx)
110128
{
111129
int ret;
112-
uint32_t ts = 0;
113-
bool any_chan_streaming = false;
114-
bool got_tx_sync_ts = false;
115130
size_t data_size_pr_stream = 0;
116131

117132
if (!initialized) {
@@ -143,40 +158,64 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
143158
return -EINVAL;
144159
}
145160

161+
/* When sending data, we always send ts = 0 to the first active transmitting channel.
162+
* The controller will populate with a ts which is fetched using bt_iso_chan_get_tx_sync.
163+
* This timestamp will be submitted to all the other channels in order to place data on all
164+
* channels in the same ISO interval.
165+
*/
166+
167+
uint32_t ts_common = 0;
168+
bool ts_common_acquired = false;
169+
uint32_t common_interval = 0;
170+
146171
for (int i = 0; i < streams_to_tx; i++) {
147-
if (le_audio_ep_state_check(bap_streams[i]->ep, BT_BAP_EP_STATE_STREAMING)) {
148-
any_chan_streaming = true;
149-
150-
if (!got_tx_sync_ts) {
151-
struct bt_iso_chan *iso_chan;
152-
153-
iso_chan = bt_bap_stream_iso_chan_get(bap_streams[i]);
154-
if (iso_chan == NULL) {
155-
LOG_ERR("Unable to get iso chan");
156-
continue;
157-
}
158-
159-
ret = bt_iso_chan_get_tx_sync(iso_chan, &tx_info[i].iso_tx);
160-
if (ret) {
161-
continue;
162-
}
163-
ts = tx_info[i].iso_tx.ts;
164-
got_tx_sync_ts = true;
165-
}
172+
if (!le_audio_ep_state_check(bap_streams[i]->ep, BT_BAP_EP_STATE_STREAMING)) {
173+
/* This bap_stream is not streaming*/
174+
continue;
166175
}
167-
}
168176

169-
if (!any_chan_streaming) {
170-
LOG_DBG("No headset in stream state");
171-
return -ECANCELED;
177+
if (common_interval != 0 && (common_interval != bap_streams[i]->qos->interval)) {
178+
LOG_ERR("Not all channels have the same ISO interval");
179+
return -EINVAL;
180+
}
181+
common_interval = bap_streams[i]->qos->interval;
182+
183+
/* Check if same audio is sent to all channels */
184+
if (enc_audio.num_ch == 1) {
185+
ret = iso_stream_send(enc_audio.data, data_size_pr_stream, bap_streams[i],
186+
&tx_info[i], ts_common);
187+
} else {
188+
ret = iso_stream_send(&enc_audio.data[data_size_pr_stream * i],
189+
data_size_pr_stream, bap_streams[i], &tx_info[i],
190+
ts_common);
191+
}
192+
193+
if (ret) {
194+
/* DBG used here as prints are handled within iso_stream_send */
195+
LOG_DBG("Failed to send to idx: %d stream: %p, ret: %d ", i, bap_streams[i],
196+
ret);
197+
continue;
198+
}
199+
200+
if (!ts_common_acquired) {
201+
ret = bt_bap_stream_get_tx_sync(bap_streams[i], &tx_info[i].iso_tx);
202+
if (ret) {
203+
LOG_WRN("Unable to get tx sync. ret: %d stream: %p", ret,
204+
bap_streams[i]);
205+
return ret;
206+
}
207+
208+
ts_common = tx_info[i].iso_tx.ts;
209+
ts_common_acquired = true;
210+
}
172211
}
173212

174-
if (ts != 0 && got_tx_sync_ts) {
213+
if (ts_common_acquired) {
175214
if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
176215
!IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL)) {
177216
struct sdu_ref_msg msg;
178217

179-
msg.timestamp = ts;
218+
msg.timestamp = ts_common;
180219
msg.adjust = true;
181220

182221
ret = zbus_chan_pub(&sdu_ref_chan, &msg, K_NO_WAIT);
@@ -186,26 +225,6 @@ int bt_le_audio_tx_send(struct bt_bap_stream **bap_streams, struct le_audio_enco
186225
}
187226
}
188227

189-
for (int i = 0; i < streams_to_tx; i++) {
190-
if (le_audio_ep_state_check(bap_streams[i]->ep, BT_BAP_EP_STATE_STREAMING)) {
191-
/* Check if same audio is sent to all channels */
192-
if (enc_audio.num_ch == 1) {
193-
ret = iso_stream_send(enc_audio.data, data_size_pr_stream,
194-
bap_streams[i], &tx_info[i]);
195-
} else {
196-
ret = iso_stream_send(&enc_audio.data[data_size_pr_stream * i],
197-
data_size_pr_stream, bap_streams[i],
198-
&tx_info[i]);
199-
}
200-
201-
if (ret) {
202-
/* DBG used here as prints are handled within iso_stream_send */
203-
LOG_DBG("Failed to send to idx: %d stream: %p, ret: %d ", i,
204-
bap_streams[i], ret);
205-
}
206-
}
207-
}
208-
209228
return 0;
210229
}
211230

@@ -217,6 +236,7 @@ int bt_le_audio_tx_stream_stopped(uint8_t stream_idx)
217236

218237
atomic_clear(&tx_info[stream_idx].iso_tx_pool_alloc);
219238
tx_info[stream_idx].hci_wrn_printed = false;
239+
220240
return 0;
221241
}
222242

0 commit comments

Comments
 (0)