Skip to content

Commit 978f863

Browse files
masz-nordicnordic-krch
authored andcommitted
[nrf noup] samples: usb: uac2: offload TDM and USB sync to FLPR
Work in progress. Signed-off-by: Marcin Szymczyk <[email protected]>
1 parent 7d2b29d commit 978f863

File tree

11 files changed

+380
-11
lines changed

11 files changed

+380
-11
lines changed

samples/subsys/usb/uac2_implicit_feedback/app.overlay

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,11 @@
7474
};
7575
};
7676
};
77+
78+
&gpio9 {
79+
status = "reserved";
80+
};
81+
82+
&cpuflpr_vpr {
83+
status = "okay";
84+
};

samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
};
1919

2020
i2s_rxtx: &tdm130 {
21-
status = "okay";
21+
status = "reserved";
2222
pinctrl-0 = <&tdm130_default_alt>;
2323
pinctrl-names = "default";
2424
memory-regions = <&cpuapp_dma_region>;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(blinky)
6+
7+
target_sources(app PRIVATE src/main.c)
8+
target_sources(app PRIVATE ../src/feedback_nrf.c)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_GPIO=n
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
#include <hal/nrf_gpio.h>
2+
#include <hal/nrf_tdm.h>
3+
#include <zephyr/kernel.h>
4+
#include <../drivers/usb/common/usb_dwc2_hw.h>
5+
#include "../../src/feedback.h"
6+
7+
/* === BUFFERS === */
8+
#define SAMPLES_NUM 6
9+
#define CHANNELS_NUM 2
10+
#define BUFFERS_NUM 3
11+
#define NEXT_BUFFER(x) ((x + 1) % BUFFERS_NUM)
12+
13+
static struct feedback_ctx * mp_fbck;
14+
15+
typedef struct {
16+
void * ptr;
17+
size_t size;
18+
} buf_t;
19+
20+
static buf_t m_iso_in_buffers[BUFFERS_NUM];
21+
static buf_t m_iso_out_buffers[BUFFERS_NUM];
22+
static uint8_t m_iso_in_idx;
23+
static uint8_t m_iso_out_idx;
24+
25+
//TODO MEMORY REGION VERIFY!
26+
static uint32_t m_fake_sample_tx[SAMPLES_NUM + 1] __aligned(4);
27+
static uint32_t m_fake_sample_rx[SAMPLES_NUM + 1] __aligned(4);
28+
29+
static void buffers_flush(void)
30+
{
31+
m_iso_in_idx = 0;
32+
m_iso_out_idx = 0;
33+
memset(m_iso_in_buffers, 0, sizeof(m_iso_in_buffers));
34+
memset(m_iso_out_buffers, 0, sizeof(m_iso_out_buffers));
35+
}
36+
37+
/* === TDM === */
38+
#define MCKCONST 1048576UL
39+
#define AUDIOPLL_FREQ 12287963UL
40+
#define WORD_SIZE 16UL
41+
#define FRAME_CLK_FREQ 48000UL
42+
#define SCK_FREQ WORD_SIZE * FRAME_CLK_FREQ * CHANNELS_NUM
43+
#define SCK_VALUE ((uint32_t)(((uint64_t)SCK_FREQ * MCKCONST) / (AUDIOPLL_FREQ + (SCK_FREQ / 2) )* 4096))
44+
45+
static const nrf_tdm_config_t m_cfg = {
46+
.mode = NRF_TDM_MODE_MASTER,
47+
.alignment = NRF_TDM_ALIGN_LEFT,
48+
.sample_width = NRF_TDM_SWIDTH_16BIT,
49+
.channels = NRF_TDM_CHANNEL_TX0_MASK | NRF_TDM_CHANNEL_TX1_MASK | NRF_TDM_CHANNEL_RX0_MASK | NRF_TDM_CHANNEL_RX1_MASK,
50+
.num_of_channels = NRF_TDM_CHANNELS_COUNT_2,
51+
.channel_delay = NRF_TDM_CHANNEL_DELAY_1CK,
52+
.mck_setup = 0,
53+
.sck_setup = SCK_VALUE,
54+
.sck_polarity = NRF_TDM_POLARITY_POSEDGE,
55+
.fsync_polarity = NRF_TDM_POLARITY_NEGEDGE,
56+
.fsync_duration = NRF_TDM_FSYNC_DURATION_CHANNEL,
57+
};
58+
59+
static const nrf_tdm_pins_t m_pins = {
60+
.sck_pin = NRF_GPIO_PIN_MAP(1,3),
61+
.fsync_pin = NRF_GPIO_PIN_MAP(1,6),
62+
.mck_pin = NRF_TDM_PIN_NOT_CONNECTED,
63+
.sdout_pin = NRF_GPIO_PIN_MAP(1,4),
64+
.sdin_pin = NRF_GPIO_PIN_MAP(1,5),
65+
};
66+
67+
static bool m_tdm_started;
68+
static uint8_t m_tdm_counter;
69+
static uint8_t m_tdm_plus_ones;
70+
static uint8_t m_tdm_minus_ones;
71+
72+
static void tdm_init(void)
73+
{
74+
// TODO: delay access to USB core and TDM registers based on signal from APP
75+
k_msleep(100);
76+
77+
nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,3), NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT,
78+
NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);
79+
nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,6), NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT,
80+
NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);
81+
nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,4), NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT,
82+
NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);
83+
nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1,5), NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT,
84+
NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);
85+
nrf_tdm_pins_set(NRF_TDM130, &m_pins);
86+
}
87+
88+
static void tdm_start(buf_t * p_in, buf_t * p_out)
89+
{
90+
nrf_tdm_enable(NRF_TDM130);
91+
nrf_tdm_configure(NRF_TDM130, &m_cfg);
92+
nrf_tdm_sck_configure(NRF_TDM130, NRF_TDM_SRC_ACLK, false);
93+
nrf_tdm_mck_configure(NRF_TDM130, NRF_TDM_SRC_ACLK, false);
94+
nrf_tdm_event_clear(NRF_TDM130, NRF_TDM_EVENT_RXPTRUPD);
95+
nrf_tdm_event_clear(NRF_TDM130, NRF_TDM_EVENT_TXPTRUPD);
96+
nrf_tdm_event_clear(NRF_TDM130, NRF_TDM_EVENT_STOPPED);
97+
nrf_tdm_tx_count_set(NRF_TDM130, SAMPLES_NUM);
98+
nrf_tdm_rx_count_set(NRF_TDM130, SAMPLES_NUM);
99+
nrf_tdm_tx_buffer_set(NRF_TDM130, (const uint32_t *)p_in->ptr);
100+
nrf_tdm_rx_buffer_set(NRF_TDM130, (uint32_t *)p_out->ptr);
101+
nrf_tdm_transfer_direction_set(NRF_TDM130, NRF_TDM_RXTXEN_DUPLEX);
102+
nrf_tdm_task_trigger(NRF_TDM130, NRF_TDM_TASK_START);
103+
}
104+
105+
static void tdm_disable(void)
106+
{
107+
nrf_tdm_task_trigger(NRF_TDM130, NRF_TDM_TASK_STOP);
108+
// TODO: wait for stopped and only then call tdm_start()
109+
m_tdm_started = false;
110+
m_tdm_counter = 0;
111+
}
112+
113+
// TODO TBD how should size from usb be handled?
114+
115+
static void tdm_set_new_rx_ptr(buf_t * p_buf)
116+
{
117+
int offset = feedback_samples_offset(mp_fbck);
118+
119+
m_tdm_plus_ones <<= 1;
120+
m_tdm_minus_ones <<= 1;
121+
122+
if ((offset < 0) && (POPCOUNT(m_tdm_plus_ones) < -offset)) {
123+
m_tdm_plus_ones |= 1;
124+
p_buf->size = SAMPLES_NUM + 1;
125+
} else if ((offset > 0) && (POPCOUNT(m_tdm_minus_ones) < offset)) {
126+
m_tdm_minus_ones |= 1;
127+
p_buf->size = SAMPLES_NUM - 1;
128+
} else {
129+
p_buf->size = SAMPLES_NUM;
130+
}
131+
132+
// TODO case when pending_mic_samples >= samples_to_send ?
133+
nrf_tdm_tx_count_set(NRF_TDM130, p_buf->size);
134+
nrf_tdm_rx_buffer_set(NRF_TDM130, (uint32_t *)p_buf->ptr);
135+
}
136+
137+
static void tdm_set_new_tx_ptr(buf_t * p_buf)
138+
{
139+
if (p_buf->size == 0)
140+
{
141+
memset(p_buf->ptr, 0, SAMPLES_NUM + 1);
142+
}
143+
144+
if (m_tdm_plus_ones & 1) {
145+
p_buf->size = SAMPLES_NUM + 1;
146+
} else if (m_tdm_minus_ones & 1) {
147+
p_buf->size = SAMPLES_NUM - 1;
148+
} else {
149+
p_buf->size = SAMPLES_NUM;
150+
};
151+
152+
nrf_tdm_tx_count_set(NRF_TDM130, p_buf->size);
153+
nrf_tdm_tx_buffer_set(NRF_TDM130, (const uint32_t *)p_buf->ptr);
154+
p_buf->ptr = NULL;
155+
}
156+
157+
static bool tdm_data_ready(void)
158+
{
159+
return m_tdm_counter >= 2;
160+
}
161+
162+
static bool tdm_needs_restart(void)
163+
{
164+
// TODO
165+
return false;
166+
}
167+
168+
/* === USB === */
169+
170+
static struct usb_dwc2_reg * const regs = (struct usb_dwc2_reg *)NRF_USBHSCORE0;
171+
172+
static bool usb_sof_changed(void)
173+
{
174+
static uint32_t sof_prev;
175+
volatile uint32_t sof_curr = usb_dwc2_get_dsts_soffn(regs->dsts);
176+
177+
if (sof_prev != sof_curr)
178+
{
179+
sof_prev = sof_curr;
180+
return true;
181+
}
182+
183+
return false;
184+
}
185+
186+
static void get_next_iso_in_data(buf_t * p_buf)
187+
{
188+
// TODO @tmon
189+
p_buf->ptr = m_fake_sample_rx;
190+
}
191+
192+
static void release_iso_in_data(buf_t * p_buf)
193+
{
194+
// TODO @tmon
195+
(void)p_buf;
196+
}
197+
198+
// TODO TBD - what is responsibility of this func vs new_tx_ptr()?
199+
static void iso_out_data_received(buf_t * p_buf)
200+
{
201+
}
202+
203+
static void get_recv_buffer_for_iso_out(buf_t * p_buf)
204+
{
205+
// TODO @tmon
206+
p_buf->ptr = m_fake_sample_tx;
207+
p_buf->size = 0;
208+
}
209+
210+
static void usb_process_buffers(void)
211+
{
212+
m_iso_in_idx = NEXT_BUFFER(m_iso_in_idx);
213+
get_next_iso_in_data(&m_iso_in_buffers[m_iso_in_idx]);
214+
215+
uint8_t next_in_idx = NEXT_BUFFER(m_iso_in_idx);
216+
if (m_iso_in_buffers[next_in_idx].ptr) {
217+
release_iso_in_data(&m_iso_in_buffers[next_in_idx]);
218+
m_iso_in_buffers[next_in_idx].ptr = NULL;
219+
}
220+
221+
m_iso_out_idx = NEXT_BUFFER(m_iso_out_idx);
222+
get_recv_buffer_for_iso_out(&m_iso_out_buffers[m_iso_out_idx]);
223+
224+
uint8_t next_out_idx = NEXT_BUFFER(m_iso_out_idx);
225+
if (m_iso_out_buffers[next_out_idx].ptr) {
226+
iso_out_data_received(&m_iso_out_buffers[next_out_idx]);
227+
m_iso_out_buffers[next_out_idx].ptr = NULL;
228+
}
229+
230+
m_tdm_counter++;
231+
}
232+
233+
/* === */
234+
235+
int main(void)
236+
{
237+
tdm_init();
238+
mp_fbck = feedback_init();
239+
240+
while (1) {
241+
if (usb_sof_changed())
242+
{
243+
feedback_process(mp_fbck);
244+
usb_process_buffers();
245+
}
246+
247+
if (nrf_tdm_event_check(NRF_TDM130, NRF_TDM_EVENT_TXPTRUPD))
248+
{
249+
tdm_set_new_tx_ptr(&m_iso_out_buffers[m_iso_out_idx]);
250+
nrf_tdm_event_clear(NRF_TDM130, NRF_TDM_EVENT_TXPTRUPD);
251+
}
252+
253+
if (nrf_tdm_event_check(NRF_TDM130, NRF_TDM_EVENT_RXPTRUPD))
254+
{
255+
tdm_set_new_rx_ptr(&m_iso_in_buffers[m_iso_in_idx]);
256+
nrf_tdm_event_clear(NRF_TDM130, NRF_TDM_EVENT_RXPTRUPD);
257+
}
258+
259+
if (tdm_needs_restart())
260+
{
261+
tdm_disable();
262+
buffers_flush();
263+
}
264+
265+
if (!m_tdm_started && tdm_data_ready())
266+
{
267+
tdm_start(&m_iso_in_buffers[0], &m_iso_out_buffers[0]);
268+
feedback_start(mp_fbck, m_tdm_counter, true);
269+
m_tdm_started = true;
270+
}
271+
}
272+
273+
return 0;
274+
}

samples/subsys/usb/uac2_implicit_feedback/prj.conf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
CONFIG_I2S=y
2-
1+
CONFIG_I2S=n
2+
CONFIG_CLOCK_CONTROL=y
3+
CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL=y
34
#USB related configs
45
CONFIG_USB_DEVICE_STACK_NEXT=y
56
CONFIG_USBD_AUDIO2_CLASS=y

samples/subsys/usb/uac2_implicit_feedback/src/feedback.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define FEEDBACK_H_
99

1010
#include <stdint.h>
11+
#include <stdbool.h>
1112

1213
/* This sample is currently supporting only 48 kHz sample rate. */
1314
#define SAMPLE_RATE 48000

0 commit comments

Comments
 (0)