1 /*
2 * Copyright (c) 2023-2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include <sample_usbd.h>
11 #include "feedback.h"
12
13 #include <zephyr/cache.h>
14 #include <zephyr/device.h>
15 #include <zephyr/usb/usbd.h>
16 #include <zephyr/usb/class/usbd_uac2.h>
17 #include <zephyr/drivers/i2s.h>
18 #include <zephyr/logging/log.h>
19
20 LOG_MODULE_REGISTER(uac2_sample, LOG_LEVEL_INF);
21
22 #define HEADPHONES_OUT_TERMINAL_ID UAC2_ENTITY_ID(DT_NODELABEL(out_terminal))
23 #define MICROPHONE_IN_TERMINAL_ID UAC2_ENTITY_ID(DT_NODELABEL(in_terminal))
24
25 #define SAMPLES_PER_SOF 48
26 #define SAMPLE_FREQUENCY (SAMPLES_PER_SOF * 1000)
27 #define SAMPLE_BIT_WIDTH 16
28 #define NUMBER_OF_CHANNELS 2
29 #define BYTES_PER_SAMPLE DIV_ROUND_UP(SAMPLE_BIT_WIDTH, 8)
30 #define BYTES_PER_SLOT (BYTES_PER_SAMPLE * NUMBER_OF_CHANNELS)
31 #define MIN_BLOCK_SIZE ((SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT)
32 #define BLOCK_SIZE (SAMPLES_PER_SOF * BYTES_PER_SLOT)
33 #define MAX_BLOCK_SIZE ((SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT)
34
35 /* Absolute minimum is 5 TX buffers (1 actively consumed by I2S, 2nd queued as
36 * next buffer, 3rd acquired by USB stack to receive data to, and 2 to handle
37 * SOF/I2S offset errors), but add 2 additional buffers to prevent out of memory
38 * errors when USB host decides to perform rapid terminal enable/disable cycles.
39 */
40 #define I2S_BLOCKS 7
41 K_MEM_SLAB_DEFINE_STATIC(i2s_tx_slab, MAX_BLOCK_SIZE, I2S_BLOCKS, 4);
42 K_MEM_SLAB_DEFINE_STATIC(i2s_rx_slab, MAX_BLOCK_SIZE, I2S_BLOCKS, 4);
43
44 struct usb_i2s_ctx {
45 const struct device *i2s_dev;
46 bool headphones_enabled;
47 bool microphone_enabled;
48 bool i2s_started;
49 bool rx_started;
50 bool usb_data_received;
51 /* Counter used to determine when to start I2S and then when to start
52 * sending RX packets to host. Overflows are not a problem because this
53 * variable is not necessary after both I2S and RX is started.
54 */
55 uint8_t i2s_counter;
56 struct feedback_ctx *fb;
57
58 /* Leftover samples from I2S receive buffer, already compacted to mono,
59 * that were not sent to host. The buffer, if not NULL, is allocated
60 * from I2S RX slab.
61 */
62 uint8_t *pending_mic_buf;
63 uint8_t pending_mic_samples;
64
65 /* Rolling bit buffers for tracking nominal + 1 and nominal - 1 samples
66 * sent. Bits are mutually exclusive, i.e.:
67 * plus_ones | minus_ones = plus_ones ^ minus_ones
68 *
69 * Used to avoid overcompensation in feedback regulator. LSBs indicate
70 * latest write size.
71 */
72 uint8_t plus_ones;
73 uint8_t minus_ones;
74 };
75
uac2_terminal_update_cb(const struct device * dev,uint8_t terminal,bool enabled,bool microframes,void * user_data)76 static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal,
77 bool enabled, bool microframes,
78 void *user_data)
79 {
80 struct usb_i2s_ctx *ctx = user_data;
81
82 /* This sample is for Full-Speed only devices. */
83 __ASSERT_NO_MSG(microframes == false);
84
85 if (terminal == HEADPHONES_OUT_TERMINAL_ID) {
86 ctx->headphones_enabled = enabled;
87 } else if (terminal == MICROPHONE_IN_TERMINAL_ID) {
88 ctx->microphone_enabled = enabled;
89 }
90
91 if (ctx->i2s_started && !ctx->headphones_enabled &&
92 !ctx->microphone_enabled) {
93 i2s_trigger(ctx->i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_DROP);
94 ctx->i2s_started = false;
95 ctx->i2s_counter = 0;
96 ctx->plus_ones = ctx->minus_ones = 0;
97 if (ctx->pending_mic_samples) {
98 k_mem_slab_free(&i2s_rx_slab, ctx->pending_mic_buf);
99 ctx->pending_mic_buf = NULL;
100 ctx->pending_mic_samples = 0;
101 }
102 }
103 }
104
uac2_get_recv_buf(const struct device * dev,uint8_t terminal,uint16_t size,void * user_data)105 static void *uac2_get_recv_buf(const struct device *dev, uint8_t terminal,
106 uint16_t size, void *user_data)
107 {
108 ARG_UNUSED(dev);
109 struct usb_i2s_ctx *ctx = user_data;
110 void *buf = NULL;
111 int ret;
112
113 if (terminal == HEADPHONES_OUT_TERMINAL_ID) {
114 __ASSERT_NO_MSG(size <= MAX_BLOCK_SIZE);
115
116 if (!ctx->headphones_enabled) {
117 LOG_ERR("Buffer request on disabled terminal");
118 return NULL;
119 }
120
121 ret = k_mem_slab_alloc(&i2s_tx_slab, &buf, K_NO_WAIT);
122 if (ret != 0) {
123 buf = NULL;
124 }
125 }
126
127 return buf;
128 }
129
uac2_data_recv_cb(const struct device * dev,uint8_t terminal,void * buf,uint16_t size,void * user_data)130 static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal,
131 void *buf, uint16_t size, void *user_data)
132 {
133 struct usb_i2s_ctx *ctx = user_data;
134 int ret;
135
136 ctx->usb_data_received = true;
137
138 if (!ctx->headphones_enabled && !ctx->microphone_enabled) {
139 k_mem_slab_free(&i2s_tx_slab, buf);
140 return;
141 }
142
143 if (!size) {
144 /* This code path is expected when host only records microphone
145 * data and is not streaming any audio to the headphones. Simply
146 * transmit as many zero-filled samples were last sent to allow
147 * the feedback regulator to work.
148 *
149 * When host is streaming audio, this can be a transient error.
150 * While the "feedback regulator delay" is likely to differ,
151 * it is still probably best to just zero-fill last sent number
152 * of samples. If we overcompensate as a result, the situation
153 * will stabilize after a while anyway.
154 *
155 * In either case, we have to keep I2S going and the only way
156 * we can control the SOF to I2S offset is by varying the number
157 * of samples sent.
158 */
159 if (ctx->plus_ones & 1) {
160 size = (SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT;
161 } else if (ctx->minus_ones & 1) {
162 size = (SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT;
163 } else {
164 size = SAMPLES_PER_SOF * BYTES_PER_SLOT;
165 }
166 memset(buf, 0, size);
167 sys_cache_data_flush_range(buf, size);
168 }
169
170 LOG_DBG("Received %d data to input terminal %d", size, terminal);
171
172 ret = i2s_write(ctx->i2s_dev, buf, size);
173 if (ret < 0) {
174 ctx->i2s_started = false;
175 ctx->i2s_counter = 0;
176 ctx->plus_ones = ctx->minus_ones = 0;
177 if (ctx->pending_mic_samples) {
178 k_mem_slab_free(&i2s_rx_slab, ctx->pending_mic_buf);
179 ctx->pending_mic_buf = NULL;
180 ctx->pending_mic_samples = 0;
181 }
182
183 /* Most likely underrun occurred, prepare I2S restart */
184 i2s_trigger(ctx->i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
185
186 ret = i2s_write(ctx->i2s_dev, buf, size);
187 if (ret < 0) {
188 /* Drop data block, will try again on next frame */
189 k_mem_slab_free(&i2s_tx_slab, buf);
190 }
191 }
192
193 if (ret == 0) {
194 ctx->i2s_counter++;
195 }
196 }
197
uac2_buf_release_cb(const struct device * dev,uint8_t terminal,void * buf,void * user_data)198 static void uac2_buf_release_cb(const struct device *dev, uint8_t terminal,
199 void *buf, void *user_data)
200 {
201 if (terminal == MICROPHONE_IN_TERMINAL_ID) {
202 k_mem_slab_free(&i2s_rx_slab, buf);
203 }
204 }
205
206 /* Determine next number of samples to send, called at most once every SOF */
next_mic_num_samples(struct usb_i2s_ctx * ctx)207 static int next_mic_num_samples(struct usb_i2s_ctx *ctx)
208 {
209 int offset = feedback_samples_offset(ctx->fb);
210
211 /* The rolling buffers essentially handle controller dead time, i.e.
212 * the buffers are used to prevent overcompensating on feedback offset.
213 * Remove the oldest entry by shifting the values by one bit.
214 */
215 ctx->plus_ones <<= 1;
216 ctx->minus_ones <<= 1;
217
218 if ((offset < 0) && (POPCOUNT(ctx->plus_ones) < -offset)) {
219 /* I2S buffer starts at least 1 sample before SOF, send nominal
220 * + 1 samples to host in order to shift offset towards 0.
221 */
222 ctx->plus_ones |= 1;
223 return SAMPLES_PER_SOF + 1;
224 }
225
226 if ((offset > 0) && (POPCOUNT(ctx->minus_ones) < offset)) {
227 /* I2S buffer starts at least 1 sample after SOF, send nominal
228 * - 1 samples to host in order to shift offset towards 0
229 */
230 ctx->minus_ones |= 1;
231 return SAMPLES_PER_SOF - 1;
232 }
233
234 /* I2S is either spot on, or the offset is expected to correct soon */
235 return SAMPLES_PER_SOF;
236 }
237
process_mic_data(const struct device * dev,struct usb_i2s_ctx * ctx)238 static void process_mic_data(const struct device *dev, struct usb_i2s_ctx *ctx)
239 {
240 size_t num_bytes;
241 uint8_t *dst, *src;
242 uint8_t *mic_buf;
243 void *rx_block;
244 int ret;
245 int samples_to_send, mic_samples, rx_samples, leftover_samples;
246
247 samples_to_send = next_mic_num_samples(ctx);
248
249 if (ctx->pending_mic_samples >= samples_to_send) {
250 /* No need to fetch new I2S samples, this happens shortly after
251 * we have "borrowed" samples from next buffer. This is expected
252 * and means that the streams have synchronized.
253 */
254 rx_block = NULL;
255 rx_samples = 0;
256 } else {
257 ret = i2s_read(ctx->i2s_dev, &rx_block, &num_bytes);
258 if (ret) {
259 /* No data available, I2S will restart soon */
260 return;
261 }
262 sys_cache_data_invd_range(rx_block, num_bytes);
263
264 /* I2S operates on 2 channels (stereo) */
265 rx_samples = num_bytes / (BYTES_PER_SAMPLE * 2);
266 }
267
268 /* Prepare microphone data to send, use pending samples if any */
269 src = rx_block;
270 if (ctx->pending_mic_buf) {
271 mic_buf = ctx->pending_mic_buf;
272 mic_samples = ctx->pending_mic_samples;
273 dst = &ctx->pending_mic_buf[mic_samples * BYTES_PER_SAMPLE];
274 } else if (rx_samples >= 1) {
275 /* First sample is already in place */
276 mic_buf = rx_block;
277 dst = &mic_buf[BYTES_PER_SAMPLE];
278 src += 2 * BYTES_PER_SAMPLE;
279 mic_samples = 1;
280 rx_samples--;
281 } else {
282 /* Something went horribly wrong, free the buffer and leave */
283 k_mem_slab_free(&i2s_rx_slab, rx_block);
284 return;
285 }
286
287 /* Copy as many samples as possible, stop if mic buffer is ready */
288 while ((mic_samples < samples_to_send) && (rx_samples > 0)) {
289 memcpy(dst, src, BYTES_PER_SAMPLE);
290
291 dst += BYTES_PER_SAMPLE;
292 src += 2 * BYTES_PER_SAMPLE;
293
294 mic_samples++;
295 rx_samples--;
296 }
297
298 /* Is mic buffer ready to go? */
299 if (mic_samples < samples_to_send) {
300 /* No, we have to borrow sample from next buffer. This can only
301 * happen if we fully drained current receive buffer.
302 */
303 __ASSERT_NO_MSG(rx_samples == 0);
304
305 if (rx_block != mic_buf) {
306 /* RX buffer no longer needed, samples are in mic_buf */
307 k_mem_slab_free(&i2s_rx_slab, rx_block);
308 }
309
310 ret = i2s_read(ctx->i2s_dev, &rx_block, &num_bytes);
311 if (ret) {
312 /* No data, I2S will likely restart due to error soon */
313 ctx->pending_mic_buf = mic_buf;
314 ctx->pending_mic_samples = mic_samples;
315 return;
316 }
317 sys_cache_data_invd_range(rx_block, num_bytes);
318
319 src = rx_block;
320 rx_samples = num_bytes / (BYTES_PER_SAMPLE * 2);
321 }
322
323 /* Copy remaining sample, under normal conditions (i.e. connected to
324 * non-malicious host) this is guaranteed to fully fill mic_buf.
325 */
326 while ((mic_samples < samples_to_send) && (rx_samples > 0)) {
327 memcpy(dst, src, BYTES_PER_SAMPLE);
328
329 dst += BYTES_PER_SAMPLE;
330 src += 2 * BYTES_PER_SAMPLE;
331
332 mic_samples++;
333 rx_samples--;
334 }
335
336 /* Are we still short on samples? */
337 if (mic_samples < samples_to_send) {
338 /* The only possibility for this code to execute is that we were
339 * short on samples and the next block (pointed to by rx_block)
340 * did not contain enough samples to fill the gap.
341 */
342 __ASSERT_NO_MSG(rx_block != mic_buf);
343
344 /* Bailing out at this point likely leads to faster recovery.
345 * Note that this should never happen during normal operation.
346 */
347 ctx->pending_mic_buf = mic_buf;
348 ctx->pending_mic_samples = mic_samples;
349
350 /* RX buffer is no longer needed */
351 k_mem_slab_free(&i2s_rx_slab, rx_block);
352 return;
353 }
354
355 /* Handle any potential leftover, start by sanitizing length */
356 leftover_samples = mic_samples - samples_to_send + rx_samples;
357 if (leftover_samples > (MAX_BLOCK_SIZE / BYTES_PER_SAMPLE)) {
358 size_t dropped_samples =
359 leftover_samples - (MAX_BLOCK_SIZE / BYTES_PER_SAMPLE);
360
361 LOG_WRN("Too many leftover samples, dropping %d samples",
362 dropped_samples);
363 if (rx_samples >= dropped_samples) {
364 rx_samples -= dropped_samples;
365 } else {
366 mic_samples -= (dropped_samples - rx_samples);
367 rx_samples = 0;
368 }
369
370 leftover_samples = (MAX_BLOCK_SIZE / BYTES_PER_SAMPLE);
371 }
372
373 if (leftover_samples == 0) {
374 /* No leftover samples */
375 if ((rx_block != NULL) && (rx_block != mic_buf)) {
376 /* All samples were copied, free source buffer */
377 k_mem_slab_free(&i2s_rx_slab, rx_block);
378 }
379 rx_block = NULL;
380 } else if ((mic_samples > samples_to_send) ||
381 ((rx_samples > 0) && (rx_block == mic_buf))) {
382 /* Leftover samples have to be copied to new buffer */
383 ret = k_mem_slab_alloc(&i2s_rx_slab, &rx_block, K_NO_WAIT);
384 if (ret != 0) {
385 LOG_WRN("Out of memory dropping %d samples",
386 leftover_samples);
387 mic_samples = samples_to_send;
388 rx_samples = 0;
389 rx_block = NULL;
390 }
391 }
392
393 /* At this point rx_block is either
394 * * NULL if there are no leftover samples, OR
395 * * src buffer if leftover data can be copied from back to front, OR
396 * * brand new buffer if there is leftover data in mic buffer.
397 */
398 ctx->pending_mic_buf = rx_block;
399 ctx->pending_mic_samples = 0;
400
401 /* Copy excess samples from pending mic buf, if any */
402 if (mic_samples > samples_to_send) {
403 size_t bytes;
404
405 /* Samples in mic buffer are already compacted */
406 bytes = (mic_samples - samples_to_send) * BYTES_PER_SAMPLE;
407 memcpy(ctx->pending_mic_buf, &mic_buf[mic_samples], bytes);
408
409 ctx->pending_mic_samples = mic_samples - samples_to_send;
410 dst = &ctx->pending_mic_buf[bytes];
411 } else {
412 dst = ctx->pending_mic_buf;
413 }
414
415 /* Copy excess samples from src buffer, so we don't lose any */
416 while (rx_samples > 0) {
417 memcpy(dst, src, BYTES_PER_SAMPLE);
418
419 dst += BYTES_PER_SAMPLE;
420 src += 2 * BYTES_PER_SAMPLE;
421
422 ctx->pending_mic_samples++;
423 rx_samples--;
424 }
425
426 /* Finally send the microphone samples to host */
427 sys_cache_data_flush_range(mic_buf, mic_samples * BYTES_PER_SAMPLE);
428 if (usbd_uac2_send(dev, MICROPHONE_IN_TERMINAL_ID,
429 mic_buf, mic_samples * BYTES_PER_SAMPLE) < 0) {
430 k_mem_slab_free(&i2s_rx_slab, mic_buf);
431 }
432 }
433
uac2_sof(const struct device * dev,void * user_data)434 static void uac2_sof(const struct device *dev, void *user_data)
435 {
436 ARG_UNUSED(dev);
437 struct usb_i2s_ctx *ctx = user_data;
438
439 if (ctx->i2s_started) {
440 feedback_process(ctx->fb);
441 }
442
443 /* If we didn't receive data since last SOF but either terminal is
444 * enabled, then we have to come up with the buffer ourself to keep
445 * I2S going.
446 */
447 if (!ctx->usb_data_received &&
448 (ctx->microphone_enabled || ctx->headphones_enabled)) {
449 /* No data received since last SOF but we have to keep going */
450 void *buf;
451 int ret;
452
453 ret = k_mem_slab_alloc(&i2s_tx_slab, &buf, K_NO_WAIT);
454 if (ret != 0) {
455 buf = NULL;
456 }
457
458 if (buf) {
459 /* Use size 0 to utilize zero-fill functionality */
460 uac2_data_recv_cb(dev, HEADPHONES_OUT_TERMINAL_ID,
461 buf, 0, user_data);
462 }
463 }
464 ctx->usb_data_received = false;
465
466 /* We want to maintain 3 SOFs delay, i.e. samples received from host
467 * during SOF n should be transmitted on I2S during SOF n+3. This
468 * provides enough wiggle room for software scheduling that effectively
469 * eliminates "buffers not provided in time" problem.
470 *
471 * ">= 2" translates into 3 SOFs delay because the timeline is:
472 * USB SOF n
473 * OUT DATA0 n received from host
474 * USB SOF n+1
475 * DATA0 n is available to UDC driver (See Universal Serial Bus
476 * Specification Revision 2.0 5.12.5 Data Prebuffering) and copied
477 * to I2S buffer before SOF n+2; i2s_counter = 1
478 * OUT DATA0 n+1 received from host
479 * USB SOF n+2
480 * DATA0 n+1 is copied; i2s_counter = 2
481 * OUT DATA0 n+2 received from host
482 * USB SOF n+3
483 * This function triggers I2S start
484 * DATA0 n+2 is copied; i2s_counter is no longer relevant
485 * OUT DATA0 n+3 received from host
486 */
487 if (!ctx->i2s_started &&
488 (ctx->headphones_enabled || ctx->microphone_enabled) &&
489 ctx->i2s_counter >= 2) {
490 i2s_trigger(ctx->i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_START);
491 ctx->i2s_started = true;
492 feedback_start(ctx->fb, ctx->i2s_counter);
493 ctx->i2s_counter = 0;
494 }
495
496 /* Start sending I2S RX data only when there are at least 3 buffers
497 * ready with data. This guarantees that there'll always be a buffer
498 * available from which sample can be borrowed.
499 */
500 if (!ctx->rx_started && ctx->i2s_started && ctx->i2s_counter >= 3) {
501 ctx->rx_started = true;
502 }
503
504 if (ctx->rx_started) {
505 process_mic_data(dev, ctx);
506 }
507 }
508
509 static struct uac2_ops usb_audio_ops = {
510 .sof_cb = uac2_sof,
511 .terminal_update_cb = uac2_terminal_update_cb,
512 .get_recv_buf = uac2_get_recv_buf,
513 .data_recv_cb = uac2_data_recv_cb,
514 .buf_release_cb = uac2_buf_release_cb,
515 };
516
517 static struct usb_i2s_ctx main_ctx;
518
main(void)519 int main(void)
520 {
521 const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(uac2_headset));
522 struct usbd_context *sample_usbd;
523 struct i2s_config config;
524 int ret;
525
526 main_ctx.i2s_dev = DEVICE_DT_GET(DT_NODELABEL(i2s_rxtx));
527
528 if (!device_is_ready(main_ctx.i2s_dev)) {
529 printk("%s is not ready\n", main_ctx.i2s_dev->name);
530 return 0;
531 }
532
533 config.word_size = SAMPLE_BIT_WIDTH;
534 config.channels = NUMBER_OF_CHANNELS;
535 config.format = I2S_FMT_DATA_FORMAT_I2S;
536 config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
537 config.frame_clk_freq = SAMPLE_FREQUENCY;
538 config.mem_slab = &i2s_tx_slab;
539 config.block_size = MAX_BLOCK_SIZE;
540 config.timeout = 0;
541
542 ret = i2s_configure(main_ctx.i2s_dev, I2S_DIR_TX, &config);
543 if (ret < 0) {
544 printk("Failed to configure TX stream: %d\n", ret);
545 return 0;
546 }
547
548 config.mem_slab = &i2s_rx_slab;
549 ret = i2s_configure(main_ctx.i2s_dev, I2S_DIR_RX, &config);
550 if (ret < 0) {
551 printk("Failed to configure RX stream: %d\n", ret);
552 return 0;
553 }
554
555 main_ctx.fb = feedback_init();
556
557 usbd_uac2_set_ops(dev, &usb_audio_ops, &main_ctx);
558
559 sample_usbd = sample_usbd_init_device(NULL);
560 if (sample_usbd == NULL) {
561 return -ENODEV;
562 }
563
564 ret = usbd_enable(sample_usbd);
565 if (ret) {
566 return ret;
567 }
568
569 return 0;
570 }
571