VOI611 SDK 開發(fā)接入指南
本文主要描述了基于SDK方案的開發(fā)流程,適用于嵌入式開發(fā)工程師及個(gè)人開發(fā)者快速入門,了解使用 VOI611 內(nèi)置 MCU 開發(fā)。
1.方案概述
VOI611 是一顆針對(duì)嵌入式產(chǎn)品的深度學(xué)習(xí)語音識(shí)別芯片,內(nèi)置神經(jīng)網(wǎng)絡(luò)硬件加速模塊NPU,標(biāo)準(zhǔn)ARM處理器Cortex-M3,集成多種控制和通信接口。
VOI611 不僅可以運(yùn)行多種神經(jīng)網(wǎng)絡(luò),在有噪聲干擾的近場(chǎng)和遠(yuǎn)場(chǎng)情況下,支持離線語音命令識(shí)別,還可以在設(shè)備不聯(lián)網(wǎng)的情況下,通過說出簡(jiǎn)單命令詞方式,有效控制目標(biāo)電器設(shè)備,執(zhí)行既定的操作行為。

VOI611 智能語音處理解決方案是基于深度學(xué)習(xí)語音識(shí)別芯片設(shè)計(jì)的全套智能語音解決方案,探境科技提供SDK可以對(duì)芯片上的各硬件進(jìn)行開發(fā)、定制,例如:
- 定制外圍設(shè)備
- 定制語音識(shí)別反饋處理和定制反饋語音
- 定制MCU和ASR通信的串口碼
2.開發(fā)環(huán)境
2.1 Windows 開發(fā)環(huán)境
由探境提供的IET_ENV軟件編譯環(huán)境,解壓即可使用,目錄如下
├── sdk?
├── tools
├── start-編譯環(huán)境-iet-env.bat
└── ?使用說明.md
2.2 如何進(jìn)入編譯環(huán)境
雙擊運(yùn)行 start-編譯環(huán)境-iet-env.bat 腳本,進(jìn)入相應(yīng)SDK版本
cd VOI611_SDK_2.1
2.3 編譯和打包
進(jìn)入SDK的根目錄,執(zhí)行清除和編譯指令
make clean
make
生成的升級(jí)文件位于當(dāng)前目錄的output-package/upgrade-package/package下
app_iet_upgrade.bin iet_upgrade_01.bin wav_iet_upgrade.bin
boot_iet_upgrade.bin iet_upgrade.bin weight_iet_upgrade_01.bin
iet_flash_xMB_checksum.bin para_iet_upgrade.bin weight_iet_upgrade.bin
iet_flash_xMB_checksum.bin
主要用于批量生產(chǎn)階段,在Flash備料環(huán)節(jié)進(jìn)行批量的燒錄。(生產(chǎn)流程為:預(yù)燒錄Flash芯片-->貼片加工-->產(chǎn)測(cè)驗(yàn)證)
iet_upgrade.bin
該文件系列包含(iet_upgrade.bin / iet_upgrade_01.bin / iet_upgrade_02.bin / ...)
iet_upgrade.bin = boot_iet_upgrade.bin + para_iet_upgrade.bin + app_iet_upgrade.bin + wav_iet_upgrade.bin + weight_iet_upgrade.bin
para_iet_upgrade.bin
主要用于標(biāo)識(shí) flash layout 信息,記錄了:app_iet_upgrade.bin 、 wav_iet_upgrade.bin 、 weight_iet_upgrade.bin 等文件地址。
boot_iet_upgrade.bin
VOI611芯片上電后,首先運(yùn)行這部分的軟件,并且載入 para_iet_upgrade.bin 的設(shè)定。
3. SDK 介紹
3.1 SDK 目錄結(jié)構(gòu)說明
├── bootloader
├── demo
│?? ├── include 所有依賴的Lib文件的頭文件聲明
│?? ├── lib 依賴的Lib文件
│?? ├── obj 依賴的.o文件
│?? ├── source demo APP 以及 Makefile
│?? └── tool 鏈接器
├── document 文檔說明
├── Makefile 編譯腳本
├── output-package
│?? ├── conf 配置文件
│?? ├── upgrade-package 升級(jí)包目錄
│?? ├── wav 語音反饋文件
│?? └── weight 訓(xùn)練模型文件
└── tool
├── package
└── tts 語音合成腳本
3.2 IC類型設(shè)置
VOI611有兩種類型IC分別是1CA和1CC,軟件需要根據(jù)不同的型號(hào)配置。
SDK默認(rèn)編譯出來的固件是1CC,如果需要編譯1CA固件,需要修改如下兩個(gè)文件。
- demo/source/main.c
#define IC_TYPE_1CC (1) //1CC設(shè)置
#define IC_TYPE_1CC (0) //1CA設(shè)置
- output-package/conf/upgrade_conf.json
"hw_ver": "1CC" //1CC設(shè)置
"hw_ver": "1CA" //1CA設(shè)置
3.3 GPIO配置使用
VOI611 SDK 允許用戶根據(jù)不同的硬件環(huán)境來配置Pinmux
共16個(gè)GPIO,全部為復(fù)用管腳,具體描述如下表:
Pin num | Function0 | Function1 | Function2 |
---|---|---|---|
19 | PDM_CLK | GPIOC2 | |
20 | I2S_SDI | GPIOD2 | |
38 | MSPI_SCK | GPIOA3 | |
39 | MSPI_SDO | GPIOC3 | |
40 | MSPI_SDI | GPIOD3 | |
41 | MSPI_CSN | GPIOB3 | |
54 | UART1_RX | GPIOD1 | |
55 | UART1_TX | GPIOC1 | |
56 | UART0_TX | GPIOA1 | |
57 | UART0_RX | GPIOB1 | |
60 | JTAG_TDO | PWM3_O | GPIOD0 |
61 | JTAG_TDI | PWM2_O | GPIOC0 |
62 | JTAG_TMS | PWM1_O | GPIOB0 |
63 | JTAG_TCK | PWM0_O | GPIOA0 |
64 | I2C_SDA | GPIOB2 | |
65 | I2C_SCL | GPIOA2 |
- GPIO 讀寫操作例程
#include "asr_gpio.h"
void main(void)
{
uint8_t ui1_group = 0,ui1_pin = 0; //GPIOA0 group = 0 ,pin = 0;
uint32_t ui4_data = 0,ui4_value = 0
uint32_t ui4_source_contrl = 0; //0 software control 1 hardware control
uint32_t ui4_direction = 1; //1 output, 0 input
i4_ret = asr_gpio_open(ui1_group, ui1_pin, ui4_direction, ui4_data, ui4_source_contrl)
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_write(ui1_group, ui1_pin, ui4_value);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_read(ui1_group, ui1_pin, &ui4_value);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_close(ui1_group, ui1_pin);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
}
- GPIO 中斷操作例程 ( 只有GPIOA0/GPIOB0/GPIOC0/GPIOD0具有中斷功能 )
#include "asr_gpio.h"
static void goio_interrupt_callback(void)
{
APP_MSG("do what you want here.\n");
}
void main(void)
{
uint8_t ui1_group = 0,ui1_pin = 0;
uint32_t ui4_data = 0,ui4_value = 0
uint32_t ui4_source_contrl = 0; //0 software control 1 hardware control
uint32_t ui4_direction = 0; //1 output, 0 input
uint8_t ui1_int_polarity = 0; //0 low volage trigger,1 high volage trigger
uint8_t ui1_int_flag = 1,ui1_int_level = 0,ui1_int_bothedge = 0;
i4_ret = asr_gpio_open(ui1_group, ui1_pin, ui4_direction, ui4_data, ui4_source_contrl);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_interrupt_config(ui1_group, ui1_pin, ui1_int_flag, ui1_int_level,
ui1_int_polarity,ui1_int_bothedge,goio_interrupt_callback);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_interrupt_enable(ui1_group, ui1_pin, ui1_int_flag,
ui1_int_level, ui1_int_polarity,ui1_int_bothedge,goio_interrupt_callback);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
ui1_int_flag = 0;
i4_ret = asr_gpio_interrupt_disable(ui1_group, ui1_pin, ui1_int_flag,
ui1_int_level, ui1_int_polarity,ui1_int_bothedge,goio_interrupt_callback);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_gpio_interrupt_clear(ui1_group, ui1_pin, ui1_int_flag,
ui1_int_level, ui1_int_polarity,ui1_int_bothedge,goio_interrupt_callback);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
}
3.4 PWM配置使用
VOI611 硬件有4路PWM,如下表:
Pin num | Function0 | Function1 | Function2 |
---|---|---|---|
60 | JTAG_TDO | PWM3_O | GPIOD0 |
61 | JTAG_TDI | PWM2_O | GPIOC0 |
62 | JTAG_TMS | PWM1_O | GPIOB0 |
63 | JTAG_TCK | PWM0_O | GPIOA0 |
PWM口對(duì)應(yīng)的IO是復(fù)用的,使用PWM功能時(shí)需要將對(duì)應(yīng)的IO配置為PWM功能
- PWM操作例程
#include "asr_pwm.h"
#define HS_BACH_PWM_GROUP 0 //group A
#define HS_BACH_PWM_PIN 0 //pin 0
#define HS_BACH_PWM_NUM 0
#define HS_BACH_PWM_20KHZ (20)
#define HS_BACH_PWM_50_PERCENT (50)
#define HS_BACH_PWM_0_PERCENT (0)
#define HS_BACH_PWM_100_PERCENT (100)
void main(void)
{
int32_t i4_ret;
i4_ret = asr_pinmux_function_select(HS_BACH_PWM_GROUP,HS_BACH_PWM_PIN,E_FUNC_PWM);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_pwm_init(HS_BACH_PWM_NUM, HS_BACH_PWM_20KHZ, HS_BACH_PWM_100_PERCENT);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_pwm_start(HS_BACH_PWM_NUM);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_pwm_reset_config(HS_BACH_PWM_NUM, BACH_PWM_20KHZ, HS_BACH_PWM_0_PERCENT);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
asr_pwm_stop(uint32_t ui4_num);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_pwm_start(HS_BACH_PWM_NUM);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_pwm_close(HS_BACH_PWM_NUM);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
}
3.5 UART配置使用
VOI611 硬件提供2路UART,默認(rèn)UART0用于升級(jí),通訊,調(diào)試功能
Pin num | Function0 | Function1 | Function2 |
---|---|---|---|
54 | UART1_RX | GPIOD1 | |
55 | UART1_TX | GPIOC1 | |
56 | UART0_TX | GPIOA1 | |
57 | UART0_RX | GPIOB1 |
- UART 操作例程
#define BACH_UART 0
#define BAUD_RATE (115200)
#define COM_CUSTOMER_UART_FRAME_RX_TIMEOUT_MS 50 //接收超時(shí)
#define SAMPLE_UART_FRAME_LENGTH 11 //接收長(zhǎng)度
static void com_customer_uart_frame_rx_callback(void *asr_uart, uint8_t* pui1_data, uint16_t ui2_len)
{
//do something
}
void main(void)
{
asr_uart_customer.port_num = BACH_UART;
asr_uart_customer.baudrate = BAUD_RATE;
asr_uart_open(&asr_uart_customer, com_customer_uart_frame_rx_callback,
COM_CUSTOMER_UART_FRAME_RX_TIMEOUT_MS, SAMPLE_UART_FRAME_LENGTH, 1, 0);
}
3.6 Timer配置說明
VOI611 硬件提供4個(gè)定時(shí)器,實(shí)現(xiàn)定時(shí)功能
- Timer 使用例程
#include "asr_timer.h"
#define TIME_300MS (300)
static void asr_timer_callback()
{
APP_MSG("do what you want.\n");
}
int main()
{
int32_t i4_ret;
i4_ret = asr_timer_setup(TIMER_3, TIME_300MS, asr_timer_callback);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_timer_start(ui4_timer_id);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_timer_stop(ui4_timer_id);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
i4_ret = asr_timer_close(ui4_timer_id);
ASR_CHECK_FAIL_VALUE(i4_ret, E_OK);
return i4_ret;
}
3.7 反饋音定制
反饋音是語音反饋處理的一部分,為了產(chǎn)品獲得更好的用戶體驗(yàn),通常在用戶發(fā)出指令之后產(chǎn)品會(huì)反饋語音;
探境提供了語音合成的工具longyin_tts,可以試聽和批量生成TTS

