1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-05-09 Urey first version
9 */
10
11 #include <stdio.h>
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <rtdevice.h>
15
16 #include <drivers/audio.h>
17
18 #include "audio_pipe.h"
19
20
21 #define AUDIO_DEBUG 0
22 #if AUDIO_DEBUG
23 #define AUDIO_DBG(...) printf("[AUDIO]:"),printf(__VA_ARGS__)
24 #else
25 #define AUDIO_DBG(...)
26 #endif
27
28 static struct rt_audio_pipe audio_pipe;
29
_audio_send_replay_frame(struct rt_audio_device * audio)30 static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
31 {
32 rt_err_t result = RT_EOK;
33 rt_base_t level;
34 struct rt_audio_frame frame;
35
36 RT_ASSERT(audio != RT_NULL);
37
38 //check repaly queue is empty
39 if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK)
40 {
41 AUDIO_DBG("TX queue is empty\n");
42 result = -RT_EEMPTY;
43
44 level = rt_hw_interrupt_disable();
45 audio->replay->activated = RT_FALSE;
46 rt_hw_interrupt_enable(level);
47
48 goto _exit;
49 }
50
51 if (audio->ops->transmit != RT_NULL)
52 {
53 AUDIO_DBG("audio transmit...\n");
54 if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size)
55 {
56 result = -RT_EBUSY;
57
58 goto _exit;
59 }
60 }
61
62 //pop the head frame...
63 rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
64
65 _exit: return result;
66 }
67
_audio_flush_replay_frame(struct rt_audio_device * audio)68 static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
69 {
70 struct rt_audio_frame frame;
71
72 if (audio->replay == RT_NULL)
73 return -RT_EIO;
74 while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
75 {
76 //pop the head frame...
77 rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
78
79 /* notify transmitted complete. */
80 if (audio->parent.tx_complete != RT_NULL)
81 audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
82 }
83
84 return RT_EOK;
85 }
86
_audio_dev_init(struct rt_device * dev)87 static rt_err_t _audio_dev_init(struct rt_device *dev)
88 {
89 rt_err_t result = RT_EOK;
90 struct rt_audio_device *audio;
91
92 RT_ASSERT(dev != RT_NULL);
93 audio = (struct rt_audio_device *) dev;
94
95 /* initialize replay & record */
96 audio->replay = RT_NULL;
97 audio->record = RT_NULL;
98
99 /* apply configuration */
100 if (audio->ops->init)
101 result = audio->ops->init(audio);
102
103 return result;
104 }
105
_audio_dev_open(struct rt_device * dev,rt_uint16_t oflag)106 static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
107 {
108 struct rt_audio_device *audio;
109
110 RT_ASSERT(dev != RT_NULL);
111 audio = (struct rt_audio_device *) dev;
112
113 /* check device flag with the open flag */
114 if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
115 return -RT_EIO;
116 if ((oflag & RT_DEVICE_OFLAG_WRONLY) && !(dev->flag & RT_DEVICE_FLAG_WRONLY))
117 return -RT_EIO;
118
119 /* get open flags */
120 dev->open_flag = oflag & 0xff;
121
122 /* initialize the Rx/Tx structure according to open flag */
123 if (oflag & RT_DEVICE_OFLAG_WRONLY)
124 {
125 AUDIO_DBG("open audio device ,oflag = %x\n",oflag);
126 if (audio->replay == RT_NULL)
127 {
128 struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
129
130 if (replay == RT_NULL)
131 {
132 AUDIO_DBG("request memory for replay error\n");
133 return -RT_ENOMEM;
134 }
135
136 //init queue for audio replay
137 rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL);
138
139 replay->activated = RT_FALSE;
140 audio->replay = replay;
141 }
142
143 dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
144 }
145
146 if (oflag & RT_DEVICE_OFLAG_RDONLY)
147 {
148 if (audio->record == RT_NULL)
149 {
150 struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
151
152 if (record == RT_NULL)
153 {
154 AUDIO_DBG("request memory for record error\n");
155 return -RT_ENOMEM;
156 }
157
158 //init pipe for record
159 {
160 rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE);
161
162 if (buf == RT_NULL)
163 {
164 rt_free(record);
165 AUDIO_DBG("request pipe memory error\n");
166
167 return -RT_ENOMEM;
168 }
169
170 rt_audio_pipe_init(&audio_pipe, "recpipe", (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), buf,
171 CFG_AUDIO_RECORD_PIPE_SIZE);
172 }
173
174 record->activated = RT_FALSE;
175 audio->record = record;
176 }
177
178 //open record pipe
179 if (audio->record != RT_NULL)
180 {
181 rt_device_open(RT_DEVICE(&audio_pipe), RT_DEVICE_OFLAG_RDONLY);
182 }
183
184 dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
185 }
186
187 return RT_EOK;
188 }
189
_audio_dev_close(struct rt_device * dev)190 static rt_err_t _audio_dev_close(struct rt_device *dev)
191 {
192 struct rt_audio_device *audio;
193 RT_ASSERT(dev != RT_NULL);
194 audio = (struct rt_audio_device *) dev;
195
196 //shutdown the lower device
197 if (audio->ops->shutdown != RT_NULL)
198 audio->ops->shutdown(audio);
199
200 if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
201 {
202 struct rt_audio_frame frame;
203 //stop replay stream
204 audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
205
206 //flush all frame
207 while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
208 {
209 //pop the head frame...
210 rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
211
212 /* notify transmitted complete. */
213 if (audio->parent.tx_complete != RT_NULL)
214 audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
215 }
216
217 dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
218 }
219
220 if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
221 {
222 //stop record stream
223 audio->ops->stop(audio, AUDIO_STREAM_RECORD);
224
225 //close record pipe
226 if (audio->record != RT_NULL)
227 rt_device_close(RT_DEVICE(&audio_pipe));
228
229 dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
230 }
231
232 return RT_EOK;
233 }
234
_audio_dev_read(struct rt_device * dev,rt_off_t pos,void * buffer,rt_size_t size)235 static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
236 {
237 struct rt_audio_device *audio;
238 RT_ASSERT(dev != RT_NULL);
239 audio = (struct rt_audio_device *) dev;
240 if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
241 return 0;
242
243 return rt_device_read(RT_DEVICE(&audio_pipe), pos, buffer, size);
244 }
245
_audio_dev_write(struct rt_device * dev,rt_off_t pos,const void * buffer,rt_size_t size)246 static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
247 {
248 rt_err_t result = RT_EOK;
249 rt_base_t level;
250 struct rt_audio_device *audio;
251
252 RT_ASSERT(dev != RT_NULL);
253 audio = (struct rt_audio_device *) dev;
254
255 if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
256 return 0;
257
258 AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size);
259 //push a new frame to tx queue
260 {
261 result = rt_data_queue_push(&audio->replay->queue, buffer, size,
262 RT_WAITING_FOREVER);
263 if (result != RT_EOK)
264 {
265 AUDIO_DBG("TX frame queue push error\n");
266 rt_set_errno(-RT_EFULL);
267 return 0;
268 }
269 }
270
271 //check tx state...
272 level = rt_hw_interrupt_disable();
273 if (audio->replay->activated != RT_TRUE)
274 {
275 audio->replay->activated = RT_TRUE;
276 rt_hw_interrupt_enable(level);
277
278 _audio_send_replay_frame(audio);
279 }
280 else
281 {
282 rt_hw_interrupt_enable(level);
283 }
284
285 return size;
286 }
287
_audio_dev_control(struct rt_device * dev,int cmd,void * args)288 static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
289 {
290 rt_err_t result = RT_EOK;
291 struct rt_audio_device *audio;
292 RT_ASSERT(dev != RT_NULL);
293 audio = (struct rt_audio_device *) dev;
294
295 //dev stat...
296 switch (cmd)
297 {
298 case AUDIO_CTL_GETCAPS:
299 {
300 struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
301
302 AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
303 if (audio->ops->getcaps != RT_NULL)
304 {
305 result = audio->ops->getcaps(audio, caps);
306 }
307 }
308 break;
309 case AUDIO_CTL_CONFIGURE:
310 {
311 struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
312
313 AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
314 if (audio->ops->configure != RT_NULL)
315 {
316 result = audio->ops->configure(audio, caps);
317 }
318 }
319
320 break;
321 case AUDIO_CTL_SHUTDOWN:
322 {
323 AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n");
324
325 if (audio->ops->shutdown != RT_NULL)
326 result = audio->ops->shutdown(audio);
327
328 //flush replay frame...
329 _audio_flush_replay_frame(audio);
330 }
331 break;
332
333 case AUDIO_CTL_START:
334 {
335 int stream = *(int *) args;
336
337 AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream);
338 if (audio->ops->start != RT_NULL)
339 result = audio->ops->start(audio, stream);
340 }
341 break;
342 case AUDIO_CTL_STOP:
343 {
344 int stream = *(int *) args;
345
346 AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream);
347 if (audio->ops->start != RT_NULL)
348 result = audio->ops->stop(audio, stream);
349
350 if (stream == AUDIO_STREAM_REPLAY)
351 {
352 _audio_flush_replay_frame(audio);
353 }
354 }
355 break;
356 case AUDIO_CTL_PAUSE:
357 {
358 int stream = *(int *) args;
359
360 AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream);
361 if (audio->ops->start != RT_NULL)
362 result = audio->ops->suspend(audio, stream);
363 }
364 break;
365 case AUDIO_CTL_RESUME:
366 {
367 int stream = *(int *) args;
368
369 AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream);
370 if (audio->ops->start != RT_NULL)
371 result = audio->ops->resume(audio, stream);
372
373 //resume tx frame...
374 if (stream == AUDIO_STREAM_REPLAY)
375 _audio_send_replay_frame(audio);
376 }
377 break;
378 case AUDIO_CTL_ALLOCBUFFER:
379 {
380 struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args;
381
382 if (desc)
383 {
384 desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2;
385 desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER);
386
387 result = RT_EOK;
388 }
389 else result = -RT_EIO;
390 }
391 break;
392 case AUDIO_CTL_FREEBUFFER:
393 {
394 rt_uint8_t *data_ptr = (rt_uint8_t *) args;
395 if (data_ptr)
396 rt_mp_free(data_ptr);
397 }
398 break;
399 default:
400 result = audio->ops->control(audio, cmd, args);
401 break;
402 }
403
404 return result;
405 }
406
407 #ifdef RT_USING_DEVICE_OPS
408 const static struct rt_device_ops audio_ops =
409 {
410 _audio_dev_init,
411 _audio_dev_open,
412 _audio_dev_close,
413 _audio_dev_read,
414 _audio_dev_write,
415 _audio_dev_control
416 };
417 #endif
418
rt_audio_register(struct rt_audio_device * audio,const char * name,rt_uint32_t flag,void * data)419 rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
420 {
421 struct rt_device *device;
422 RT_ASSERT(audio != RT_NULL);
423 device = &(audio->parent);
424
425 device->type = RT_Device_Class_Sound;
426 device->rx_indicate = RT_NULL;
427 device->tx_complete = RT_NULL;
428
429 #ifdef RT_USING_DEVICE_OPS
430 device->ops = &audio_ops;
431 #else
432 device->init = _audio_dev_init;
433 device->open = _audio_dev_open;
434 device->close = _audio_dev_close;
435 device->read = _audio_dev_read;
436 device->write = _audio_dev_write;
437 device->control = _audio_dev_control;
438 #endif
439 device->user_data = data;
440
441 //init memory pool for replay
442 {
443 rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ);
444 rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ,
445 AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2);
446 }
447
448 /* register a character device */
449 return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
450 }
451
rt_audio_samplerate_to_speed(rt_uint32_t bitValue)452 int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
453 {
454 int speed = 0;
455 switch (bitValue)
456 {
457 case AUDIO_SAMP_RATE_8K:
458 speed = 8000;
459 break;
460 case AUDIO_SAMP_RATE_11K:
461 speed = 11052;
462 break;
463 case AUDIO_SAMP_RATE_16K:
464 speed = 16000;
465 break;
466 case AUDIO_SAMP_RATE_22K:
467 speed = 22050;
468 break;
469 case AUDIO_SAMP_RATE_32K:
470 speed = 32000;
471 break;
472 case AUDIO_SAMP_RATE_44K:
473 speed = 44100;
474 break;
475 case AUDIO_SAMP_RATE_48K:
476 speed = 48000;
477 break;
478 case AUDIO_SAMP_RATE_96K:
479 speed = 96000;
480 break;
481 case AUDIO_SAMP_RATE_128K:
482 speed = 128000;
483 break;
484 case AUDIO_SAMP_RATE_160K:
485 speed = 160000;
486 break;
487 case AUDIO_SAMP_RATE_172K:
488 speed = 176400;
489 break;
490 case AUDIO_SAMP_RATE_192K:
491 speed = 192000;
492 break;
493 default:
494
495 break;
496 }
497
498 return speed;
499 }
500
rt_audio_format_to_bits(rt_uint32_t format)501 rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format)
502 {
503 switch (format)
504 {
505 case AUDIO_FMT_PCM_U8:
506 case AUDIO_FMT_PCM_S8:
507 return 8;
508 case AUDIO_FMT_PCM_S16_LE:
509 case AUDIO_FMT_PCM_S16_BE:
510 case AUDIO_FMT_PCM_U16_LE:
511 case AUDIO_FMT_PCM_U16_BE:
512 return 16;
513 default:
514 return 32;
515 };
516 }
517
rt_audio_tx_complete(struct rt_audio_device * audio,rt_uint8_t * pbuf)518 void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf)
519 {
520 rt_err_t result;
521 AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf);
522
523 //try to send all frame
524 do
525 {
526 result = _audio_send_replay_frame(audio);
527 } while (result == RT_EOK);
528
529 /* notify transmitted complete. */
530 if (audio->parent.tx_complete != RT_NULL)
531 audio->parent.tx_complete(&audio->parent, (void *) pbuf);
532 }
533
rt_audio_rx_done(struct rt_audio_device * audio,rt_uint8_t * pbuf,rt_size_t len)534 void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
535 {
536 //save data to record pipe
537 rt_device_write(RT_DEVICE(RT_DEVICE(&audio_pipe)), 0, pbuf, len);
538
539 /* invoke callback */
540 if (audio->parent.rx_indicate != RT_NULL)
541 audio->parent.rx_indicate(&audio->parent, len);
542 }
543
544