snd驱动以及优化

This commit is contained in:
zhangzheng
2024-12-27 08:25:51 +08:00
parent 7aa4ee1812
commit 49060a965b
42 changed files with 1934 additions and 59 deletions

View File

@@ -52,7 +52,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
S('c') = CHAR, S('C') = INT,
S('c') = INT, S('C') = UINT,
S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
S('m') = NOARG,
S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
@@ -62,7 +62,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
S('c') = INT, S('s') = PTR, S('n') = PTR,
S('c') = UINT, S('s') = PTR, S('n') = PTR,
S('l') = LLPRE,
}, { /* 2: ll-prefixed */
S('d') = LLONG, S('i') = LLONG,
@@ -438,7 +438,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
unsigned st, ps;
int cnt=0, l=0;
size_t i;
char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
char buf[sizeof(uintmax_t)*3];
const char *prefix;
int t, pl;
wchar_t wc[2], *ws;
@@ -589,6 +589,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
}
p = MAX(p, z-a + !arg.i);
break;
narrow_c:
case 'c':
*(a=z-(p=1))=arg.i;
fl &= ~ZERO_PAD;
@@ -603,6 +604,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
fl &= ~ZERO_PAD;
break;
case 'C':
if (!arg.i) goto narrow_c;
wc[0] = arg.i;
wc[1] = 0;
arg.p = wc;

View File

@@ -53,3 +53,8 @@
#define NET_DRV_WRITE ((umword_t)0) //!< 网络驱动写
#define NET_DRV_READ ((umword_t)1) //!< 网络驱动读
#define NET_DRV_MAP ((umword_t)2) //!< net map
#define SND_DRV_PROT 0x0009
#define SND_DRV_WRITE ((umword_t)0) //!< snd驱动写
#define SND_DRV_READ ((umword_t)1) //!< snd驱动读
#define SND_DRV_MAP ((umword_t)2) //!< snd map

View File

@@ -0,0 +1,8 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
int snd_drv_cli_write(obj_handler_t dm9000_obj, obj_handler_t shm_obj, int len);
int snd_drv_cli_read(obj_handler_t dm9000_obj, obj_handler_t shm_obj);
int snd_drv_cli_map(obj_handler_t dm9000_obj, obj_handler_t *sem_obj);

View File

@@ -0,0 +1,9 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
#include "snd_drv_types.h"
int snd_drv_write(obj_handler_t obj, int len);
int snd_drv_read(obj_handler_t obj, int len);
int snd_drv_map(obj_handler_t *hd);
void snd_drv_init(snd_drv_t *ns);

View File

@@ -0,0 +1,9 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
typedef struct snd_drv
{
rpc_svr_obj_t svr;
} snd_drv_t;

View File

