SDK Software Structure¶
1. SDK Software Structure Diagram¶
2. SDK Directory Structure¶
--components // Functional components
----asr // Speech recognition
----alg // Voice preprocessing algorithm library
------denoise // Noise reduction
----assist // Auxiliary functions, e.g., timing functions for testing algorithms
----audio_in_manage // Audio capture real-time task
----audio_pre_rslt_iis_out // Audio preprocessing result output component
----ci_nvdm // Non-volatile Data Management
----cmd_info // Firmware information parsing
----codec_manage // Codec manager
----fft // FFT manager
----flash_control // Flash manager
----flash_encrypt // Flash encryption policy
----freertos // Operating system
----led // RGB LED control manager
----log // Log printing
----msg_com // UART protocol
----ota // OTA upgrade
----player // Player
----RISCV // RISCV related
----sys_monitor // System monitor
--projects // Application example code
----offline_asr_pro_sample // CI13LC series chip template project
--driver // Drivers
----boards // Board support, e.g., CI13LC
----ci13lc_chip_driver // Internal chip drivers, such as I2C drivers
----third_device_driver // External drivers, such as external codec driver ES8388
--startup // Startup code
--system // Common header definitions
--tools // Firmware build tools
--utils // Debugging toolset
3. SDK User Code Description¶
The SDK user code area is shown in Figure 3-1 below:
The following files are located in: CI13LC_SDK\projects\offline_asr_pro_sample\src\
| File Name | Description |
|---|---|
| sample_main.c | Main function file: contains task creation, platform initialization, system startup code |
| system_hook.c | Event hook interface C file: system startup, wake-up, exit wake-up, speech recognition event hooks |
| system_hook.h | Event hook interface header file |
| system_msg_deal.c | System message handling task C file |
| system_msg_deal.h | System message handling task header file |
| user_config.h | User configuration macro definitions header file |
| user_msg_deal.c | User code C file: UART protocol, I2C protocol, button messages, etc. |
| user_msg_deal.h | User code header file |
4. Code Addition Examples¶
(1) Adding protocol handling code for wake words:
Find CI13LC_SDK\projects\offline_asr_pro_sample\src:
- First, add the function declaration in
user_msg_deal.h, for example:
void wake_up_xxx_deal(void);
- Then add the function definition in
user_msg_deal.c, for example:
void wake_up_xxx_deal(void)
{
/* Add your logic code here */
}
- Finally, call the function in
system_hook.c, for example:
__WEAK void sys_weakup_hook(void)
{
#if MSG_COM_USE_UART_EN
vmup_send_notify(VMUP_MSG_DATA_NOTIFY_WAKEUPENTER);
#endif
/* Add your function call here */
wake_up_xxx_deal();
}
Note
For other system states (system startup, exit wake-up, speech recognition), you can add code following the same approach, but make sure to call them in the corresponding event hook functions.
(2) Adding handling code based on command word ID:
Find the deal_asr_msg_by_cmd_id function in CI13LC_SDK\projects\offline_asr_pro_sample\src\user_msg_deal.c.
The command words corresponding to command IDs are specified in CI13LC_SDK\projects\offline_asr_pro_sample\firmware\user_file\cmd_info\[60000]cmd_info.xlsx.
uint32_t deal_asr_msg_by_cmd_id(sys_msg_asr_data_t *asr_msg, cmd_handle_t cmd_handle, uint16_t cmd_id)
{
uint32_t ret = 1;
int select_index = -1;
switch(cmd_id)
{
case 2: // "Turn on air conditioner"
{
/* Add your handling code for command ID here */
break;
}
/* Add more case statements to handle other command IDs */
/* Code omitted */
default:
ret = 0;
break;
}
/* Code omitted */
}
(3) Adding handling code based on semantic ID:
Find the deal_asr_msg_by_semantic_id function in CI13LC_SDK\projects\offline_asr_pro_sample\src\user_msg_deal.c.
For more information about semantic IDs, please visit ☞[《CI13LC Series Chip Semantic ID Documentation》](./CI13LC语义ID文档说明.md
uint32_t deal_asr_msg_by_semantic_id(sys_msg_asr_data_t *asr_msg, cmd_handle_t cmd_handle, uint32_t semantic_id)
{
uint32_t ret = 1;
if (PRODUCT_GENERAL == get_product_id_from_semantic_id(semantic_id))
{
uint8_t vol;
int select_index = -1;
switch(get_function_id_from_semantic_id(semantic_id))
{
case VOLUME_UP: // Increase volume
vol = vol_set(vol_get() + 1);
select_index = (vol == VOLUME_MAX) ? 1:0;
break;
case XXX_XXX:
/* Add your handling code for semantic ID here */
break;
/* Add more case statements to handle other semantic IDs */
/* Code omitted */
default:
ret = 0;
break;
}
/* Code omitted */
}
/* Code omitted */
}
5. SDK Code Logic Analysis¶
Due to the specific requirements of the speech recognition system, the SDK already includes a large amount of initialization work. To help users quickly understand the code structure and workflow, we provide a brief explanation of the program startup process and working states.
As shown in the figure above, after power-on, the system enters the main function to initialize the hardware, creates a vTaskCreate thread, and then starts the FreeRTOS system. The vTaskCreate thread creates threads for recognition and playback, after which the system enters sleep mode and starts capturing audio input.
When valid audio input is provided to the recognition thread, the recognition thread will send a message to the user thread through a message queue for processing. In the SDK’s user thread, some operations such as playing the corresponding prompt, switching system states, and sending UART protocols have already been implemented. When adding code, users generally only need to add code in the user thread. Therefore, understanding the message handling mechanism in the user thread makes it easy to extend functionality.
When the external communication UART sends a UART protocol to control the voice board, the UART protocol will be parsed in the UART interrupt. After successful parsing, the vmup_port_send_packet_rev_msg function will be called in the interrupt to send a UART message to the user thread. After receiving this message, the user thread will call deal_userdef_msg >> userapp_deal_com_msg >> userapp_deal_cmd in sequence to execute the function synchronously or asynchronously (most are executed synchronously, but playing prompts is an asynchronous request). After completion, an ACK will be sent back to the communication UART.


