Skip to content

Rapid application development*


1. LVP SDK software framework*

2. SDK directory structure*

2.1 Top-level directory structure*

lvp_tws/
▸ 3rdparty/             # Third party code
▸ app/                  # Application code *
▸ arch/                 # Startup code, application development does not need to care about this directory
▸ base/                 # Underlying common code
▸ boards/               # The board-level configuration code is configured based on hardware and does not need to be modified *
▸ configs/              # Default configuration
▸ docs/                 # Explanatory document
▸ drivers/              # Driver code
▸ include/              # Common header file
▸ lib/                  # Library file
▸ lvp/                  # Voice processing and frame calls *
▸ output/               # Output path
▸ scripts/              # Common script
▸ tools/                # Auxiliary tool *
▸ utility/              # Common code
  Kconfig               # Compile and configure source code
  Makefile

2.2 LVP core code directory structure*

lvp_tws/lvp/
▾ lvp/                  # Voice processing framework and application framework core
  ▸ app_core/           # Apply core for more details in the next section
  ▾ common/             # Common functional interface
      lvp_audio_in.c    # audio in module
      lvp_audio_in.h
      lvp_buffer.c      # Pipelined buffer management interface
      lvp_i2c_msg.c     # i2c communication module
      lvp_i2c_msg.h
      lvp_queue.c       # Queue management interface
      lvp_queue.h
      lvp_uart_record.c # Recording module
      lvp_uart_record.h
      Makefile
      uart_message_v2.c # message 2.0 protocol asynchronous interface
      uart_message_v2.h
  ▾ vui/                # Speech processing model
    ▸ kws/
    ▸ vpr/
      Kconfig
      Makefile
    Kconfig
    lvp_kws.c           # Speech processing interface
    lvp_kws.h
    lvp_mode.c          # Mode management interface
    lvp_mode.h
    lvp_mode_idle.c     # idle mode
    lvp_mode_record.c   # Recording mode
    lvp_mode_tws.c      # Voice processing mode, which calls the app core interface to drive the app framework
    lvp_mode_tws.h
    main.c              # System initialization and main loop
    Makefile

2.3.1 Board level directory structure*

lvp_tws/boards/
▾ boards/                       # Board level configuration is all about hardware
  ▾ nationalchip/
    ▸ grus_gx8002_fpga_1v/
    ▸ grus_gx8002a_fan_1v/
    ▾ grus_gx8002b_dev_1v/
      ▾ include/
          board_config.h        # Some numerical configuration
          board_misc_config.h   # Miscellaneous configuration, each board level may be different
        audio_board.c           # audio in/out configuration
        board.name              # The enable switch exposed to the compilation configuration
        boot_board.c
        clock_board.c           # Clock configuration
        Kconfig
        Makefile
        misc_board.c            # Pin multiplexing and other miscellaneous configurations and interfaces
    ▸ grus_gx8002b_gsensor_1v/
    ▸ grus_gx8002t_test_1v/
      vendor.name
    Kconfig
    Makefile

2.3.2 Gain adjustment*

Gain adjustment, gain can be adjusted in the compilation configuration, run the command 'make menuconfig', enter 'Board Options', at the end of the gain can be configured;

  • Analog gain(pga)

    • Adjustable range: 0~48dB
    • Adjustment step: 0-18dB,Step 6dB; 19-48dB,Step 1dB
  • Digital gain(audio in)

    • Adjustable range: 0~10
    • Step adjustment: Use the mapping mode, 0-10 mapping 0-54dB, Step 6dB
  • Code reference

    • The actual parameter code is in the corresponding board path

      /lvp_tws/boards/nationalchip/grus_gx8002b_dev_1v/audio_board.c
      .pga_gain           = CONFIG_BOARD_MIC_GAIN_A, // pga_gain supports only analog mic, 0-18dB, step by 6dB, 19-48dB, step by 1dB
      .audio_in_gain      = CONFIG_BOARD_MIC_GAIN_B, // GX_AUDIO_IN_GAIN
      

2.3.3 GPIO configuration*

In misc_board.c, there is a configurable two-dimensional array with ids that do not need to be modified. func represents the number of the corresponding function, and the number starts from 0. The corresponding function can be modified according to the requirements of the board.

