Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2.8-branch] applications: nrf5340_audio: Fix audio sync timer off by one tick #19410

Draft
wants to merge 3 commits into
base: v2.8-branch
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 70 additions & 44 deletions applications/nrf5340_audio/src/modules/audio_sync_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include "audio_sync_timer.h"

#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <nrfx_dppi.h>
Expand All @@ -18,49 +16,69 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(audio_sync_timer, CONFIG_AUDIO_SYNC_TIMER_LOG_LEVEL);

#define AUDIO_SYNC_TIMER_NET_APP_IPC_EVT_CHANNEL 4
#define AUDIO_SYNC_TIMER_NET_APP_IPC_EVT NRF_IPC_EVENT_RECEIVE_4
#include "audio_sync_timer.h"

#define AUDIO_SYNC_TIMER_NET_APP_IPC_START_EVT_CHANNEL 4
#define AUDIO_SYNC_TIMER_NET_APP_IPC_START_EVT NRF_IPC_EVENT_RECEIVE_4

#define AUDIO_SYNC_HF_TIMER_INSTANCE_NUMBER 1

#define AUDIO_SYNC_HF_TIMER_I2S_FRAME_START_EVT_CAPTURE_CHANNEL 0
#define AUDIO_SYNC_HF_TIMER_I2S_FRAME_START_EVT_CAPTURE NRF_TIMER_TASK_CAPTURE0
#define AUDIO_SYNC_HF_TIMER_CURR_TIME_CAPTURE_CHANNEL 1
#define AUDIO_SYNC_HF_TIMER_CURR_TIME_CAPTURE NRF_TIMER_TASK_CAPTURE1

static const nrfx_timer_t audio_sync_hf_timer_instance =
NRFX_TIMER_INSTANCE(AUDIO_SYNC_HF_TIMER_INSTANCE_NUMBER);

static uint8_t dppi_channel_i2s_frame_start;
#define AUDIO_SYNC_HF_TIMER_I2S_FRAME_START_EVT_CAPTURE NRF_TIMER_TASK_CAPTURE0
#define AUDIO_SYNC_HF_TIMER_CURR_TIME_CAPTURE_CHANNEL 1
#define AUDIO_SYNC_HF_TIMER_CURR_TIME_CAPTURE NRF_TIMER_TASK_CAPTURE1

#define AUDIO_SYNC_LF_TIMER_INSTANCE_NUMBER 0

#define AUDIO_SYNC_LF_TIMER_I2S_FRAME_START_EVT_CAPTURE_CHANNEL 0
#define AUDIO_SYNC_LF_TIMER_I2S_FRAME_START_EVT_CAPTURE NRF_RTC_TASK_CAPTURE_0
#define AUDIO_SYNC_LF_TIMER_CURR_TIME_CAPTURE_CHANNEL 1
#define AUDIO_SYNC_LF_TIMER_CURR_TIME_CAPTURE NRF_RTC_TASK_CAPTURE_1

static uint8_t dppi_channel_curr_time_capture;
#define AUDIO_SYNC_LF_TIMER_I2S_FRAME_START_EVT_CAPTURE NRF_RTC_TASK_CAPTURE_0
#define AUDIO_SYNC_LF_TIMER_CURR_TIME_CAPTURE_CHANNEL 1
#define AUDIO_SYNC_LF_TIMER_CURR_TIME_CAPTURE NRF_RTC_TASK_CAPTURE_1

static const nrfx_rtc_config_t rtc_cfg = NRFX_RTC_DEFAULT_CONFIG;
static const nrfx_timer_t audio_sync_hf_timer_instance =
NRFX_TIMER_INSTANCE(AUDIO_SYNC_HF_TIMER_INSTANCE_NUMBER);

static const nrfx_rtc_t audio_sync_lf_timer_instance =
NRFX_RTC_INSTANCE(AUDIO_SYNC_LF_TIMER_INSTANCE_NUMBER);

static const nrfx_timer_config_t cfg = {
.frequency = NRFX_MHZ_TO_HZ(1UL),
.mode = NRF_TIMER_MODE_TIMER,
.bit_width = NRF_TIMER_BIT_WIDTH_32,
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
.p_context = NULL
};

static const nrfx_rtc_config_t rtc_cfg = NRFX_RTC_DEFAULT_CONFIG;

