cancel
Showing results for 
Search instead for 
Did you mean: 

Sending Audio to Speaker using Non-Blocking Mode(DMA).

Kannika_Mallu
Visitor

when i make the macro LUDWIG_SAI_DMA_MODE 0 i can hear audio in continous loop without noise because it runs in blocking mode.when give 1 to  LUDWIG_SAI_DMA_MODE, I can able to hear the audio for sometimes after that i hear noise. When i hear noise i suspend the task it will point to while(updatePointer==-1). 

/*
 * audio.c
 *
 *  Created on: Jun 30, 2025
 *      Author: KannikaMMallu
 */
#include "audio.h"
#include "sai.h"
#include "tx_api.h"

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

__IO int16_t UpdatePointer = -1;

extern int16_t PlayBuff[PLAY_BUFF_SIZE];

/* USER CODE END PTD */

TX_THREAD audio_thread;
UCHAR audio_thread_stack[4096];
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* USER CODE BEGIN 3 */
void audio_thread_entry(ULONG thread_input)
{
    Audio();
}

void Audio_ThreadX_Init(void)
{
    // Create the audio thread
    tx_thread_create(&audio_thread, "Audio Thread", audio_thread_entry, 0,
                     audio_thread_stack, sizeof(audio_thread_stack),
                     10, 10, TX_NO_TIME_SLICE, TX_AUTO_START);
}

  /* USER CODE END 3 */
/* Private variables ---------------------------------------------------------*/


int Audio(void)
{

	/* USER CODE BEGIN 1 */
	//check audio buffer is loaded to internal memory
	/* Check if the buffer has been loaded in flash */
	  SAI_check_audio_buffer();
	  /* USER CODE END 1 */

#if LUDWIG_SAI_DMA_MODE
  SAI_DMA_circular_link_create();

  // Pre-fill the entire buffer before starting playback
      SAI_read_audio_buffer_from_mem((uint16_t *)PlayBuff, PLAY_BUFF_SIZE);

  // Start DMA transfer to I2S
      SAI_send_audio_buffer_to_i2s((uint8_t *)PlayBuff, PLAY_BUFF_SIZE);

#endif

  while (1)
  {
#if LUDWIG_SAI_DMA_MODE

/* Wait a callback event */
	  while (UpdatePointer == -1);

  	  if(UpdatePointer == 0) //half of the buffer is complete
  	  {
  		SAI_read_audio_buffer_from_mem((uint16_t *)&PlayBuff[0], PLAY_BUFF_SIZE / 2);
  	  }
  	  else
  	  {
          SAI_read_audio_buffer_from_mem((uint16_t *)&PlayBuff[PLAY_BUFF_SIZE / 2], PLAY_BUFF_SIZE / 2);
  	  }
  	UpdatePointer = -1;


#else

  	  //Read audio buffer of 64 samples
      SAI_read_audio_buffer_from_mem((uint16_t *)PlayBuff, PLAY_BUFF_SIZE);

  	  //Send the process data to I2S in blocking mode
  	  SAI_send_audio_buffer_to_i2s((uint8_t *)PlayBuff, PLAY_BUFF_SIZE);
#endif
    } //end of while
}
/*
 * sai.c
 *
 *  Created on: May 6, 2025
 *      Author: Mahesha
 */
#include "stm32wbaxx_it.h"
#include "sai.h"
#include "linked_list.h"

extern DMA_QListTypeDef SAIQueue;

int16_t PlayBuff[PLAY_BUFF_SIZE];

extern __IO int16_t UpdatePointer;

static uint32_t PlaybackPosition = PLAY_HEADER;

void SAI_check_audio_buffer(void)
{
	/* Check if the buffer has been loaded in flash */

	if(*((uint64_t *)AUDIO_FILE_ADDRESS) != 0x017EFE2446464952 )
		Error_Handler();

	  /* Associate the DMA handle */
	//__HAL_LINKDMA(&hsai_BlockB1, hdmatx, handle_GPDMA1_Channel1);
}

void SAI_DMA_circular_link_create(void)
{
	/* Associate the DMA handle */
	__HAL_LINKDMA(&hsai_BlockB1, hdmatx, handle_GPDMA1_Channel1);

	MX_SAIQueue_Config();

	/* Set queue circular mode for sai queue */
	HAL_DMAEx_List_SetCircularMode(&SAIQueue);

	/* Link SAI queue to DMA channel */
	HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &SAIQueue);
}

void SAI_send_audio_buffer_to_i2s(uint8_t *sendPlayBuff, uint16_t Size)
{
#if LUDWIG_SAI_DMA_MODE
	if(HAL_OK != HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t *)sendPlayBuff, Size))
	{
		Error_Handler();
	}
#else

	if(HAL_OK != HAL_SAI_Transmit(&hsai_BlockB1, (uint8_t *)sendPlayBuff, Size,5000))
	{
		Error_Handler();
	}
#endif
}

void SAI_read_audio_buffer_from_mem(uint16_t *readPlayBuff, uint16_t Size)
{
	/* check the end of the file */
	for (uint16_t i = 0; i < Size; i++)
	    {
	        if ((PlaybackPosition + Size*2) >= AUDIO_FILE_SIZE)
	            PlaybackPosition = PLAY_HEADER;

	        readPlayBuff[i] = *(uint16_t *)(AUDIO_FILE_ADDRESS + PlaybackPosition);
	        PlaybackPosition += 2;
	    }
}

/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

/**
  * @brief GPDMA1 Initialization Function
  *  None
  * @retval None
  */
void MX_SAI_GPDMA_Init(void)
{

  /* USER CODE BEGIN GPDMA1_Init 0 */

  /* USER CODE END GPDMA1_Init 0 */

  /* Peripheral clock enable */
  __HAL_RCC_GPDMA1_CLK_ENABLE();

  /* GPDMA1 interrupt Init */
    HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, 5, 5);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);

  /* USER CODE BEGIN GPDMA1_Init 1 */

  /* USER CODE END GPDMA1_Init 1 */
  handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
  handle_GPDMA1_Channel1.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
  handle_GPDMA1_Channel1.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
  handle_GPDMA1_Channel1.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
  handle_GPDMA1_Channel1.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
  handle_GPDMA1_Channel1.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
  if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1, DMA_CHANNEL_NPRIV) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN GPDMA1_Init 2 */

  /* USER CODE END GPDMA1_Init 2 */

}

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */
/**
  * @brief Tx Transfer Half completed callbacks
  *   hsai : pointer to a SAI_HandleTypeDef structure that contains
  *                the configuration information for SAI module.
  * @retval None
  */
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
    UpdatePointer = 0;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);

}
/**
  * @brief Tx Transfer completed callbacks.
  *   hsai : pointer to a SAI_HandleTypeDef structure that contains
  *                the configuration information for SAI module.
  * @retval None
  */
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
{
    UpdatePointer = PLAY_BUFF_SIZE/2;

}

void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
{
    printf("SAI ERROR! ErrorCode=0x%08lX\n", (unsigned long)hsai->ErrorCode);
}
0 REPLIES 0