@@ -0,0 +1,73 @@
#include "rpc_prot.h"
#include "snd_drv_cli.h"
#include "snd_drv_types.h"
#include "u_rpc.h"
#include "u_rpc_svr.h"
#include "u_arch.h"
#include "u_rpc_buf.h"
#include "u_hd_man.h"
#include "u_rpc_buf.h"
#include <u_env.h>
#include <stdio.h>
#include <assert.h>
RPC_GENERATION_CALL2(snd_drv_t, SND_DRV_PROT, SND_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
int snd_drv_cli_write(obj_handler_t dm9000_obj, obj_handler_t shm_obj, int len)
{
rpc_obj_handler_t_t rpc_hd = {
.data = shm_obj,
};
rpc_int_t rpc_len = {
.data = len,
};
msg_tag_t tag = snd_drv_t_write_call(dm9000_obj, &rpc_hd, &rpc_len);
return msg_tag_get_val(tag);
}
RPC_GENERATION_CALL2(snd_drv_t, SND_DRV_PROT, SND_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
int snd_drv_cli_read(obj_handler_t dm9000_obj, obj_handler_t shm_obj)
{
rpc_obj_handler_t_t rpc_hd = {
.data = shm_obj,
};
rpc_int_t rpc_len = {
.data = 0,
};
msg_tag_t tag = snd_drv_t_read_call(dm9000_obj, &rpc_hd, &rpc_len);
return msg_tag_get_val(tag);
}
RPC_GENERATION_CALL1(snd_drv_t, SND_DRV_PROT, SND_DRV_MAP, map,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_INOUT, RPC_TYPE_BUF, cli_hd)
int snd_drv_cli_map(obj_handler_t dm9000_obj, obj_handler_t *sem_obj)
{
assert(sem_obj);
obj_handler_t newfd;
newfd = handler_alloc();
if (newfd == HANDLER_INVALID)
{
return -ENOENT;
}
rpc_obj_handler_t_t rpc_sem_obj = {
.data = newfd,
.del_map_flags = VPAGE_FLAGS_MAP,
};
msg_tag_t tag = snd_drv_t_map_call(dm9000_obj, &rpc_sem_obj);
if (msg_tag_get_val(tag) < 0)
{
handler_free(newfd);
return msg_tag_get_val(tag);
}
*sem_obj = newfd;
return msg_tag_get_val(tag);
}

View File

@@ -0,0 +1,51 @@
#include "rpc_prot.h"
#include "snd_drv_svr.h"
#include "snd_drv_types.h"
#include "u_rpc.h"
#include "u_rpc_svr.h"
#include "u_arch.h"
#include "u_rpc_buf.h"
#include "u_hd_man.h"
#include "u_rpc_buf.h"
#include <stdio.h>
RPC_GENERATION_OP2(snd_drv_t, SND_DRV_PROT, SND_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
{
return snd_drv_write(rpc_hd_get(0), len->data);
}
RPC_GENERATION_DISPATCH2(snd_drv_t, SND_DRV_PROT, SND_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, svr_hd,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, type)
RPC_GENERATION_OP2(snd_drv_t, SND_DRV_PROT, SND_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
{
return snd_drv_read(rpc_hd_get(0), len->data);
}
RPC_GENERATION_DISPATCH2(snd_drv_t, SND_DRV_PROT, SND_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
RPC_GENERATION_OP1(snd_drv_t, SND_DRV_PROT, SND_DRV_MAP, map,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_INOUT, RPC_TYPE_BUF, cli_hd)
{
int ret = snd_drv_map(&cli_hd->data);
if (ret < 0)
{
printf("snd drv aailed to request map");
}
return ret;
}
RPC_GENERATION_DISPATCH1(snd_drv_t, SND_DRV_PROT, SND_DRV_MAP, map,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_INOUT, RPC_TYPE_BUF, cli_hd)
RPC_DISPATCH3(snd_drv_t, SND_DRV_PROT, typeof(SND_DRV_READ), SND_DRV_WRITE, write, SND_DRV_READ, read, SND_DRV_MAP, map)
void snd_drv_init(snd_drv_t *ns)
{
rpc_svr_obj_init(&ns->svr, rpc_snd_drv_t_dispatch, SND_DRV_PROT);
}

View File

@@ -7,7 +7,7 @@
int u_irq_request(int irq_no, void *stack, void *msg_buf, obj_handler_t *ret_irq_obj, void (*irq_func)(void), u_irq_prio_t prio)
{
static obj_handler_t irq_obj;
obj_handler_t irq_obj;
irq_obj = handler_alloc();
if (irq_obj == HANDLER_INVALID)
@@ -28,16 +28,16 @@ int u_irq_request(int irq_no, void *stack, void *msg_buf, obj_handler_t *ret_irq
}
obj_handler_t th_hd;
if (ret_irq_obj)
{
*ret_irq_obj = irq_obj;
}
int ret = u_thread_create(&th_hd, stack, msg_buf, irq_func);
if (ret < 0)
{
handler_free_umap(irq_obj);
return ret;
}
if (ret_irq_obj)
{
*ret_irq_obj = irq_obj;
}
u_thread_run(th_hd, IRQ_THREAD_PRIO);
return ret;

View File

@@ -15,7 +15,7 @@
#define STACK_SIZE (4 * 1024) //(1024 + 256)
#else
#define HEAP_SIZE (2 * 1024)
#define STACK_SIZE (3 * 1024) //(1024 + 256)
#define STACK_SIZE (4 * 1024) //(1024 + 256)
#endif
#if defined(__CC_ARM)

View File

@@ -1,13 +1,12 @@
#一次读取一行,每行代表启动的应用程序
# fatfs
# dm9000_drv
# net
cpiofs -m /bin
pin
i2c
pca9555
display
eth
nes
net
# pin
# i2c
# pca9555
# display
# eth
# snd
# net
# nes
sh

View File

@@ -193,6 +193,7 @@ static ns_node_t *node_lookup(ns_node_t *dir, const char *name,
}
if (name[0] == 0)
{
*ret_inx = 0;
return dir;
}
node = dir;
@@ -605,7 +606,7 @@ int namespace_query(const char *path, obj_handler_t *hd)
if (path[0] == '/' && path[1] == 0)
{
*hd = ns_hd;
return 0;
return 1;
}
ns_lock();
node = node_lookup(&ns.root_node, path, &ret_inx);

View File

@@ -1,7 +1,7 @@
#include <u_util.h>
#if !IS_ENABLED(CONFIG_MMU)
#define HEAP_SIZE 2048
#define STACK_SIZE (3*1024)
#define HEAP_SIZE 32 * 1024
#define STACK_SIZE (3 * 1024)
#if defined(__CC_ARM)
#define HEAP_ATTR SECTION("HEAP") __attribute__((zero_init))

View File

@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.13)
add_subdirectory(nes_simulator)
# add_subdirectory(nes_simulator)
add_subdirectory(coremark)
add_subdirectory(tinycc-arm-thumb)
add_subdirectory(app_test)
# add_subdirectory(tinycc-arm-thumb)
# add_subdirectory(app_test)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_BOARD_NAME})
add_subdirectory(${CONFIG_BOARD_NAME})
endif()

View File

@@ -1,5 +1,5 @@
#define HEAP_SIZE (100 * 1024)
#define HEAP_SIZE (64 * 1024)
#define STACK_SIZE (1024 * 3)
#if defined(__CC_ARM)

View File

@@ -2,7 +2,7 @@
.balign 4
.global nes_rom
nes_rom:
.incbin "/Users/zhangzheng/mkrtos-real/mkrtos_user/user/app/nes_simulator/nes_rom/超级玛丽.nes"
.incbin "/Users/zhangzheng/mkrtos-real/mkrtos_user/user/app/nes_simulator/nes_rom/超级马里奥兄弟3[MM之神汉化](JP)[ACT](3Mb).nes"
.global nes_rom_end
nes_rom_end:
.long 0

View File

@@ -2249,9 +2249,9 @@ IO_W: //I/O write
ldr r2,=io_write_tbl ////3
add r2,r2,r4
add r2,r2,r1,lsl#2 //<<2
ldrmi r1,[r2] ////pc
orr r1,r1,#0x1
bx r1
ldrmi r2,[r2] ////pc
orr r2,r2,#0x1
bx r2
b empty_R //
nop
.data
@@ -2521,16 +2521,17 @@ joy1_R: //4017
K6502_Read://apu Rendering DPCM channel #5 r0=APU->ApuC5Address*
//---------------------------------------------------------------
//EXPORT K6502_Read //switch ( wAddr & 0xe000 ) apu.c
stmfd sp!,{lr}
stmfd sp!,{r4, lr}
mov r4, r1
mov r1,r0,lsr#13 //>>13= & 0xe000
ldr r2,=CPU_RAM////// ram+rom
add r2, r2, r4
ldr r1,[r2,r1,lsl#2] //lookup rom ptr..ptr
bic r0,r0,#0xe000 //and r0,#0x1fff &0x1fff
ldrb r0,[r1,r0]
ldmfd sp!,{lr}
ldmfd sp!,{r4, lr}
bx lr
// nop
//------------------------------------------------------------------------

View File

@@ -30,7 +30,7 @@
#define APU_OVERSAMPLE
#define APU_VOLUME_DECAY(x) ((x) -= ((x) >> 7))
//需要用到的汇编的代码及参数
uint8_t K6502_Read( uint16_t wAddr ); //6502.s
uint8_t K6502_Read( uint16_t wAddr, uint32_t nes_ram_offset ); //6502.s
extern uint32_t clocks; //6502.s
//noise lookups for both modes */
//噪音查找两种模式 */
@@ -512,6 +512,7 @@ void apu_dmcreload(dmc_t *chan)
chan->dma_length = chan->cached_dmalength;
chan->irq_occurred = FALSE;
}
extern uint32_t nes_ram_offset;
/* DELTA MODULATION CHANNEL
** =========================
@@ -540,7 +541,7 @@ int apu_dmc(dmc_t *chan)
if (7 == delta_bit)
{
chan->cur_byte = K6502_Read(chan->address); //chan->cur_byte = nes6502_getbyte(chan->address);*********************
chan->cur_byte = K6502_Read(chan->address, nes_ram_offset); //chan->cur_byte = nes6502_getbyte(chan->address);*********************
/* steal a cycle from CPU偷从CPU周期*/
clocks++; // nes6502_burn(1);//要CPU时钟数加1**********************************************************************
@@ -1082,7 +1083,6 @@ void Apu_Write4017(uint8 value, uint32 address )
#endif
}
void Apu_Write4015(uint8_t value, uint32_t address )
{
apudata_t d;

View File

@@ -9,8 +9,14 @@
#include <u_sys.h>
#include <unistd.h>
#include <sys/ioctl.h>
// #include "drv_audio.h"
// #include "drv_input.h"
#include "ns_cli.h"
#include "u_sleep.h"
#include <u_hd_man.h>
#include <u_task.h>
#include <u_factory.h>
#include <u_share_mem.h>
#include <snd_drv_cli.h>
#include <assert.h>
//////////////////////////////////////////////////////////////////////////////////
// 本程序移植自网友ye781205的NES模拟器工程
@@ -495,6 +501,7 @@ void nes_emulate_frame(void)
apu_soundoutput(); // 输出游戏声音
framecnt++;
nes_frame++;
#if 0
if (nes_frame > jump_frame_cnt)
{
nes_frame = 0; // 跳帧
@@ -507,6 +514,13 @@ void nes_emulate_frame(void)
jump_frame_cnt = 1;
}
}
#else
if (nes_frame > NES_SKIP_FRAME)
{
nes_frame = 0;
}
#endif
#if 0
printf("fps:%d\n", 1000 / ((sys_read_tick() - st_tick) / framecnt));
#endif
@@ -520,9 +534,31 @@ void debug_6502(u16 reg0, u8 reg1)
//////////////////////////////////////////////////////////////////////////////////
// nes,音频输出支持部分
static obj_handler_t snd_drv_hd;
static addr_t addr;
static umword_t size;
static obj_handler_t shm_hd;
// NES打开音频输出
int nes_sound_open(int samples_per_sync, int sample_rate)
{
int ret;
msg_tag_t tag;
again:
ret = ns_query("/snd", &snd_drv_hd, 0x1);
if (ret < 0)
{
u_sleep_ms(50);
goto again;
}
shm_hd = handler_alloc();
assert(shm_hd != HANDLER_INVALID);
tag = facotry_create_share_mem(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, shm_hd),
SHARE_MEM_CNT_BUDDY_CNT, 2048);
assert(msg_tag_get_prot(tag) >= 0);
tag = share_mem_map(shm_hd, vma_addr_create(VPAGE_PROT_RW, VMA_ADDR_RESV, 0), &addr, &size);
assert(msg_tag_get_prot(tag) >= 0);
// f1c100s_audio_config(1,16,sample_rate);
// f1c100s_audio_open(samples_per_sync*2);
return 1;
@@ -534,5 +570,10 @@ void nes_sound_close(void)
// NES音频输出到SAI缓存
void nes_apu_fill_buffer(int samples, u16 *wavebuf)
{
// audio_pcm_play((unsigned char*)wavebuf,APU_PCMBUF_SIZE*2);
memcpy((void *)addr, wavebuf, APU_PCMBUF_SIZE * 2);
int ret = snd_drv_cli_write(snd_drv_hd, shm_hd, APU_PCMBUF_SIZE * 2);
if (ret < 0)
{
printf("snd write error.\n");
}
}

View File

@@ -5,3 +5,4 @@ add_subdirectory(display)
add_subdirectory(i2c)
add_subdirectory(pca9555)
add_subdirectory(eth)
add_subdirectory(snd)

View File

@@ -480,6 +480,7 @@ error_status emac_speed_config(emac_auto_negotiation_type nego, emac_duplex_type
{
return ERROR;
}
u_sleep_ms(10);
} while (!(data & PHY_LINKED_STATUS_BIT) && (timeout < PHY_TIMEOUT));
if (timeout == PHY_TIMEOUT)
@@ -501,6 +502,7 @@ error_status emac_speed_config(emac_auto_negotiation_type nego, emac_duplex_type
{
return ERROR;
}
u_sleep_ms(10);
} while (!(data & PHY_NEGO_COMPLETE_BIT) && (timeout < PHY_TIMEOUT));
if (timeout == PHY_TIMEOUT)

View File

@@ -23,7 +23,7 @@ typedef struct eth_priv_data
static eth_priv_data_t eth_priv_data;
static int eth_bus_configure(mk_eth_t *drv, enum mk_eth_ioctl_op op, mk_ioctl_set_info_t *info)
static int eth_bus_configure(mk_eth_t *drv, enum mk_eth_ioctl_op op, mk_eth_ioctl_set_info_t *info)
{
assert(drv);
eth_priv_data_t *priv_data = drv->priv_data;

View File

@@ -59,6 +59,12 @@ int pca9555_set_mode(pca9555_t *io9555, enum pca9555_io_mode mode, uint16_t val)
{
io9555->imode &= ~val;
}
ret = lseek(io9555->i2c_fd, (0 << 16) | (io9555->i2c_addr), SEEK_SET);
if (ret < 0)
{
printf("%s:%d ret:%d\n", __func__, __LINE__, ret);
return ret;
}
const uint8_t write_init_data[] = {
PCA_REG_CTRL,
io9555->imode & 0xff,
@@ -84,6 +90,14 @@ int pca9555_output_write(pca9555_t *io9555, uint16_t val)
io9555->odata & 0xff,
(io9555->odata >> 8) & 0xff,
};
ret = lseek(io9555->i2c_fd, (0 << 16) | (io9555->i2c_addr), SEEK_SET);
if (ret < 0)
{
printf("%s:%d ret:%d\n", __func__, __LINE__, ret);
return ret;
}
ret = write(io9555->i2c_fd, write_init_data, sizeof(write_init_data));
if (ret != sizeof(write_init_data))
{

View File

@@ -153,6 +153,24 @@ static int pin_configure(mk_pin_t *pin, int number, mk_pin_mode_t cfg)
gpio_pin_mux_config(pin_port_data, number % 16, cfg.mux_cfg);
break;
}
case MK_PIN_MODE_MUX_OUTPUT_UP:
{
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_pin_mux_config(pin_port_data, number % 16, cfg.mux_cfg);
break;
}
case MK_PIN_MODE_MUX_OUTPUT_DOWN:
{
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
gpio_pin_mux_config(pin_port_data, number % 16, cfg.mux_cfg);
break;
}
case MK_PIN_MODE_IRQ_RISING:
{
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;

View File

@@ -0,0 +1,89 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DAT32F437ZMT7 -DUSE_STDPERIPH_DRIVER -DAT_SURF_F437_V1 ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DAT32F437ZMT7 -DUSE_STDPERIPH_DRIVER -DAT_SURF_F437_V1 ")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -DAT32F437ZMT7 -DUSE_STDPERIPH_DRIVER -DAT_SURF_F437_V1 ")
file(
GLOB deps
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/libraries/drivers/src/*.c
*.c
)
add_executable(
snd.elf
${deps}
${START_SRC}
)
target_link_libraries(
snd.elf
PUBLIC
-Bstatic
${LIBC_NAME}
mk_drv
mk_char
--whole-archive
${START_LIB}
libc_be
sys
sys_util
sys_svr
printf
--no-whole-archive
${GCC_LIB_PATH}/libgcc.a
)
target_include_directories(
snd.elf
PUBLIC
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/util/inc
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/libraries/drivers/inc
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/libraries/cmsis/cm4/device_support
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/libraries/cmsis/cm4/core_support
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/project/at_surf_f437_board/
${CMAKE_SOURCE_DIR}/mkrtos_bsp/AT32/AT32F435_437_Firmware_Library_V2.2.0/middlewares/i2c_application_library
${CMAKE_CURRENT_SOURCE_DIR}/
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/user/drv/lib/mk_snd
${CMAKE_SOURCE_DIR}/mkrtos_user/user/drv/lib/mk_pin
${CMAKE_SOURCE_DIR}/mkrtos_user/user/drv/lib/mk_pca9555
${CMAKE_SOURCE_DIR}/mkrtos_user/user/drv/lib/mk_i2c
)
add_dependencies(
snd.elf
${START_LIB}
sys
sys_util
mk_char
mk_drv
printf
# mk_snd
)
set_target_properties(
snd.elf PROPERTIES LINK_FLAGS
"-T ${CMAKE_CURRENT_LIST_DIR}/${ARCH_NAME}/link.lds ${CORTEX_M_LINK_FLAGS} --gc-section -no-dynamic-linker "
#--no-warn-rwx-segments
)
add_custom_target(
snd_dump ALL
COMMAND
${CMAKE_OBJDUMP} -s -S snd.elf > ${CMAKE_SOURCE_DIR}/build/output/snd.S
COMMAND
${CMAKE_READELF} -a snd.elf > ${CMAKE_SOURCE_DIR}/build/output/snd.txt
COMMAND
${CMAKE_OBJCOPY} -O binary -S snd.elf snd.bin
COMMAND
${CMAKE_SIZE} snd.elf
COMMAND
${CMAKE_COMMAND} -E copy snd.bin ${CMAKE_SOURCE_DIR}/build/output/cpio/snd
COMMAND
cp snd.elf ${CMAKE_SOURCE_DIR}/build/output/snd.elf
)
add_dependencies(snd_dump snd.elf)

View File

@@ -0,0 +1,124 @@
ENTRY(_start_)
SECTIONS
{
.text : {
. = ALIGN(4);
__text_start__ = .;
KEEP(*(.first))
*(.text)
*(.text.*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(SORT(.rodata.*))
*(.rodata)
KEEP(*(.eh_frame*))
. = ALIGN(4);
__rel_start__ = .;
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
__rel_end__ = .;
}
.ARM.exidx : {
. = ALIGN(4);
__exdix_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
/* This is used by the startup in order to initialize the .data secion */
__exdix_end = .;
}
.permissions_table : {
. = ALIGN(4);
__permissions_table_start__ = .;
KEEP(*(.permissions_table))
__permissions_table_end__ = .;
}
PROVIDE(__ram_size__ = __bss_end__ - __data_start__);
.data : {
. = ALIGN(4);
__data_start__ = .;
__got_start__ = .;
*(.got)
__got_end__ = .;
. = ALIGN(4);
*(.data)
*(.data.*)
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
_shell_command_start = .;
KEEP(*(shellCommand))
_shell_command_end = .;
. = ALIGN(4);
/* All data end */
__data_end__ = .;
}
PROVIDE(__heap_size__ = __heap_end__ - __heap_start__);
PROVIDE(__stack_size__ = __stack_end__ - __stack_start__);
.bss : {
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
__bss_start__ = .;
*(.bss)
*(COMMON)
. = ALIGN(4);
__heap_start__ = .;
KEEP(*(.bss.heap))
__heap_end__ = .;
. = ALIGN(4);
__stack_start__ = .;
KEEP(*(.bss.stack))
__stack_end__ = .;
*(.bss.*)
/* This is used by the startup in order to initialize the .bss secion */
. = ALIGN(4);
__bss_end__ = .;
}
_end = .;
}

View File

@@ -0,0 +1,176 @@
/**
**************************************************************************
* @file at32f435_437_conf.h
* @brief at32f435_437 config header file
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __AT32F435_437_CONF_H
#define __AT32F435_437_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <u_types.h>
/**
* @brief in the following line adjust the value of high speed external crystal (hext)
* used in your application
*
* tip: to avoid modifying this file each time you need to use different hext, you
* can define the hext value in your toolchain compiler preprocessor.
*
*/
#if !defined HEXT_VALUE
#define HEXT_VALUE ((uint32_t)8000000) /*!< value of the high speed external crystal in hz */
#endif
/**
* @brief in the following line adjust the high speed external crystal (hext) startup
* timeout value
*/
#define HEXT_STARTUP_TIMEOUT ((uint16_t)0x3000) /*!< time out for hext start up */
#define HICK_VALUE ((uint32_t)8000000) /*!< value of the high speed internal clock in hz */
#define LEXT_VALUE ((uint32_t)32768) /*!< value of the low speed external clock in hz */
/* module define -------------------------------------------------------------*/
#define CRM_MODULE_ENABLED
#define TMR_MODULE_ENABLED
#define ERTC_MODULE_ENABLED
#define GPIO_MODULE_ENABLED
#define I2C_MODULE_ENABLED
#define USART_MODULE_ENABLED
#define PWC_MODULE_ENABLED
#define CAN_MODULE_ENABLED
#define ADC_MODULE_ENABLED
#define DAC_MODULE_ENABLED
#define SPI_MODULE_ENABLED
#define EDMA_MODULE_ENABLED
#define DMA_MODULE_ENABLED
#define DEBUG_MODULE_ENABLED
#define FLASH_MODULE_ENABLED
#define CRC_MODULE_ENABLED
#define WWDT_MODULE_ENABLED
#define WDT_MODULE_ENABLED
#define EXINT_MODULE_ENABLED
#define SDIO_MODULE_ENABLED
#define XMC_MODULE_ENABLED
#define USB_MODULE_ENABLED
#define ACC_MODULE_ENABLED
#define MISC_MODULE_ENABLED
#define QSPI_MODULE_ENABLED
#define DVP_MODULE_ENABLED
#define SCFG_MODULE_ENABLED
#define EMAC_MODULE_ENABLED
/* includes ------------------------------------------------------------------*/
#ifdef CRM_MODULE_ENABLED
#include "at32f435_437_crm.h"
#endif
#ifdef TMR_MODULE_ENABLED
#include "at32f435_437_tmr.h"
#endif
#ifdef ERTC_MODULE_ENABLED
#include "at32f435_437_ertc.h"
#endif
#ifdef GPIO_MODULE_ENABLED
#include "at32f435_437_gpio.h"
#endif
#ifdef I2C_MODULE_ENABLED
#include "at32f435_437_i2c.h"
#endif
#ifdef USART_MODULE_ENABLED
#include "at32f435_437_usart.h"
#endif
#ifdef PWC_MODULE_ENABLED
#include "at32f435_437_pwc.h"
#endif
#ifdef CAN_MODULE_ENABLED
#include "at32f435_437_can.h"
#endif
#ifdef ADC_MODULE_ENABLED
#include "at32f435_437_adc.h"
#endif
#ifdef DAC_MODULE_ENABLED
#include "at32f435_437_dac.h"
#endif
#ifdef SPI_MODULE_ENABLED
#include "at32f435_437_spi.h"
#endif
#ifdef DMA_MODULE_ENABLED
#include "at32f435_437_dma.h"
#endif
#ifdef DEBUG_MODULE_ENABLED
#include "at32f435_437_debug.h"
#endif
#ifdef FLASH_MODULE_ENABLED
#include "at32f435_437_flash.h"
#endif
#ifdef CRC_MODULE_ENABLED
#include "at32f435_437_crc.h"
#endif
#ifdef WWDT_MODULE_ENABLED
#include "at32f435_437_wwdt.h"
#endif
#ifdef WDT_MODULE_ENABLED
#include "at32f435_437_wdt.h"
#endif
#ifdef EXINT_MODULE_ENABLED
#include "at32f435_437_exint.h"
#endif
#ifdef SDIO_MODULE_ENABLED
#include "at32f435_437_sdio.h"
#endif
#ifdef XMC_MODULE_ENABLED
#include "at32f435_437_xmc.h"
#endif
#ifdef ACC_MODULE_ENABLED
#include "at32f435_437_acc.h"
#endif
#ifdef MISC_MODULE_ENABLED
#include "at32f435_437_misc.h"
#endif
#ifdef EDMA_MODULE_ENABLED
#include "at32f435_437_edma.h"
#endif
#ifdef QSPI_MODULE_ENABLED
#include "at32f435_437_qspi.h"
#endif
#ifdef SCFG_MODULE_ENABLED
#include "at32f435_437_scfg.h"
#endif
#ifdef EMAC_MODULE_ENABLED
#include "at32f435_437_emac.h"
#endif
#ifdef DVP_MODULE_ENABLED
#include "at32f435_437_dvp.h"
#endif
#ifdef USB_MODULE_ENABLED
#include "at32f435_437_usb.h"
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,640 @@
/**
**************************************************************************
* @file at_surf_f437_board_audio.c
* @brief the driver library of the audio.
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#include "at_surf_f437_board_audio.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#include "mk_pca9555_drv.h"
#include "u_irq_helper.h"
#include "mk_i2c_drv.h"
#include "u_sleep.h"
#include "u_sys.h"
#include "mk_pin_drv.h"
/**
* @brief wm8988 register default value
*/
uint16_t reg_addr_data[] =
{
(WM8988_R0_LEFT_INPUT_VOLUME << 9) | 0x012F, /*Left Input Channel Volume*/
(WM8988_R1_RIGHT_INPUT_VOLUME << 9) | 0x012F, /*Right Input Channel Volume*/
(WM8988_R2_LOUT1_VOLUME << 9) | 0x0179, /*Left Output Channel Volume*/
(WM8988_R3_ROUT1_VOLUME << 9) | 0x0179, /*Right Output Channel Volume*/
(WM8988_R5_ADC_DAC_CONTROL << 9) | 0x0006, /*De-emphasis Control and Digital soft mute*/
(WM8988_REG_BITW16),
(WM8988_REG_FREQ_48_K),
(WM8988_R10_LEFT_DAC_VOLUME << 9) | 0x01FF, /*Left Digital DAC Volume Control*/
(WM8988_R11_RIGHT_DAC_VOLUME << 9) | 0x01FF, /*Right Digital DAC Volume Control*/
(WM8988_R12_BASS_CONTROL << 9) | 0x000F, /*Bass Control*/
(WM8988_R13_TREBLE_CONTROL << 9) | 0x000F, /*Treble Control*/
(WM8988_R16_3D_CONTROL << 9) | 0x0000, /*3D stereo Enhancment*/
(WM8988_R21_LEFT_ADC_VOLUME << 9) | 0x01C3, /*Left ADC Digital Volume*/
(WM8988_R22_RIGHT_ADC_VOLUME << 9) | 0x01C3, /*Right ADC Digital Volume*/
(WM8988_R23_ADDITIONAL_1_CONTROL << 9) | 0x00C2, /*Additional Control 1*/
(WM8988_R24_ADDITIONAL_2_CONTROL << 9) | 0x0000, /*Additional Control 2*/
(WM8988_R27_ADDITIONAL_3_CONTROL << 9) | 0x0000, /*Additional Control 3*/
(WM8988_R31_ADC_INPUT_MODE << 9) | 0x0000, /*ADC input mode*/
// (WM8988_R32_ADC_L_SIGNAL_PATH << 9) | 0x0040, /*ADC Signal Path Control left LINPUT2*/
// (WM8988_R33_ADC_R_SIGNAL_PATH << 9) | 0x0040, /*ADC Signal Path Control right RINPUT2*/
(WM8988_R32_ADC_L_SIGNAL_PATH << 9) | 0x0000, /*ADC Signal Path Control left LINPUT1 */
(WM8988_R33_ADC_R_SIGNAL_PATH << 9) | 0x0000, /*ADC Signal Path Control right RINPUT1*/
(WM8988_R34_LEFT_OUT_MIX_1 << 9) | 0x0152, /*Left DAC mixer Control*/
(WM8988_R35_LEFT_OUT_MIX_2 << 9) | 0x0050, /*Left DAC mixer Control*/
(WM8988_R36_RIGHT_OUT_MIX_1 << 9) | 0x0052, /*Right DAC mixer Control*/
(WM8988_R37_RIGHT_OUT_MIX_2 << 9) | 0x0150, /*Right DAC mixer Control*/
(WM8988_R40_LOUT2_VOLUME << 9) | 0x01FF, /*Output left channel volume*/
(WM8988_R41_ROUT2_VOLUME << 9) | 0x01FF, /*Output left channel volume*/
(WM8988_R43_LOW_POWER_PALYBACK << 9) | 0x0008, /*Output left channel volume*/
(WM8988_R25_PWR_1_MGMT << 9) | 0x017C, /*Power Management1*/
(WM8988_R26_PWR_2_MGMT << 9) | 0x01F8, /*Power Management2*/
};
static int pca9555_fd;
static int i2c_fd;
static int pin_fd;
#define DEV_PIN_PATH "/pin"
#define DEV_PCA9555_PATH "/pca9555"
#define DEV_I2C2_PATH "/i2c2"
#define WAV_DECODE_SIZE (367) /* single channel */
int16_t music_output_buffer[DMA_BUFFER_SIZE];
audio_codec_type audio_codec;
uint16_t spk_dma_buffer[DMA_BUFFER_SIZE];
uint16_t mic_dma_buffer[DMA_BUFFER_SIZE];
void DMA1_Channel3_IRQHandler(void);
void DMA1_Channel4_IRQHandler(void);
volatile uint32_t i2s_dma_tx_end;
volatile uint32_t i2s_dma_rx_end;
void audio_output_cp(void *src, int len)
{
audio_wait_data_tx_end();
memcpy(spk_dma_buffer, src, len);
dma_channel_enable(I2S_DMA_TX_CHANNEL, FALSE);
dma_data_number_set(I2S_DMA_TX_CHANNEL, len >> 1);
dma_channel_enable(I2S_DMA_TX_CHANNEL, TRUE);
}
/**
* @brief mclk clock conifg
* @param none
* @retval none
*/
void mclk_timer_init(void)
{
int ret;
#if 0
gpio_init_type gpio_init_struct;
#endif
tmr_output_config_type tmr_oc_init_structure;
uint16_t prescaler_value = (uint16_t)(sys_read_clk() / 24000000) - 1;
crm_periph_clock_enable(CRM_TMR8_PERIPH_CLOCK, TRUE);
#if 0
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_pin_mux_config(GPIOC, GPIO_PINS_SOURCE6, GPIO_MUX_3);
gpio_init_struct.gpio_pins = GPIO_PINS_6;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOC, &gpio_init_struct);
#endif
again:
pin_fd = open(DEV_PIN_PATH, O_RDWR, 0777);
if (pin_fd < 0)
{
u_sleep_ms(50);
goto again;
}
ret = ioctl(pin_fd, MK_PIN_SET_MODE, ((mk_pin_cfg_t){
.mode = MK_PIN_MODE_MUX_OUTPUT,
.pin = (2 * 16) + 6,
.cfg = GPIO_MUX_3,
})
.cfg_raw);
if (ret < 0)
{
printf("gpio init failed.\n");
while (1)
;
}
tmr_base_init(TMR8, 1, prescaler_value);
tmr_cnt_dir_set(TMR8, TMR_COUNT_UP);
tmr_clock_source_div_set(TMR8, TMR_CLOCK_DIV1);
tmr_output_default_para_init(&tmr_oc_init_structure);
tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
tmr_oc_init_structure.oc_idle_state = FALSE;
tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_oc_init_structure.oc_output_state = TRUE;
tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure);
tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_1, 1);
tmr_output_channel_buffer_enable(TMR8, TMR_SELECT_CHANNEL_1, TRUE);
/* tmr enable counter */
tmr_counter_enable(TMR8, TRUE);
tmr_output_enable(TMR8, TRUE);
}
/**
* @brief audio codec i2s reset
* @param none
* @retval none
*/
void codec_i2s_reset(void)
{
i2s_enable(SPI1, FALSE);
i2s_enable(I2S_SPIx, FALSE);
dma_channel_enable(I2S_DMA_TX_CHANNEL, FALSE);
dma_channel_enable(I2S_DMA_RX_CHANNEL, FALSE);
}
typedef struct pin_cfg
{
int pin;
gpio_mux_sel_type mux_type;
int mode;
} pin_cfg_t;
static const pin_cfg_t audio_pins[] = {
{(1 * 16 + 13), GPIO_MUX_5, MK_PIN_MODE_MUX_OUTPUT_DOWN},
{(1 * 16 + 12), GPIO_MUX_5, MK_PIN_MODE_MUX_OUTPUT_UP},
{(1 * 16 + 15), GPIO_MUX_5, MK_PIN_MODE_MUX_OUTPUT_DOWN},
{(1 * 16 + 14), GPIO_MUX_6, MK_PIN_MODE_MUX_OUTPUT_UP},
};
static uint8_t i2s_dma_tx_intr_stack[1024];
static obj_handler_t i2s_dma_tx_intr_obj;
static uint8_t i2s_dma_rx_intr_stack[1024];
static obj_handler_t i2s_dma_rx_intr_obj;
/**
* @brief audio codec i2s init
* @param freq: audio sampling freq
* @param bitw_format: bit width
* @retval error status
*/
void codec_i2s_init(audio_codec_type *param)
{
int ret;
dma_init_type dma_init_struct;
i2s_init_type i2s_init_struct;
crm_periph_clock_enable(I2S_CK_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2S_WS_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2S_SD_OUT_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2S_SD_IN_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2S_DMAx_CLK, TRUE);
crm_periph_clock_enable(I2S_SPIx_CLK, TRUE);
param->spk_tx_size = DMA_BUFFER_SIZE;
param->mic_rx_size = DMA_BUFFER_SIZE;
for (int i = 0; i < ARRAY_SIZE(audio_pins); i++)
{
ret = ioctl(pin_fd, MK_PIN_SET_MODE, ((mk_pin_cfg_t){
.mode = audio_pins[i].mode,
.pin = audio_pins[i].pin,
.cfg = audio_pins[i].mux_type,
})
.cfg_raw);
if (ret < 0)
{
printf("audio pin set error.\n");
while (1)
;
}
}
#if 0
gpio_init_type gpio_init_struct;
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
/* i2s2 ws pins */
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init_struct.gpio_pins = I2S_WS_GPIO_PIN;
gpio_init(I2S_WS_GPIO_PORT, &gpio_init_struct);
gpio_pin_mux_config(I2S_WS_GPIO_PORT, I2S_WS_GPIO_PINS_SOURCE, I2S_WS_GPIO_MUX);
/* i2s2 ck pins */
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
gpio_init_struct.gpio_pins = I2S_CK_GPIO_PIN;
gpio_init(I2S_CK_GPIO_PORT, &gpio_init_struct);
gpio_pin_mux_config(I2S_CK_GPIO_PORT, I2S_CK_GPIO_PINS_SOURCE, I2S_CK_GPIO_MUX);
/* i2s2 SD pins */
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
gpio_init_struct.gpio_pins = I2S_SD_OUT_GPIO_PIN;
gpio_init(I2S_SD_OUT_GPIO_PORT, &gpio_init_struct);
gpio_pin_mux_config(I2S_SD_OUT_GPIO_PORT, I2S_SD_OUT_GPIO_PINS_SOURCE, I2S_SD_OUT_GPIO_MUX);
/* i2s2_EXT pins slave rx */
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init_struct.gpio_pins = I2S_SD_IN_GPIO_PIN;
gpio_init(I2S_SD_IN_GPIO_PORT, &gpio_init_struct);
gpio_pin_mux_config(I2S_SD_IN_GPIO_PORT, I2S_SD_IN_GPIO_PINS_SOURCE, I2S_SD_IN_GPIO_MUX);
#endif
/* dma config */
dma_reset(I2S_DMA_TX_CHANNEL);
dma_reset(I2S_DMA_RX_CHANNEL);
/* dma1 channel3: speaker i2s1 tx */
dma_default_para_init(&dma_init_struct);
dma_init_struct.buffer_size = param->spk_tx_size;
dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_base_addr = (uint32_t)spk_dma_buffer;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_struct.memory_inc_enable = TRUE;
dma_init_struct.peripheral_base_addr = (uint32_t)I2S_DT_ADDRESS;
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_struct.peripheral_inc_enable = FALSE;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init_struct.loop_mode_enable = FALSE;
dma_init(I2S_DMA_TX_CHANNEL, &dma_init_struct);
dma_interrupt_enable(I2S_DMA_TX_CHANNEL, DMA_FDT_INT, TRUE);
// dma_interrupt_enable(I2S_DMA_TX_CHANNEL, DMA_HDT_INT, TRUE);
// nvic_irq_enable(I2S_DMA_TX_IRQn, 1, 0);
ret = u_irq_request(I2S_DMA_TX_IRQn, (void *)(i2s_dma_tx_intr_stack + sizeof(i2s_dma_tx_intr_stack)),
NULL, &i2s_dma_tx_intr_obj, DMA1_Channel3_IRQHandler, u_irq_prio_create(1, 0));
if (ret < 0)
{
printf("irq request error.\n");
while (1)
;
}
/* dma1 channel4: microphone i2s2 rx */
dma_default_para_init(&dma_init_struct);
dma_init_struct.buffer_size = param->mic_rx_size;
dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_base_addr = (uint32_t)mic_dma_buffer;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_struct.memory_inc_enable = TRUE;
dma_init_struct.peripheral_base_addr = (uint32_t)(&(I2S_EXTx->dt));
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_struct.peripheral_inc_enable = FALSE;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init_struct.loop_mode_enable = FALSE;
dma_init(I2S_DMA_RX_CHANNEL, &dma_init_struct);
dma_interrupt_enable(I2S_DMA_RX_CHANNEL, DMA_FDT_INT, TRUE);
// dma_interrupt_enable(I2S_DMA_RX_CHANNEL, DMA_HDT_INT, TRUE);
// nvic_irq_enable(I2S_DMA_RX_IRQn, 2, 0);
ret = u_irq_request(I2S_DMA_RX_IRQn, (void *)(i2s_dma_rx_intr_stack + sizeof(i2s_dma_rx_intr_stack)),
NULL, &i2s_dma_rx_intr_obj, DMA1_Channel4_IRQHandler, u_irq_prio_create(2, 0));
if (ret < 0)
{
printf("irq request error.\n");
while (1)
;
}
/* i2s2 rx init */
/* i2s2 Tx init */
spi_i2s_reset(I2S_SPIx);
i2s_default_para_init(&i2s_init_struct);
i2s_init_struct.audio_protocol = I2S_AUDIO_PROTOCOL_PHILLIPS;
i2s_init_struct.data_channel_format = I2S_DATA_16BIT_CHANNEL_16BIT;
i2s_init_struct.mclk_output_enable = TRUE;
i2s_init_struct.audio_sampling_freq = I2S_AUDIO_FREQUENCY_48K;
i2s_init_struct.clock_polarity = I2S_CLOCK_POLARITY_LOW;
i2s_init_struct.operation_mode = I2S_MODE_SLAVE_TX;
i2s_init(I2S_SPIx, &i2s_init_struct);
/* i2s2EXT Rx init */
i2s_init_struct.operation_mode = I2S_MODE_SLAVE_RX;
i2s_init(I2S_EXTx, &i2s_init_struct);
spi_i2s_dma_transmitter_enable(I2S_SPIx, TRUE);
spi_i2s_dma_receiver_enable(I2S_EXTx, TRUE);
dmamux_enable(I2S_DMAx, TRUE);
dmamux_init(I2S_DMA_TX_DMAMUX_CHANNEL, I2S_DMA_TX_DMAREQ);
dmamux_init(I2S_DMA_RX_DMAMUX_CHANNEL, I2S_DMA_RX_DMAREQ);
dma_channel_enable(I2S_DMA_TX_CHANNEL, TRUE);
dma_channel_enable(I2S_DMA_RX_CHANNEL, TRUE);
i2s_enable(I2S_EXTx, TRUE);
i2s_enable(I2S_SPIx, TRUE);
}
/**
* @brief power on
* @param none
* @retval none
*/
void audio_pa_power_on(void)
{
#if 0
pca9555_out_mode_config(AUDIO_PA_ON_PIN);
pca9555_bits_reset(AUDIO_PA_ON_PIN);
#endif
ioctl(pca9555_fd, PCA9555_SET_OUTPUT_MODE, AUDIO_PA_ON_PIN);
ioctl(pca9555_fd, PCA9555_IO_RESET, AUDIO_PA_ON_PIN);
}
/**
* @brief power off
* @param none
* @retval none
*/
void audio_pa_power_off(void)
{
#if 0
pca9555_out_mode_config(AUDIO_PA_ON_PIN);
pca9555_bits_set(AUDIO_PA_ON_PIN);
#endif
ioctl(pca9555_fd, PCA9555_SET_OUTPUT_MODE, AUDIO_PA_ON_PIN);
ioctl(pca9555_fd, PCA9555_IO_SET, AUDIO_PA_ON_PIN);
}
/**
* @brief audio codec init
* @param none
* @retval error status
*/
error_status audio_init(void)
{
uint32_t reg_len = sizeof(reg_addr_data) / sizeof(uint16_t);
uint32_t i = 0;
uint8_t i2c_cmd[2];
int ret;
again:
pca9555_fd = open(DEV_PCA9555_PATH, O_RDWR, 0777);
if (pca9555_fd < 0)
{
u_sleep_ms(50);
goto again;
}
again2:
i2c_fd = open(DEV_I2C2_PATH, O_RDWR, 0777);
if (i2c_fd < 0)
{
u_sleep_ms(50);
goto again2;
}
audio_pa_power_on();
ret = lseek(i2c_fd, (0 << 16) | (WM8988_I2C_ADDR_CSB_LOW), SEEK_SET);
if (ret < 0)
{
printf("%s:%d ret:%d\n", __func__, __LINE__, ret);
return ret;
}
for (i = 0; i < reg_len; i++)
{
i2c_cmd[0] = (uint8_t)(reg_addr_data[i] >> 8);
i2c_cmd[1] = (uint8_t)reg_addr_data[i] & 0xFF;
ret = write(i2c_fd, i2c_cmd, 2);
if (ret != 2)
{
printf("error:%s:%d ret:%d\n", __func__, __LINE__, ret);
return -1;
}
}
/* timer init */
mclk_timer_init();
codec_i2s_init(&audio_codec);
audio_codec_modify_freq(WM8988_REG_FREQ_22_05K);
audio_dma_counter_set(WAV_DECODE_SIZE);
// audio_wait_data_tx_end();
audio_spk_volume_set(220, 220);
#if 1
for (int i = 0; i < DMA_BUFFER_SIZE; i++)
{
music_output_buffer[i] = 0;
}
#endif
return SUCCESS;
}
/**
* @brief set audio volume
* @param left_volume
* @param right_volume
* @retval error_status
*/
error_status audio_spk_volume_set(uint8_t left_volume, uint8_t right_volume)
{
uint16_t audio_left;
uint16_t audio_right;
int ret;
uint8_t i2c_cmd[2];
audio_left = WM8988_R10_LEFT_DAC_VOLUME << 9 | 0x100 | left_volume;
audio_right = WM8988_R11_RIGHT_DAC_VOLUME << 9 | 0x100 | right_volume;
i2c_cmd[0] = (uint8_t)(audio_left >> 8);
i2c_cmd[1] = (uint8_t)audio_left & 0xFF;
ret = write(i2c_fd, i2c_cmd, 2);
if (ret != 2)
{
printf("error:%s:%d ret:%d\n", __func__, __LINE__, ret);
return ERROR;
}
i2c_cmd[0] = (uint8_t)(audio_right >> 8);
i2c_cmd[1] = (uint8_t)audio_right & 0xFF;
ret = write(i2c_fd, i2c_cmd, 2);
if (ret != 2)
{
printf("error:%s:%d ret:%d\n", __func__, __LINE__, ret);
return ERROR;
}
return SUCCESS;
}
/**
* @brief audio codec modify freq
* @param freq: freq (wm8988 microphone and speaker must as same freq)
WM8988_REG_FREQ_8_K
WM8988_REG_FREQ_8_0214_K
WM8988_REG_FREQ_11_025_K
WM8988_REG_FREQ_12_K
WM8988_REG_FREQ_16K
WM8988_REG_FREQ_22_05K
WM8988_REG_FREQ_24K
WM8988_REG_FREQ_32_K
WM8988_REG_FREQ_44_1_K
WM8988_REG_FREQ_48_K
WM8988_REG_FREQ_88_235K
WM8988_REG_FREQ_96_K
* @retval none
*/
void audio_codec_modify_freq(uint16_t freq)
{
int ret;
uint8_t i2c_cmd[2];
i2c_cmd[0] = (uint8_t)(freq >> 8);
i2c_cmd[1] = (uint8_t)freq & 0xFF;
ret = write(i2c_fd, i2c_cmd, 2);
if (ret != 2)
{
printf("error:%s:%d ret:%d\n", __func__, __LINE__, ret);
while (1)
;
}
}
/**
* @brief audio codec modify freq
* @param freq: freq (wm8988 microphone and speaker must as same freq)
WM8988_REG_FREQ_8_K
WM8988_REG_FREQ_8_0214_K
WM8988_REG_FREQ_11_025_K
WM8988_REG_FREQ_12_K
WM8988_REG_FREQ_16K
WM8988_REG_FREQ_22_05K
WM8988_REG_FREQ_24K
WM8988_REG_FREQ_32_K
WM8988_REG_FREQ_44_1_K
WM8988_REG_FREQ_48_K
WM8988_REG_FREQ_88_235K
WM8988_REG_FREQ_96_K
* @retval none
*/
void audio_dma_counter_set(uint16_t counter)
{
audio_codec.spk_tx_size = counter * 2;
}
/**
* @brief wait data transmit end
* @param none
* @retval none
*/
void audio_wait_data_tx_end(void)
{
while (i2s_dma_tx_end == 0)
;
i2s_dma_tx_end = 0;
}
/**
* @brief audio codec modify freq
* @param counter: freq (wm8988 microphone and speaker must as same freq)
* @retval none
*/
void modify_dma_tx_counter(uint16_t counter)
{
static uint16_t counter_last = 0xFFFF;
/* the frequency value changes */
if (counter_last != counter)
{
dma_channel_enable(I2S_DMA_TX_CHANNEL, FALSE);
dma_data_number_set(I2S_DMA_TX_CHANNEL, counter);
dma_channel_enable(I2S_DMA_TX_CHANNEL, TRUE);
audio_codec.spk_tx_size = counter;
counter_last = counter;
}
}
/**
* @brief this function handles dma1 channel3 interrupt.
* @param none
* @retval none
*/
void DMA1_Channel3_IRQHandler(void)
{
while (1)
{
msg_tag_t tag = uirq_wait(i2s_dma_tx_intr_obj, 0);
if (msg_tag_get_val(tag) >= 0)
{
if (dma_interrupt_flag_get(I2S_DMA_TX_HDT_FLAG) == SET)
{
dma_flag_clear(I2S_DMA_TX_HDT_FLAG);
}
else if (dma_interrupt_flag_get(I2S_DMA_TX_FDT_FLAG) == SET)
{
// memcpy(spk_dma_buffer, (uint16_t *)music_output_buffer, DMA_BUFFER_SIZE);
// modify_dma_tx_counter(audio_codec.spk_tx_size);
i2s_dma_tx_end = 1;
dma_flag_clear(I2S_DMA_TX_FDT_FLAG);
}
uirq_ack(i2s_dma_tx_intr_obj, I2S_DMA_TX_IRQn);
}
}
}
/**
* @brief this function handles dma1 channel4 interrupt.
* @param none
* @retval none
*/
void DMA1_Channel4_IRQHandler(void)
{
while (1)
{
msg_tag_t tag = uirq_wait(i2s_dma_rx_intr_obj, 0);
if (msg_tag_get_val(tag) >= 0)
{
if (dma_interrupt_flag_get(I2S_DMA_RX_HDT_FLAG) == SET)
{
dma_flag_clear(I2S_DMA_RX_HDT_FLAG);
}
else if (dma_interrupt_flag_get(I2S_DMA_RX_FDT_FLAG) == SET)
{
dma_flag_clear(I2S_DMA_RX_FDT_FLAG);
}
uirq_ack(i2s_dma_rx_intr_obj, I2S_DMA_RX_IRQn);
}
}
}

View File

@@ -0,0 +1,200 @@
/**
**************************************************************************
* @file at_surf_f437_board_audio.c
* @brief header file for at-start board. set of firmware functions to
* manage leds and push-button. initialize delay function.
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#ifndef __AT32_SURF_F437_BOARD_AUDIO_H
#define __AT32_SURF_F437_BOARD_AUDIO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "at32f435_437_conf.h"
#include "u_types.h"
/**
* @brief wm8988 register
*/
#define WM8988_R0_LEFT_INPUT_VOLUME 0x00
#define WM8988_R1_RIGHT_INPUT_VOLUME 0x01
#define WM8988_R2_LOUT1_VOLUME 0x02
#define WM8988_R3_ROUT1_VOLUME 0x03
#define WM8988_R4_RESERVED 0x04
#define WM8988_R5_ADC_DAC_CONTROL 0x05
#define WM8988_R6_RESERVED 0x06
#define WM8988_R7_AUDIO_INTERFACE 0x07
#define WM8988_R8_SAMPLE_RATE 0x08
#define WM8988_R9_RESERVED 0x09
#define WM8988_R10_LEFT_DAC_VOLUME 0x0A
#define WM8988_R11_RIGHT_DAC_VOLUME 0x0B
#define WM8988_R12_BASS_CONTROL 0x0C
#define WM8988_R13_TREBLE_CONTROL 0x0D
#define WM8988_R14_
#define WM8988_R15_RESET 0x0F
#define WM8988_R16_3D_CONTROL 0x10
#define WM8988_R17_ALC1 0x11
#define WM8988_R18_ALC2 0x12
#define WM8988_R19_ALC3 0x13
#define WM8988_R20_NOISE_GATE 0x14
#define WM8988_R21_LEFT_ADC_VOLUME 0x15
#define WM8988_R22_RIGHT_ADC_VOLUME 0x16
#define WM8988_R23_ADDITIONAL_1_CONTROL 0x17
#define WM8988_R24_ADDITIONAL_2_CONTROL 0x18
#define WM8988_R25_PWR_1_MGMT 0x19
#define WM8988_R26_PWR_2_MGMT 0x1A
#define WM8988_R27_ADDITIONAL_3_CONTROL 0x1B
#define WM8988_R31_ADC_INPUT_MODE 0x1F
#define WM8988_R32_ADC_L_SIGNAL_PATH 0x20
#define WM8988_R33_ADC_R_SIGNAL_PATH 0x21
#define WM8988_R34_LEFT_OUT_MIX_1 0x22
#define WM8988_R35_LEFT_OUT_MIX_2 0x23
#define WM8988_R36_RIGHT_OUT_MIX_1 0x24
#define WM8988_R37_RIGHT_OUT_MIX_2 0x25
#define WM8988_R38_RESERVED
#define WM8988_R39_RESERVED
#define WM8988_R40_LOUT2_VOLUME 0x28
#define WM8988_R41_ROUT2_VOLUME 0x29
#define WM8988_R42_RESERVED
#define WM8988_R43_LOW_POWER_PALYBACK 0x43
#define WM8988_I2C_ADDR_CSB_LOW 0x34
#define WM8988_I2C_ADDR_CSB_HIGH 0x36
/**
* @brief wm8988 freq
*/
#define WM8988_REG_FREQ_8_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x000C) /* 8 kHz */
#define WM8988_REG_FREQ_8_0214_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x002E) /* 8.0214 kHz */
#define WM8988_REG_FREQ_11_025_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0032) /* 11.0259 kHz */
#define WM8988_REG_FREQ_12_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0010) /* 12 kHz */
#define WM8988_REG_FREQ_16K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0014) /* 16kHz */
#define WM8988_REG_FREQ_22_05K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0036) /* 22.0588kHz */
#define WM8988_REG_FREQ_24K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0038) /* 24kHz */
#define WM8988_REG_FREQ_32_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0018) /* 32 kHz */
#define WM8988_REG_FREQ_44_1_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0022) /* 44.118 kHz */
#define WM8988_REG_FREQ_48_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x0000) /* 48 kHz */
#define WM8988_REG_FREQ_88_235K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x003E) /* 88.235kHz */
#define WM8988_REG_FREQ_96_K ((WM8988_R8_SAMPLE_RATE << 9) | 0x0081 | 0x001C) /* 96 kHz */
/**
* @brief wm8988 bit width
*/
#define WM8988_REG_BITW16 ((WM8988_R7_AUDIO_INTERFACE << 9) | 0x0042)
/** @defgroup USB_device_audio_codec_exported_functions
* @{
*/
/**
* @brief wm8988 buffer size
*/
#define DMA_BUFFER_SIZE 367
#define AUDIO_FREQ_16K 16000
#define AUDIO_FREQ_48K 48000
#define AUDIO_BITW_16 16
#define AUDIO_MIC_CHANEL_NUM 2
#define AUDIO_MIC_DEFAULT_BITW AUDIO_BITW_16
#define AUDIO_SPK_CHANEL_NUM 2
#define AUDIO_SPK_DEFAULT_BITW AUDIO_BITW_16
/**
* @brief wm8988 pin definition
*/
#define I2S_DMAx_CLK CRM_DMA1_PERIPH_CLOCK
#define I2S_SPIx_CLK CRM_SPI2_PERIPH_CLOCK
#define I2S_SPIx SPI2
#define I2S_EXTx I2S2EXT
#define I2S_DMAx DMA1
#define I2S_DT_ADDRESS (&(SPI2->dt))
#define I2S_CK_GPIO_CLK CRM_GPIOB_PERIPH_CLOCK
#define I2S_CK_GPIO_PIN GPIO_PINS_13
#define I2S_CK_GPIO_PINS_SOURCE GPIO_PINS_SOURCE13
#define I2S_CK_GPIO_PORT GPIOB
#define I2S_CK_GPIO_MUX GPIO_MUX_5
#define I2S_WS_GPIO_CLK CRM_GPIOB_PERIPH_CLOCK
#define I2S_WS_GPIO_PIN GPIO_PINS_12
#define I2S_WS_GPIO_PINS_SOURCE GPIO_PINS_SOURCE12
#define I2S_WS_GPIO_PORT GPIOB
#define I2S_WS_GPIO_MUX GPIO_MUX_5
#define I2S_SD_OUT_GPIO_CLK CRM_GPIOB_PERIPH_CLOCK
#define I2S_SD_OUT_GPIO_PIN GPIO_PINS_15
#define I2S_SD_OUT_GPIO_PINS_SOURCE GPIO_PINS_SOURCE15
#define I2S_SD_OUT_GPIO_PORT GPIOB
#define I2S_SD_OUT_GPIO_MUX GPIO_MUX_5
#define I2S_SD_IN_GPIO_CLK CRM_GPIOB_PERIPH_CLOCK
#define I2S_SD_IN_GPIO_PIN GPIO_PINS_14
#define I2S_SD_IN_GPIO_PINS_SOURCE GPIO_PINS_SOURCE14
#define I2S_SD_IN_GPIO_PORT GPIOB
#define I2S_SD_IN_GPIO_MUX GPIO_MUX_6
#define AUDIO_PA_ON_PIN PCA_IO0_PINS_2
#define I2S_DMA_TX_CHANNEL DMA1_CHANNEL3
#define I2S_DMA_TX_DMAMUX_CHANNEL DMA1MUX_CHANNEL3
#define I2S_DMA_TX_DMAREQ DMAMUX_DMAREQ_ID_SPI2_TX
#define I2S_DMA_TX_IRQn DMA1_Channel3_IRQn
// #define I2S_DMA_TX_IRQHandler DMA1_Channel3_IRQHandler
#define I2S_DMA_TX_HDT_FLAG DMA1_HDT3_FLAG
#define I2S_DMA_TX_FDT_FLAG DMA1_FDT3_FLAG
#define I2S_DMA_RX_CHANNEL DMA1_CHANNEL4
#define I2S_DMA_RX_DMAMUX_CHANNEL DMA1MUX_CHANNEL4
#define I2S_DMA_RX_DMAREQ DMAMUX_DMAREQ_ID_I2S2_EXT_RX
#define I2S_DMA_RX_IRQn DMA1_Channel4_IRQn
// #define I2S_DMA_RX_IRQHandler DMA1_Channel4_IRQHandler
#define I2S_DMA_RX_HDT_FLAG DMA1_HDT4_FLAG
#define I2S_DMA_RX_FDT_FLAG DMA1_FDT4_FLAG
/**
* @brief audio codec interface
*/
typedef struct
{
uint32_t spk_tx_size;
uint32_t mic_rx_size;
}audio_codec_type;
/**
* @brief audio codec interface
*/
error_status audio_init(void);
error_status audio_spk_volume_set(uint8_t left_volume, uint8_t right_volume);
void audio_codec_modify_freq(uint16_t freq);
void audio_dma_counter_set(uint16_t counter);
extern audio_codec_type audio_codec;
void audio_wait_data_tx_end(void);
void audio_output_cp(void *src, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,17 @@
#define HEAP_SIZE (2048)
#define STACK_SIZE (1024 * 2)
#if defined(__CC_ARM)
#define HEAP_ATTR SECTION("HEAP") __attribute__((zero_init))
#define STACK_ATTR SECTION("STACK") __attribute__((zero_init))
#elif defined(__GNUC__)
#define HEAP_ATTR __attribute__((__section__(".bss.heap")))
#define STACK_ATTR __attribute__((__section__(".bss.stack")))
#elif defined(__IAR_SYSTEMS_ICC__)
#define HEAP_ATTR
#define STACK_ATTR
#endif
__attribute__((used)) HEAP_ATTR static char _____heap_____[HEAP_SIZE];
__attribute__((used)) STACK_ATTR static char _____stack_____[STACK_SIZE];

View File

@@ -0,0 +1,81 @@
#include <stdio.h>
#include <u_vmam.h>
#include <at32f435_437_conf.h>
#include <u_sleep.h>
#include <u_sys.h>
#include <u_task.h>
#include <mk_dtb_parse.h>
#include <mk_dev.h>
#include <mk_drv.h>
#include "ns_cli.h"
#include "rpc_prot.h"
#include "u_hd_man.h"
#include "u_share_mem.h"
#include <assert.h>
#include <sys/stat.h>
#include <errno.h>
#include <snd_drv_svr.h>
#include "mk_snd_drv_impl.h"
static snd_drv_t snd_drv; //!< 网络驱动的协议
int snd_drv_write(obj_handler_t obj, int len)
{
int ret = -1;
addr_t addr = 0;
umword_t size = 0;
msg_tag_t tag = share_mem_map(obj, vma_addr_create(VPAGE_PROT_RWX, 0, 0), &addr, &size);
if (msg_tag_get_val(tag) < 0)
{
handler_free_umap(obj);
printf("snd write error.\n");
return msg_tag_get_val(tag);
}
audio_output_cp((uint8_t *)addr, len);
// mk_printf("snd write len:%d.\n", MIN(size, len));
handler_free_umap(obj);
return len;
}
int snd_drv_read(obj_handler_t obj, int len)
{
int ret = -1;
addr_t addr = 0;
umword_t size = 0;
msg_tag_t tag = share_mem_map(obj, vma_addr_create(VPAGE_PROT_RWX, 0, 0), &addr, &size);
uint32_t _err;
// ret = emac_read_packet((uint8_t *)addr, size);
handler_free_umap(obj);
return ret;
}
int snd_drv_map(obj_handler_t *hd)
{
// *hd = emac_get_sema();
return -1;
}
int main(int argc, char *argv[])
{
obj_handler_t hd;
int ret;
task_set_obj_name(TASK_THIS, TASK_THIS, "tk_snd");
task_set_obj_name(TASK_THIS, THREAD_MAIN, "th_snd");
printf("%s init..\n", argv[0]);
mk_drv_init();
mk_dev_init();
drv_snd_init();
dtb_parse_init();
snd_drv_init(&snd_drv);
ret = rpc_meta_init(THREAD_MAIN, &hd);
assert(ret >= 0);
ns_register("/snd", hd, FILE_NODE);
meta_reg_svr_obj(&snd_drv.svr, SND_DRV_PROT);
while (1)
{
rpc_loop();
}
}

View File

@@ -0,0 +1,92 @@
#include <u_types.h>
#include <errno.h>
#include <libfdt.h>
#include <mk_dev.h>
#include <stdio.h>
#include <assert.h>
#include "mk_drv.h"
#include "mk_snd_drv.h"
#include "mk_dtb_parse.h"
#include <u_prot.h>
#include <u_vmam.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "mk_snd_drv_impl.h"
#include "at_surf_f437_board_audio.h"
typedef struct snd_priv_data
{
} snd_priv_data_t;
static snd_priv_data_t snd_priv_data;
static int snd_bus_configure(mk_snd_t *drv)
{
assert(drv);
snd_priv_data_t *priv_data = drv->priv_data;
return 0;
}
static int snd_bus_read(mk_snd_t *drv, uint8_t *data, int len)
{
return -1;
}
static int snd_bus_write(mk_snd_t *drv, uint8_t *data, int len)
{
return -1;
}
static mk_snd_ops_t snd_ops = {
.snd_configure = snd_bus_configure,
.snd_read = snd_bus_read,
.snd_write = snd_bus_write,
};
static mk_snd_dev_t snd_dev = {
.ops = &snd_ops,
.snd.priv_data = &snd_priv_data,
};
static int snd_probe(mk_dev_t *dev)
{
int ret;
/* ioremap */
ret = dev_regs_map(dev, dev->dtb);
if (ret < 0)
{
printf("snd dev regs map failed.\n");
return -ENOMEM;
}
if (audio_init() != SUCCESS)
{
printf("audio init failed.\n");
return -EIO;
}
printf("snd init success.\r\n");
/* 注册snd设备 */
// mk_snd_register(dev, &snd_dev);
return 0;
}
static mk_drv_compatible_t drv_compatilbe[] =
{
{"at32f43x,snd"},
{NULL},
};
static mk_drv_t snd_drv =
{
.compatilbe = drv_compatilbe,
.probe = snd_probe,
.data = NULL,
};
void drv_snd_init(void)
{
mk_drv_register(&snd_drv);
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "at_surf_f437_board_audio.h"
void drv_snd_init(void);

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMKRTOS_DRV " )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMKRTOS_DRV ")
set(CMAKE_CXX_FLAGS "${CMAKE_ASM_FLAGS} -DMKRTOS_DRV ")
# if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_BOARD_NAME})
# add_subdirectory(${CONFIG_BOARD_NAME})
# endif()
add_subdirectory(ATSURFF437)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_BOARD_NAME})
add_subdirectory(${CONFIG_BOARD_NAME})
endif()
# add_subdirectory(ATSURFF437)
add_subdirectory(lib)