static uint8_t dppi_channel_i2s_frame_start;
static uint8_t dppi_channel_curr_time_capture;
static uint8_t dppi_channel_sync_start;
static uint8_t dppi_channel_timer_sync_with_rtc;
static uint8_t dppi_channel_rtc_start;
static volatile uint32_t num_rtc_overflows;

static nrfx_timer_config_t cfg = {.frequency = NRFX_MHZ_TO_HZ(1UL),
.mode = NRF_TIMER_MODE_TIMER,
.bit_width = NRF_TIMER_BIT_WIDTH_32,
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
.p_context = NULL};
static volatile uint32_t num_rtc_overflows;

static uint32_t timestamp_from_rtc_and_timer_get(uint32_t ticks, uint32_t remainder_us)
{
const uint64_t rtc_ticks_in_femto_units = 30517578125UL;
const uint32_t rtc_overflow_time_us = 512000000UL;
uint64_t remainder_fs;

remainder_fs = (uint64_t)remainder_us * 1000000000UL;

if (remainder_fs > rtc_ticks_in_femto_units) {
nrfx_err_t ret;

ret = nrfx_dppi_channel_enable(dppi_channel_timer_sync_with_rtc);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel enable error (timer sync): %d", ret);
}

nrfx_rtc_tick_enable(&audio_sync_lf_timer_instance, true);
}

remainder_fs %= rtc_ticks_in_femto_units;
remainder_us = remainder_fs / 1000000000UL;

return ((ticks * rtc_ticks_in_femto_units) / 1000000000UL) +
(num_rtc_overflows * rtc_overflow_time_us) + remainder_us;
Expand Down Expand Up @@ -127,6 +145,18 @@ static void unused_timer_isr_handler(nrf_timer_event_t event_type, void *ctx)

static void rtc_isr_handler(nrfx_rtc_int_type_t int_type)
{
if (int_type == NRFX_RTC_INT_TICK) {
nrfx_err_t ret;

nrfx_rtc_tick_enable(&audio_sync_lf_timer_instance, false);

ret = nrfx_dppi_channel_disable(dppi_channel_timer_sync_with_rtc);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel disable error (timer sync): %d", ret);
return;
}
}

if (int_type == NRFX_RTC_INT_OVERFLOW) {
num_rtc_overflows++;
}
Expand Down Expand Up @@ -177,6 +207,7 @@ static int audio_sync_timer_init(void)
dppi_channel_i2s_frame_start);

nrf_i2s_publish_set(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART, dppi_channel_i2s_frame_start);

ret = nrfx_dppi_channel_enable(dppi_channel_i2s_frame_start);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel enable error (I2S frame start): %d", ret);
Expand All @@ -186,7 +217,7 @@ static int audio_sync_timer_init(void)
/* Initialize capturing of current timestamps */
ret = nrfx_dppi_channel_alloc(&dppi_channel_curr_time_capture);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel alloc error (I2S frame start) - Return value: %d", ret);
LOG_ERR("nrfx DPPI channel alloc error (curr time capture): %d", ret);
return -ENOMEM;
}

Expand All @@ -202,36 +233,39 @@ static int audio_sync_timer_init(void)

ret = nrfx_dppi_channel_enable(dppi_channel_curr_time_capture);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel enable error (I2S frame start) - Return value: %d", ret);
LOG_ERR("nrfx DPPI channel enable error (curr time capture): %d", ret);
return -EIO;
}

/* Initialize functionality for synchronization between APP and NET core */
ret = nrfx_dppi_channel_alloc(&dppi_channel_rtc_start);
ret = nrfx_dppi_channel_alloc(&dppi_channel_sync_start);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel alloc error (timer clear): %d", ret);
LOG_ERR("nrfx DPPI channel alloc error (sync start): %d", ret);
return -ENOMEM;
}

nrf_rtc_subscribe_set(audio_sync_lf_timer_instance.p_reg, NRF_RTC_TASK_CLEAR,
dppi_channel_rtc_start);
dppi_channel_sync_start);

nrf_timer_subscribe_set(audio_sync_hf_timer_instance.p_reg, NRF_TIMER_TASK_START,
dppi_channel_rtc_start);
dppi_channel_sync_start);

