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 
24 #define SAMPLE_FREQUENCY    (SAMPLES_PER_SOF * 1000)
25 #define SAMPLE_BIT_WIDTH    16
26 #define NUMBER_OF_CHANNELS  2
27 #define BYTES_PER_SAMPLE    DIV_ROUND_UP(SAMPLE_BIT_WIDTH, 8)
28 #define BYTES_PER_SLOT      (BYTES_PER_SAMPLE * NUMBER_OF_CHANNELS)
29 #define MIN_BLOCK_SIZE      ((SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT)
30 #define BLOCK_SIZE          (SAMPLES_PER_SOF * BYTES_PER_SLOT)
31 #define MAX_BLOCK_SIZE      ((SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT)
32 
33 /* Absolute minimum is 5 buffers (1 actively consumed by I2S, 2nd queued as next
34  * buffer, 3rd acquired by USB stack to receive data to, and 2 to handle SOF/I2S
35  * offset errors), but add 2 additional buffers to prevent out of memory errors
36  * when USB host decides to perform rapid terminal enable/disable cycles.
37  */
38 #define I2S_BUFFERS_COUNT   7
39 K_MEM_SLAB_DEFINE_STATIC(i2s_tx_slab, ROUND_UP(MAX_BLOCK_SIZE, UDC_BUF_GRANULARITY),
40 			 I2S_BUFFERS_COUNT, UDC_BUF_ALIGN);
41 
42 struct usb_i2s_ctx {
43 	const struct device *i2s_dev;
44 	bool terminal_enabled;
45 	bool i2s_started;
46 	/* Number of blocks written, used to determine when to start I2S.
47 	 * Overflows are not a problem becuse this variable is not necessary
48 	 * after I2S is started.
49 	 */
50 	uint8_t i2s_blocks_written;
51 	struct feedback_ctx *fb;
52 };
53 
uac2_terminal_update_cb(const struct device * dev,uint8_t terminal,bool enabled,bool microframes,void * user_data)54 static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal,
55 				    bool enabled, bool microframes,
56 				    void *user_data)
57 {
58 	struct usb_i2s_ctx *ctx = user_data;
59 
60 	/* This sample has only one terminal therefore the callback can simply
61 	 * ignore the terminal variable.
62 	 */
63 	__ASSERT_NO_MSG(terminal == HEADPHONES_OUT_TERMINAL_ID);
64 	/* This sample is for Full-Speed only devices. */
65 	__ASSERT_NO_MSG(microframes == false);
66 
67 	ctx->terminal_enabled = enabled;
68 	if (ctx->i2s_started && !enabled) {
69 		i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP);
70 		ctx->i2s_started = false;
71 		ctx->i2s_blocks_written = 0;
72 		feedback_reset_ctx(ctx->fb);
73 	}
74 }
75 
uac2_get_recv_buf(const struct device * dev,uint8_t terminal,uint16_t size,void * user_data)76 static void *uac2_get_recv_buf(const struct device *dev, uint8_t terminal,
77 			       uint16_t size, void *user_data)
78 {
79 	ARG_UNUSED(dev);
80 	struct usb_i2s_ctx *ctx = user_data;
81 	void *buf = NULL;
82 	int ret;
83 
84 	if (terminal == HEADPHONES_OUT_TERMINAL_ID) {
85 		__ASSERT_NO_MSG(size <= MAX_BLOCK_SIZE);
86 
87 		if (!ctx->terminal_enabled) {
88 			LOG_ERR("Buffer request on disabled terminal");
89 			return NULL;
90 		}
91 
92 		ret = k_mem_slab_alloc(&i2s_tx_slab, &buf, K_NO_WAIT);
93 		if (ret != 0) {
94 			buf = NULL;
95 		}
96 	}
97 
98 	return buf;
99 }
100 
uac2_data_recv_cb(const struct device * dev,uint8_t terminal,void * buf,uint16_t size,void * user_data)101 static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal,
102 			      void *buf, uint16_t size, void *user_data)
103 {
104 	struct usb_i2s_ctx *ctx = user_data;
105 	int ret;
106 
107 	if (!ctx->terminal_enabled) {
108 		k_mem_slab_free(&i2s_tx_slab, buf);
109 		return;
110 	}
111 
112 	if (!size) {
113 		/* Zero fill to keep I2S going. If this is transient error, then
114 		 * this is probably best we can do. Otherwise, host will likely
115 		 * either disable terminal (or the cable will be disconnected)
116 		 * which will stop I2S.
117 		 */
118 		size = BLOCK_SIZE;
119 		memset(buf, 0, size);
120 		sys_cache_data_flush_range(buf, size);
121 	}
122 
123 	LOG_DBG("Received %d data to input terminal %d", size, terminal);
124 
125 	ret = i2s_write(ctx->i2s_dev, buf, size);
126 	if (ret < 0) {
127 		ctx->i2s_started = false;
128 		ctx->i2s_blocks_written = 0;
129 		feedback_reset_ctx(ctx->fb);
130 
131 		/* Most likely underrun occurred, prepare I2S restart */
132 		i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_PREPARE);
133 
134 		ret = i2s_write(ctx->i2s_dev, buf, size);
135 		if (ret < 0) {
136 			/* Drop data block, will try again on next frame */
137 			k_mem_slab_free(&i2s_tx_slab, buf);
138 		}
139 	}
140 
141 	if (ret == 0) {
142 		ctx->i2s_blocks_written++;
143 	}
144 }
145 
uac2_buf_release_cb(const struct device * dev,uint8_t terminal,void * buf,void * user_data)146 static void uac2_buf_release_cb(const struct device *dev, uint8_t terminal,
147 				void *buf, void *user_data)
148 {
149 	/* This sample does not send audio data so this won't be called */
150 }
151 
152 /* Variables for debug use to facilitate simple how feedback value affects
153  * audio data rate experiments. These debug variables can also be used to
154  * determine how well the feedback regulator deals with errors. The values
155  * are supposed to be modified by debugger.
156  *
157  * Setting use_hardcoded_feedback to true, essentially bypasses the feedback
158  * regulator and makes host send hardcoded_feedback samples every 16384 SOFs
159  * (when operating at Full-Speed).
160  *
161  * The feedback at Full-Speed is Q10.14 value. For 48 kHz audio sample rate,
162  * there are nominally 48 samples every SOF. The corresponding value is thus
163  * 48 << 14. Such feedback value would result in host sending always 48 samples.
164  * Now, if we want to receive more samples (because 1 ms according to audio
165  * sink is shorter than 1 ms according to USB Host 500 ppm SOF timer), then
166  * the feedback value has to be increased. The fractional part is 14-bit wide
167  * and therefore increment by 1 means 1 additional sample every 2**14 SOFs.
168  * (48 << 14) + 1 therefore results in host sending 48 samples 16383 times and
169  * 49 samples 1 time during every 16384 SOFs.
170  *
171  * Similarly, if we want to receive less samples (because 1 ms according to
172  * audio signk is longer than 1 ms according to USB Host), then the feedback
173  * value has to be decreased. (48 << 14) - 1 therefore results in host sending
174  * 48 samples 16383 times and 47 samples 1 time during every 16384 SOFs.
175  *
176  * If the feedback value differs by more than 1 (i.e. LSB), then the +1/-1
177  * samples packets are generally evenly distributed. For example feedback value
178  * (48 << 14) + (1 << 5) results in 48 samples 511 times and 49 samples 1 time
179  * during every 512 SOFs.
180  *
181  * For High-Speed above changes slightly, because the feedback format is Q16.16
182  * and microframes are used. The 48 kHz audio sample rate is achieved by sending
183  * 6 samples every SOF (microframe). The nominal value is the average number of
184  * samples to send every microframe and therefore for 48 kHz the nominal value
185  * is (6 << 16).
186  */
187 static volatile bool use_hardcoded_feedback;
188 static volatile uint32_t hardcoded_feedback = (48 << 14) + 1;
189 
uac2_feedback_cb(const struct device * dev,uint8_t terminal,void * user_data)190 static uint32_t uac2_feedback_cb(const struct device *dev, uint8_t terminal,
191 				 void *user_data)
192 {
193 	/* Sample has only one UAC2 instance with one terminal so both can be
194 	 * ignored here.
195 	 */
196 	ARG_UNUSED(dev);
197 	ARG_UNUSED(terminal);
198 	struct usb_i2s_ctx *ctx = user_data;
199 
200 	if (use_hardcoded_feedback) {
201 		return hardcoded_feedback;
202 	} else {
203 		return feedback_value(ctx->fb);
204 	}
205 }
206 
uac2_sof(const struct device * dev,void * user_data)207 static void uac2_sof(const struct device *dev, void *user_data)
208 {
209 	ARG_UNUSED(dev);
210 	struct usb_i2s_ctx *ctx = user_data;
211 
212 	if (ctx->i2s_started) {
213 		feedback_process(ctx->fb);
214 	}
215 
216 	/* We want to maintain 3 SOFs delay, i.e. samples received during SOF n
217 	 * should be on I2S during SOF n+3. This provides enough wiggle room
218 	 * for software scheduling that effectively eliminates "buffers not
219 	 * provided in time" problem.
220 	 *
221 	 * ">= 2" translates into 3 SOFs delay because the timeline is:
222 	 * USB SOF n
223 	 *   OUT DATA0 n received from host
224 	 * USB SOF n+1
225 	 *   DATA0 n is available to UDC driver (See Universal Serial Bus
226 	 *   Specification Revision 2.0 5.12.5 Data Prebuffering) and copied
227 	 *   to I2S buffer before SOF n+2; i2s_blocks_written = 1
228 	 *   OUT DATA0 n+1 received from host
229 	 * USB SOF n+2
230 	 *   DATA0 n+1 is copied; i2s_block_written = 2
231 	 *   OUT DATA0 n+2 received from host
232 	 * USB SOF n+3
233 	 *   This function triggers I2S start
234 	 *   DATA0 n+2 is copied; i2s_block_written is no longer relevant
235 	 *   OUT DATA0 n+3 received from host
236 	 */
237 	if (!ctx->i2s_started && ctx->terminal_enabled &&
238 	    ctx->i2s_blocks_written >= 2) {
239 		i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START);
240 		ctx->i2s_started = true;
241 		feedback_start(ctx->fb, ctx->i2s_blocks_written);
242 	}
243 }
244 
245 static struct uac2_ops usb_audio_ops = {
246 	.sof_cb = uac2_sof,
247 	.terminal_update_cb = uac2_terminal_update_cb,
248 	.get_recv_buf = uac2_get_recv_buf,
249 	.data_recv_cb = uac2_data_recv_cb,
250 	.buf_release_cb = uac2_buf_release_cb,
251 	.feedback_cb = uac2_feedback_cb,
252 };
253 
254 static struct usb_i2s_ctx main_ctx;
255 
main(void)256 int main(void)
257 {
258 	const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(uac2_headphones));
259 	struct usbd_context *sample_usbd;
260 	struct i2s_config config;
261 	int ret;
262 
263 	main_ctx.i2s_dev = DEVICE_DT_GET(DT_NODELABEL(i2s_tx));
264 
265 	if (!device_is_ready(main_ctx.i2s_dev)) {
266 		printk("%s is not ready\n", main_ctx.i2s_dev->name);
267 		return 0;
268 	}
269 
270 	config.word_size = SAMPLE_BIT_WIDTH;
271 	config.channels = NUMBER_OF_CHANNELS;
272 	config.format = I2S_FMT_DATA_FORMAT_I2S;
273 	config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
274 	config.frame_clk_freq = SAMPLE_FREQUENCY;
275 	config.mem_slab = &i2s_tx_slab;
276 	config.block_size = MAX_BLOCK_SIZE;
277 	config.timeout = 0;
278 
279 	ret = i2s_configure(main_ctx.i2s_dev, I2S_DIR_TX, &config);
280 	if (ret < 0) {
281 		printk("Failed to configure TX stream: %d\n", ret);
282 		return 0;
283 	}
284 
285 	main_ctx.fb = feedback_init();
286 
287 	usbd_uac2_set_ops(dev, &usb_audio_ops, &main_ctx);
288 
289 	sample_usbd = sample_usbd_init_device(NULL);
290 	if (sample_usbd == NULL) {
291 		return -ENODEV;
292 	}
293 
294 	ret = usbd_enable(sample_usbd);
295 	if (ret) {
296 		return ret;
297 	}
298 
299 	return 0;
300 }
301