Analog Microphone

This example code collects AMIC data and encodes it into PCM voice data using the CODEC.

AMIC collects analog voice data, which is encoded by CODEC and sent to the I2S receive FIFO. The data is then transferred to UART using GDMA.

On the PC side, a serial assistant receives the data transmitted by UART. Audio parsing software is used to analyze the data and play the recorded voice. In this example, the audio parsing software used is Audacity.

Requirements

For requirements, please refer to the Requirements.

In addition, you need to install PuTTY or UartAssist serial assistant tools and audio parsing tools like Audacity on the PC terminal.

Wiring

Connect the AMIC module to the EVB, connect MICBIAS to 1.8V, GND to GND, MIC_P to P2_6, and MIC_N to P2_7;

Connect the FT232 module to the EVB to receive UART data, connecting P3_2 to RXD, and P3_3 to TXD.

Building and Downloading

For building and downloading, please refer to the Building and Downloading.

Experimental Verification

Preparation Stage

  1. Start the PC terminal with PuTTY or UartAssist, use ASCII to receive data, open the UART COM port, and make the following UART settings:

  • Baud rate: 3000000

  • 8 data bits

  • 1 stop bit

  • No parity

  • No hardware flow control

  • Set the output data bytes to redirect to a file.

  1. Start the audio parsing software and select the parsing format according to the settings in CODEC. In this example, you can refer to the following Audacity settings.

  • Encoding: 16-bit PCM

  • Endianness: Little Endian

  • Channels: 1 channel

  • Sample rate: 1600 Hz

Testing Stage

  1. From start to finish of recording, the collected voice data is encoded by CODEC as PCM data and sent to the PC terminal via UART.

  2. Use the audio parsing software to view the decoded voice waveform and play the voice.

Code Overview

This section introduces the code and process description for initialization and corresponding function implementation in the sample.

Source Code Directory

The directory for project file and source code are as follows:

  • Project directory: sdk\samples\peripheral\codec\amic\proj

  • Source code directory: sdk\samples\peripheral\codec\amic\src

Initialization

The initialization flow for peripherals can refer to Initialization Flow in General Introduction.

