2024-01-27 12:15 PM
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
-output
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:
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