Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
okll00
rt-thread
提交
94746d8e
R
rt-thread
项目概览
okll00
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
94746d8e
编写于
8月 16, 2017
作者:
Y
yygg_you
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
audio驱动使用系统内的dataqueue,修复一些缩进,乱码
上级
05496a5c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
484 addition
and
785 deletion
+484
-785
components/drivers/audio/audio.c
components/drivers/audio/audio.c
+349
-655
components/drivers/include/drivers/audio.h
components/drivers/include/drivers/audio.h
+135
-130
未找到文件。
components/drivers/audio/audio.c
浏览文件 @
94746d8e
/*
* audio.c
* File : audio.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
*
* Created on: 20161019
* Author: Urey
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-05-09 Urey first version
*/
#include <stdio.h>
...
...
@@ -19,383 +36,70 @@
#define AUDIO_DBG(...)
#endif
rt_err_t
_audio_queue_init
(
struct
rt_audio_queue
*
queue
,
rt_uint16_t
size
,
rt_uint16_t
lwm
)
static
rt_err_t
_audio_send_replay_frame
(
struct
rt_audio_device
*
audio
)
{
RT_ASSERT
(
queue
!=
RT_NULL
);
queue
->
count
=
0
;
queue
->
size
=
size
;
queue
->
lwm
=
lwm
;
queue
->
waiting_lwm
=
RT_FALSE
;
queue
->
get_index
=
0
;
queue
->
put_index
=
0
;
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_frame
frame
;
rt_list_init
(
&
(
queue
->
suspended_push_list
));
rt_list_init
(
&
(
queue
->
suspended_pop_list
));
RT_ASSERT
(
audio
!=
RT_NULL
);
queue
->
queue
=
(
struct
rt_audio_frame
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_frame
)
*
size
);
if
(
queue
->
queue
==
RT_NULL
)
//check repaly queue is empty
if
(
rt_data_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
)
!=
RT_EOK
)
{
return
-
RT_ENOMEM
;
}
return
RT_EOK
;
}
rt_err_t
_audio_queue_push
(
struct
rt_audio_queue
*
queue
,
struct
rt_audio_frame
*
frame
,
rt_int32_t
timeout
)
{
rt_ubase_t
level
;
rt_thread_t
thread
;
rt_err_t
result
;
RT_ASSERT
(
queue
!=
RT_NULL
);
result
=
RT_EOK
;
thread
=
rt_thread_self
();
AUDIO_DBG
(
"%s count = %d
\n
"
,
__func__
,
queue
->
count
);
level
=
rt_hw_interrupt_disable
();
while
(
queue
->
count
==
queue
->
size
)
{
// audio queue is full
queue
->
waiting_lwm
=
RT_TRUE
;
/* queue is full */
if
(
timeout
==
0
)
{
result
=
-
RT_ETIMEOUT
;
goto
__exit
;
}
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT
;
AUDIO_DBG
(
"TX queue is empty
\n
"
);
result
=
-
RT_EEMPTY
;
/* reset thread error number */
thread
->
error
=
RT_EOK
;
/* suspend thread on the push list */
rt_thread_suspend
(
thread
);
rt_list_insert_before
(
&
(
queue
->
suspended_push_list
),
&
(
thread
->
tlist
));
/* start timer */
if
(
timeout
>
0
)
{
/* reset the timeout of thread timer and start it */
rt_timer_control
(
&
(
thread
->
thread_timer
),
RT_TIMER_CTRL_SET_TIME
,
&
timeout
);
rt_timer_start
(
&
(
thread
->
thread_timer
));
}
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
/* do schedule */
rt_schedule
();
/* thread is waked up */
result
=
thread
->
error
;
level
=
rt_hw_interrupt_disable
();
if
(
result
!=
RT_EOK
)
goto
__exit
;
}
queue
->
queue
[
queue
->
put_index
].
data_ptr
=
frame
->
data_ptr
;
queue
->
queue
[
queue
->
put_index
].
data_size
=
frame
->
data_size
;
queue
->
queue
[
queue
->
put_index
].
data_ofs
=
frame
->
data_ofs
;
queue
->
put_index
=
(
queue
->
put_index
+
1
)
%
queue
->
size
;
queue
->
count
++
;
if
(
!
rt_list_isempty
(
&
(
queue
->
suspended_pop_list
)))
{
/* there is at least one thread in suspended list */
/* get thread entry */
thread
=
rt_list_entry
(
queue
->
suspended_pop_list
.
next
,
struct
rt_thread
,
tlist
);
/* resume it */
rt_thread_resume
(
thread
);
rt_hw_interrupt_enable
(
level
);
/* perform a schedule */
rt_schedule
();
return
result
;
}
__exit:
rt_hw_interrupt_enable
(
level
);
return
result
;
}
rt_err_t
_audio_queue_pop
(
struct
rt_audio_queue
*
queue
,
struct
rt_audio_frame
*
frame
,
rt_int32_t
timeout
)
{
rt_ubase_t
level
;
rt_thread_t
thread
;
rt_err_t
result
;
RT_ASSERT
(
queue
!=
RT_NULL
);
RT_ASSERT
(
frame
!=
RT_NULL
);
result
=
RT_EOK
;
thread
=
rt_thread_self
();
AUDIO_DBG
(
"%s count = %d
\n
"
,
__func__
,
queue
->
count
);
level
=
rt_hw_interrupt_disable
();
while
(
queue
->
count
==
0
)
{
/* queue is empty */
if
(
timeout
==
0
)
{
result
=
-
RT_ETIMEOUT
;
goto
__exit
;
}
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT
;
/* reset thread error number */
thread
->
error
=
RT_EOK
;
/* suspend thread on the pop list */
rt_thread_suspend
(
thread
);
rt_list_insert_before
(
&
(
queue
->
suspended_pop_list
),
&
(
thread
->
tlist
));
/* start timer */
if
(
timeout
>
0
)
{
/* reset the timeout of thread timer and start it */
rt_timer_control
(
&
(
thread
->
thread_timer
),
RT_TIMER_CTRL_SET_TIME
,
&
timeout
);
rt_timer_start
(
&
(
thread
->
thread_timer
));
}
/* enable interrupt */
audio
->
replay
->
activated
=
RT_FALSE
;
rt_hw_interrupt_enable
(
level
);
/* do schedule */
rt_schedule
();
/* thread is waked up */
result
=
thread
->
error
;
level
=
rt_hw_interrupt_disable
();
if
(
result
!=
RT_EOK
)
goto
__exit
;
goto
_exit
;
}
frame
->
data_ptr
=
queue
->
queue
[
queue
->
get_index
].
data_ptr
;
frame
->
data_size
=
queue
->
queue
[
queue
->
get_index
].
data_size
;
frame
->
data_ofs
=
queue
->
queue
[
queue
->
get_index
].
data_ofs
;
queue
->
get_index
=
(
queue
->
get_index
+
1
)
%
queue
->
size
;
queue
->
count
--
;
if
((
queue
->
waiting_lwm
==
RT_TRUE
)
&&
(
queue
->
put_index
-
queue
->
get_index
)
<=
queue
->
lwm
)
if
(
audio
->
ops
->
transmit
!=
RT_NULL
)
{
queue
->
waiting_lwm
=
RT_FALSE
;
/*
* there is at least one thread in suspended list
* and less than low water mark
*/
if
(
!
rt_list_isempty
(
&
(
queue
->
suspended_push_list
)))
AUDIO_DBG
(
"audio transmit...
\n
"
);
if
(
audio
->
ops
->
transmit
(
audio
,
frame
.
data_ptr
,
RT_NULL
,
frame
.
data_size
)
!=
frame
.
data_size
)
{
/* get thread entry */
thread
=
rt_list_entry
(
queue
->
suspended_push_list
.
next
,
struct
rt_thread
,
tlist
);
/* resume it */
rt_thread_resume
(
thread
);
rt_hw_interrupt_enable
(
level
);
result
=
-
RT_EBUSY
;
/* perform a schedule */
rt_schedule
();
goto
_exit
;
}
return
result
;
}
__exit:
rt_hw_interrupt_enable
(
level
);
return
result
;
}
rt_err_t
_audio_queue_peak
(
struct
rt_audio_queue
*
queue
,
struct
rt_audio_frame
*
frame
)
{
rt_ubase_t
level
;
RT_ASSERT
(
queue
!=
RT_NULL
);
AUDIO_DBG
(
"%s count = %d
\n
"
,
__func__
,
queue
->
count
);
level
=
rt_hw_interrupt_disable
();
if
(
queue
->
count
==
0
)
{
rt_hw_interrupt_enable
(
level
);
return
-
RT_EEMPTY
;
}
frame
->
data_ptr
=
queue
->
queue
[
queue
->
get_index
].
data_ptr
;
frame
->
data_size
=
queue
->
queue
[
queue
->
get_index
].
data_size
;
frame
->
data_ofs
=
queue
->
queue
[
queue
->
get_index
].
data_ofs
;
rt_hw_interrupt_enable
(
level
);
//pop the head frame...
rt_data_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
,
RT_WAITING_FOREVER
);
return
RT_EOK
;
_exit:
return
result
;
}
rt_err_t
_audio_queue_unpeak
(
struct
rt_audio_queue
*
queue
,
struct
rt_audio_frame
*
frame
)
static
rt_err_t
_audio_flush_replay_frame
(
struct
rt_audio_device
*
audio
)
{
rt_ubase_t
level
;
RT_ASSERT
(
queue
!=
RT_NULL
);
struct
rt_audio_frame
frame
;
level
=
rt_hw_interrupt_disable
();
if
(
queue
->
count
==
0
)
if
(
audio
->
replay
==
RT_NULL
)
return
-
RT_EIO
;
while
(
rt_data_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
)
==
RT_EOK
)
{
rt_hw_interrupt_enable
(
level
);
//pop the head frame...
rt_data_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
,
RT_WAITING_FOREVER
);
return
-
RT_EEMPTY
;
/* notify transmitted complete. */
if
(
audio
->
parent
.
tx_complete
!=
RT_NULL
)
audio
->
parent
.
tx_complete
(
&
audio
->
parent
,
(
void
*
)
frame
.
data_ptr
);
}
queue
->
queue
[
queue
->
get_index
].
data_ptr
=
frame
->
data_ptr
;
queue
->
queue
[
queue
->
get_index
].
data_size
=
frame
->
data_size
;
queue
->
queue
[
queue
->
get_index
].
data_ofs
=
frame
->
data_ofs
;
rt_hw_interrupt_enable
(
level
);
return
RT_EOK
;
}
rt_err_t
_audio_queue_reset
(
struct
rt_audio_queue
*
queue
)
{
struct
rt_thread
*
thread
;
register
rt_ubase_t
temp
;
rt_enter_critical
();
/* wakeup all suspend threads */
/* resume on pop list */
while
(
!
rt_list_isempty
(
&
(
queue
->
suspended_pop_list
)))
{
/* disable interrupt */
temp
=
rt_hw_interrupt_disable
();
/* get next suspend thread */
thread
=
rt_list_entry
(
queue
->
suspended_pop_list
.
next
,
struct
rt_thread
,
tlist
);
/* set error code to RT_ERROR */
thread
->
error
=
-
RT_ERROR
;
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
* suspend list
*/
rt_thread_resume
(
thread
);
/* enable interrupt */
rt_hw_interrupt_enable
(
temp
);
}
/* resume on push list */
while
(
!
rt_list_isempty
(
&
(
queue
->
suspended_push_list
)))
{
/* disable interrupt */
temp
=
rt_hw_interrupt_disable
();
/* get next suspend thread */
thread
=
rt_list_entry
(
queue
->
suspended_push_list
.
next
,
struct
rt_thread
,
tlist
);
/* set error code to RT_ERROR */
thread
->
error
=
-
RT_ERROR
;
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
* suspend list
*/
rt_thread_resume
(
thread
);
/* enable interrupt */
rt_hw_interrupt_enable
(
temp
);
}
rt_exit_critical
();
rt_schedule
();
}
static
rt_err_t
_audio_send_replay_frame
(
struct
rt_audio_device
*
audio
)
{
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_frame
frame
;
RT_ASSERT
(
audio
!=
RT_NULL
);
//check repaly queue is empty
if
(
_audio_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
)
!=
RT_EOK
)
{
AUDIO_DBG
(
"TX queue is empty
\n
"
);
result
=
-
RT_EEMPTY
;
level
=
rt_hw_interrupt_disable
();
audio
->
replay
->
activated
=
RT_FALSE
;
rt_hw_interrupt_enable
(
level
);
goto
_exit
;
}
if
(
audio
->
ops
->
transmit
!=
RT_NULL
)
{
AUDIO_DBG
(
"audio transmit...
\n
"
);
if
(
audio
->
ops
->
transmit
(
audio
,
frame
.
data_ptr
,
RT_NULL
,
frame
.
data_size
)
!=
frame
.
data_size
)
{
result
=
-
RT_EBUSY
;
goto
_exit
;
}
}
//pop the head frame...
_audio_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
,
RT_WAITING_NO
);
_exit:
return
result
;
}
static
rt_err_t
_audio_flush_replay_frame
(
struct
rt_audio_device
*
audio
)
{
struct
rt_audio_frame
frame
;
if
(
audio
->
replay
==
RT_NULL
)
return
-
RT_EIO
;
while
(
_audio_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
)
==
RT_EOK
)
{
//pop the head frame...
_audio_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
,
RT_WAITING_NO
);
/* notify transmitted complete. */
if
(
audio
->
parent
.
tx_complete
!=
RT_NULL
)
audio
->
parent
.
tx_complete
(
&
audio
->
parent
,(
void
*
)
frame
.
data_ptr
);
}
return
RT_EOK
;
}
static
rt_err_t
_audio_dev_init
(
struct
rt_device
*
dev
)
{
rt_err_t
result
=
RT_EOK
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
/* initialize replay & record */
audio
->
replay
=
RT_NULL
;
...
...
@@ -410,12 +114,12 @@ static rt_err_t _audio_dev_init(struct rt_device *dev)
static
rt_err_t
_audio_dev_open
(
struct
rt_device
*
dev
,
rt_uint16_t
oflag
)
{
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_device
*
audio
;
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
/* check device flag with the open flag */
if
((
oflag
&
RT_DEVICE_OFLAG_RDONLY
)
&&
!
(
dev
->
flag
&
RT_DEVICE_FLAG_RDONLY
))
...
...
@@ -429,64 +133,65 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
/* initialize the Rx/Tx structure according to open flag */
if
(
oflag
&
RT_DEVICE_OFLAG_WRONLY
)
{
AUDIO_DBG
(
"open audio device ,oflag = %x
\n
"
,
oflag
);
if
(
audio
->
replay
==
RT_NULL
)
{
struct
rt_audio_replay
*
replay
=
(
struct
rt_audio_replay
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_replay
));
AUDIO_DBG
(
"open audio device ,oflag = %x
\n
"
,
oflag
);
if
(
audio
->
replay
==
RT_NULL
)
{
struct
rt_audio_replay
*
replay
=
(
struct
rt_audio_replay
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_replay
));
if
(
replay
==
RT_NULL
)
{
AUDIO_DBG
(
"request memory for replay error
\n
"
);
return
-
RT_ENOMEM
;
}
if
(
replay
==
RT_NULL
)
{
AUDIO_DBG
(
"request memory for replay error
\n
"
);
return
-
RT_ENOMEM
;
}
//init queue for audio replay
_audio_queue_init
(
&
replay
->
queue
,
CFG_AUDIO_REPLAY_QUEUE_COUNT
,
CFG_AUDIO_REPLAY_QUEUE_COUNT
/
2
);
//init queue for audio replay
rt_data_queue_init
(
&
replay
->
queue
,
CFG_AUDIO_REPLAY_QUEUE_COUNT
,
CFG_AUDIO_REPLAY_QUEUE_COUNT
/
2
,
RT_NULL
);
replay
->
activated
=
RT_FALSE
;
audio
->
replay
=
replay
;
}
replay
->
activated
=
RT_FALSE
;
audio
->
replay
=
replay
;
}
dev
->
open_flag
|=
RT_DEVICE_OFLAG_WRONLY
;
}
if
(
oflag
&
RT_DEVICE_OFLAG_RDONLY
)
if
(
oflag
&
RT_DEVICE_OFLAG_RDONLY
)
{
if
(
audio
->
record
==
RT_NULL
)
{
struct
rt_audio_record
*
record
=
(
struct
rt_audio_record
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_record
));
if
(
record
==
RT_NULL
)
{
AUDIO_DBG
(
"request memory for record error
\n
"
);
return
-
RT_ENOMEM
;
}
//init pipe for record
{
rt_size_t
size
=
CFG_AUDIO_RECORD_PIPE_SIZE
;
rt_uint8_t
*
buf
=
rt_malloc
(
CFG_AUDIO_RECORD_PIPE_SIZE
);
if
(
buf
==
RT_NULL
)
{
rt_free
(
record
);
AUDIO_DBG
(
"request pipe memory error
\n
"
);
return
-
RT_ENOMEM
;
}
rt_pipe_init
(
&
record
->
pipe
,
"recpipe"
,
RT_PIPE_FLAG_FORCE_WR
|
RT_PIPE_FLAG_BLOCK_RD
,
buf
,
CFG_AUDIO_RECORD_PIPE_SIZE
);
}
record
->
activated
=
RT_FALSE
;
audio
->
record
=
record
;
}
//open record pipe
if
(
audio
->
record
!=
RT_NULL
)
{
rt_device_open
(
RT_DEVICE
(
&
audio
->
record
->
pipe
),
RT_DEVICE_OFLAG_RDONLY
);
}
if
(
audio
->
record
==
RT_NULL
)
{
struct
rt_audio_record
*
record
=
(
struct
rt_audio_record
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_record
));
if
(
record
==
RT_NULL
)
{
AUDIO_DBG
(
"request memory for record error
\n
"
);
return
-
RT_ENOMEM
;
}
//init pipe for record
{
rt_size_t
size
=
CFG_AUDIO_RECORD_PIPE_SIZE
;
rt_uint8_t
*
buf
=
rt_malloc
(
CFG_AUDIO_RECORD_PIPE_SIZE
);
if
(
buf
==
RT_NULL
)
{
rt_free
(
record
);
AUDIO_DBG
(
"request pipe memory error
\n
"
);
return
-
RT_ENOMEM
;
}
rt_pipe_init
(
&
record
->
pipe
,
"recpipe"
,
RT_PIPE_FLAG_FORCE_WR
|
RT_PIPE_FLAG_BLOCK_RD
,
buf
,
CFG_AUDIO_RECORD_PIPE_SIZE
);
}
record
->
activated
=
RT_FALSE
;
audio
->
record
=
record
;
}
//open record pipe
if
(
audio
->
record
!=
RT_NULL
)
{
rt_device_open
(
RT_DEVICE
(
&
audio
->
record
->
pipe
),
RT_DEVICE_OFLAG_RDONLY
);
}
dev
->
open_flag
|=
RT_DEVICE_OFLAG_RDONLY
;
}
...
...
@@ -496,96 +201,93 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
static
rt_err_t
_audio_dev_close
(
struct
rt_device
*
dev
)
{
struct
rt_audio_device
*
audio
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
//shutdown the lower device
if
(
audio
->
ops
->
shutdown
!=
RT_NULL
)
audio
->
ops
->
shutdown
(
audio
);
//shutdown the lower device
if
(
audio
->
ops
->
shutdown
!=
RT_NULL
)
audio
->
ops
->
shutdown
(
audio
);
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_WRONLY
)
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_WRONLY
)
{
struct
rt_audio_frame
frame
;
//stop replay stream
audio
->
ops
->
stop
(
audio
,
AUDIO_STREAM_REPLAY
);
struct
rt_audio_frame
frame
;
//stop replay stream
audio
->
ops
->
stop
(
audio
,
AUDIO_STREAM_REPLAY
);
//flush all frame
while
(
_audio_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
)
==
RT_EOK
)
{
_audio_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
,
RT_WAITING_NO
);
//flush all frame
while
(
rt_data_queue_peak
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
)
==
RT_EOK
)
{
//pop the head frame...
rt_data_queue_pop
(
&
audio
->
replay
->
queue
,
&
frame
.
data_ptr
,
&
frame
.
data_size
,
RT_WAITING_FOREVER
);
//indicate this frame complete(maybe upper device need free data)
if
(
dev
->
tx_complete
!=
RT_NULL
)
dev
->
tx_complete
(
dev
,(
void
*
)
frame
.
data_ptr
);
}
/* notify transmitted complete. */
if
(
audio
->
parent
.
tx_complete
!=
RT_NULL
)
audio
->
parent
.
tx_complete
(
&
audio
->
parent
,
(
void
*
)
frame
.
data_ptr
);
}
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_WRONLY
;
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_WRONLY
;
}
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_RDONLY
)
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_RDONLY
)
{
//stop record stream
audio
->
ops
->
stop
(
audio
,
AUDIO_STREAM_RECORD
);
//stop record stream
audio
->
ops
->
stop
(
audio
,
AUDIO_STREAM_RECORD
);
//close record pipe
if
(
audio
->
record
!=
RT_NULL
)
rt_device_close
(
RT_DEVICE
(
&
audio
->
record
->
pipe
));
//close record pipe
if
(
audio
->
record
!=
RT_NULL
)
rt_device_close
(
RT_DEVICE
(
&
audio
->
record
->
pipe
));
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_RDONLY
;
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_RDONLY
;
}
return
RT_EOK
;
return
RT_EOK
;
}
static
rt_size_t
_audio_dev_read
(
struct
rt_device
*
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
struct
rt_audio_device
*
audio
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
if
(
!
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_RDONLY
)
||
(
audio
->
record
==
RT_NULL
))
return
0
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
if
(
!
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_RDONLY
)
||
(
audio
->
record
==
RT_NULL
))
return
0
;
return
rt_device_read
(
RT_DEVICE
(
&
audio
->
record
->
pipe
),
pos
,
buffer
,
size
);
}
static
rt_size_t
_audio_dev_write
(
struct
rt_device
*
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
{
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_device
*
audio
;
rt_err_t
result
=
RT_EOK
;
rt_base_t
level
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
if
(
!
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_WRONLY
)
||
(
audio
->
replay
==
RT_NULL
))
return
0
;
if
(
!
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_WRONLY
)
||
(
audio
->
replay
==
RT_NULL
))
return
0
;
AUDIO_DBG
(
"audio write : pos = %d,buffer = %x,size = %d
\n
"
,
pos
,(
rt_uint32_t
)
buffer
,
size
);
//push a new frame to tx queue
{
struct
rt_audio_frame
frame
;
frame
.
data_ptr
=
buffer
;
frame
.
data_size
=
size
;
frame
.
data_ofs
=
0
;
result
=
_audio_queue_push
(
&
audio
->
replay
->
queue
,
&
frame
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
result
=
rt_data_queue_push
(
&
audio
->
replay
->
queue
,
buffer
,
size
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
AUDIO_DBG
(
"TX frame queue push error
\n
"
);
rt_set_errno
(
-
RT_EFULL
);
AUDIO_DBG
(
"TX frame queue push error
\n
"
);
rt_set_errno
(
-
RT_EFULL
);
return
0
;
}
}
//check tx state...
level
=
rt_hw_interrupt_disable
();
if
(
audio
->
replay
->
activated
!=
RT_TRUE
)
if
(
audio
->
replay
->
activated
!=
RT_TRUE
)
{
audio
->
replay
->
activated
=
RT_TRUE
;
rt_hw_interrupt_enable
(
level
);
audio
->
replay
->
activated
=
RT_TRUE
;
rt_hw_interrupt_enable
(
level
);
_audio_send_replay_frame
(
audio
);
_audio_send_replay_frame
(
audio
);
}
return
size
;
...
...
@@ -593,251 +295,243 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi
static
rt_err_t
_audio_dev_control
(
struct
rt_device
*
dev
,
rt_uint8_t
cmd
,
void
*
args
)
{
rt_err_t
result
=
RT_EOK
;
struct
rt_audio_device
*
audio
;
rt_err_t
result
=
RT_EOK
;
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
audio
=
(
struct
rt_audio_device
*
)
dev
;
//dev stat...
switch
(
cmd
)
{
case
AUDIO_CTL_GETCAPS
:
{
struct
rt_audio_caps
*
caps
=
(
struct
rt_audio_caps
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d
\n
"
,
caps
->
main_type
,
caps
->
sub_type
);
if
(
audio
->
ops
->
getcaps
!=
RT_NULL
)
{
result
=
audio
->
ops
->
getcaps
(
audio
,
caps
);
}
}
break
;
case
AUDIO_CTL_CONFIGURE
:
{
struct
rt_audio_caps
*
caps
=
(
struct
rt_audio_caps
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d
\n
"
,
caps
->
main_type
,
caps
->
sub_type
);
if
(
audio
->
ops
->
configure
!=
RT_NULL
)
{
result
=
audio
->
ops
->
configure
(
audio
,
caps
);
}
}
break
;
case
AUDIO_CTL_SHUTDOWN
:
{
AUDIO_DBG
(
"AUDIO_CTL_SHUTDOWN
\n
"
);
if
(
audio
->
ops
->
shutdown
!=
RT_NULL
)
result
=
audio
->
ops
->
shutdown
(
audio
);
//flush replay frame...
_audio_flush_replay_frame
(
audio
);
}
break
;
case
AUDIO_CTL_START
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_START: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
start
(
audio
,
stream
);
}
break
;
case
AUDIO_CTL_STOP
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_STOP: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
stop
(
audio
,
stream
);
if
(
stream
==
AUDIO_STREAM_REPLAY
)
{
_audio_flush_replay_frame
(
audio
);
}
}
break
;
case
AUDIO_CTL_PAUSE
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_PAUSE: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
suspend
(
audio
,
stream
);
}
break
;
case
AUDIO_CTL_RESUME
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_RESUME: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
resume
(
audio
,
stream
);
//resume tx frame...
if
(
stream
==
AUDIO_STREAM_REPLAY
)
_audio_send_replay_frame
(
audio
);
}
break
;
#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER
case
AUDIO_CTL_ALLOCBUFFER
:
{
struct
rt_audio_buf_desc
*
desc
=
(
struct
rt_audio_buf_desc
*
)
args
;
if
((
audio
->
ops
->
buffer_alloc
!=
RT_NULL
)
&&
(
desc
!=
RT_NULL
))
{
result
=
audio
->
ops
->
buffer_alloc
(
audio
,
&
desc
->
data_ptr
,
&
desc
->
data_size
);
break
;
}
result
=
-
RT_EIO
;
}
break
;
case
AUDIO_CTL_FREEBUFFER
:
{
rt_uint8_t
*
data_ptr
=
(
rt_uint8_t
*
)
args
;
if
((
audio
->
ops
->
buffer_free
!=
RT_NULL
)
&&
(
data_ptr
!=
RT_NULL
))
{
audio
->
ops
->
buffer_free
(
audio
,
data_ptr
);
break
;
}
}
break
;
#endif
default:
result
=
audio
->
ops
->
control
(
audio
,
cmd
,
args
);
break
;
}
switch
(
cmd
)
{
case
AUDIO_CTL_GETCAPS
:
{
struct
rt_audio_caps
*
caps
=
(
struct
rt_audio_caps
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d
\n
"
,
caps
->
main_type
,
caps
->
sub_type
);
if
(
audio
->
ops
->
getcaps
!=
RT_NULL
)
{
result
=
audio
->
ops
->
getcaps
(
audio
,
caps
);
}
}
break
;
case
AUDIO_CTL_CONFIGURE
:
{
struct
rt_audio_caps
*
caps
=
(
struct
rt_audio_caps
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d
\n
"
,
caps
->
main_type
,
caps
->
sub_type
);
if
(
audio
->
ops
->
configure
!=
RT_NULL
)
{
result
=
audio
->
ops
->
configure
(
audio
,
caps
);
}
}
break
;
case
AUDIO_CTL_SHUTDOWN
:
{
AUDIO_DBG
(
"AUDIO_CTL_SHUTDOWN
\n
"
);
if
(
audio
->
ops
->
shutdown
!=
RT_NULL
)
result
=
audio
->
ops
->
shutdown
(
audio
);
//flush replay frame...
_audio_flush_replay_frame
(
audio
);
}
break
;
case
AUDIO_CTL_START
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_START: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
start
(
audio
,
stream
);
}
break
;
case
AUDIO_CTL_STOP
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_STOP: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
stop
(
audio
,
stream
);
if
(
stream
==
AUDIO_STREAM_REPLAY
)
{
_audio_flush_replay_frame
(
audio
);
}
}
break
;
case
AUDIO_CTL_PAUSE
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_PAUSE: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
suspend
(
audio
,
stream
);
}
break
;
case
AUDIO_CTL_RESUME
:
{
int
stream
=
*
(
int
*
)
args
;
AUDIO_DBG
(
"AUDIO_CTL_RESUME: stream = %d
\n
"
,
stream
);
if
(
audio
->
ops
->
start
!=
RT_NULL
)
result
=
audio
->
ops
->
resume
(
audio
,
stream
);
//resume tx frame...
if
(
stream
==
AUDIO_STREAM_REPLAY
)
_audio_send_replay_frame
(
audio
);
}
break
;
case
AUDIO_CTL_ALLOCBUFFER
:
{
struct
rt_audio_buf_desc
*
desc
=
(
struct
rt_audio_buf_desc
*
)
args
;
if
(
desc
)
{
desc
->
data_size
=
AUDIO_DEVICE_DECODE_MP_BLOCK_SZ
*
2
;
desc
->
data_ptr
=
rt_mp_alloc
(
&
audio
->
mp
,
RT_WAITING_FOREVER
);
result
=
RT_EOK
;
}
else
result
=
-
RT_EIO
;
}
break
;
case
AUDIO_CTL_FREEBUFFER
:
{
rt_uint8_t
*
data_ptr
=
(
rt_uint8_t
*
)
args
;
if
(
data_ptr
)
rt_mp_free
(
data_ptr
);
}
break
;
default:
result
=
audio
->
ops
->
control
(
audio
,
cmd
,
args
);
break
;
}
return
result
;
}
rt_err_t
rt_audio_register
(
struct
rt_audio_device
*
audio
,
const
char
*
name
,
rt_uint32_t
flag
,
void
*
data
)
{
struct
rt_device
*
device
;
RT_ASSERT
(
audio
!=
RT_NULL
);
device
=
&
(
audio
->
parent
);
device
->
type
=
RT_Device_Class_Sound
;
device
->
type
=
RT_Device_Class_Sound
;
device
->
rx_indicate
=
RT_NULL
;
device
->
tx_complete
=
RT_NULL
;
device
->
init
=
_audio_dev_init
;
device
->
open
=
_audio_dev_open
;
device
->
close
=
_audio_dev_close
;
device
->
read
=
_audio_dev_read
;
device
->
write
=
_audio_dev_write
;
device
->
control
=
_audio_dev_control
;
device
->
user_data
=
data
;
device
->
init
=
_audio_dev_init
;
device
->
open
=
_audio_dev_open
;
device
->
close
=
_audio_dev_close
;
device
->
read
=
_audio_dev_read
;
device
->
write
=
_audio_dev_write
;
device
->
control
=
_audio_dev_control
;
device
->
user_data
=
data
;
//init memory pool for replay
{
rt_uint8_t
*
mempool
=
rt_malloc
(
AUDIO_DEVICE_DECODE_MP_SZ
);
rt_mp_init
(
&
audio
->
mp
,
"adu_mp"
,
mempool
,
AUDIO_DEVICE_DECODE_MP_SZ
,
AUDIO_DEVICE_DECODE_MP_BLOCK_SZ
*
2
);
}
/* register a character device */
return
rt_device_register
(
device
,
name
,
flag
|
RT_DEVICE_FLAG_REMOVABLE
);
}
rt_size_t
rt_audio_get_buffer_size
(
struct
rt_audio_device
*
audio
)
{
// return (audio->config.period_count * audio->config.period_size);
return
0
;
}
int
rt_audio_samplerate_to_speed
(
rt_uint32_t
bitValue
)
{
int
speed
=
0
;
switch
(
bitValue
)
{
case
AUDIO_SAMP_RATE_8K
:
speed
=
8000
;
break
;
case
AUDIO_SAMP_RATE_11K
:
speed
=
11052
;
break
;
case
AUDIO_SAMP_RATE_16K
:
speed
=
16000
;
break
;
case
AUDIO_SAMP_RATE_22K
:
speed
=
22050
;
break
;
case
AUDIO_SAMP_RATE_32K
:
speed
=
32000
;
break
;
case
AUDIO_SAMP_RATE_44K
:
speed
=
44100
;
break
;
case
AUDIO_SAMP_RATE_48K
:
speed
=
48000
;
break
;
case
AUDIO_SAMP_RATE_96K
:
speed
=
96000
;
break
;
case
AUDIO_SAMP_RATE_128K
:
speed
=
128000
;
break
;
case
AUDIO_SAMP_RATE_160K
:
speed
=
160000
;
break
;
case
AUDIO_SAMP_RATE_172K
:
speed
=
176400
;
break
;
case
AUDIO_SAMP_RATE_192K
:
speed
=
192000
;
break
;
default:
break
;
}
return
speed
;
}
int
speed
=
0
;
switch
(
bitValue
)
{
case
AUDIO_SAMP_RATE_8K
:
speed
=
8000
;
break
;
case
AUDIO_SAMP_RATE_11K
:
speed
=
11052
;
break
;
case
AUDIO_SAMP_RATE_16K
:
speed
=
16000
;
break
;
case
AUDIO_SAMP_RATE_22K
:
speed
=
22050
;
break
;
case
AUDIO_SAMP_RATE_32K
:
speed
=
32000
;
break
;
case
AUDIO_SAMP_RATE_44K
:
speed
=
44100
;
break
;
case
AUDIO_SAMP_RATE_48K
:
speed
=
48000
;
break
;
case
AUDIO_SAMP_RATE_96K
:
speed
=
96000
;
break
;
case
AUDIO_SAMP_RATE_128K
:
speed
=
128000
;
break
;
case
AUDIO_SAMP_RATE_160K
:
speed
=
160000
;
break
;
case
AUDIO_SAMP_RATE_172K
:
speed
=
176400
;
break
;
case
AUDIO_SAMP_RATE_192K
:
speed
=
192000
;
break
;
default:
break
;
}
return
speed
;
}
rt_uint32_t
rt_audio_format_to_bits
(
rt_uint32_t
format
)
{
switch
(
format
)
{
case
AUDIO_FMT_PCM_U8
:
case
AUDIO_FMT_PCM_S8
:
return
8
;
case
AUDIO_FMT_PCM_S16_LE
:
case
AUDIO_FMT_PCM_S16_BE
:
case
AUDIO_FMT_PCM_U16_LE
:
case
AUDIO_FMT_PCM_U16_BE
:
return
16
;
default:
return
32
;
case
AUDIO_FMT_PCM_U8
:
case
AUDIO_FMT_PCM_S8
:
return
8
;
case
AUDIO_FMT_PCM_S16_LE
:
case
AUDIO_FMT_PCM_S16_BE
:
case
AUDIO_FMT_PCM_U16_LE
:
case
AUDIO_FMT_PCM_U16_BE
:
return
16
;
default:
return
32
;
};
}
void
rt_audio_tx_complete
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
)
void
rt_audio_tx_complete
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
)
{
rt_err_t
result
;
AUDIO_DBG
(
"audio tx complete ptr=%x...
\n
"
,(
rt_uint32_t
)
pbuf
);
//try to send all frame
do
{
result
=
_audio_send_replay_frame
(
audio
);
}
while
(
result
==
RT_EOK
);
/* notify transmitted complete. */
if
(
audio
->
parent
.
tx_complete
!=
RT_NULL
)
audio
->
parent
.
tx_complete
(
&
audio
->
parent
,(
void
*
)
pbuf
);
rt_err_t
result
;
AUDIO_DBG
(
"audio tx complete ptr=%x...
\n
"
,(
rt_uint32_t
)
pbuf
);
//try to send all frame
do
{
result
=
_audio_send_replay_frame
(
audio
);
}
while
(
result
==
RT_EOK
);
/* notify transmitted complete. */
if
(
audio
->
parent
.
tx_complete
!=
RT_NULL
)
audio
->
parent
.
tx_complete
(
&
audio
->
parent
,
(
void
*
)
pbuf
);
}
void
rt_audio_rx_done
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
,
rt_size_t
len
)
void
rt_audio_rx_done
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
,
rt_size_t
len
)
{
rt_err_t
result
=
RT_EOK
;
rt_err_t
result
=
RT_EOK
;
//save data to record pipe
rt_device_write
(
RT_DEVICE
(
RT_DEVICE
(
&
audio
->
record
->
pipe
)),
0
,
pbuf
,
len
);
rt_device_write
(
RT_DEVICE
(
RT_DEVICE
(
&
audio
->
record
->
pipe
)),
0
,
pbuf
,
len
);
/* invoke callback */
if
(
audio
->
parent
.
rx_indicate
!=
RT_NULL
)
audio
->
parent
.
rx_indicate
(
&
audio
->
parent
,
len
);
if
(
audio
->
parent
.
rx_indicate
!=
RT_NULL
)
audio
->
parent
.
rx_indicate
(
&
audio
->
parent
,
len
);
}
components/drivers/include/drivers/audio.h
浏览文件 @
94746d8e
/*
* File : audio.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-05-09 Urey first version
*/
#ifndef __AUDIO_H__
#define __AUDIO_H__
//#define AUDIO_DEVICE_USE_PRIVATE_BUFFER
/* AUDIO command */
#define _AUDIO_CTL(a)
(0x10 + a)
#define _AUDIO_CTL(a) (0x10 + a)
#define AUDIO_CTL_GETCAPS _AUDIO_CTL(1)
#define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2)
#define AUDIO_CTL_SHUTDOWN _AUDIO_CTL(3)
#define AUDIO_CTL_START _AUDIO_CTL(4)
#define AUDIO_CTL_STOP _AUDIO_CTL(5)
#define AUDIO_CTL_PAUSE _AUDIO_CTL(6)
#define AUDIO_CTL_RESUME _AUDIO_CTL(7)
#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(8)
#define AUDIO_CTL_ALLOCBUFFER _AUDIO_CTL(9)
#define AUDIO_CTL_FREEBUFFER _AUDIO_CTL(10)
#define AUDIO_CTL_HWRESET _AUDIO_CTL(11)
#define AUDIO_CTL_GETCAPS
_AUDIO_CTL(1)
#define AUDIO_CTL_CONFIGURE
_AUDIO_CTL(2)
#define AUDIO_CTL_SHUTDOWN
_AUDIO_CTL(3)
#define AUDIO_CTL_START
_AUDIO_CTL(4)
#define AUDIO_CTL_STOP
_AUDIO_CTL(5)
#define AUDIO_CTL_PAUSE
_AUDIO_CTL(6)
#define AUDIO_CTL_RESUME
_AUDIO_CTL(7)
#define AUDIO_CTL_GETBUFFERINFO
_AUDIO_CTL(8)
#define AUDIO_CTL_ALLOCBUFFER
_AUDIO_CTL(9)
#define AUDIO_CTL_FREEBUFFER
_AUDIO_CTL(10)
#define AUDIO_CTL_HWRESET
_AUDIO_CTL(11)
/* Audio Device Types */
#define AUDIO_TYPE_QUERY 0x00
#define AUDIO_TYPE_INPUT 0x01
#define AUDIO_TYPE_OUTPUT 0x02
#define AUDIO_TYPE_MIXER 0x04
#define AUDIO_TYPE_SELECTOR 0x08
#define AUDIO_TYPE_EFFECT 0x10
#define AUDIO_TYPE_QUERY
0x00
#define AUDIO_TYPE_INPUT
0x01
#define AUDIO_TYPE_OUTPUT
0x02
#define AUDIO_TYPE_MIXER
0x04
#define AUDIO_TYPE_SELECTOR
0x08
#define AUDIO_TYPE_EFFECT
0x10
/* Audio Format Types */
#define AUDIO_FMT_PCM_U8 0x0001
#define AUDIO_FMT_PCM_S8 0x0002
#define AUDIO_FMT_PCM_U16_LE 0x0010
#define AUDIO_FMT_PCM_S16_BE 0x0020
#define AUDIO_FMT_PCM_S16_LE 0x0040
#define AUDIO_FMT_PCM_U16_BE 0x0080
#define AUDIO_FMT_PCM_U24_LE 0x0100
#define AUDIO_FMT_PCM_S24_BE 0x0200
#define AUDIO_FMT_PCM_S24_LE 0x0400
#define AUDIO_FMT_PCM_U24_BE 0x0800
#define AUDIO_FMT_PCM_U32_LE 0x1000
#define AUDIO_FMT_PCM_S32_BE 0x2000
#define AUDIO_FMT_PCM_S32_LE 0x4000
#define AUDIO_FMT_PCM_U32_BE 0x8000
#define AUDIO_FMT_PCM_U8
0x0001
#define AUDIO_FMT_PCM_S8
0x0002
#define AUDIO_FMT_PCM_U16_LE
0x0010
#define AUDIO_FMT_PCM_S16_BE
0x0020
#define AUDIO_FMT_PCM_S16_LE
0x0040
#define AUDIO_FMT_PCM_U16_BE
0x0080
#define AUDIO_FMT_PCM_U24_LE
0x0100
#define AUDIO_FMT_PCM_S24_BE
0x0200
#define AUDIO_FMT_PCM_S24_LE
0x0400
#define AUDIO_FMT_PCM_U24_BE
0x0800
#define AUDIO_FMT_PCM_U32_LE
0x1000
#define AUDIO_FMT_PCM_S32_BE
0x2000
#define AUDIO_FMT_PCM_S32_LE
0x4000
#define AUDIO_FMT_PCM_U32_BE
0x8000
/* Supported Sampling Rates */
#define AUDIO_SAMP_RATE_8K 0x0001
#define AUDIO_SAMP_RATE_11K 0x0002
#define AUDIO_SAMP_RATE_16K 0x0004
#define AUDIO_SAMP_RATE_22K 0x0008
#define AUDIO_SAMP_RATE_32K 0x0010
#define AUDIO_SAMP_RATE_44K 0x0020
#define AUDIO_SAMP_RATE_48K 0x0040
#define AUDIO_SAMP_RATE_96K 0x0080
#define AUDIO_SAMP_RATE_128K 0x0100
#define AUDIO_SAMP_RATE_160K 0x0200
#define AUDIO_SAMP_RATE_172K 0x0400
#define AUDIO_SAMP_RATE_192K 0x0800
#define AUDIO_SAMP_RATE_8K
0x0001
#define AUDIO_SAMP_RATE_11K
0x0002
#define AUDIO_SAMP_RATE_16K
0x0004
#define AUDIO_SAMP_RATE_22K
0x0008
#define AUDIO_SAMP_RATE_32K
0x0010
#define AUDIO_SAMP_RATE_44K
0x0020
#define AUDIO_SAMP_RATE_48K
0x0040
#define AUDIO_SAMP_RATE_96K
0x0080
#define AUDIO_SAMP_RATE_128K
0x0100
#define AUDIO_SAMP_RATE_160K
0x0200
#define AUDIO_SAMP_RATE_172K
0x0400
#define AUDIO_SAMP_RATE_192K
0x0800
/* Supported Bit Rates */
#define AUDIO_BIT_RATE_22K 0x01
#define AUDIO_BIT_RATE_44K 0x02
#define AUDIO_BIT_RATE_48K 0x04
#define AUDIO_BIT_RATE_96K 0x08
#define AUDIO_BIT_RATE_128K 0x10
#define AUDIO_BIT_RATE_160K 0x20
#define AUDIO_BIT_RATE_172K 0x40
#define AUDIO_BIT_RATE_192K 0x80
#define AUDIO_BIT_RATE_22K
0x01
#define AUDIO_BIT_RATE_44K
0x02
#define AUDIO_BIT_RATE_48K
0x04
#define AUDIO_BIT_RATE_96K
0x08
#define AUDIO_BIT_RATE_128K
0x10
#define AUDIO_BIT_RATE_160K
0x20
#define AUDIO_BIT_RATE_172K
0x40
#define AUDIO_BIT_RATE_192K
0x80
/* Support Dsp(input/output) Units controls */
#define AUDIO_DSP_PARAM
0
/* get/set all params */
#define AUDIO_DSP_SAMPLERATE
1
/* Ƶ */
#define AUDIO_DSP_FMT 2
#define AUDIO_DSP_CHANNELS 3
#define AUDIO_DSP_PARAM
0
/* get/set all params */
#define AUDIO_DSP_SAMPLERATE
1
/* Ƶ */
#define AUDIO_DSP_FMT
2
#define AUDIO_DSP_CHANNELS
3
/* Supported Mixer Units controls */
#define AUDIO_MIXER_QUERY 0x0000
#define AUDIO_MIXER_MUTE 0x0001
#define AUDIO_MIXER_VOLUME 0x0002
#define AUDIO_MIXER_BASS 0x0004
#define AUDIO_MIXER_MID 0x0008
#define AUDIO_MIXER_TREBLE 0x0010
#define AUDIO_MIXER_EQUALIZER 0x0020
#define AUDIO_MIXER_LINE 0x0040
#define AUDIO_MIXER_DIGITAL 0x0080
#define AUDIO_MIXER_MIC 0x0100
#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command
#define CFG_AUDIO_REPLAY_QUEUE_COUNT 4
#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024)
#define AUDIO_MIXER_QUERY 0x0000
#define AUDIO_MIXER_MUTE 0x0001
#define AUDIO_MIXER_VOLUME 0x0002
#define AUDIO_MIXER_BASS 0x0004
#define AUDIO_MIXER_MID 0x0008
#define AUDIO_MIXER_TREBLE 0x0010
#define AUDIO_MIXER_EQUALIZER 0x0020
#define AUDIO_MIXER_LINE 0x0040
#define AUDIO_MIXER_DIGITAL 0x0080
#define AUDIO_MIXER_MIC 0x0100
#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command
#define CFG_AUDIO_REPLAY_QUEUE_COUNT 4
#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024)
#define AUDIO_DEVICE_MP_CNT (4)
#define AUDIO_DEVICE_DECODE_MP_BLOCK_SZ (4352 * 4)
#define AUDIO_DEVICE_DECODE_MP_SZ ((AUDIO_DEVICE_DECODE_MP_BLOCK_SZ*2 + 4)*AUDIO_DEVICE_MP_CNT)
enum
{
...
...
@@ -104,36 +129,19 @@ enum
/* the preferred number and size of audio pipeline buffer for the audio device */
struct
rt_audio_buf_info
{
rt_uint32_t
buffer_size
;
/* Preferred qty of buffers */
rt_uint32_t
buffer_count
;
/* Preferred size of the buffers */
rt_uint32_t
buffer_size
;
/* Preferred qty of buffers */
rt_uint32_t
buffer_count
;
/* Preferred size of the buffers */
};
struct
rt_audio_buf_desc
{
rt_uint8_t
*
data_ptr
;
rt_size_t
data_size
;
rt_uint8_t
*
data_ptr
;
rt_size_t
data_size
;
};
struct
rt_audio_frame
{
const
void
*
data_ptr
;
rt_size_t
data_size
;
rt_size_t
data_ofs
;
};
struct
rt_audio_queue
{
rt_uint16_t
count
;
rt_uint16_t
size
;
rt_uint16_t
lwm
;
rt_bool_t
waiting_lwm
;
rt_uint16_t
get_index
;
rt_uint16_t
put_index
;
struct
rt_audio_frame
*
queue
;
rt_list_t
suspended_push_list
;
rt_list_t
suspended_pop_list
;
};
struct
rt_audio_device
;
...
...
@@ -141,25 +149,21 @@ struct rt_audio_caps;
struct
rt_audio_configure
;
struct
rt_audio_ops
{
rt_err_t
(
*
getcaps
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_caps
*
caps
);
rt_err_t
(
*
configure
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_caps
*
caps
);
rt_err_t
(
*
getcaps
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_caps
*
caps
);
rt_err_t
(
*
configure
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_caps
*
caps
);
rt_err_t
(
*
init
)
(
struct
rt_audio_device
*
audio
);
rt_err_t
(
*
shutdown
)
(
struct
rt_audio_device
*
audio
);
rt_err_t
(
*
start
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
stop
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
suspend
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
resume
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
init
)
(
struct
rt_audio_device
*
audio
);
rt_err_t
(
*
shutdown
)
(
struct
rt_audio_device
*
audio
);
rt_err_t
(
*
start
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
stop
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
suspend
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
resume
)
(
struct
rt_audio_device
*
audio
,
int
stream
);
rt_err_t
(
*
control
)
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
cmd
,
void
*
arg
);
rt_size_t
(
*
transmit
)
(
struct
rt_audio_device
*
audio
,
const
void
*
writeBuf
,
void
*
readBuf
,
rt_size_t
size
);
rt_err_t
(
*
control
)
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
cmd
,
void
*
arg
);
rt_size_t
(
*
transmit
)
(
struct
rt_audio_device
*
audio
,
const
void
*
writeBuf
,
void
*
readBuf
,
rt_size_t
size
);
//get page size of codec or private buffer's info
void
(
*
buffer_info
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_buf_info
*
info
);
#ifdef AUDIO_DEVICE_USE_PRIVATE_BUFFER
rt_err_t
(
*
buffer_alloc
)
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
**
data_ptr
,
rt_size_t
*
size
);
void
(
*
buffer_free
)
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
data_ptr
);
#endif
void
(
*
buffer_info
)
(
struct
rt_audio_device
*
audio
,
struct
rt_audio_buf_info
*
info
);
};
...
...
@@ -174,42 +178,44 @@ struct rt_audio_configure
struct
rt_audio_caps
{
int
main_type
;
int
sub_type
;
union
{
rt_uint32_t
mask
;
int
value
;
struct
rt_audio_configure
config
;
}
udata
;
int
main_type
;
int
sub_type
;
union
{
rt_uint32_t
mask
;
int
value
;
struct
rt_audio_configure
config
;
}
udata
;
};
struct
rt_audio_replay
{
rt_bool_t
activated
;
struct
rt_
audio_queue
queue
;
struct
rt_
data_queue
queue
;
};
struct
rt_audio_record
{
rt_bool_t
activated
;
struct
rt_pipe_device
pipe
;
struct
rt_pipe_device
pipe
;
};
struct
rt_audio_device
{
struct
rt_device
parent
;
struct
rt_audio_ops
*
ops
;
struct
rt_audio_ops
*
ops
;
struct
rt_mempool
mp
;
struct
rt_audio_replay
*
replay
;
struct
rt_audio_record
*
record
;
struct
rt_audio_replay
*
replay
;
struct
rt_audio_record
*
record
;
};
rt_err_t
rt_audio_register
(
struct
rt_audio_device
*
audio
,
const
char
*
name
,
rt_uint32_t
flag
,
void
*
data
);
void
rt_audio_tx_complete
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
);
void
rt_audio_rx_done
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
,
rt_size_t
len
);
rt_uint32_t
rt_audio_format_to_bits
(
rt_uint32_t
format
);
rt_err_t
rt_audio_register
(
struct
rt_audio_device
*
audio
,
const
char
*
name
,
rt_uint32_t
flag
,
void
*
data
);
void
rt_audio_tx_complete
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
);
void
rt_audio_rx_done
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
,
rt_size_t
len
);
rt_uint32_t
rt_audio_format_to_bits
(
rt_uint32_t
format
);
/* Device Control Commands */
...
...
@@ -219,7 +225,6 @@ rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format);
#define CODEC_CMD_SAMPLERATE 3
#define CODEC_CMD_EQ 4
#define CODEC_CMD_3D 5
#define CODEC_CMD_SWITCH 6
#define CODEC_VOLUME_MAX (63)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录