/lvp_tws/boards/nationalchip/grus_gx8002b_dev_1v/misc_board.c
static const GX_PIN_CONFIG pin_table[] = {
/*   id  func     func0                 | func1          |  func2              | func3 ... */
    { 0,  1},  // 0:JTAG_TMS            | 1:GPIO_00      | 2:I2S_IN_BCLK_OUT_M | 3:I2S_OUT_BCLK_OUT_M
               // 4:SPI_CSn_M           | 5:SPI_CSn_S    | 6:REC_BCLK_OUT      | 7:PDM_DATA
               // 8:I2S_OUT_BCLK_IN_S   | 9:REC_BCLK_IN  | 10:I2S_IN_BCLK_IN_S
    { 1,  1},  // 0:JTAG_CK             | 1:GPIO_01      | 2:I2S_IN_DATA_IN     | 3:I2S_OUT_DATA_OUT
               // 4:SPI_MISO_M          | 5:SPI_MISO_S   | 6:REC_DATA_OUT       | 7:PDM_CLK_IN
               // 8:PWM_CLK_IN          | 9:PDM_CLK_OUT
    { 2,  0},  // 0:GPIO_02             | 1:PWM_CLK_IN    //i2c addr decision: low->0x35, high->0x36
    { 3,  1},  // 0:I2C0_SDA            | 1:GPIO_03      | 2:PDM_CLK_IN         | 3:PDM_CLK_OUT
    { 4,  1},  // 0:I2C0_SCL            | 1:GPIO_04      | 2:PDM_DATA
    { 5,  1},  // 0:UART0_TX            | 1:GPIO_05      | 2:I2C1_SDA           | 3:PDM_CLK_IN
               // 4:DAC_OUT_L           | 5:PDM_CLK_OUT
    { 6,  1},  // 0:UART0_RX            | 1:GPIO_06      | 2:I2C1_SCL           | 3:PDM_DATA
               // 4:DAC_OUT_R           | 5:PWM_CLK_IN
    { 7,  1},  // 0:PDM_CLK_IN          | 1:GPIO_07      | 2:I2S_IN_MCLK_OUT_M  | 3:I2S_OUT_MCLK_OUT_M
               // 4:SPI_SCLK_M          | 5:SPI_SCLK_S   | 6:REC_MCLK_OUT       | 7:DAC_OUT_L
               // 8:I2S_OUT_MCLK_IN_S   | 9:REC_MCLK_IN  | 10:I2S_IN_MCLK_IN_S  | 11:UART0_CTS
               // 12:PDM_CLK_OUT
    { 8,  1},  // 0:PDM_DATA            | 1:GPIO_08      | 2:I2S_IN_LRCLK_OUT_M | 3:I2S_OUT_LRCLK_OUT_M
               // 4:SPI_MOSI_M          | 5:SPI_MOSI_S   | 6:REC_LRCLK_OUT      | 7:DAC_OUT_R
               // 8:I2S_OUT_LRCLK_IN_S  | 9:REC_LRCLK_IN | 10:I2S_IN_LRCLK_IN_S | 11:UART0_RTS
               // 12:PWM_CLK_IN
    { 9,  1},  // 0:I2C1_SDA            | 1:GPIO_09      | 2:I2S_IN_BCLK_OUT_M  | 3:I2S_OUT_BCLK_OUT_M
               // 4:SPI_CSn_M           | 5:SPI_CSn_S    | 6:REC_BCLK_OUT       | 7:UART1_CTS
               // 8:I2S_OUT_BCLK_IN_S   | 9:REC_BCLK_IN  | 10:I2S_IN_BCLK_IN_S
    {10,  1},  // 0:I2C1_SCL            | 1:GPIO_10      | 2:I2S_IN_DATA_IN     | 3:I2S_OUT_DATA_OUT
               // 4:SPI_MISO_M          | 5:SPI_MISO_S   | 6:REC_DATA_OUT       | 7:UART1_RTS
               // 8:PWM_CLK_IN
    {11,  1},  // 0:UART1_TX            | 1:GPIO_11      | 2:I2S_IN_MCLK_OUT_M  | 3:I2S_OUT_MCLK_OUT_M
               // 4:SPI_SCLK_M          | 5:SPI_SCLK_S   | 6:REC_MCLK_OUT       | 7:DAC_OUT_L
               // 8:I2S_OUT_MCLK_IN_S   | 9:REC_MCLK_IN  | 10:I2S_IN_MCLK_IN_S
    {12,  1},  // 0:UART1_RX            | 1:GPIO_12      | 2:I2S_IN_LRCLK_OUT_M | 3:I2S_OUT_LRCLK_OUT_M
               // 4:SPI_MOSI_M          | 5:SPI_MOSI_S   | 6:REC_LRCLK_OUT      | 7:DAC_OUT_R
               // 8:I2S_OUT_LRCLK_IN_S  | 9:REC_LRCLK_IN | 10:I2S_IN_LRCLK_IN_S
};
Generally, the above two-dimensional array does not need to be changed, unless there is a special need; General functions only need to enable the corresponding function in the compilation configuration 'Board Options', the code will automatically configure the function of GPIO, modify the function of GPIO only need to modify in the' BoardSetUserPinMux 'interface.

The options in the compile configuration correspond to the pin configuration in the code