試聽設(shè)置
- 場(chǎng)景設(shè)置,共有6個(gè)場(chǎng)景可選擇
- 發(fā)聲人設(shè)置,可選擇男性,女性,兒童等不同音色
- 音量,語速,語調(diào)設(shè)置
- 添加試聽文字,點(diǎn)擊 試聽 即可
批量生成設(shè)置
- 設(shè)置轉(zhuǎn)換起始ID(程序根據(jù)這個(gè)ID播放提示音)
- 添加生成列表,每條反饋音一行
- 點(diǎn)擊 批量轉(zhuǎn)換 等待完成,點(diǎn)擊 結(jié)果目錄 就可以看到生成的反饋音
反饋音如何加入固件中
- 把批量生成的反饋音文件加入到 ./output-package/wav/ 目錄下即可
如何播放反饋音
- 調(diào)用SDK的API接口 com_common_play_voice
void com_common_play_voice(uint8_t ui1_idx)
{
ASR_RET e_ret;
asr_play_param r_play_param;
r_play_param.i2_play_index = (int16_t)ui1_idx;
if ((ui1_idx <= ui1_wav_count) && (ui1_is_mute == 0))
{
e_ret = asr_audio_play(&r_play_param);
ASR_CHECK_FAIL(e_ret);
}
}
3.8 權(quán)重文件
- 權(quán)重文件位于 output-package/weight 目錄下的二進(jìn)制文件,是以.bin為后綴名。
- 權(quán)重文件bin文件主要存放探境科技為該產(chǎn)品ASR定制的神經(jīng)網(wǎng)絡(luò)訓(xùn)練模型和ASR權(quán)重
- 新的權(quán)重文件,用戶只需要替換這個(gè).bin文件即可
注意:weight 目錄下只能有一個(gè)bin文件
4. APP 開發(fā)
4.1 SDK常用的路徑和文件
- 外設(shè)接口API文件路徑 demo/include/peripheral
- 常用文件
demo/source/asr_sample.c
demo/source/app_cfg/bach_app_cfg.c
demo/source/app_cfg/com_common.c
demo/source/app_cfg/com_raw.c
demo/source/app_cfg/com_reg.c
4.2 系統(tǒng)設(shè)置
文件bach_app_cfg.c主要配置ROM,RAM分區(qū),硬件設(shè)定等,通常修改較多的地方
const uint8_t ui1_cfg_release = 1; //0 debug 1 release
const uint8_t ui1_cfg_comm_uart = 0; // app comunicatoin port
const uint32_t ui4_cfg_comm_baudrate = 9600;//app com port buadrate
4.3 應(yīng)用開發(fā)
文件 asr_sample.c 識(shí)別結(jié)果功能邏輯都這里實(shí)現(xiàn),重點(diǎn)部分
static void sample_kws_result(uint16_t ui2_word_index, uint8_t ui1_cmd_idx, uint8_t ui1_voice)
{
sample_customization_result(ui2_word_index, &ui1_cmd_idx, &ui1_voice);
#if (SAMPLE_COMM_CONFIG_TYPE == SAMPLE_COMM_CONFIG_REG)
com_reg_kws_result(ui2_word_index, ui1_cmd_idx, ui1_voice);
#else
com_customer_kws_result(ui2_word_index, ui1_cmd_idx, ui1_voice);
#endif
}
void sample_app(void)
{
...
KWS_CONFIG r_config;
r_config.kws_result_callback = sample_kws_result; //識(shí)別結(jié)果回調(diào)函數(shù)
r_config.kws_notify_callback = com_common_kws_notify; //事件通知回調(diào)函數(shù)
...
#if (SAMPLE_COMM_CONFIG_TYPE == SAMPLE_COMM_CONFIG_REG) //探境標(biāo)準(zhǔn)寄存器
com_reg_app();
#elif (SAMPLE_COMM_CONFIG_TYPE == SAMPLE_COMM_CONFIG_CUSTOMER) //客制化協(xié)議
com_customer_app();
#elif (SAMPLE_COMM_CONFIG_TYPE == SAMPLE_COMM_CONFIG_NONE) //串口源數(shù)據(jù)
com_raw_app();
#endif
}