View File

@@ -80,7 +80,7 @@ static int mk_eth_drv_ioctl(mk_dev_t *pin, int cmd, umword_t args)
return msg_tag_get_val(tag);
}
ret = mk_copy_mem_to_task(src_pid, (void *)args,
cur_pid, &info, sizeof(mk_ioctl_set_info_t));
cur_pid, &info, sizeof(mk_eth_ioctl_set_info_t));
if (ret < 0)
{
return ret;

View File

@@ -8,10 +8,10 @@ enum mk_eth_ioctl_op
ETH_SET_MAC_ADDR,
};
typedef struct mk_ioctl_set_info
typedef struct mk_eth_ioctl_set_info
{
uint8_t mac_addr[6];
} mk_ioctl_set_info_t;
} mk_eth_ioctl_set_info_t;
/**
* @brief eth设备数据
*
@@ -26,7 +26,7 @@ typedef struct mk_eth
*/
typedef struct mk_eth_ops
{
int (*eth_configure)(mk_eth_t *drv, enum mk_eth_ioctl_op op, mk_ioctl_set_info_t *info);
int (*eth_configure)(mk_eth_t *drv, enum mk_eth_ioctl_op op, mk_eth_ioctl_set_info_t *info);
int (*eth_read)(mk_eth_t *drv, uint8_t *data, int len);
int (*eth_write)(mk_eth_t *drv, uint8_t *dat, int len);
} mk_eth_ops_t;

