Digital Microphone

This sample implements the function of DMIC collecting analog voice and decoding it with CODEC.

DMIC collects voice data, encodes it with CODEC, sends it to I2S receiving FIFO, and uses DMA to carry the data to UART.

The PC receives the data transferred from the UART through the serial assistant, parses the data using audio parsing software, and plays the recorded voice.

Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

For more requirements, please refer to Quick Start.

Wiring

EVB external DMIC module, connect P2_2 to CLK, P2_3 to DATA.

EVB external FT232 module, connect P3_2 to RX, P3_3 to TX.

Building and Downloading

This sample can be found in the SDK folder:

Project file: samples\peripheral\codec\dmic\proj\rtl87x2g\mdk

Project file: samples\peripheral\codec\dmic\proj\rtl87x2g\gcc

To build and run the sample, follow the steps listed below:

  1. Open sample project file.

  2. To build the target, follow the steps listed on the Generating App Image in Quick Start.

  3. After a successful compilation, the app bin app_MP_xxx.bin will be generated in the directory mdk\bin or gcc\bin.

  4. To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.

  5. Press reset button on EVB board and it will start running.

Experimental Verification

Preparation Phase

  1. Start a PC terminal like PuTTY or UartAssist and connect to the used COM port with the following UART settings:

  • Baud rate: 3000000

  • 8 data bits

  • 1 stop bit

  • No parity

  • No hardware flow control

  1. Start an audio parsing software.

Testing Phase

  1. From the beginning to the end of the recording, the captured audio data is decoded and transmitted to the PC terminal via UART.

  2. Copy the decoded data from the PC terminal to a newly created HEX bin file.

  3. Use audio parsing software to view the waveform of the decoded voice, or play the voice.

Code Overview

This chapter will be introduced according to the following several parts:

  1. Source Code Directory.

  2. Peripheral initialization will be introduced in chapter Initialization.

  3. Functional implementation after initialization will be introduced in chapter Functional Implementation.

Source Code Directory

  1. Project Directory: sdk\samples\peripheral\codec\dmic\proj

  2. Source Code Directory: sdk\samples\peripheral\codec\dmic\src

Source files are currently categorized into several groups as below.

└── Project: dmic
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── Lib                      includes all binary symbol files that user application is built on
            └── rtl87x2g_io.lib
        ├── Peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_rcc.c
            ├── rtl_pinmux.c
            ├── rtl_uart.c
            ├── rtl_gdma.c
            ├── rtl_nvic.c
            ├── rtl_codec.c
            └── rtl_i2s.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            └── io_codec.c

Initialization

The initialization process includes the initialization of the codec, uart, i2s, and gdma modules as follows


board_codec_init contains the PAD and PINMUX settings for CODEC and DMIC:

  1. Configure PAD: set pins, PINMUX mode, PowerOn, no internal Pull-Up.

  2. Configure PINMUX: Assign pins to DMIC1_CLK, DMIC1_DAT, BCLK_SPORT0, LRC_RX_SPORT0, SDI_CODEC_SLAVE, and SDO_CODEC_SLAVE functions respectively.

Pad_Config(DMIC_MSBC_CLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
           PAD_OUT_LOW);
Pad_Config(DMIC_MSBC_DAT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
           PAD_OUT_LOW);

Pinmux_Config(DMIC_MSBC_CLK_PIN, DMIC1_CLK);
Pinmux_Config(DMIC_MSBC_DAT_PIN, DMIC1_DAT);

Pad_Config(CODEC_BCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE,
           PAD_OUT_LOW);
Pad_Config(CODEC_LRCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE,
           PAD_OUT_LOW);
Pad_Config(CODEC_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
Pad_Config(CODEC_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);

Pinmux_Config(CODEC_BCLK_PIN, BCLK_SPORT0);
Pinmux_Config(CODEC_LRCLK_PIN, LRC_RX_SPORT0);
Pinmux_Config(CODEC_TX_PIN,    SDI_CODEC_SLAVE);
Pinmux_Config(CODEC_RX_PIN,    SDO_CODEC_SLAVE);

board_uart_init contains the PAD and PINMUX settings for UART, refer to amic initialization.

driver_i2s_init contains the initialization of I2S peripherals, refer to amic initialization.

driver_uart_init contains the initialization of UART peripherals, refer to amic initialization.

driver_gdma_init contains the initialization of GDMA peripherals, refer to amic initialization.


driver_codec_init contains the initialization of CODEC peripherals:

  1. Enable PCC clock.

  2. Select DMIC for microphone type.

  3. Set the DMIC clock frequency to 2500kHz.

  4. Set the data latch method for channel 0 digital microphone to rising edge latch.

  5. Set the sampling frequency to 16kHz.

  6. Set the data format to I2S format.

  7. Set the channel width to 32 bits.

  8. Set the RX data width to 16 bits.

  9. Set the I2S channel order to left and right.

RCC_PeriphClockCmd(APBPeriph_CODEC, APBPeriph_CODEC_CLOCK, ENABLE);
...
CODEC_InitStruct.CODEC_Ch0MicType       = CODEC_CH_DMIC;
CODEC_InitStruct.CODEC_DmicClock        = DMIC_Clock_2500KHz;
CODEC_InitStruct.CODEC_Ch0DmicDataLatch = DMIC_Ch_Rising_Latch;
CODEC_InitStruct.CODEC_SampleRate0      = SAMPLE_RATE_16KHz;
CODEC_InitStruct.CODEC_I2SFormat        = CODEC_I2S_DataFormat_I2S;
CODEC_InitStruct.CODEC_I2SChannelLen    = I2S_CHANNELLEN_32;
CODEC_InitStruct.CODEC_I2SRxDataWidth   = CODEC_I2S_Rx_DataWidth_16Bits;
CODEC_InitStruct.CODEC_I2SChSequence    = CODEC_I2S_CH_L_R;

Functional Implementation

  1. Enable I2S transmit mode and receive mode; enable GDMA channel 0.

I2S_Cmd(I2S0, I2S_MODE_TX | I2S_MODE_RX, ENABLE);
GDMA_Cmd(GDMA_Channel_DMIC_NUM, ENABLE);
  1. DMIC collects analog voice data, decodes it by CODEC, sends it to I2S0 receiving FIFO, and carries the data to UART5 by using GDMA; when the data transmission is completed, it triggers the GDMA_INT_Transfer interrupt, and enters the interrupt handler GDMA_Channel_DMIC_Handler.

    1. Reset the source and destination addresses.

    2. Reset the GDMA transfer data size.

    3. Clear the GDMA channel 0 GDMA_INT_Transfer interrupt pending bit and enable GDMA channel 0.

GDMA_SetSourceAddress(GDMA_Channel_DMIC, (uint32_t)(&(I2S0->I2S_RX_FIFO_RD_ADDR)));
GDMA_SetDestinationAddress(GDMA_Channel_DMIC, (uint32_t)(&(UART5->UART_RBR_THR)));

GDMA_SetBufferSize(GDMA_Channel_DMIC, AUDIO_FRAME_SIZE / 4);

GDMA_ClearINTPendingBit(GDMA_Channel_DMIC_NUM, GDMA_INT_Transfer);
GDMA_Cmd(GDMA_Channel_DMIC_NUM, ENABLE);