nrf_ipc_receive_config_set(NRF_IPC, AUDIO_SYNC_TIMER_NET_APP_IPC_EVT_CHANNEL,
nrf_ipc_receive_config_set(NRF_IPC, AUDIO_SYNC_TIMER_NET_APP_IPC_START_EVT_CHANNEL,
NRF_IPC_CHANNEL_4);
nrf_ipc_publish_set(NRF_IPC, AUDIO_SYNC_TIMER_NET_APP_IPC_EVT, dppi_channel_rtc_start);

ret = nrfx_dppi_channel_enable(dppi_channel_rtc_start);
nrf_ipc_publish_set(NRF_IPC, AUDIO_SYNC_TIMER_NET_APP_IPC_START_EVT,
dppi_channel_sync_start);

ret = nrfx_dppi_channel_enable(dppi_channel_sync_start);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel enable error (timer clear): %d", ret);
LOG_ERR("nrfx DPPI channel enable error (sync start): %d", ret);
return -EIO;
}

/* Initialize functionality for synchronization between RTC and TIMER */
ret = nrfx_dppi_channel_alloc(&dppi_channel_timer_sync_with_rtc);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel alloc error (timer clear): %d", ret);
LOG_ERR("nrfx DPPI channel alloc error (timer sync): %d", ret);
return -ENOMEM;
}

Expand All @@ -240,14 +274,6 @@ static int audio_sync_timer_init(void)
nrf_timer_subscribe_set(audio_sync_hf_timer_instance.p_reg, NRF_TIMER_TASK_CLEAR,
dppi_channel_timer_sync_with_rtc);

nrfx_rtc_tick_enable(&audio_sync_lf_timer_instance, false);

ret = nrfx_dppi_channel_enable(dppi_channel_timer_sync_with_rtc);
if (ret - NRFX_ERROR_BASE_NUM) {
LOG_ERR("nrfx DPPI channel enable error (timer clear): %d", ret);
return -EIO;
}

nrfx_rtc_enable(&audio_sync_lf_timer_instance);

LOG_DBG("Audio sync timer initialized");
Expand Down
37 changes: 37 additions & 0 deletions applications/nrf5340_audio/unicast_server/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,43 @@

ret = bt_mgmt_adv_start(0, ext_adv_buf, ext_adv_buf_cnt, NULL, 0, true);
ERR_CHK(ret);

Check failure on line 568 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

TRAILING_WHITESPACE

applications/nrf5340_audio/unicast_server/main.c:568 trailing whitespace
// Test monotonicity

Check failure on line 569 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

applications/nrf5340_audio/unicast_server/main.c:569 do not use C99 // comments
uint32_t timestamps_us[10];
int counter;
for (counter = 0; counter < 1000000; counter++){

Check warning on line 572 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LINE_SPACING

applications/nrf5340_audio/unicast_server/main.c:572 Missing a blank line after declarations

Check failure on line 572 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:572 space required before the open brace '{'
// progress bar

Check failure on line 573 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

applications/nrf5340_audio/unicast_server/main.c:573 do not use C99 // comments
if ((counter % 1000) == 0) {
LOG_ERR("%u", counter);
}

// get some timestamps

Check failure on line 578 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

applications/nrf5340_audio/unicast_server/main.c:578 do not use C99 // comments
int i;
for (i=0;i<10;i++){

Check warning on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LINE_SPACING

applications/nrf5340_audio/unicast_server/main.c:580 Missing a blank line after declarations

Check failure on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:580 spaces required around that '=' (ctx:VxV)

Check failure on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:580 space required after that ';' (ctx:VxV)

Check failure on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:580 spaces required around that '<' (ctx:VxV)

Check failure on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:580 space required after that ';' (ctx:VxV)

Check failure on line 580 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

applications/nrf5340_audio/unicast_server/main.c:580 space required before the open brace '{'
timestamps_us[i] = audio_sync_timer_capture();
}

// check if there's a negative delta
int incorrect_entry = -1;
for (i=1;i<10;i++){

Check warning on line 586 in applications/nrf5340_audio/unicast_server/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LINE_SPACING

applications/nrf5340_audio/unicast_server/main.c:586 Missing a blank line after declarations
if (timestamps_us[i-1] > timestamps_us[i]){
incorrect_entry = i-1;
}
}

// report error
if (incorrect_entry >= 0){
LOG_ERR("\nIncorrect timestamp:");
for (i=0;i<10;i++){
if (incorrect_entry == i){
LOG_ERR("t[%u] = %u <<--", i, timestamps_us[i]);
} else {
LOG_ERR("t[%u] = %u", i, timestamps_us[i]);
}
}
break;
}
}
return 0;
}

Loading