-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
samples: usb: add UAC2 explicit feedback sample
The sample illustrates how to calculate feedback value based on I2S sample clock measurement or indirect I2S FRAMESTART and USBD SOF. The sample is currently only supported on nrf5340dk_nrf5340_cpuapp target because the feedback measurement uses target specific peripherals. While it should be possible to perform feedback value calculation entirely in software (possibly with some additional filtering due to software scheduling jitter), the I2S API does not provide necessary timestamps. Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
- Loading branch information
1 parent
c0cd83a
commit 73a3f2a
Showing
13 changed files
with
950 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.20.0) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(usb_audio_async_i2s) | ||
|
||
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) | ||
target_sources(app PRIVATE src/main.c) | ||
|
||
if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP) | ||
target_sources(app PRIVATE src/feedback_nrf53.c) | ||
else() | ||
target_sources(app PRIVATE src/feedback_dummy.c) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Copyright (c) 2023-2024 Nordic Semiconductor ASA | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
menu "UAC2 external feedback sample options" | ||
|
||
config APP_USE_I2S_LRCLK_EDGES_COUNTER | ||
bool "Measure I2S LRCLK edges directly" | ||
help | ||
Use this to use I2S LRCLK edge counting for calculating feedback. | ||
On nRF53 this option requires externally connecting I2S LRCLK back to | ||
separate GPIOTE input pin (P1.09). | ||
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" | ||
|
||
source "Kconfig.zephyr" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
.. zephyr:code-sample:: uac2-explicit-feedback | ||
:name: USB Audio asynchronous explicit feedback sample | ||
:relevant-api: _usb_device_core_api i2s_interface | ||
|
||
USB Audio 2 explicit feedback sample playing audio on I2S. | ||
|
||
Overview | ||
******** | ||
|
||
This sample demonstrates how to implement USB asynchronous audio playback with | ||
explicit feedback. It can run on any board with USB and I2S support, but the | ||
feedback calculation is currently only implemented for the Nordic nRF5340 IC. | ||
|
||
The device running this sample presents itself to the host as a Full-Speed | ||
Asynchronous USB Audio 2 class device supporting 48 kHz 16-bit 2-channel | ||
(stereo) playback. | ||
|
||
Explicit Feedback | ||
***************** | ||
|
||
Asynchronous USB Audio is used when the actual sample clock is not controlled by | ||
USB host. Because the sample clock is independent from USB SOF it is inevitable | ||
that 1 ms according to audio sink (I2S) will be either slightly longer or | ||
shorter than 1 ms according to audio source (USB host). In the long run, this | ||
discrepancy leads to overruns or underruns. By providing explicit feedback to | ||
host, the device can tell host how many samples on average it needs every frame. | ||
The host achieves the average by sending either nominal or nominal ±1 sample | ||
packets every frame. | ||
|
||
The dummy feedback implementation, used when there is no target-specific | ||
feedback code available, returns a feedback value that results in host sending | ||
nominal number of samples every frame. Theoretically it should be possible to | ||
obtain the timing information based on I2S and USB interrupts, but currently | ||
neither subsystem provides the necessary timestamp information. | ||
|
||
Explcit Feedback on nRF5340 | ||
*************************** | ||
|
||
The nRF5340 is capable of counting both edges of I2S LRCLK relative to USB SOF | ||
with the use of DPPI, TIMER and GPIOTE input. Alternatively, if the GPIOTE input | ||
is not available, the DPPI and TIMER peripherals on nRF5340 can be configured to | ||
provide relative timing information between I2S FRAMESTART and USB SOF. | ||
|
||
This sample in both modes (direct sample counting and indirect I2S buffer output | ||
to USB SOF offset) has been tested on :ref:`nrf5340dk_nrf5340`. | ||
|
||
The sample defaults to indirect feedback calculation because direct sample | ||
counting requires external connection between I2S LRCLK output pin to GPIOTE | ||
input pin (hardcoded to P1.09) on :ref:`nrf5340dk_nrf5340`. In the indirect mode | ||
no extra connections are necessary and the sample can even be used without any | ||
I2S device connected where I2S signals can be checked e.g. on logic analyzer. | ||
|
||
Building and Running | ||
******************** | ||
|
||
The code can be found in :zephyr_file:`samples/subsys/usb/uac2_explicit_feedback`. | ||
|
||
To build and flash the application: | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/subsys/usb/uac2_explicit_feedback | ||
:board: nrf5340dk_nrf5340_cpuapp | ||
:goals: build flash | ||
:compact: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <dt-bindings/usb/audio.h> | ||
|
||
/ { | ||
uac2_headphones: usb_audio2 { | ||
compatible = "zephyr,uac2"; | ||
status = "okay"; | ||
audio-function = <AUDIO_FUNCTION_OTHER>; | ||
|
||
uac_aclk: aclk { | ||
compatible = "zephyr,uac2-clock-source"; | ||
clock-type = "internal-programmable"; | ||
frequency-control = "host-programmable"; | ||
sampling-frequencies = <48000>; | ||
}; | ||
|
||
out_terminal: out_terminal { | ||
compatible = "zephyr,uac2-input-terminal"; | ||
clock-source = <&uac_aclk>; | ||
terminal-type = <USB_TERMINAL_STREAMING>; | ||
front-left; | ||
front-right; | ||
}; | ||
|
||
headphones_output: headphones { | ||
compatible = "zephyr,uac2-output-terminal"; | ||
data-source = <&out_terminal>; | ||
clock-source = <&uac_aclk>; | ||
terminal-type = <OUTPUT_TERMINAL_HEADPHONES>; | ||
}; | ||
|
||
as_iso_out: out_interface { | ||
compatible = "zephyr,uac2-audio-streaming"; | ||
linked-terminal = <&out_terminal>; | ||
subslot-size = <2>; | ||
bit-resolution = <16>; | ||
}; | ||
}; | ||
}; |
2 changes: 2 additions & 0 deletions
2
samples/subsys/usb/uac2_explicit_feedback/boards/nrf5340dk_nrf5340_cpuapp.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#Enable timer for asynchronous feedback | ||
CONFIG_NRFX_TIMER2=y |
28 changes: 28 additions & 0 deletions
28
samples/subsys/usb/uac2_explicit_feedback/boards/nrf5340dk_nrf5340_cpuapp.overlay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "../app.overlay" | ||
|
||
&pinctrl { | ||
i2s0_default_alt: i2s0_default_alt { | ||
group1 { | ||
psels = <NRF_PSEL(I2S_SCK_M, 1, 15)>, | ||
<NRF_PSEL(I2S_LRCK_M, 1, 12)>, | ||
<NRF_PSEL(I2S_SDOUT, 1, 13)>; | ||
}; | ||
}; | ||
}; | ||
|
||
&clock { | ||
hfclkaudio-frequency = <12288000>; | ||
}; | ||
|
||
i2s_tx: &i2s0 { | ||
status = "okay"; | ||
pinctrl-0 = <&i2s0_default_alt>; | ||
pinctrl-names = "default"; | ||
clock-source = "ACLK"; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
CONFIG_I2S=y | ||
|
||
#USB related configs | ||
CONFIG_USB_DEVICE_STACK_NEXT=y | ||
CONFIG_USBD_AUDIO2_CLASS=y | ||
CONFIG_SAMPLE_USBD_PID=0x000E | ||
CONFIG_SAMPLE_USBD_PRODUCT="UAC2 explicit feedback sample" | ||
|
||
#LOG subsystem related configs | ||
CONFIG_LOG=y | ||
CONFIG_USBD_LOG_LEVEL_WRN=y | ||
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
sample: | ||
name: USB Audio 2 asynchronous explicit feedback sample | ||
tests: | ||
sample.subsys.usb.uac2_explicit_feedback: | ||
tags: usb i2s | ||
platform_allow: nrf5340dk_nrf5340_cpuapp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright (c) 2024 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef FEEDBACK_H_ | ||
#define FEEDBACK_H_ | ||
|
||
#include <stdint.h> | ||
|
||
/* Nominal number of samples received on each SOF. This sample is currently | ||
* supporting only 48 kHz sample rate. | ||
*/ | ||
#define SAMPLES_PER_SOF 48 | ||
|
||
struct feedback_ctx *feedback_init(void); | ||
void feedback_reset_ctx(struct feedback_ctx *ctx); | ||
void feedback_process(struct feedback_ctx *ctx); | ||
void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued); | ||
uint32_t feedback_value(struct feedback_ctx *ctx); | ||
|
||
#endif /* FEEDBACK_H_ */ |
39 changes: 39 additions & 0 deletions
39
samples/subsys/usb/uac2_explicit_feedback/src/feedback_dummy.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (c) 2024 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/kernel.h> | ||
#include "feedback.h" | ||
|
||
#warning "No target specific feedback code, overruns/underruns will occur" | ||
|
||
#define FEEDBACK_K 10 | ||
|
||
struct feedback_ctx *feedback_init(void) | ||
{ | ||
return NULL; | ||
} | ||
|
||
void feedback_process(struct feedback_ctx *ctx) | ||
{ | ||
ARG_UNUSED(ctx); | ||
} | ||
|
||
void feedback_reset_ctx(struct feedback_ctx *ctx) | ||
{ | ||
ARG_UNUSED(ctx); | ||
} | ||
|
||
void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued) | ||
{ | ||
ARG_UNUSED(ctx); | ||
ARG_UNUSED(i2s_blocks_queued); | ||
} | ||
|
||
uint32_t feedback_value(struct feedback_ctx *ctx) | ||
{ | ||
/* Always request nominal number of samples */ | ||
return SAMPLES_PER_SOF << FEEDBACK_K; | ||
} |
Oops, something went wrong.