The initialization process includes initializing the CODEC / UART / I2S / GDMA modules as follows.

  1. Call Pad_Config() and Pinmux_Config() to configure the PAD and PINMUX of the corresponding pins. The I2S pin multiplexing functions are BCLK_SPORT0, LRC_RX_SPORT0, SDI_CODEC_SLAVE, and SDO_CODEC_SLAVE.

    void board_codec_init(void)
    {
       Pad_Config(AMIC_MSBC_CLK_PIN, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,PAD_OUT_HIGH);
       Pad_Config(AMIC_MSBC_DAT_PIN, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,PAD_OUT_LOW);
    
       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);
    }
    
  2. Call Pad_Config() and Pinmux_Config() to configure the PAD and PINMUX for the UART module corresponding pins.

    void board_uart_init (void)
    {
      Pad_Config(UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
      Pad_Config(UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
    
      Pinmux_Config(UART_TX_PIN, UART5_TX);
      Pinmux_Config(UART_RX_PIN, UART5_RX);
    }
    
  3. Execute I2S_StructInit() and I2S_Init() to initialize the I2S peripheral. Configuration parameters for the I2S0 initialization are as follows:

I2S Initialization Parameters

I2S Hardware Parameters

Setting in the I2S_InitStruct

I2S master RX

Sample Rate (Mi)

I2S_InitTypeDef::I2S_RxBClockMi

0x271

Sample Rate (Ni)

I2S_InitTypeDef::I2S_RxBClockNi

0x10

Device Mode

I2S_InitTypeDef::I2S_DeviceMode

I2S_DeviceMode_Master

Channel Type

I2S_InitTypeDef::I2S_RxChannelType

I2S_Channel_Mono

Data Format

I2S_InitTypeDef::I2S_RxDataFormat

I2S_Mode

Data Width

I2S_InitTypeDef::I2S_RxDataWidth

I2S_Width_16Bits

  1. Execute UART_StructInit() and UART_Init() to initialize the UART peripheral. Configuration parameters for the UART initialization are as follows:

UART Initialization Parameters

UART Hardware Parameters

Setting in the UART_InitStruct

UART

UART Div

UART_InitTypeDef::UART_Div

1

UART Ovsr

UART_InitTypeDef::UART_Ovsr

8

UART OvsrAdj

UART_InitTypeDef::UART_OvsrAdj

0x492

UART Tx Dma En

UART_InitTypeDef::UART_TxDmaEn

ENABLE

UART Dma En

UART_InitTypeDef::UART_DmaEn

UART_DMA_ENABLE

  1. Execute GDMA_StructInit() and GDMA_Init() to initialize the GDMA peripheral. Configuration parameters for the GDMA initialization are as follows:

GDMA Initialization Parameters

GDMA Hardware Parameters

Setting in the GDMA_InitStruct

GDMA Channel

Channel Num

GDMA_InitTypeDef::GDMA_ChannelNum

0

Transfer Direction

GDMA_InitTypeDef::GDMA_DIR

GDMA_DIR_PeripheralToPeripheral

Buffer Size

GDMA_InitTypeDef::GDMA_BufferSize

1000

Source Address Increment or Decrement

GDMA_InitTypeDef::GDMA_SourceInc

DMA_SourceInc_Fix

Destination Address Increment or Decrement

GDMA_InitTypeDef::GDMA_DestinationInc

DMA_DestinationInc_Fix

Source Data Size

GDMA_InitTypeDef::GDMA_SourceDataSize

GDMA_DataSize_Word

Destination Data Size

GDMA_InitTypeDef::GDMA_DestinationDataSize

GDMA_DataSize_Byte

Source Burst Transaction Length

GDMA_InitTypeDef::GDMA_SourceMsize

GDMA_Msize_4

Destination Burst Transaction Length

GDMA_InitTypeDef::GDMA_DestinationMsize

GDMA_Msize_16

Source Address

GDMA_InitTypeDef::GDMA_SourceAddr

&(I2S1->I2S_RX_FIFO_RD_ADDR)

Destination Address

GDMA_InitTypeDef::GDMA_DestinationAddr

&(UART5->UART_RBR_THR)

Source Handshake

GDMA_InitTypeDef::GDMA_SourceHandshake

GDMA_Handshake_I2S1_TDM0_RX

Destination Handshake

GDMA_InitTypeDef::GDMA_DestHandshake

GDMA_Handshake_UART5_TX

  1. Configure the GDMA transfer complete interrupt GDMA_INT_Transfer and NVIC. Related NVIC configuration can be referred to in Interrupt Configuration.

  2. Initialize the CODEC peripheral.

    1. Call CODEC_AnalogCircuitInit() to initialize the analog circuit.

    2. Call RCC_PeriphClockCmd() to enable the CODEC clock.

    3. Execute CODEC_StructInit() and CODEC_Init() to initialize the CODEC peripheral. Configuration parameters for the CODEC initialization are as follows:

CODEC Initialization Parameters

CODEC Hardware Parameters

Setting in the CODEC_InitStruct

CODEC

Mic Type

CODEC_InitTypeDef::CODEC_Ch0MicType

CODEC_CH_AMIC

MICBST Mode

CODEC_InitTypeDef::CODEC_MicBstMode

MICBST_Mode_Differential

SampleRate

CODEC_InitTypeDef::CODEC_SampleRate0

SAMPLE_RATE_16KHz

I2S Data Format

CODEC_InitTypeDef::CODEC_I2SFormat

CODEC_I2S_DataFormat_I2S

I2S Channel Len

CODEC_InitTypeDef::CODEC_I2SChannelLen

I2S_CHANNELLEN_32

I2S Data Width

CODEC_InitTypeDef::CODEC_I2SRxDataWidth

CODEC_I2S_Rx_DataWidth_16Bits

I2S Channel Sequence

CODEC_InitTypeDef::CODEC_I2SChSequence

CODEC_I2S_CH_L_R

  1. Call I2S_Cmd() to enable the I2S receive mode. Call GDMA_Cmd() to enable GDMA transfer.

Functional Implementation

After AMIC collects the voice data, the CODEC module AD conversion puts the voice data into the I2S RX FIFO. The data in the I2S RX FIFO is then transferred to the UART TX FIFO via GDMA. In the serial assistant, save the data sent by UART to a file, and parse the file data using audio parsing software. The data transmission order in each module is shown in the figure below.

this should be AMIC waveform

Data Transfer Module (AMIC)

  1. When the GDMA transfer amount reaches the set BlockSize, it triggers the GDMA_INT_Transfer interrupt. As the audio data undergoes AD conversion via CODEC, the data size is relatively large and a single GDMA transfer cannot meet the demand. The source address, destination address, and BlockSize are reset in the interrupt handler, and GDMA transfer is re-enabled to ensure the transmission of a large amount of data continuously.

    GDMA_SetSourceAddress(GDMA_Channel_AMIC, (uint32_t)(&(I2S0->I2S_RX_FIFO_RD_ADDR)));
    GDMA_SetDestinationAddress(GDMA_Channel_AMIC, (uint32_t)(&(UART5->UART_RBR_THR)));
    
    GDMA_SetBufferSize(GDMA_Channel_AMIC, AUDIO_FRAME_SIZE / 4);
    
    GDMA_ClearINTPendingBit(GDMA_Channel_AMIC_NUM, GDMA_INT_Transfer);
    GDMA_Cmd(GDMA_Channel_AMIC_NUM, ENABLE);