notice:

  • 1.Note that a function may have multiple pins. For example, I2S and I2C1 have two sets of pins to realize the function. Therefore, it is necessary to pay attention to the pins used at the board level during configuration.
  • 2.For the description of functions in I2S and SPI, the suffix _S represents the slave mode, such as I2S_IN_BCLK_IN_S, and the suffix _M represents the master, such as I2S_OUT_MCLK_OUT_M.

2.4 Application software (app) development*

2.4.1 app core code directory structure*

lvp_tws/lvp/app_core/
▾ lvp/
  ▾ app_core/
      lvp_app.h
      lvp_app_core.c       # The app framework code is responsible for calling the interface exposed by the application
      lvp_app_core.h
      Makefile

2.4.2 User app development directory structure *

lvp_tws/app/
▾ app/
  ▸ neck_fan/               # Hanging neck fan application
  ▾ sample/                 # Example, new application development just make changes here or refer to it to create a new one
      app.mk                # makefile file
      app.name              # Used to expose the application enable switch in the Kconfig system
      Kconfig               # Used to add the configuration that needs to be done in the compilation configuration
      lvp_app_sample.c      # For application code, if you need to split multiple c files, please put them in the same directory
  ▸ voice_controller/       # Voice control application
    Kconfig                 # For app framework
    Makefile                # For app framework

2.4.3 User app development example *

lvp_tws/app/sample/lvp_app_sample.c
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
/* Lower-Power Voice Process
* Copyright (C) 2001-2020 NationalChip Co., Ltd
* ALL RIGHTS RESERVED!
*
* lvp_app_sample.c
*
*/

#include <lvp_app.h>
#include <lvp_buffer.h>

#ifdef CONFIG_LVP_FACTORY_MIC_TEST
#include "lvp_mic_test.h"
#endif

#define LOG_TAG "[SAMPLE_APP]"

//=================================================================================================

// The standby interface, which is used to implement the standby preparation of the application, is called before entering low power
static int SampleAppSuspend(void *priv)
{
    printf(LOG_TAG" ---- %s ----\n", __func__);
    printf("%s\n", (unsigned char *)priv);
    return 0;
}

// Wake up interface, used to achieve the application after wake up preparation work, the system is called after wake up
static int SampleAppResume(void *priv)
{
    printf(LOG_TAG" ---- %s ----\n", __func__);
    printf("%s\n", (unsigned char *)priv);
    return 0;
}

static int SampleAppInit(void)
{
    printf(LOG_TAG" ---- %s ----\n", __func__);

    return 0;
}

// App Event Process; Called when an event is triggered, such as identifying keywords, or other custom events
// Used in response to events
// Call the LvpTriggerPlcEvent interface in the app framework to trigger the event
static int SampleAppEventResponse(APP_EVENT *app_event)
{
#ifdef CONFIG_LVP_FACTORY_MIC_TEST
    // This is just a reference example of using mic test interface, without considering the problem of sleep and the problem of switching between test and working mode, which needs to be considered in the actual scheme
    // There are two steps to use:
    // 1 After obtaining contex, LvpMicTestProcess is called with the obtained contex
    // 2 After testing a certain amount of contex, the test is stopped and LvpMicTestGetResult is called to obtain the test result, which is displayed as a string
    static int count = 0;
    LVP_CONTEXT *context;
    unsigned int ctx_size;
    LvpGetContext(app_event->ctx_index, &context, &ctx_size);
    if(count < 100)
    {
        LvpMicTestProcess(context);
        count++;
    }

    if(count == 100) // Define your own time for the test
    {
        char *str = LvpMicTestGetResult();
        printf("%s\n", str);
        count = 1000;
    }
#else
    if (app_event->event_id < 100)
        return 0;

    LVP_CONTEXT *context;
    unsigned int ctx_size;
    LvpGetContext(app_event->ctx_index, &context, &ctx_size);

    printf(LOG_TAG"event_id %d\n", app_event->event_id);
    printf(LOG_TAG"kws %d\n", context->kws);
    printf(LOG_TAG"vad %d\n", context->fft_vad);
    printf(LOG_TAG"G-vad %d\n", context->G_vad);
#endif
    return 0;
}

// APP Main Loop; Is called in the main loop to implement code that needs to be looped. Return application status
static int SampleAppTaskLoop(void)
{
    return 0;
}

// The above interface is filled into the app framework and called by app core
LVP_APP sample_app = {
    .app_name = "sample app",
    .AppInit = SampleAppInit,
    .AppEventResponse = SampleAppEventResponse,
    .AppTaskLoop = SampleAppTaskLoop,
    .AppSuspend = SampleAppSuspend,
    .suspend_priv = "SampleAppSuspend",
    .AppResume = SampleAppResume,
    .resume_priv = "SampleAppResume",
};

LVP_REGISTER_APP(sample_app);