AUDIO loopback with DISCO_H747I

Dependencies:   BSP_DISCO_H747I

Building

hg clone https://mbed.org/teams/ST/code/DISCO_H747I_AUDIO_demo

cd DISCO_H747I_AUDIO_demo

mbed deploy

mbed compile -m DISCO_H747I -t <GCC_ARM/ARM/IAR> -f

Running

A single printf is done at main start

Audio is recorded from board micro (U21) next to joystick.

Audio output is the jack connector (CN11) (green one).

Warning

Audio configuration is not compatible with Ethernet HW patch

https://os.mbed.com/teams/ST/wiki/DISCO_H747I-modifications-for-Ethernet

main.cpp

Committer:
Jerome Coutant
Date:
2019-11-07
Revision:
0:78e37c7585e6

File content as of revision 0:78e37c7585e6:

#include "mbed.h"
#include "stm32h747i_discovery.h"
#include "stm32h747i_discovery_audio.h"

extern "C" {

    /* Audio frequency */
#define AUDIO_FREQUENCY            BSP_AUDIO_FREQUENCY_16K
#define AUDIO_IN_PDM_BUFFER_SIZE  (uint32_t)(128*AUDIO_FREQUENCY/16000*DEFAULT_AUDIO_IN_CHANNEL_NBR)

    /* Size of the recorder buffer */
#define RECORD_BUFFER_SIZE        4096

    /* Define record Buf at D3SRAM @0x38000000 since the BDMA for SAI4 use only this memory */
#if defined (TOOLCHAIN_IAR)  /* IAR */
    /* No need to update linker script */
#pragma location=0x38000000
    uint16_t recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE];
#else  /* GCC_ARM and ARM */
    /* Linker scripts need to be updated to add RAM_D3 section */
    ALIGN_32BYTES(uint16_t recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE]) __attribute__((section(".RAM_D3")));
#endif

    uint16_t playbackBuf[RECORD_BUFFER_SIZE * 2];

    /* Pointer to record_data */
    uint32_t playbackPtr;

    extern SAI_HandleTypeDef haudio_out_sai;
    extern SAI_HandleTypeDef haudio_in_sai;


    /**
      * @brief  This function handles DMA2 Stream 1 interrupt request.
      * @param  None
      * @retval None
      */
    void AUDIO_OUT_SAIx_DMAx_IRQHandler(void)
    /* DMA2_Stream1_IRQHandler redefinition in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.h */
    {
        HAL_DMA_IRQHandler(haudio_out_sai.hdmatx);
    }


    /**
      * @brief  This function handles BDMA Channel 1 for SAI_PDM interrupt request.
      * @param  None
      * @retval None
      */
    void AUDIO_IN_SAI_PDMx_DMAx_IRQHandler(void)
    /* BDMA_Channel1_IRQHandler redefinition in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.h */
    {
        HAL_DMA_IRQHandler(haudio_in_sai.hdmarx);
    }


    /**
      * @brief Calculates the remaining file size and new position of the pointer.
      * @param  None
      * @retval None
      */
    void BSP_AUDIO_IN_TransferComplete_CallBack(void)
    /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */
    {
        if (BSP_AUDIO_IN_GetInterface() == AUDIO_IN_INTERFACE_PDM) {
            /* Invalidate Data Cache to get the updated content of the SRAM*/
            SCB_InvalidateDCache_by_Addr((uint32_t *)&recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE / 2], AUDIO_IN_PDM_BUFFER_SIZE * 2);

            BSP_AUDIO_IN_PDMToPCM((uint16_t *)&recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE / 2], &playbackBuf[playbackPtr]);

            /* Clean Data Cache to update the content of the SRAM */
            SCB_CleanDCache_by_Addr((uint32_t *)&playbackBuf[playbackPtr], AUDIO_IN_PDM_BUFFER_SIZE / 4);

            playbackPtr += AUDIO_IN_PDM_BUFFER_SIZE / 4 / 2;
            if (playbackPtr >= RECORD_BUFFER_SIZE) {
                playbackPtr = 0;
            }
        }
    }


    /**
      * @brief  Manages the DMA Half Transfer complete interrupt.
      * @param  None
      * @retval None
      */
    void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
    /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */
    {
        if (BSP_AUDIO_IN_GetInterface() == AUDIO_IN_INTERFACE_PDM) {
            /* Invalidate Data Cache to get the updated content of the SRAM*/
            SCB_InvalidateDCache_by_Addr((uint32_t *)&recordPDMBuf[0], AUDIO_IN_PDM_BUFFER_SIZE * 2);

            BSP_AUDIO_IN_PDMToPCM((uint16_t *)&recordPDMBuf[0], &playbackBuf[playbackPtr]);

            /* Clean Data Cache to update the content of the SRAM */
            SCB_CleanDCache_by_Addr((uint32_t *)&playbackBuf[playbackPtr], AUDIO_IN_PDM_BUFFER_SIZE / 4);

            playbackPtr += AUDIO_IN_PDM_BUFFER_SIZE / 4 / 2;
            if (playbackPtr >= RECORD_BUFFER_SIZE) {
                playbackPtr = 0;
            }
        }
    }


    /**
      * @brief  Audio IN Error callback function
      * @param  None
      * @retval None
      */
    void BSP_AUDIO_IN_Error_CallBack(void)
    /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */
    {
        MBED_ASSERT(0);
    }

} // extern C


int main()
{
    printf("\n\nAUDIO LOOPBACK EXAMPLE WITH AUDIO PDM FOR DISCO-H747I\n");

    /* Set audio input interface */
    BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_PDM);

    /* Initialize audio IN at REC_FREQ*/
    if (BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AUDIO_FREQUENCY, DEFAULT_AUDIO_IN_BIT_RESOLUTION, DEFAULT_AUDIO_IN_CHANNEL_NBR) != AUDIO_OK) {
        /* Record Error */
        MBED_ASSERT(0);
    }

    /* Initialize audio OUT at REC_FREQ*/
    if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, 50, AUDIO_FREQUENCY) != AUDIO_OK) {
        /* Record Error */
        MBED_ASSERT(0);
    }

    /* Set audio slot */
    BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);

    /* Start the record */
    BSP_AUDIO_IN_Record((uint16_t *)recordPDMBuf, AUDIO_IN_PDM_BUFFER_SIZE);

    wait_us(1000); // 1 ms

    /* Start audio output */
    BSP_AUDIO_OUT_Play((uint16_t *)playbackBuf, RECORD_BUFFER_SIZE * 2);
}