Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wwsmg1
rt-thread
提交
3aa97964
R
rt-thread
项目概览
wwsmg1
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3aa97964
编写于
5月 07, 2017
作者:
B
Bernard Xiong
提交者:
GitHub
5月 07, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #732 from yygg/master
[DeviceDrivers] Add audio driver.
上级
5b73dfa0
c046b78f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
1066 addition
and
3 deletion
+1066
-3
components/drivers/audio/SConscript
components/drivers/audio/SConscript
+9
-0
components/drivers/audio/audio.c
components/drivers/audio/audio.c
+843
-0
components/drivers/include/drivers/audio.h
components/drivers/include/drivers/audio.h
+214
-3
未找到文件。
components/drivers/audio/SConscript
0 → 100644
浏览文件 @
3aa97964
from
building
import
*
cwd
=
GetCurrentDir
()
src
=
Glob
(
'*.c'
)
CPPPATH
=
[
cwd
]
group
=
DefineGroup
(
'cJSON'
,
src
,
depend
=
[
'RT_USING_AUDIO'
],
CPPPATH
=
CPPPATH
)
Return
(
'group'
)
components/drivers/audio/audio.c
0 → 100644
浏览文件 @
3aa97964
/*
* audio.c
*
* Created on: 20161019
* Author: Urey
*/
#include <stdio.h>
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <drivers/audio.h>
#define AUDIO_DEBUG 0
#if AUDIO_DEBUG
#define AUDIO_DBG(...) printf("[AUDIO]:"),printf(__VA_ARGS__)
#else
#define AUDIO_DBG(...)
#endif
rt_err_t
_audio_queue_init
(
struct
rt_audio_queue
*
queue
,
rt_uint16_t
size
,
rt_uint16_t
lwm
)
{
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_list_init
(
&
(
queue
->
suspended_push_list
));
rt_list_init
(
&
(
queue
->
suspended_pop_list
));
queue
->
queue
=
(
struct
rt_audio_frame
*
)
rt_malloc
(
sizeof
(
struct
rt_audio_frame
)
*
size
);
if
(
queue
->
queue
==
RT_NULL
)
{
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
;
/* 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 */
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
;
}
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
)
{
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
)))
{
/* 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
);
/* perform a schedule */
rt_schedule
();
}
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
);
return
RT_EOK
;
}
rt_err_t
_audio_queue_unpeak
(
struct
rt_audio_queue
*
queue
,
struct
rt_audio_frame
*
frame
)
{
rt_ubase_t
level
;
RT_ASSERT
(
queue
!=
RT_NULL
);
level
=
rt_hw_interrupt_disable
();
if
(
queue
->
count
==
0
)
{
rt_hw_interrupt_enable
(
level
);
return
-
RT_EEMPTY
;
}
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
;
/* initialize replay & record */
audio
->
replay
=
RT_NULL
;
audio
->
record
=
RT_NULL
;
/* apply configuration */
if
(
audio
->
ops
->
init
)
result
=
audio
->
ops
->
init
(
audio
);
return
result
;
}
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_ASSERT
(
dev
!=
RT_NULL
);
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
))
return
-
RT_EIO
;
if
((
oflag
&
RT_DEVICE_OFLAG_WRONLY
)
&&
!
(
dev
->
flag
&
RT_DEVICE_FLAG_WRONLY
))
return
-
RT_EIO
;
/* get open flags */
dev
->
open_flag
=
oflag
&
0xff
;
/* 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
));
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
);
replay
->
activated
=
RT_FALSE
;
audio
->
replay
=
replay
;
}
dev
->
open_flag
|=
RT_DEVICE_OFLAG_WRONLY
;
}
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
);
}
dev
->
open_flag
|=
RT_DEVICE_OFLAG_RDONLY
;
}
return
RT_EOK
;
}
static
rt_err_t
_audio_dev_close
(
struct
rt_device
*
dev
)
{
struct
rt_audio_device
*
audio
;
RT_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
//shutdown the lower device
if
(
audio
->
ops
->
shutdown
!=
RT_NULL
)
audio
->
ops
->
shutdown
(
audio
);
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_WRONLY
)
{
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
);
//indicate this frame complete(maybe upper device need free data)
if
(
dev
->
tx_complete
!=
RT_NULL
)
dev
->
tx_complete
(
dev
,(
void
*
)
frame
.
data_ptr
);
}
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_WRONLY
;
}
if
(
dev
->
open_flag
&
RT_DEVICE_OFLAG_RDONLY
)
{
//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
));
dev
->
open_flag
&=
~
RT_DEVICE_OFLAG_RDONLY
;
}
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
;
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
;
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_ASSERT
(
dev
!=
RT_NULL
);
audio
=
(
struct
rt_audio_device
*
)
dev
;
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
)
{
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
)
{
audio
->
replay
->
activated
=
RT_TRUE
;
rt_hw_interrupt_enable
(
level
);
_audio_send_replay_frame
(
audio
);
}
return
size
;
}
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_ASSERT
(
dev
!=
RT_NULL
);
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
;
}
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
->
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
;
/* 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
;
}
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
;
};
}
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
);
}
void
rt_audio_rx_done
(
struct
rt_audio_device
*
audio
,
rt_uint8_t
*
pbuf
,
rt_size_t
len
)
{
rt_err_t
result
=
RT_EOK
;
//save data to record pipe
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
);
}
components/drivers/include/drivers/audio.h
浏览文件 @
3aa97964
#ifndef AUDIO_H__
#define AUDIO_H__
#ifndef __AUDIO_H__
#define __AUDIO_H__
//#define AUDIO_DEVICE_USE_PRIVATE_BUFFER
/* AUDIO command */
#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)
/* 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
/* 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
/* 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
/* 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
/* 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
/* 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)
enum
{
AUDIO_STREAM_REPLAY
=
0
,
AUDIO_STREAM_RECORD
,
AUDIO_STREAM_LAST
=
AUDIO_STREAM_RECORD
,
};
/* 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 */
};
struct
rt_audio_buf_desc
{
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
;
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
(
*
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
);
//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
};
struct
rt_audio_configure
{
rt_uint32_t
channels
;
rt_uint32_t
samplefmt
;
rt_uint32_t
samplerate
;
rt_uint32_t
samplefmts
;
};
struct
rt_audio_caps
{
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_audio_record
{
rt_bool_t
activated
;
struct
rt_pipe_device
pipe
;
};
struct
rt_audio_device
{
struct
rt_device
parent
;
struct
rt_audio_ops
*
ops
;
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
);
/* Device Control Commands */
#define CODEC_CMD_RESET 0
...
...
@@ -11,4 +222,4 @@
#define CODEC_VOLUME_MAX (63)
#endif
#endif
/* __AUDIO_H__ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录