cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with DMA in Ping Pong buffer schema

guidoglorioso01
Associate II

Hello everyone i am quite stuck and i want to se if you have any idea.

I am making a project wich has 3 devices. 

- ESP32 wich receive from bluetooth an audio stream

- Nucleo F401Re wich receive from the ESP32 via I2S the audio and then process it.

- MAX98357A wich is an amp who receive the audio processed from the nucleo and then play it.

I manage to send the audio without the nucleo and all sound good, but i need the nucleo for the project.

When i add the nucleo to the ecuation, i hear the testing sound and a noise attached. 

What i am doing now in the ST is only receiving the data and sending it to the MAX. For that i am using a ping pong buffer and the both I2S with DMA in circular mode (all as master):

-Input

guidoglorioso01_0-1706385277144.pngguidoglorioso01_3-1706385346469.png

 

 

-output

guidoglorioso01_1-1706385308953.pngguidoglorioso01_2-1706385329047.png

The ESP32 sample rate is 44,1kHZ and all the streams are stereo.

Here is the code i am using for ping pong buffering: 

 

 #define BUFFER_SAMPLE_LEN  400
#define DATOS_P_CANAL 	BUFFER_SAMPLE_LEN
#define BUFF_SIZE 		DATOS_P_CANAL*2
#define PINPONG_BUFF_SIZE BUFF_SIZE*2

extern I2S_HandleTypeDef hi2s2;
extern I2S_HandleTypeDef hi2s3;

static volatile int16_t data_ready_r,data_ready_t ;

//#############################################################################
//Double Buffering
//#############################################################################
//Buffers de entrada
int16_t bufferIn[PINPONG_BUFF_SIZE];
static volatile int16_t *ptrDmaIn = &bufferIn[0];
static volatile int16_t *ptrProcessIn = &bufferIn[(PINPONG_BUFF_SIZE/2)-1];

//Buffers de Salida AB
int16_t bufferOut_AB[PINPONG_BUFF_SIZE];
static volatile int16_t *ptrProcessOutAB = &bufferOut_AB[(PINPONG_BUFF_SIZE/2)-1];
static volatile int16_t *ptrDmaOutAB = &bufferOut_AB[0];
void initI2SDriver() {
	semRx_I2S = xSemaphoreCreateBinary();
	semTxAB_I2S = xSemaphoreCreateBinary();
	semTxCD_I2S = xSemaphoreCreateBinary();
	semDataReadyToSendDMA = xSemaphoreCreateBinary();
	semDataReadyToProc = xSemaphoreCreateBinary();

	xSemaphoreGive(semRx_I2S);
	xSemaphoreGive(semTxAB_I2S);
	xSemaphoreGive(semTxCD_I2S);
	xSemaphoreGive(semDataReadyToSendDMA);
	xSemaphoreTake(semDataReadyToProc, 0);

	HAL_I2S_Transmit_DMA(&hi2s3,(uint16_t *) ptrDmaOutAB, PINPONG_BUFF_SIZE);

	HAL_I2S_Receive_DMA(&hi2s2,(uint16_t *) ptrDmaIn, PINPONG_BUFF_SIZE);
}


//#############################################################################
//CALLBACKS DMA
//#############################################################################

//I2S 2
void callbackI2SRx_CMP() {
	if(data_ready_r){
		ptrDmaIn = &bufferIn[(PINPONG_BUFF_SIZE / 2)-1];
		ptrProcessIn = &bufferIn[0];
		data_ready_r = 0;
	}

	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR( semRx_I2S, &xHigherPriorityTaskWoken );
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
void callbackI2SRx_HALF() {
	if(data_ready_r){
		ptrDmaIn = &bufferIn[0];
		ptrProcessIn = &bufferIn[(PINPONG_BUFF_SIZE / 2)-1];
		data_ready_r = 0;
	}

	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR( semRx_I2S, &xHigherPriorityTaskWoken );
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

//I2S 3
void callbackI2STx_CMP() {
	ptrDmaOutAB = &bufferOut_AB[(PINPONG_BUFF_SIZE / 2)-1];
	ptrProcessOutAB = &bufferOut_AB[0];

	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR( semTxAB_I2S, &xHigherPriorityTaskWoken );
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}
void callbackI2STx_HALF() {

	ptrDmaOutAB = &bufferOut_AB[0];
	ptrProcessOutAB = &bufferOut_AB[(PINPONG_BUFF_SIZE / 2)-1];

	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR( semTxAB_I2S, &xHigherPriorityTaskWoken );
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}


//#############################################################################
//Task recieve
//#############################################################################
void task_I2S_recieve() {
	while(1) {
		//xSemaphoreTake(semDataReadyToSendDMA,portMAX_DELAY);

		xSemaphoreTake(semTxAB_I2S,portMAX_DELAY);
		//xSemaphoreTake(semTxCD_I2S,portMAX_DELAY);

		xSemaphoreTake(semRx_I2S,portMAX_DELAY);

	pruebaLoopback();
	}
}

void pruebaLoopback() {

	for(int i =0;i<BUFF_SIZE;i++){
		ptrProcessOutAB[i] = ptrProcessIn[i];
	}
	data_ready_r = 1;
	data_ready_t = 1;
}

 

One thing that i notice using a sine wave signal was that sometimes the first 2 numbers are trash and in some random places i have 0 or 1 wich are not okey.

ie:

guidoglorioso01_4-1706386062867.png

guidoglorioso01_5-1706386089598.png

 

the second glitch is what i think is causing the noise but i don know how to eliminate those. (Seems to be random places were they appear).

Also i put a prebuilt sine signal in the buffer and played it and all sound good so i discard the output as the problem.

A possible solution for those could be i thought to use a low pass filter, but it´s not what i really want 

0 REPLIES 0