Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
RT-Thread
rt-thread
提交
0822f026
R
rt-thread
项目概览
RT-Thread
/
rt-thread
9 个月 前同步成功
通知
752
Star
8909
Fork
4735
代码
文件
提交
分支
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,体验更适合开发者的 AI 搜索 >>
提交
0822f026
编写于
3月 29, 2023
作者:
V
vandoul
提交者:
mysterywolf
3月 30, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[bsp][lpc55sxx] add i2s and wm8904 driver
上级
d6e40f2a
变更
5
展开全部
隐藏空白更改
内联
并排
Showing
5 changed file
with
1687 addition
and
0 deletion
+1687
-0
bsp/lpc55sxx/Libraries/drivers/SConscript
bsp/lpc55sxx/Libraries/drivers/SConscript
+6
-0
bsp/lpc55sxx/Libraries/drivers/drv_i2s.c
bsp/lpc55sxx/Libraries/drivers/drv_i2s.c
+301
-0
bsp/lpc55sxx/Libraries/drivers/drv_i2s.h
bsp/lpc55sxx/Libraries/drivers/drv_i2s.h
+43
-0
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c
+1123
-0
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.h
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.h
+214
-0
未找到文件。
bsp/lpc55sxx/Libraries/drivers/SConscript
浏览文件 @
0822f026
...
...
@@ -43,6 +43,12 @@ if GetDepend('BSP_USING_WDT'):
if
GetDepend
(
'BSP_USING_PWM'
):
src
+=
[
'drv_pwm.c'
]
if
GetDepend
(
'BSP_USING_I2S'
):
src
+=
[
'drv_i2s.c'
]
if
GetDepend
(
'BSP_USING_WM8904'
):
src
+=
[
'drv_sound_wm8904.c'
]
path
=
[
cwd
,
cwd
+
'/config'
]
group
=
DefineGroup
(
'Drivers'
,
src
,
depend
=
[
''
],
CPPPATH
=
path
)
...
...
bsp/lpc55sxx/Libraries/drivers/drv_i2s.c
0 → 100644
浏览文件 @
0822f026
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-12 Vandoul the first version
*/
#include <rtthread.h>
#include "fsl_i2s.h"
#include "fsl_i2s_dma.h"
#include "drv_i2s.h"
#define DBG_TAG "DRVI2S"
#include "rtdbg.h"
#ifdef BSP_USING_I2S
#if !defined(BSP_USING_I2S0) && \
!defined(BSP_USING_I2S1) && \
!defined(BSP_USING_I2S2) && \
!defined(BSP_USING_I2S3) && \
!defined(BSP_USING_I2S4) && \
!defined(BSP_USING_I2S5) && \
!defined(BSP_USING_I2S6) && \
!defined(BSP_USING_I2S7)
#error "Please define at least one I2Sx"
#endif
#include <rtdevice.h>
enum
{
#ifdef BSP_USING_I2S0
I2S0_INDEX
,
#endif
#ifdef BSP_USING_I2S1
I2S1_INDEX
,
#endif
#ifdef BSP_USING_I2S2
I2S2_INDEX
,
#endif
#ifdef BSP_USING_I2S3
I2S3_INDEX
,
#endif
#ifdef BSP_USING_I2S4
I2S4_INDEX
,
#endif
#ifdef BSP_USING_I2S5
I2S5_INDEX
,
#endif
#ifdef BSP_USING_I2S6
I2S6_INDEX
,
#endif
#ifdef BSP_USING_I2S7
I2S7_INDEX
,
#endif
};
struct
lpc_i2s_clock_and_irq_param
{
clock_attach_id_t
i2s_clock
;
reset_ip_name_t
i2s_reset_bit
;
IRQn_Type
irq_type
;
};
struct
lpc_i2s
{
struct
rt_device
device
;
i2s_handle_t
i2s_handle
;
struct
lpc_i2s_config
config
;
uint32_t
index
;
I2S_Type
*
i2s_base
;
const
char
*
device_name
;
};
#define LPC_I2S_CONFIG_MODE_IS_SLAVE(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_SLAVE)
#define LPC_I2S_CONFIG_MODE_IS_MASTER(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_MASTER)
#define LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(index) {.i2s_clock = kPLL0_DIV_to_FLEXCOMM##index, .i2s_reset_bit = kFC##index##_RST_SHIFT_RSTn, .irq_type = FLEXCOMM##index##_IRQn,}
const
static
struct
lpc_i2s_clock_and_irq_param
lpc_i2s_clock_and_irq_param_table
[]
=
{
#ifdef BSP_USING_I2S0
// {.i2s_clock = kPLL0_DIV_to_FLEXCOMM0, .i2s_reset_bit = kFC0_RST_SHIFT_RSTn, .irq_type = FLEXCOMM0_IRQn,},
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
0
),
#endif
#ifdef BSP_USING_I2S1
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
1
),
#endif
#ifdef BSP_USING_I2S2
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
2
),
#endif
#ifdef BSP_USING_I2S3
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
3
),
#endif
#ifdef BSP_USING_I2S4
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
4
),
#endif
#ifdef BSP_USING_I2S5
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
5
),
#endif
#ifdef BSP_USING_I2S6
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
6
),
#endif
#ifdef BSP_USING_I2S7
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT
(
7
),
#endif
};
static
struct
lpc_i2s
lpc_i2s_table
[]
=
{
#ifdef BSP_USING_I2S0
{.
index
=
I2S0_INDEX
,.
i2s_base
=
I2S0
,.
device_name
=
"i2s0"
},
#endif
#ifdef BSP_USING_I2S1
{.
index
=
I2S1_INDEX
,.
i2s_base
=
I2S1
,.
device_name
=
"i2s1"
},
#endif
#ifdef BSP_USING_I2S2
{.
index
=
I2S2_INDEX
,.
i2s_base
=
I2S2
,.
device_name
=
"i2s2"
},
#endif
#ifdef BSP_USING_I2S3
{.
index
=
I2S3_INDEX
,.
i2s_base
=
I2S3
,.
device_name
=
"i2s3"
},
#endif
#ifdef BSP_USING_I2S4
{.
index
=
I2S4_INDEX
,.
i2s_base
=
I2S4
,.
device_name
=
"i2s4"
},
#endif
#ifdef BSP_USING_I2S5
{.
index
=
I2S5_INDEX
,.
i2s_base
=
I2S5
,.
device_name
=
"i2s5"
},
#endif
#ifdef BSP_USING_I2S6
{.
index
=
I2S6_INDEX
,.
i2s_base
=
I2S6
,.
device_name
=
"i2s6"
},
#endif
#ifdef BSP_USING_I2S7
{.
index
=
I2S7_INDEX
,.
i2s_base
=
I2S7
,.
device_name
=
"i2s7"
},
#endif
};
static
void
transfer_callback
(
I2S_Type
*
base
,
i2s_handle_t
*
handle
,
status_t
completionStatus
,
void
*
userData
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
handle
,
struct
lpc_i2s
,
i2s_handle
);
if
(
LPC_I2S_CONFIG_MODE_IS_SLAVE
(
i2s_dev
))
{
if
(
i2s_dev
->
device
.
rx_indicate
!=
RT_NULL
)
{
i2s_dev
->
device
.
rx_indicate
(
&
i2s_dev
->
device
,
completionStatus
);
}
}
else
{
if
(
i2s_dev
->
device
.
tx_complete
!=
RT_NULL
)
{
i2s_dev
->
device
.
tx_complete
(
&
i2s_dev
->
device
,
RT_NULL
);
}
}
}
static
void
i2s_clock_and_irq_config
(
struct
lpc_i2s
*
dev
)
{
const
struct
lpc_i2s_clock_and_irq_param
*
clock_and_irq_param
=
&
lpc_i2s_clock_and_irq_param_table
[
dev
->
index
];
// CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 0U, true);
// CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 1U, false);
CLOCK_AttachClk
(
clock_and_irq_param
->
i2s_clock
);
RESET_PeripheralReset
(
clock_and_irq_param
->
i2s_reset_bit
);
NVIC_ClearPendingIRQ
(
clock_and_irq_param
->
irq_type
);
/* Enable interrupts for I2S */
EnableIRQ
(
clock_and_irq_param
->
irq_type
);
}
rt_err_t
rt_i2s_init
(
rt_device_t
dev
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
i2s_clock_and_irq_config
(
i2s_dev
);
return
RT_EOK
;
}
rt_err_t
rt_i2s_open
(
rt_device_t
dev
,
rt_uint16_t
oflag
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
i2s_config_t
config
;
if
(
i2s_dev
->
config
.
mode
==
LPC_I2S_CONFIG_MODE_SLAVE
)
{
RT_ASSERT
(
i2s_dev
->
config
.
is_blocking
==
0
);
I2S_RxGetDefaultConfig
(
&
config
);
config
.
divider
=
CLOCK_GetPll0OutFreq
()
/
i2s_dev
->
config
.
sampling_rate
/
i2s_dev
->
config
.
data_bits
/
i2s_dev
->
config
.
channels
;
config
.
masterSlave
=
kI2S_MasterSlaveNormalSlave
;
I2S_RxInit
(
i2s_dev
->
i2s_base
,
&
config
);
I2S_RxTransferCreateHandle
(
i2s_dev
->
i2s_base
,
&
i2s_dev
->
i2s_handle
,
transfer_callback
,
NULL
);
}
else
if
(
i2s_dev
->
config
.
mode
==
LPC_I2S_CONFIG_MODE_MASTER
)
{
RT_ASSERT
(
i2s_dev
->
config
.
is_blocking
==
0
);
I2S_TxGetDefaultConfig
(
&
config
);
config
.
divider
=
CLOCK_GetPll0OutFreq
()
/
i2s_dev
->
config
.
sampling_rate
/
i2s_dev
->
config
.
data_bits
/
i2s_dev
->
config
.
channels
;
config
.
masterSlave
=
kI2S_MasterSlaveNormalMaster
;
I2S_TxInit
(
i2s_dev
->
i2s_base
,
&
config
);
I2S_TxTransferCreateHandle
(
i2s_dev
->
i2s_base
,
&
i2s_dev
->
i2s_handle
,
transfer_callback
,
NULL
);
}
return
RT_EOK
;
}
rt_err_t
rt_i2s_close
(
rt_device_t
dev
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
I2S_Deinit
(
i2s_dev
->
i2s_base
);
return
RT_EOK
;
}
rt_ssize_t
rt_i2s_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
if
(
!
LPC_I2S_CONFIG_MODE_IS_SLAVE
(
i2s_dev
))
{
return
-
RT_ERROR
;
}
i2s_transfer_t
transfer
;
transfer
.
data
=
buffer
;
transfer
.
dataSize
=
size
;
if
(
kStatus_Success
==
I2S_RxTransferNonBlocking
(
i2s_dev
->
i2s_base
,
&
i2s_dev
->
i2s_handle
,
transfer
))
return
size
;
else
return
-
RT_EBUSY
;
}
rt_ssize_t
rt_i2s_write
(
rt_device_t
dev
,
rt_off_t
pos
,
const
void
*
buffer
,
rt_size_t
size
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
if
(
!
LPC_I2S_CONFIG_MODE_IS_MASTER
(
i2s_dev
))
{
return
-
RT_ERROR
;
}
i2s_transfer_t
transfer
;
transfer
.
data
=
(
uint8_t
*
)
buffer
;
transfer
.
dataSize
=
size
;
if
(
kStatus_Success
==
I2S_TxTransferNonBlocking
(
i2s_dev
->
i2s_base
,
&
i2s_dev
->
i2s_handle
,
transfer
))
return
size
;
else
return
-
RT_EBUSY
;
}
rt_err_t
rt_i2s_control
(
rt_device_t
dev
,
int
cmd
,
void
*
args
)
{
struct
lpc_i2s
*
i2s_dev
=
rt_container_of
(
dev
,
struct
lpc_i2s
,
device
);
rt_err_t
ret
=
RT_EOK
;
RT_ASSERT
(
dev
!=
RT_NULL
);
RT_ASSERT
(
args
!=
RT_NULL
);
switch
(
cmd
)
{
case
RT_I2S_CTRL_RESET
:
i2s_clock_and_irq_config
(
i2s_dev
);
break
;
case
RT_I2S_CTRL_SET_CONFIG
:
{
struct
lpc_i2s_config
*
config
=
(
struct
lpc_i2s_config
*
)
args
;
i2s_dev
->
config
=
*
config
;
}
break
;
default:
ret
=
-
RT_ERROR
;
break
;
}
return
ret
;
}
#ifdef RT_USING_DEVICE_OPS
const
static
struct
rt_device_ops
i2s_core_ops
=
{
rt_i2s_init
,
rt_i2s_open
,
rt_i2s_close
,
rt_i2s_read
,
rt_i2s_write
,
rt_i2s_control
,
};
#endif
/* RT_USING_DEVICE_OPS */
int
rt_hw_i2s_init
(
void
)
{
struct
serial_configure
config
=
RT_SERIAL_CONFIG_DEFAULT
;
int
i
;
for
(
i
=
0
;
i
<
sizeof
(
lpc_i2s_table
)
/
sizeof
(
lpc_i2s_table
[
0
]);
i
++
)
{
#ifdef RT_USING_DEVICE_OPS
lpc_i2s_table
[
i
].
device
.
ops
=
&
i2s_core_ops
;
#else
lpc_i2s_table
[
i
].
device
.
init
=
rt_i2s_init
;
lpc_i2s_table
[
i
].
device
.
open
=
rt_i2s_open
;
lpc_i2s_table
[
i
].
device
.
close
=
rt_i2s_close
;
lpc_i2s_table
[
i
].
device
.
read
=
rt_i2s_read
;
lpc_i2s_table
[
i
].
device
.
write
=
rt_i2s_write
;
lpc_i2s_table
[
i
].
device
.
control
=
rt_i2s_control
;
#endif
/* register UART device */
rt_device_register
(
&
lpc_i2s_table
[
i
].
device
,
lpc_i2s_table
[
i
].
device_name
,
RT_DEVICE_FLAG_RDWR
|
RT_DEVICE_FLAG_INT_RX
);
}
return
0
;
}
INIT_BOARD_EXPORT
(
rt_hw_i2s_init
);
#endif
bsp/lpc55sxx/Libraries/drivers/drv_i2s.h
0 → 100644
浏览文件 @
0822f026
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-12 Vandoul the first version
*/
#ifndef __DRV_I2S_H__
#define __DRV_I2S_H__
#ifdef __cplusplus
extern
"C"
{
#endif
#include <rtthread.h>
#pragma pack(push,1)
struct
lpc_i2s_config
{
uint32_t
sampling_rate
;
uint8_t
mode
;
uint8_t
data_bits
;
uint8_t
channels
;
uint8_t
is_blocking
;
};
#pragma pack(pop)
#define LPC_I2S_CONFIG_MODE_NULL 0
#define LPC_I2S_CONFIG_MODE_SLAVE 1
#define LPC_I2S_CONFIG_MODE_MASTER 2
#define RT_I2S_CTRL_RESET (RT_DEVICE_CTRL_BASE(Bus) + 1)
#define RT_I2S_CTRL_SET_CONFIG (RT_DEVICE_CTRL_BASE(Bus) + 2)
#ifdef __cplusplus
}
#endif
#endif
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c
0 → 100644
浏览文件 @
0822f026
此差异已折叠。
点击以展开。
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.h
0 → 100644
浏览文件 @
0822f026
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-12 Vandoul the first version
*/
#ifndef __DRV_SOUND_WM8904_H__
#define __DRV_SOUND_WM8904_H__
#include <rtthread.h>
typedef
enum
{
WM8904_RESET
=
0x00
,
WM8904_ANALOG_ADC_0
=
0x0A
,
WM8904_POWER_MGMT_0
=
0x0C
,
WM8904_POWER_MGMT_2
=
0x0E
,
WM8904_POWER_MGMT_3
=
0x0F
,
WM8904_POWER_MGMT_6
=
0x12
,
WM8904_CLK_RATES_0
=
0x14
,
WM8904_CLK_RATES_1
=
0x15
,
WM8904_CLK_RATES_2
=
0x16
,
WM8904_AUDIO_IF_0
=
0x18
,
WM8904_AUDIO_IF_1
=
0x19
,
WM8904_AUDIO_IF_2
=
0x1A
,
WM8904_AUDIO_IF_3
=
0x1B
,
WM8904_DAC_DIG_1
=
0x21
,
WM8904_DAC_DIG_0
=
0x27
,
WM8904_ANALOG_LEFT_IN_0
=
0x2C
,
WM8904_ANALOG_RIGHT_IN_0
=
0x2D
,
WM8904_ANALOG_LEFT_IN_1
=
0x2E
,
WM8904_ANALOG_RIGHT_IN_1
=
0x2F
,
WM8904_ANALOG_OUT1_LEFT
=
0x39
,
WM8904_ANALOG_OUT1_RIGHT
=
0x3A
,
WM8904_ANALOG_OUT12_ZC
=
0x3D
,
WM8904_DC_SERVO_0
=
0x43
,
WM8904_ANALOG_HP_0
=
0x5A
,
WM8904_CHRG_PUMP_0
=
0x62
,
WM8904_CLS_W_0
=
0x68
,
WM8904_WRT_SEQUENCER_0
=
0x6C
,
WM8904_WRT_SEQUENCER_3
=
0x6F
,
WM8904_WRT_SEQUENCER_4
=
0x70
,
WM8904_DAC_DIGITAL_VOLUME_LEFT
=
0x1E
,
WM8904_DAC_DIGITAL_VOLUME_RIGHT
=
0x1F
,
WM8904_ADC_DIGITAL_VOLUME_LEFT
=
0x24
,
WM8904_ADC_DIGITAL_VOLUME_RIGHT
=
0x25
,
WM8904_ANALOG_OUT2_LEFT
=
0x3B
,
WM8904_ANALOG_OUT2_RIGHT
=
0x3C
,
/* FLL control register */
WM8904_FLL_CONTROL_1
=
0x74
,
WM8904_FLL_CONTROL_2
=
0x75
,
WM8904_FLL_CONTROL_3
=
0x76
,
WM8904_FLL_CONTROL_4
=
0x77
,
WM8904_FLL_CONTROL_5
=
0x78
,
/* GPIO control register */
WM8904_GPIO_CONTROL_1
=
0x79
,
WM8904_GPIO_CONTROL_2
=
0x7A
,
WM8904_GPIO_CONTROL_3
=
0x7B
,
WM8904_GPIO_CONTROL_4
=
0x7C
,
/* FLL nco */
WM89004_FLL_NCO_TEST_0
=
0xF7
,
WM89004_FLL_NCO_TEST_1
=
0xF8
,
}
wm8904_reg_t
;
#define WM8904_LRC_POLARITY_POS (4U)
#define WM8904_LRC_POLARITY_NOOMAL (0)
#define WM8904_LRC_POLARITY_INVERTED (1U << WM8904_LRC_POLARITY_POS)
typedef
enum
_wm8904_module
{
WM8904_MODULE_ADC
=
0
,
/*!< module ADC */
WM8904_MODULE_DAC
,
/*!< module DAC */
WM8904_MODULE_PGA
,
/*!< module PGA */
WM8904_MODULE_HEADPHONE
,
/*!< module headphone */
WM8904_MODULE_LINEOUT
,
/*!< module line out */
}
wm8904_module_t
;
enum
{
WM8904_HEADPHONE_LEFT
=
1U
,
WM8904_HEADPHONE_RIGHT
=
2U
,
WM8904_LINEOUT_LEFT
=
4U
,
WM8904_LINEOUT_RIGHT
=
8U
,
};
typedef
enum
_wm8904_timeslot
{
WM8904_TIMESLOT_0
=
0U
,
WM8904_TIMESLOT_1
,
}
wm8904_timeslot_t
;
typedef
enum
{
WM8904_PROTOCOL_RIGHT_JUSTIFIED
=
0x00
,
WM8904_PROTOCOL_LEFT_JUSTIFIED
=
0x01
,
WM8904_PROTOCOL_I2S
=
0x02
,
WM8904_PROTOCOL_PCMA
=
0x03
,
WM8904_PROTOCOL_PCMB
=
0x13
,
}
wm8904_protocol_t
;
/*! @brief The SYSCLK / fs ratio. */
typedef
enum
_wm8904_fs_ratio
{
WM8904_FSRATIO_64X
=
0x0
,
/*!< SYSCLK is 64 * sample rate * frame width */
WM8904_FSRATIO_128X
=
0x1
,
/*!< SYSCLK is 128 * sample rate * frame width */
WM8904_FSRATIO_192X
=
0x2
,
/*!< SYSCLK is 192 * sample rate * frame width */
WM8904_FSRATIO_256X
=
0x3
,
/*!< SYSCLK is 256 * sample rate * frame width */
WM8904_FSRATIO_384X
=
0x4
,
/*!< SYSCLK is 384 * sample rate * frame width */
WM8904_FSRATIO_512X
=
0x5
,
/*!< SYSCLK is 512 * sample rate * frame width */
WM8904_FSRATIO_768X
=
0x6
,
/*!< SYSCLK is 768 * sample rate * frame width */
WM8904_FSRATIO_1024X
=
0x7
,
/*!< SYSCLK is 1024 * sample rate * frame width */
WM8904_FSRATIO_1408X
=
0x8
,
/*!< SYSCLK is 1408 * sample rate * frame width */
WM8904_FSRATIO_1536X
=
0x9
/*!< SYSCLK is 1536 * sample rate * frame width */
}
wm8904_fs_ratio_t
;
/*! @brief Sample rate. */
typedef
enum
_wm8904_sample_rate
{
WM8904_SAMPLERATE_8kHz
=
0x0
,
/*!< 8 kHz */
WM8904_SAMPLERATE_12kHz
=
0x1
,
/*!< 12kHz */
WM8904_SAMPLERATE_16kHz
=
0x2
,
/*!< 16kHz */
WM8904_SAMPLERATE_24kHz
=
0x3
,
/*!< 24kHz */
WM8904_SAMPLERATE_32kHz
=
0x4
,
/*!< 32kHz */
WM8904_SAMPLERATE_48kHz
=
0x5
,
/*!< 48kHz */
WM8904_SAMPLERATE_11025Hz
=
0x6
,
/*!< 11.025kHz */
WM8904_SAMPLERATE_22050Hz
=
0x7
,
/*!< 22.05kHz */
WM8904_SAMPLERATE_44100Hz
=
0x8
/*!< 44.1kHz */
}
wm8904_sample_rate_t
;
/*! @brief Bit width. */
typedef
enum
_wm8904_bit_width
{
WM8904_BITWIDTH_16
=
0x0
,
/*!< 16 bits */
WM8904_BITWIDTH_20
=
0x1
,
/*!< 20 bits */
WM8904_BITWIDTH_24
=
0x2
,
/*!< 24 bits */
WM8904_BITWIDTH_32
=
0x3
/*!< 32 bits */
}
wm8904_bit_width_t
;
enum
{
WM8904_RECORD_SOURCE_DIFFERENTIAL_LINE
=
1U
,
/*!< record source from differential line */
WM8904_RECORD_SOURCE_LINE_INPUT
=
2U
,
/*!< record source from line input */
WM8904_RECORD_SOURCE_DIFFERENTIAL_MIC
=
4U
,
/*!< record source from differential mic */
WM8904_RECORD_SOURCE_DIGITAL_MIC
=
8U
,
/*!< record source from digital microphone */
};
enum
{
WM8904_RECORD_CHANNEL_LEFT1
=
1U
,
/*!< left record channel 1 */
WM8904_RECORD_CHANNEL_LEFT2
=
2U
,
/*!< left record channel 2 */
WM8904_RECORD_CHANNEL_LEFT3
=
4U
,
/*!< left record channel 3 */
WM8904_RECORD_CHANNEL_RIGHT1
=
1U
,
/*!< right record channel 1 */
WM8904_RECORD_CHANNEL_RIGHT2
=
2U
,
/*!< right record channel 2 */
WM8904_RECORD_CHANNEL_RIGHT3
=
4U
,
/*!< right record channel 3 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE1
=
1U
,
/*!< differential positive record channel 1 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE2
=
2U
,
/*!< differential positive record channel 2 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE3
=
4U
,
/*!< differential positive record channel 3 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE1
=
8U
,
/*!< differential negative record channel 1 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE2
=
16U
,
/*!< differential negative record channel 2 */
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE3
=
32U
,
/*!< differential negative record channel 3 */
};
/*! @brief wm8904 play source
*
*/
enum
{
WM8904_PLAY_SOURCE_PGA
=
1U
,
/*!< play source PGA, bypass ADC */
WM8904_PLAY_SOURCE_DAC
=
4U
,
/*!< play source Input3 */
};
/*! @brief wm8904_fll_clk_source */
typedef
enum
_wm8904_fll_clk_source
{
WM8904_FLL_CLK_SOURCE_MCLK
=
0U
,
/**< wm8904 FLL clock source from MCLK */
}
wm8904_fll_clk_source_t
;
/*! @brief wm8904 fll configuration */
typedef
struct
_wm8904_fll_config
{
wm8904_fll_clk_source_t
source
;
/*!< fll reference clock source */
rt_uint32_t
ref_clock_hz
;
/*!< fll reference clock frequency */
rt_uint32_t
output_clock_hz
;
/*!< fll output clock frequency */
}
wm8904_fll_config_t
;
/*! @brief Audio format configuration. */
typedef
struct
_wm8904_audio_format
{
wm8904_fs_ratio_t
fsRatio
;
/*!< SYSCLK / fs ratio */
wm8904_sample_rate_t
sampleRate
;
/*!< Sample rate */
wm8904_bit_width_t
bitWidth
;
/*!< Bit width */
}
wm8904_audio_format_t
;
struct
wm8904_config
{
const
char
*
i2c_bus_name
;
const
char
*
i2s_bus_name
;
int
i2c_addr
;
wm8904_protocol_t
protocol
;
wm8904_audio_format_t
format
;
};
#define WM8904_I2C_ADDRESS (0x1A)
#define WM8904_I2C_BITRATE (400000U)
/* WM8904 maximum volume */
#define WM8904_MAP_HEADPHONE_LINEOUT_MAX_VOLUME 0x3FU
#define WM8904_DAC_MAX_VOLUME 0xC0U
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录