View File

@@ -56,6 +56,8 @@ enum mk_pin_mode_cfg
MK_PIN_MODE_MUX_OUTPUT,
MK_PIN_MODE_MUX_OUTPUT_OD,
MK_PIN_MODE_MUX_OUTPUT_UP,
MK_PIN_MODE_MUX_OUTPUT_DOWN,
MK_PIN_MODE_IRQ_RISING,
MK_PIN_MODE_IRQ_FALLING,

View File

@@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 3.13)
file(GLOB_RECURSE deps *.c *.S)
add_library(
mk_snd
STATIC
${deps}
)
target_link_libraries(
mk_snd
PRIVATE
fdt
sys
sys_util
sys_svr
mk_drv
)
add_dependencies(
mk_snd
fdt
sys
sys_util
sys_svr
mk_drv
)
target_include_directories(
mk_snd
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/
${CMAKE_CURRENT_SOURCE_DIR}/../mk_drv
${CMAKE_SOURCE_DIR}/mkrtos_user/user/drv/lib/mk_char
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc/${ARCH_NAME}
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/util/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/libfdt/lib/contrib
)

View File

@@ -0,0 +1,120 @@
#include "mk_snd_drv.h"
#include "u_types.h"
#include <assert.h>
#include <errno.h>
#include <mk_char_dev.h>
#include <sys/types.h>
#include <mk_access.h>
#include "u_prot.h"
#include "u_task.h"
/**
* @brief 写pin操作
*
* @param pin pin设备
* @param buf 写的buf
* @param size 写入大小
* @return int 写入的个数
*/
static int mk_snd_drv_write(mk_dev_t *pin, void *buf, size_t size, off_t *offset)
{
assert(buf);
assert(pin);
mk_snd_dev_t *pin_dev = pin->priv_data;
mk_snd_ops_t *ops = pin_dev->ops;
assert(ops);
int ret = ops->snd_write(&pin_dev->snd, buf, size);
return ret;
}
/**
* @brief 读取pin数据
*
* @param pin
* @param buf
* @param size
* @return int
*/
static int mk_snd_drv_read(mk_dev_t *pin, void *buf, size_t size, off_t *offset)
{
assert(buf);
assert(pin);
mk_snd_dev_t *pin_dev = pin->priv_data;
mk_snd_ops_t *ops = pin_dev->ops;
assert(ops);
int ret = ops->snd_read(&pin_dev->snd, buf, size);
return ret;
}
/**
* @brief 控制pin状态
*
* @param pin
* @param cmd
* @param args
* @return int
*/
static int mk_snd_drv_ioctl(mk_dev_t *pin, int cmd, umword_t args)
{
assert(pin);
pid_t src_pid = thread_get_src_pid();
pid_t cur_pid;
mk_snd_dev_t *snd_dev = pin->priv_data;
mk_snd_ops_t *ops = snd_dev->ops;
assert(ops);
int ret = 0;
msg_tag_t tag;
switch (cmd)
{
case ETH_SET_MAC_ADDR:
{
mk_ioctl_set_info_t info;
tag = task_get_pid(TASK_THIS, (umword_t *)(&cur_pid));
if (msg_tag_get_val(tag) < 0)
{
return msg_tag_get_val(tag);
}
ret = mk_copy_mem_to_task(src_pid, (void *)args,
cur_pid, &info, sizeof(mk_snd_ioctl_set_info_t));
if (ret < 0)
{
return ret;
}
if (ops->snd_configure) {
ops->snd_configure(snd_dev, cmd, &info);
}
}
break;
default:
break;
}
return ret;
}
// static mk_file_ops_t file_ops = {
// .open = NULL,
// .write = mk_snd_drv_write,
// .read = mk_snd_drv_read,
// .ioctl = mk_snd_drv_ioctl,
// .release = NULL,
// };
int mk_snd_register(mk_dev_t *dev, mk_snd_dev_t *pin_drv)
{
int ret = 0;
assert(dev);
assert(pin_drv);
// ret = mk_char_dev_register(dev, &file_ops);
// if (ret < 0)
// {
// return ret;
// }
mk_dev_set_priv_data(dev, pin_drv);
return ret;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <u_types.h>
#include <mk_drv.h>
#include <sys/types.h>
/**
* @brief snd设备数据
*
*/
typedef struct mk_snd
{
void *priv_data;
} mk_snd_t;
/**
* @brief snd设备操作对象
*
*/
typedef struct mk_snd_ops
{
int (*snd_configure)(mk_snd_t *drv);
int (*snd_read)(mk_snd_t *drv, uint8_t *data, int len);
int (*snd_write)(mk_snd_t *drv, uint8_t *dat, int len);
} mk_snd_ops_t;
/**
* @brief snd设备
*
*/
typedef struct mk_snd_dev
{
mk_snd_t snd;
mk_snd_ops_t *ops;
} mk_snd_dev_t;
int mk_snd_register(mk_dev_t *dev, mk_snd_dev_t *pin_drv);