Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
宁楠萍
rt-thread
提交
e14b1ac0
R
rt-thread
项目概览
宁楠萍
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
2
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,发现更多精彩内容 >>
提交
e14b1ac0
编写于
11月 15, 2018
作者:
E
EvalZero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[bsp][stm32f429-apollo]add audio sound and micphone driver.
上级
45960a8d
变更
9
展开全部
隐藏空白更改
内联
并排
Showing
9 changed file
with
1663 addition
and
6 deletion
+1663
-6
bsp/stm32f429-apollo/drivers/Kconfig
bsp/stm32f429-apollo/drivers/Kconfig
+5
-0
bsp/stm32f429-apollo/drivers/SConscript
bsp/stm32f429-apollo/drivers/SConscript
+14
-4
bsp/stm32f429-apollo/drivers/audio/drv_audio.h
bsp/stm32f429-apollo/drivers/audio/drv_audio.h
+41
-0
bsp/stm32f429-apollo/drivers/audio/drv_mic.c
bsp/stm32f429-apollo/drivers/audio/drv_mic.c
+254
-0
bsp/stm32f429-apollo/drivers/audio/drv_sound.c
bsp/stm32f429-apollo/drivers/audio/drv_sound.c
+594
-0
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.c
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.c
+733
-0
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.h
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.h
+19
-0
bsp/stm32f429-apollo/drivers/drv_spi.c
bsp/stm32f429-apollo/drivers/drv_spi.c
+2
-1
bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h
bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h
+1
-1
未找到文件。
bsp/stm32f429-apollo/drivers/Kconfig
浏览文件 @
e14b1ac0
...
...
@@ -18,6 +18,11 @@ config RT_USING_SPI5
bool "Enable SPI5"
default y
config RT_USING_SAI_AUDIO
select RT_USING_AUDIO
bool "Enable AUDIO"
default n
config RT_RTC_NAME
string "The name of RTC device"
default rtc
...
...
bsp/stm32f429-apollo/drivers/SConscript
浏览文件 @
e14b1ac0
...
...
@@ -2,8 +2,12 @@ from building import *
cwd
=
GetCurrentDir
()
# init src and inc vars
src
=
[]
inc
=
[]
# add the general drivers.
src
=
Split
(
"""
src
+
=
Split
(
"""
board.c
stm32f4xx_it.c
usart.c
...
...
@@ -12,6 +16,9 @@ drv_rtc.c
drv_mpu.c
"""
)
# add dwin basic include
inc
+=
[
cwd
]
# add sdio driver
if
GetDepend
(
'RT_USING_DFS'
):
src
+=
[
'drv_sdio_sd.c'
]
...
...
@@ -39,12 +46,15 @@ if GetDepend('RT_USING_SPI'):
if
GetDepend
(
'RT_USING_SFUD'
):
src
+=
[
'drv_spi_flash.c'
]
# add audio drivers.
if
GetDepend
(
'RT_USING_SAI_AUDIO'
):
src
+=
Glob
(
'./audio/*.c'
)
inc
+=
[
cwd
+
"/audio"
]
# add lcd drivers.
if
GetDepend
(
'PKG_USING_GUIENGINE'
):
src
+=
[
'drv_lcd.c'
]
CPPPATH
=
[
cwd
]
group
=
DefineGroup
(
'Drivers'
,
src
,
depend
=
[
''
],
CPPPATH
=
CPPPATH
)
group
=
DefineGroup
(
'Drivers'
,
src
,
depend
=
[
''
],
CPPPATH
=
inc
)
Return
(
'group'
)
bsp/stm32f429-apollo/drivers/audio/drv_audio.h
0 → 100644
浏览文件 @
e14b1ac0
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-14 ZeroFree first implementation
*/
#ifndef __DRV_AUDIO_H__
#define __DRV_AUDIO_H__
#include <rtthread.h>
#include <drivers/audio.h>
#include <audio_pipe.h>
/* SAIA DMA Stream TX definitions */
#define SAIA_TX_DMAx_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define SAIA_TX_DMAx_CLK_DISABLE() __HAL_RCC_DMA2_CLK_DISABLE()
#define SAIA_TX_DMAx_STREAM DMA2_Stream3
#define SAIA_TX_DMAx_CHANNEL DMA_CHANNEL_0
#define SAIA_TX_DMAx_IRQ DMA2_Stream3_IRQn
#define SAIA_TX_DMAx_PERIPH_DATA_SIZE DMA_PDATAALIGN_HALFWORD
#define SAIA_TX_DMAx_MEM_DATA_SIZE DMA_MDATAALIGN_HALFWORD
#define SAIA_TX_DMAx_IRQHandler DMA2_Stream3_IRQHandler
/* SAIB DMA Stream TX definitions */
#define SAIA_RX_DMAx_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define SAIA_RX_DMAx_CLK_DISABLE() __HAL_RCC_DMA2_CLK_DISABLE()
#define SAIA_RX_DMAx_STREAM DMA2_Stream5
#define SAIA_RX_DMAx_CHANNEL DMA_CHANNEL_0
#define SAIA_RX_DMAx_IRQ DMA2_Stream5_IRQn
#define SAIA_RX_DMAx_PERIPH_DATA_SIZE DMA_PDATAALIGN_HALFWORD
#define SAIA_RX_DMAx_MEM_DATA_SIZE DMA_MDATAALIGN_HALFWORD
#define SAIA_RX_DMAx_IRQHandler DMA2_Stream5_IRQHandler
int
SAIA_SampleRate_Set
(
uint32_t
samplerate
);
int
rt_hw_audio_init
(
char
*
i2c_bus_name
);
#endif
bsp/stm32f429-apollo/drivers/audio/drv_mic.c
0 → 100644
浏览文件 @
e14b1ac0
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-14 ZeroFree first implementation
*/
#include <rtthread.h>
#include <rthw.h>
#include <rtdevice.h>
#include <string.h>
#include "drv_audio.h"
#include "drv_wm8978.h"
#include <stm32f4xx.h>
#define DBG_ENABLE
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#define DBG_SECTION_NAME "MIC"
#include <rtdbg.h>
struct
micphone_device
{
struct
rt_device
parent
;
rt_uint16_t
*
recv_fifo
;
struct
rt_audio_pipe
record_pipe
;
/* i2c mode */
struct
rt_i2c_bus_device
*
i2c_device
;
};
#define AUDIO_RECV_BUFFER_SIZE (2048)
extern
SAI_HandleTypeDef
SAI1B_Handler
;
extern
DMA_HandleTypeDef
SAI1_RXDMA_Handler
;
extern
SAI_HandleTypeDef
SAI1A_Handler
;
extern
DMA_HandleTypeDef
SAI1_TXDMA_Handler
;
static
struct
micphone_device
micphone
;
static
uint16_t
send_fifo
[
2
]
=
{
0
,
0
};
static
void
SAIB_Init
(
void
)
{
HAL_SAI_DeInit
(
&
SAI1B_Handler
);
SAI1B_Handler
.
Instance
=
SAI1_Block_B
;
SAI1B_Handler
.
Init
.
AudioMode
=
SAI_MODESLAVE_RX
;
SAI1B_Handler
.
Init
.
Synchro
=
SAI_SYNCHRONOUS
;
SAI1B_Handler
.
Init
.
OutputDrive
=
SAI_OUTPUTDRIVE_ENABLE
;
SAI1B_Handler
.
Init
.
NoDivider
=
SAI_MASTERDIVIDER_ENABLE
;
SAI1B_Handler
.
Init
.
FIFOThreshold
=
SAI_FIFOTHRESHOLD_1QF
;
SAI1B_Handler
.
Init
.
ClockSource
=
SAI_CLKSOURCE_PLLI2S
;
SAI1B_Handler
.
Init
.
MonoStereoMode
=
SAI_MONOMODE
;
SAI1B_Handler
.
Init
.
Protocol
=
SAI_FREE_PROTOCOL
;
SAI1B_Handler
.
Init
.
DataSize
=
SAI_DATASIZE_16
;
SAI1B_Handler
.
Init
.
FirstBit
=
SAI_FIRSTBIT_MSB
;
SAI1B_Handler
.
Init
.
ClockStrobing
=
SAI_CLOCKSTROBING_RISINGEDGE
;
SAI1B_Handler
.
FrameInit
.
FrameLength
=
64
;
SAI1B_Handler
.
FrameInit
.
ActiveFrameLength
=
32
;
SAI1B_Handler
.
FrameInit
.
FSDefinition
=
SAI_FS_CHANNEL_IDENTIFICATION
;
SAI1B_Handler
.
FrameInit
.
FSPolarity
=
SAI_FS_ACTIVE_LOW
;
SAI1B_Handler
.
FrameInit
.
FSOffset
=
SAI_FS_BEFOREFIRSTBIT
;
SAI1B_Handler
.
SlotInit
.
FirstBitOffset
=
0
;
SAI1B_Handler
.
SlotInit
.
SlotSize
=
SAI_SLOTSIZE_32B
;
SAI1B_Handler
.
SlotInit
.
SlotNumber
=
2
;
SAI1B_Handler
.
SlotInit
.
SlotActive
=
SAI_SLOTACTIVE_0
|
SAI_SLOTACTIVE_1
;
HAL_SAI_Init
(
&
SAI1B_Handler
);
__HAL_SAI_ENABLE
(
&
SAI1B_Handler
);
SAIA_RX_DMAx_CLK_ENABLE
();
__HAL_LINKDMA
(
&
SAI1B_Handler
,
hdmarx
,
SAI1_RXDMA_Handler
);
SAI1_RXDMA_Handler
.
Instance
=
SAIA_RX_DMAx_STREAM
;
SAI1_RXDMA_Handler
.
Init
.
Channel
=
SAIA_RX_DMAx_CHANNEL
;
SAI1_RXDMA_Handler
.
Init
.
Direction
=
DMA_PERIPH_TO_MEMORY
;
SAI1_RXDMA_Handler
.
Init
.
PeriphInc
=
DMA_PINC_DISABLE
;
SAI1_RXDMA_Handler
.
Init
.
MemInc
=
DMA_MINC_ENABLE
;
SAI1_RXDMA_Handler
.
Init
.
PeriphDataAlignment
=
SAIA_RX_DMAx_PERIPH_DATA_SIZE
;
SAI1_RXDMA_Handler
.
Init
.
MemDataAlignment
=
SAIA_RX_DMAx_MEM_DATA_SIZE
;
SAI1_RXDMA_Handler
.
Init
.
Mode
=
DMA_CIRCULAR
;
SAI1_RXDMA_Handler
.
Init
.
Priority
=
DMA_PRIORITY_MEDIUM
;
SAI1_RXDMA_Handler
.
Init
.
FIFOMode
=
DMA_FIFOMODE_DISABLE
;
SAI1_RXDMA_Handler
.
Init
.
MemBurst
=
DMA_MBURST_SINGLE
;
SAI1_RXDMA_Handler
.
Init
.
PeriphBurst
=
DMA_PBURST_SINGLE
;
HAL_DMA_DeInit
(
&
SAI1_RXDMA_Handler
);
HAL_DMA_Init
(
&
SAI1_RXDMA_Handler
);
HAL_NVIC_SetPriority
(
SAIA_RX_DMAx_IRQ
,
0
,
1
);
HAL_NVIC_EnableIRQ
(
SAIA_RX_DMAx_IRQ
);
}
void
SAIA_RX_DMAx_IRQHandler
(
void
)
{
HAL_DMA_IRQHandler
(
&
SAI1_RXDMA_Handler
);
}
void
HAL_SAI_RxHalfCpltCallback
(
SAI_HandleTypeDef
*
hsai
)
{
if
(
hsai
==
&
SAI1B_Handler
)
{
rt_device_write
(
&
micphone
.
record_pipe
.
parent
,
0
,
micphone
.
recv_fifo
,
AUDIO_RECV_BUFFER_SIZE
/
2
);
}
}
void
HAL_SAI_RxCpltCallback
(
SAI_HandleTypeDef
*
hsai
)
{
if
(
hsai
==
&
SAI1B_Handler
)
{
rt_device_write
(
&
micphone
.
record_pipe
.
parent
,
0
,
micphone
.
recv_fifo
+
(
AUDIO_RECV_BUFFER_SIZE
/
4
),
AUDIO_RECV_BUFFER_SIZE
/
2
);
}
}
static
rt_err_t
micphone_init
(
rt_device_t
dev
)
{
SAIB_Init
();
return
RT_EOK
;
}
static
rt_err_t
micphone_open
(
rt_device_t
dev
,
rt_uint16_t
oflag
)
{
struct
micphone_device
*
mic
=
RT_NULL
;
mic
=
(
struct
micphone_device
*
)
dev
;
if
(
oflag
&
RT_DEVICE_OFLAG_RDONLY
)
{
LOG_I
(
"Open Micphone Device!"
);
rt_device_open
(
&
mic
->
record_pipe
.
parent
,
RT_DEVICE_OFLAG_RDONLY
);
/* Disable DMA Interruption */
__HAL_DMA_DISABLE_IT
(
&
SAI1_TXDMA_Handler
,
DMA_IT_TC
|
DMA_IT_HT
);
HAL_DMA_Start
(
&
SAI1_TXDMA_Handler
,
(
uint32_t
)
&
send_fifo
[
0
],
(
uint32_t
)
&
SAI1_Block_A
->
DR
,
2
);
/* Start RX DMA */
HAL_SAI_Receive_DMA
(
&
SAI1B_Handler
,
(
uint8_t
*
)(
micphone
.
recv_fifo
),
AUDIO_RECV_BUFFER_SIZE
/
2
);
}
return
RT_EOK
;
}
static
rt_size_t
micphone_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
struct
micphone_device
*
mic
=
RT_NULL
;
mic
=
(
struct
micphone_device
*
)
dev
;
return
rt_device_read
(
&
mic
->
record_pipe
.
parent
,
pos
,
buffer
,
size
);
}
static
rt_err_t
micphone_control
(
rt_device_t
dev
,
int
cmd
,
void
*
args
)
{
rt_err_t
value
,
result
=
RT_EOK
;
switch
(
cmd
)
{
case
CODEC_CMD_SET_VOLUME
:
{
// TODO
break
;
}
case
CODEC_CMD_SAMPLERATE
:
{
value
=
*
(
int
*
)
args
;
LOG_I
(
"Set Samplerate %d"
,
value
);
result
=
SAIA_SampleRate_Set
(
value
);
break
;
}
default:
break
;
}
return
result
;
}
static
rt_err_t
micphone_close
(
rt_device_t
dev
)
{
struct
micphone_device
*
mic
=
RT_NULL
;
mic
=
(
struct
micphone_device
*
)
dev
;
HAL_SAI_DMAStop
(
&
SAI1A_Handler
);
HAL_SAI_DMAStop
(
&
SAI1B_Handler
);
rt_device_close
(
&
mic
->
record_pipe
.
parent
);
LOG_I
(
"Close Micphone Device!"
);
return
RT_EOK
;
}
int
rt_hw_micphone_init
(
char
*
i2c_bus_name
)
{
int
result
=
RT_EOK
;
struct
micphone_device
*
mic
=
&
micphone
;
if
(
mic
->
recv_fifo
!=
RT_NULL
)
{
return
RT_EOK
;
}
mic
->
recv_fifo
=
rt_malloc
(
AUDIO_RECV_BUFFER_SIZE
);
if
(
mic
->
recv_fifo
==
RT_NULL
)
{
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
mic
->
recv_fifo
,
0
,
AUDIO_RECV_BUFFER_SIZE
);
mic
->
parent
.
type
=
RT_Device_Class_Sound
;
mic
->
parent
.
init
=
micphone_init
;
mic
->
parent
.
open
=
micphone_open
;
mic
->
parent
.
control
=
micphone_control
;
mic
->
parent
.
write
=
RT_NULL
;
mic
->
parent
.
read
=
micphone_read
;
mic
->
parent
.
close
=
micphone_close
;
mic
->
parent
.
user_data
=
mic
;
/* register the device */
rt_device_register
(
&
mic
->
parent
,
"mic"
,
RT_DEVICE_FLAG_RDONLY
|
RT_DEVICE_FLAG_DMA_RX
);
rt_device_init
(
&
mic
->
parent
);
{
rt_uint8_t
*
buffer
=
rt_malloc
(
AUDIO_RECV_BUFFER_SIZE
);
if
(
buffer
==
RT_NULL
)
{
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
buffer
,
0
,
AUDIO_RECV_BUFFER_SIZE
);
rt_audio_pipe_init
(
&
mic
->
record_pipe
,
"voice"
,
RT_PIPE_FLAG_FORCE_WR
|
RT_PIPE_FLAG_BLOCK_RD
,
buffer
,
AUDIO_RECV_BUFFER_SIZE
);
}
return
RT_EOK
;
__exit:
if
(
mic
->
recv_fifo
)
{
rt_free
(
mic
->
recv_fifo
);
mic
->
recv_fifo
=
RT_NULL
;
}
return
result
;
}
bsp/stm32f429-apollo/drivers/audio/drv_sound.c
0 → 100644
浏览文件 @
e14b1ac0
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-14 ZeroFree first implementation
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include <stdint.h>
#include <string.h>
#include "drv_audio.h"
#include "drv_wm8978.h"
#include <stm32f4xx.h>
#define DBG_ENABLE
#define DBG_LEVEL DBG_LOG
#define DBG_COLOR
#define DBG_SECTION_NAME "Sound"
#include <rtdbg.h>
/**
* Audio Memory Node Manage
*/
struct
rt_data_node
{
char
*
data_ptr
;
rt_uint32_t
data_size
;
};
struct
rt_data_node_list
{
struct
rt_data_node
*
node
;
rt_uint32_t
size
;
rt_uint32_t
read_index
,
write_index
;
rt_uint32_t
data_offset
;
void
(
*
read_complete
)(
struct
rt_data_node
*
node
,
void
*
user_data
);
void
*
user_data
;
};
int
rt_data_node_init
(
struct
rt_data_node_list
**
node_list
,
rt_uint32_t
size
)
{
int
result
=
RT_EOK
;
struct
rt_data_node_list
*
list
=
RT_NULL
;
struct
rt_data_node
*
node
=
RT_NULL
;
list
=
rt_malloc
(
sizeof
(
struct
rt_data_node_list
));
if
(
list
==
RT_NULL
)
{
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
list
,
0
,
sizeof
(
struct
rt_data_node_list
));
node
=
rt_malloc
(
sizeof
(
struct
rt_data_node
)
*
size
);
if
(
size
==
RT_NULL
)
{
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
node
,
0
,
sizeof
(
struct
rt_data_node
));
list
->
node
=
node
;
list
->
size
=
size
;
list
->
read_index
=
0
;
list
->
write_index
=
0
;
list
->
data_offset
=
0
;
list
->
read_complete
=
RT_NULL
;
list
->
user_data
=
0
;
*
node_list
=
list
;
return
result
;
__exit:
if
(
list
)
rt_free
(
list
);
if
(
node
)
rt_free
(
node
);
return
result
;
}
int
rt_data_node_is_empty
(
struct
rt_data_node_list
*
node_list
)
{
rt_uint32_t
read_index
,
write_index
;
rt_base_t
level
;
level
=
rt_hw_interrupt_disable
();
read_index
=
node_list
->
read_index
;
write_index
=
node_list
->
write_index
;
rt_hw_interrupt_enable
(
level
);
if
(
read_index
==
write_index
)
{
return
RT_TRUE
;
}
else
{
return
RT_FALSE
;
}
}
void
wait_node_free
(
struct
rt_data_node_list
*
node_list
)
{
while
(
node_list
->
read_index
!=
node_list
->
write_index
)
rt_thread_mdelay
(
5
);
}
int
rt_data_node_write
(
struct
rt_data_node_list
*
node_list
,
void
*
buffer
,
rt_uint32_t
size
)
{
struct
rt_data_node
*
node
=
RT_NULL
;
rt_uint32_t
read_index
,
write_index
,
next_index
;
rt_base_t
level
;
level
=
rt_hw_interrupt_disable
();
read_index
=
node_list
->
read_index
;
write_index
=
node_list
->
write_index
;
rt_hw_interrupt_enable
(
level
);
next_index
=
write_index
+
1
;
if
(
next_index
>=
node_list
->
size
)
next_index
=
0
;
if
(
next_index
==
read_index
)
{
rt_kprintf
(
"[node]:node list full, write index = %d, read index = %d
\n
"
,
write_index
,
read_index
);
return
-
RT_ERROR
;
}
level
=
rt_hw_interrupt_disable
();
/* set node attribute */
node
=
&
node_list
->
node
[
write_index
];
node
->
data_ptr
=
(
char
*
)
buffer
;
node
->
data_size
=
size
;
node_list
->
write_index
=
next_index
;
rt_hw_interrupt_enable
(
level
);
return
size
;
}
int
rt_data_node_read
(
struct
rt_data_node_list
*
node_list
,
void
*
buffer
,
rt_uint32_t
size
)
{
struct
rt_data_node
*
node
=
RT_NULL
;
rt_uint32_t
read_index
,
write_index
,
next_index
;
rt_int32_t
remain_len
,
copy_size
;
rt_uint32_t
read_offset
,
data_offset
;
rt_base_t
level
;
rt_uint32_t
result
=
size
;
level
=
rt_hw_interrupt_disable
();
read_index
=
node_list
->
read_index
;
write_index
=
node_list
->
write_index
;
rt_hw_interrupt_enable
(
level
);
read_offset
=
0
;
if
(
read_index
==
write_index
)
{
result
=
0
;
}
else
{
do
{
node
=
&
node_list
->
node
[
node_list
->
read_index
];
data_offset
=
node_list
->
data_offset
;
remain_len
=
node
->
data_size
-
data_offset
;
if
(
size
-
read_offset
>
remain_len
)
{
/* Full*/
copy_size
=
remain_len
;
}
else
{
/* reamain buffer */
copy_size
=
size
-
read_offset
;
}
memcpy
((
char
*
)
buffer
+
read_offset
,
node
->
data_ptr
+
data_offset
,
copy_size
);
read_offset
+=
copy_size
;
data_offset
+=
copy_size
;
node_list
->
data_offset
=
data_offset
;
if
(
data_offset
>=
node
->
data_size
)
{
/* notify transmitted complete. */
if
(
node_list
->
read_complete
!=
RT_NULL
)
{
node_list
->
read_complete
(
node
,
node_list
->
user_data
);
}
level
=
rt_hw_interrupt_disable
();
read_index
=
node_list
->
read_index
;
write_index
=
node_list
->
write_index
;
rt_hw_interrupt_enable
(
level
);
next_index
=
read_index
+
1
;
if
(
next_index
>=
node_list
->
size
)
next_index
=
0
;
level
=
rt_hw_interrupt_disable
();
node_list
->
read_index
=
next_index
;
node_list
->
data_offset
=
0
;
rt_hw_interrupt_enable
(
level
);
if
(
next_index
==
write_index
)
{
result
=
read_offset
;
break
;
}
}
}
while
(
read_offset
<
size
);
}
return
result
;
}
static
void
data_node_read_complete
(
struct
rt_data_node
*
node
,
void
*
user_data
)
{
struct
rt_device
*
dev
=
RT_NULL
;
dev
=
(
struct
rt_device
*
)
user_data
;
if
(
dev
->
tx_complete
!=
RT_NULL
)
{
dev
->
tx_complete
(
dev
,
node
->
data_ptr
);
}
}
/**
* RT-Thread Audio Device Driver
*/
struct
sound_device
{
struct
rt_device
parent
;
struct
rt_data_node_list
*
node_list
;
/* i2c mode */
struct
rt_i2c_bus_device
*
i2c_device
;
char
*
send_fifo
;
};
#define AUDIO_SEND_BUFFER_SIZE (2048 * 2)
SAI_HandleTypeDef
SAI1B_Handler
;
DMA_HandleTypeDef
SAI1_RXDMA_Handler
;
SAI_HandleTypeDef
SAI1A_Handler
;
DMA_HandleTypeDef
SAI1_TXDMA_Handler
;
static
struct
sound_device
*
sound
;
static
void
SAIA_Init
(
void
)
{
HAL_SAI_DeInit
(
&
SAI1A_Handler
);
// SAI1A_Handler.Init.AudioFrequency = 44100;
SAI1A_Handler
.
Instance
=
SAI1_Block_A
;
SAI1A_Handler
.
Init
.
AudioMode
=
SAI_MODEMASTER_TX
;
SAI1A_Handler
.
Init
.
Synchro
=
SAI_ASYNCHRONOUS
;
SAI1A_Handler
.
Init
.
OutputDrive
=
SAI_OUTPUTDRIVE_ENABLE
;
SAI1A_Handler
.
Init
.
NoDivider
=
SAI_MASTERDIVIDER_ENABLE
;
SAI1A_Handler
.
Init
.
FIFOThreshold
=
SAI_FIFOTHRESHOLD_EMPTY
;
SAI1A_Handler
.
Init
.
ClockSource
=
SAI_CLKSOURCE_PLLI2S
;
SAI1A_Handler
.
Init
.
MonoStereoMode
=
SAI_STEREOMODE
;
SAI1A_Handler
.
Init
.
Protocol
=
SAI_FREE_PROTOCOL
;
SAI1A_Handler
.
Init
.
DataSize
=
SAI_DATASIZE_16
;
SAI1A_Handler
.
Init
.
FirstBit
=
SAI_FIRSTBIT_MSB
;
SAI1A_Handler
.
Init
.
ClockStrobing
=
SAI_CLOCKSTROBING_RISINGEDGE
;
SAI1A_Handler
.
FrameInit
.
FrameLength
=
64
;
SAI1A_Handler
.
FrameInit
.
ActiveFrameLength
=
32
;
SAI1A_Handler
.
FrameInit
.
FSDefinition
=
SAI_FS_CHANNEL_IDENTIFICATION
;
SAI1A_Handler
.
FrameInit
.
FSPolarity
=
SAI_FS_ACTIVE_LOW
;
SAI1A_Handler
.
FrameInit
.
FSOffset
=
SAI_FS_BEFOREFIRSTBIT
;
SAI1A_Handler
.
SlotInit
.
FirstBitOffset
=
0
;
SAI1A_Handler
.
SlotInit
.
SlotSize
=
SAI_SLOTSIZE_32B
;
SAI1A_Handler
.
SlotInit
.
SlotNumber
=
2
;
SAI1A_Handler
.
SlotInit
.
SlotActive
=
SAI_SLOTACTIVE_0
|
SAI_SLOTACTIVE_1
;
HAL_SAI_Init
(
&
SAI1A_Handler
);
__HAL_SAI_ENABLE
(
&
SAI1A_Handler
);
/* DMA Configuration */
SAIA_TX_DMAx_CLK_ENABLE
();
__HAL_LINKDMA
(
&
SAI1A_Handler
,
hdmatx
,
SAI1_TXDMA_Handler
);
SAI1_TXDMA_Handler
.
Instance
=
SAIA_TX_DMAx_STREAM
;
SAI1_TXDMA_Handler
.
Init
.
Channel
=
SAIA_TX_DMAx_CHANNEL
;
SAI1_TXDMA_Handler
.
Init
.
Direction
=
DMA_MEMORY_TO_PERIPH
;
SAI1_TXDMA_Handler
.
Init
.
PeriphInc
=
DMA_PINC_DISABLE
;
SAI1_TXDMA_Handler
.
Init
.
MemInc
=
DMA_MINC_ENABLE
;
SAI1_TXDMA_Handler
.
Init
.
PeriphDataAlignment
=
SAIA_TX_DMAx_PERIPH_DATA_SIZE
;
SAI1_TXDMA_Handler
.
Init
.
MemDataAlignment
=
SAIA_TX_DMAx_MEM_DATA_SIZE
;
SAI1_TXDMA_Handler
.
Init
.
Mode
=
DMA_CIRCULAR
;
SAI1_TXDMA_Handler
.
Init
.
Priority
=
DMA_PRIORITY_HIGH
;
SAI1_TXDMA_Handler
.
Init
.
FIFOMode
=
DMA_FIFOMODE_ENABLE
;
SAI1_TXDMA_Handler
.
Init
.
FIFOThreshold
=
DMA_FIFO_THRESHOLD_1QUARTERFULL
;
SAI1_TXDMA_Handler
.
Init
.
MemBurst
=
DMA_MBURST_SINGLE
;
SAI1_TXDMA_Handler
.
Init
.
PeriphBurst
=
DMA_PBURST_SINGLE
;
HAL_DMA_DeInit
(
&
SAI1_TXDMA_Handler
);
HAL_DMA_Init
(
&
SAI1_TXDMA_Handler
);
HAL_NVIC_SetPriority
(
SAIA_TX_DMAx_IRQ
,
0
,
0
);
HAL_NVIC_EnableIRQ
(
SAIA_TX_DMAx_IRQ
);
}
const
uint16_t
SAI_PSC_TBL
[][
5
]
=
{
{
800
,
344
,
7
,
0
,
12
},
{
1102
,
429
,
2
,
18
,
2
},
{
1600
,
344
,
7
,
0
,
6
},
{
2205
,
429
,
2
,
18
,
1
},
{
3200
,
344
,
7
,
0
,
3
},
{
4410
,
429
,
2
,
18
,
0
},
{
4800
,
344
,
7
,
0
,
2
},
{
8820
,
271
,
2
,
2
,
1
},
{
9600
,
344
,
7
,
0
,
1
},
{
17640
,
271
,
2
,
2
,
0
},
{
19200
,
344
,
7
,
0
,
0
},
};
void
SAIA_DMA_Enable
(
void
)
{
SAI1_Block_A
->
CR1
|=
SAI_xCR1_DMAEN
;
}
void
SAIA_DMA_Disable
(
void
)
{
SAI1_Block_A
->
CR1
&=
~
SAI_xCR1_DMAEN
;
}
int
SAIA_SampleRate_Set
(
uint32_t
samplerate
)
{
uint16_t
i
=
0
;
RCC_PeriphCLKInitTypeDef
RCCSAI1_Sture
;
for
(
i
=
0
;
i
<
(
sizeof
(
SAI_PSC_TBL
)
/
10
);
i
++
)
{
if
((
samplerate
/
10
)
==
SAI_PSC_TBL
[
i
][
0
])
break
;
}
if
(
i
==
(
sizeof
(
SAI_PSC_TBL
)
/
10
))
return
-
RT_ERROR
;
RCCSAI1_Sture
.
PeriphClockSelection
=
RCC_PERIPHCLK_SAI_PLLI2S
;
RCCSAI1_Sture
.
PLLI2S
.
PLLI2SN
=
(
uint32_t
)
SAI_PSC_TBL
[
i
][
1
];
RCCSAI1_Sture
.
PLLI2S
.
PLLI2SQ
=
(
uint32_t
)
SAI_PSC_TBL
[
i
][
2
];
RCCSAI1_Sture
.
PLLI2SDivQ
=
SAI_PSC_TBL
[
i
][
3
]
+
1
;
HAL_RCCEx_PeriphCLKConfig
(
&
RCCSAI1_Sture
);
__HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG
(
RCC_SAIACLKSOURCE_PLLI2S
);
__HAL_SAI_DISABLE
(
&
SAI1A_Handler
);
SAIA_DMA_Disable
();
SAI1A_Handler
.
Init
.
AudioFrequency
=
samplerate
;
HAL_SAI_Init
(
&
SAI1A_Handler
);
SAIA_DMA_Enable
();
__HAL_SAI_ENABLE
(
&
SAI1A_Handler
);
return
RT_EOK
;
}
void
HAL_SAI_MspInit
(
SAI_HandleTypeDef
*
hsai
)
{
GPIO_InitTypeDef
GPIO_Initure
;
__HAL_RCC_SAI1_CLK_ENABLE
();
__HAL_RCC_GPIOE_CLK_ENABLE
();
GPIO_Initure
.
Pin
=
GPIO_PIN_2
|
GPIO_PIN_3
|
GPIO_PIN_4
|
GPIO_PIN_5
|
GPIO_PIN_6
;
GPIO_Initure
.
Mode
=
GPIO_MODE_AF_PP
;
GPIO_Initure
.
Pull
=
GPIO_PULLUP
;
GPIO_Initure
.
Speed
=
GPIO_SPEED_HIGH
;
GPIO_Initure
.
Alternate
=
GPIO_AF6_SAI1
;
HAL_GPIO_Init
(
GPIOE
,
&
GPIO_Initure
);
}
void
SAIA_TX_DMAx_IRQHandler
(
void
)
{
HAL_DMA_IRQHandler
(
&
SAI1_TXDMA_Handler
);
}
void
HAL_SAI_TxHalfCpltCallback
(
SAI_HandleTypeDef
*
hsai
)
{
int
result
;
struct
sound_device
*
snd
=
sound
;
if
(
hsai
==
&
SAI1A_Handler
)
{
result
=
rt_data_node_is_empty
(
snd
->
node_list
);
if
(
result
)
{
rt_kprintf
(
"# "
);
memset
(
snd
->
send_fifo
,
0
,
AUDIO_SEND_BUFFER_SIZE
/
2
);
}
else
{
memset
(
snd
->
send_fifo
,
0
,
AUDIO_SEND_BUFFER_SIZE
/
2
);
rt_data_node_read
(
snd
->
node_list
,
snd
->
send_fifo
,
AUDIO_SEND_BUFFER_SIZE
/
2
);
}
}
}
void
HAL_SAI_TxCpltCallback
(
SAI_HandleTypeDef
*
hsai
)
{
int
result
;
struct
sound_device
*
snd
=
sound
;
if
(
hsai
==
&
SAI1A_Handler
)
{
result
=
rt_data_node_is_empty
(
snd
->
node_list
);
if
(
result
)
{
rt_kprintf
(
"* "
);
memset
(
snd
->
send_fifo
+
(
AUDIO_SEND_BUFFER_SIZE
/
2
),
0
,
AUDIO_SEND_BUFFER_SIZE
/
2
);
}
else
{
memset
(
snd
->
send_fifo
+
(
AUDIO_SEND_BUFFER_SIZE
/
2
),
0
,
AUDIO_SEND_BUFFER_SIZE
/
2
);
rt_data_node_read
(
snd
->
node_list
,
snd
->
send_fifo
+
(
AUDIO_SEND_BUFFER_SIZE
/
2
),
AUDIO_SEND_BUFFER_SIZE
/
2
);
}
}
}
void
HAL_SAI_ErrorCallback
(
SAI_HandleTypeDef
*
hsai
)
{
rt_kprintf
(
"x "
);
}
static
rt_err_t
sound_init
(
rt_device_t
dev
)
{
int
result
;
struct
sound_device
*
snd
=
(
struct
sound_device
*
)
dev
;
SAIA_Init
();
result
=
wm8978_init
(
snd
->
i2c_device
);
return
result
;
}
static
rt_err_t
sound_open
(
rt_device_t
dev
,
rt_uint16_t
oflag
)
{
int
result
=
RT_EOK
;
struct
sound_device
*
snd
=
(
struct
sound_device
*
)
dev
;
LOG_I
(
"Open Sound Device!"
);
/* Configure DMA transmit */
result
=
HAL_SAI_Transmit_DMA
(
&
SAI1A_Handler
,
(
uint8_t
*
)(
snd
->
send_fifo
),
AUDIO_SEND_BUFFER_SIZE
/
2
);
if
(
result
!=
HAL_OK
)
{
LOG_E
(
"Start DMA Transmit Failed!"
);
result
=
-
RT_ERROR
;
}
return
result
;
}
static
rt_err_t
sound_control
(
rt_device_t
dev
,
int
cmd
,
void
*
args
)
{
int
value
,
result
=
RT_EOK
;
struct
sound_device
*
snd
=
(
struct
sound_device
*
)
dev
;
switch
(
cmd
)
{
case
CODEC_CMD_SET_VOLUME
:
value
=
*
(
int
*
)
args
;
if
(
value
<
0
||
value
>
99
)
{
LOG_W
(
"Please volume level 0 ~ 99"
);
result
=
-
RT_EINVAL
;
}
else
{
LOG_I
(
"Set volume level to %d"
,
value
);
wm8978_set_volume
(
snd
->
i2c_device
,
value
);
result
=
RT_EOK
;
}
break
;
case
CODEC_CMD_SAMPLERATE
:
value
=
*
(
int
*
)
args
;
LOG_I
(
"Set Samplerate %d"
,
value
);
SAIA_SampleRate_Set
(
value
);
break
;
default:
result
=
RT_EOK
;
}
return
result
;
}
static
rt_size_t
sound_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
{
int
result
=
RT_EOK
;
struct
sound_device
*
snd
=
(
struct
sound_device
*
)
dev
;
result
=
rt_data_node_write
(
snd
->
node_list
,
(
void
*
)
buffer
,
size
);
return
result
;
}
static
rt_err_t
sound_close
(
rt_device_t
dev
)
{
HAL_SAI_DMAStop
(
&
SAI1A_Handler
);
LOG_I
(
"Close Sound Device!"
);
return
RT_EOK
;
}
int
rt_hw_sound_hw_init
(
char
*
i2c_bus_name
)
{
int
result
=
RT_EOK
;
if
(
sound
!=
RT_NULL
)
return
RT_EOK
;
HAL_SAI_MspInit
(
NULL
);
sound
=
rt_malloc
(
sizeof
(
struct
sound_device
));
if
(
sound
==
RT_NULL
)
{
LOG_E
(
"malloc memory for sound device failed!"
);
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
sound
,
0
,
sizeof
(
struct
sound_device
));
sound
->
i2c_device
=
rt_i2c_bus_device_find
(
i2c_bus_name
);
if
(
sound
->
i2c_device
==
RT_NULL
)
{
LOG_E
(
"i2c bus device %s not found!"
,
i2c_bus_name
);
result
=
-
RT_ENOSYS
;
goto
__exit
;
}
sound
->
send_fifo
=
rt_malloc
(
AUDIO_SEND_BUFFER_SIZE
);
if
(
sound
->
send_fifo
==
RT_NULL
)
{
result
=
-
RT_ENOMEM
;
goto
__exit
;
}
memset
(
sound
->
send_fifo
,
0
,
AUDIO_SEND_BUFFER_SIZE
);
rt_data_node_init
(
&
sound
->
node_list
,
10
);
sound
->
node_list
->
read_complete
=
data_node_read_complete
;
sound
->
node_list
->
user_data
=
sound
;
sound
->
parent
.
type
=
RT_Device_Class_Sound
;
sound
->
parent
.
init
=
sound_init
;
sound
->
parent
.
open
=
sound_open
;
sound
->
parent
.
control
=
sound_control
;
sound
->
parent
.
write
=
sound_write
;
sound
->
parent
.
read
=
RT_NULL
;
sound
->
parent
.
close
=
sound_close
;
sound
->
parent
.
user_data
=
sound
;
/* register the device */
rt_device_register
(
&
sound
->
parent
,
"sound"
,
RT_DEVICE_FLAG_WRONLY
|
RT_DEVICE_FLAG_DMA_TX
);
rt_device_init
(
&
sound
->
parent
);
return
RT_EOK
;
__exit:
if
(
sound
->
send_fifo
!=
RT_NULL
)
{
rt_free
(
sound
->
send_fifo
);
sound
->
send_fifo
=
RT_NULL
;
}
if
(
sound
!=
RT_NULL
)
{
rt_free
(
sound
);
sound
=
RT_NULL
;
}
return
result
;
}
extern
int
rt_hw_micphone_init
(
char
*
i2c_bus_name
);
int
rt_hw_audio_init
(
char
*
i2c_bus_name
)
{
rt_hw_sound_hw_init
(
i2c_bus_name
);
rt_hw_micphone_init
(
i2c_bus_name
);
return
RT_EOK
;
}
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.c
0 → 100644
浏览文件 @
e14b1ac0
此差异已折叠。
点击以展开。
bsp/stm32f429-apollo/drivers/audio/drv_wm8978.h
0 → 100644
浏览文件 @
e14b1ac0
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-14 ZeroFree first implementation
*/
#ifndef __DRV_WM8978_H__
#define __DRV_WM8978_H__
#include <rtthread.h>
#include <rtdevice.h>
int
wm8978_init
(
struct
rt_i2c_bus_device
*
dev
);
int
wm8978_set_volume
(
struct
rt_i2c_bus_device
*
dev
,
int
vol
);
#endif
bsp/stm32f429-apollo/drivers/drv_spi.c
浏览文件 @
e14b1ac0
...
...
@@ -539,7 +539,7 @@ struct stm32f4_spi stm32f4_spi5 =
static
struct
rt_spi_bus
spi5_bus
;
#ifdef SPI_USE_DMA
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
...
...
@@ -558,6 +558,7 @@ void DMA2_Stream4_IRQHandler(void)
{
HAL_DMA_IRQHandler
(
stm32f4_spi5
.
spi_handle
.
hdmatx
);
}
#endif
/* SPI_USE_DMA */
#endif
...
...
bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h
浏览文件 @
e14b1ac0
...
...
@@ -71,7 +71,7 @@
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
#define HAL_RTC_MODULE_ENABLED
/* */
/* #define HAL_SAI_MODULE_ENABLED
*/
#define HAL_SAI_MODULE_ENABLED
/*
*/
#define HAL_SD_MODULE_ENABLED
/* */
#define HAL_SPI_MODULE_ENABLED
/* #define HAL_TIM_MODULE_ENABLED */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录