AnsweredAssumed Answered

STM32F407, I2S Full Duplex, Left-Right Information? Sync I2S2 and I2S3?

Question asked by noll.markus on Jan 29, 2016
Hey guys,

currently I'm working on a 4in 4out Audio-DSP based von STM32F407VGT6 with two SGTL5000 Audio Codecs.
The I2S3 is the Master I2S and also generates the MCLK, I2S2 is the slave.
SCLK und LRCLK are connected directly on the PCB:

The good thing is: It is already working. I'm using the HAL_I2sEx_TransmitReceive_DMA Function und copy the input buffer directly to the outputbuffer, so I have an audio playthrough.

This works quite well so far.


But now to my problem:

I want to mix the signals from the i2s2 und i2s3.
But I think the receiving of audiobuffers is a little bit delayed on the other i2s because I can only call the two functions to start i2s in series.

How can I sync the two I2s so that the Half-RX and Full-RX callbacks of both will trigger at the exactly same time?


My next question: The ReceiveTransmit Function saves the Data in the Buffer in this Order [ChannelX ChannelY ChannelX ChannelY...]

From Computer-Software I learned that all even-pointers are left-channel und all odd-pointers are right channel.

But I don't know if I can always assume that the data are in this order in the STM32
The second I2S works as slave and will be started a little bit delayed to the other I2S, then the data may are in this Order [ChannelY ChannelX ChannelY ChannelX]

There is a bit in the SPI-Register-Set to read out if it was right or left channel, but I don't see that the ReceiveTransmit_DMA Function makes any use of this bit.

Can I always assume that all even pointers to the buffer are ChannelA and all odd pointers to the buffer are ChannelB?


Thank you!!
Markus

This is my code:
/*
 * dsp.h
 *
 *  Created on: 03.01.2016
 *      Author: Markus
 */
#ifndef APPLICATION_USER_DSP_H_
#define APPLICATION_USER_DSP_H_
 
#define ARM_MATH_CM4
 
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_i2s.h"
#include "stm32f4xx_hal_i2s_ex.h"
#include "arm_math.h"
 
 
I2S_HandleTypeDef * i2sHandle0;
I2S_HandleTypeDef * i2sHandle1;
 
q15_t RxBuffer[2][256];
q15_t TxBuffer[2][256];
uint8_t i2s0State=2, i2s1State=2;
uint8_t EnableExchange = 0;
 
 
q15_t InputBuffer[4][64];
 
q31_t Midbuffer[4][64];
q15_t OutputBuffer[4][64];
 
q31_t BiquadCoeffTable[4][5*5];
q63_t Biquadi2s0StateTable[4][4*5];
arm_biquad_casd_df1_inst_q31  biquad0, biquad1;
 
void DSP_SetI2SHandle(I2S_HandleTypeDef * in0, I2S_HandleTypeDef * in1) {
    i2sHandle0 = in0;
    i2sHandle1 = in1;
}
 
void DSP_Start(void) {
 
    BiquadCoeffTable[0][0] = 19368;
    BiquadCoeffTable[0][1] = 38736;
    BiquadCoeffTable[0][2] = 19368;
    BiquadCoeffTable[0][3] = 1064582433;
    BiquadCoeffTable[0][4] = -527788994;
    BiquadCoeffTable[0][5] = 19368;
    BiquadCoeffTable[0][6] = 38736;
    BiquadCoeffTable[0][7] = 19368;
    BiquadCoeffTable[0][8] = 1064582433;
    BiquadCoeffTable[0][9] = -527788994;
 
    arm_biquad_cas_df1_32x64_init_q31(&biquad0,2,&BiquadCoeffTable[0],&Biquadi2s0StateTable[0],2);
    arm_biquad_cas_df1_32x64_init_q31(&biquad1,2,&BiquadCoeffTable[0],&Biquadi2s0StateTable[1],2);
 
    EnableExchange=0;
    HAL_I2SEx_TransmitReceive_DMA(i2sHandle0,&TxBuffer[0],&RxBuffer[0],256);
    HAL_I2SEx_TransmitReceive_DMA(i2sHandle1,&TxBuffer[1],&RxBuffer[1],256);
 
}
 
void DSP_DoWork(void) {
    if (i2s0State==2 && i2s1State==2) return;
 
    if (i2s1State==0) {
        uint16_t i=0;
 
        while (i<128) {
            TxBuffer[1][i]=RxBuffer[1][i];
            i++;
 
        }
        i2s1State=2;
    }
 
    if (i2s1State==1) {
        uint16_t i=128;
 
                while (i<256) {
                    TxBuffer[1][i]=RxBuffer[1][i];
                    i++;
 
                }
                i2s1State=2;
 
    }
 
    if (i2s0State==0) {
        uint16_t i=0;
 
                while (i<128) {
                    TxBuffer[0][i]=RxBuffer[0][i];
                    i++;
 
                }
                i2s0State=2;
 
    }
    if (i2s0State==1) {
        uint16_t i=128;
 
                while (i<256) {
                    TxBuffer[0][i]=RxBuffer[0][i];
                    i++;
 
                }
                i2s0State=2;
 
    }
    return;
    /*
    //Copy first segment to InputBuffers
    if (i2s0State==0) {
        uint16_t i = 0;
        uint16_t j = 0;
        while (i < 64) {
            InputBuffer[0][i] = RxBuffer[0][j];
            InputBuffer[1][i] = RxBuffer[0][j+1];
            i++;
            j=j+2;
        }
    }
    //Copy second segment to InputBuffers
    if (i2s0State==1) {
            uint16_t i = 0;
            uint16_t j = 128;
            while (i < 64) {
                InputBuffer[0][i] = RxBuffer[0][j];
                InputBuffer[1][i] = RxBuffer[0][j+1];
                i++;
                j=j+2;
            }
        }
 
    //DSP Code here!
 
    arm_q15_to_q31(&InputBuffer[0],&Midbuffer[0],64);
    arm_q15_to_q31(&InputBuffer[1],&Midbuffer[1],64);
    arm_biquad_cas_df1_32x64_q31(&biquad0,&Midbuffer[0],&Midbuffer[0],64);
    arm_biquad_cas_df1_32x64_q31(&biquad1,&Midbuffer[1],&Midbuffer[1],64);
    arm_q31_to_q15(&Midbuffer[0],&OutputBuffer[0],64);
    arm_q31_to_q15(&Midbuffer[1], &OutputBuffer[1],64);
 
 
 
 
    //Copy first segment to output buffers
    if (i2s0State==0) {
        uint16_t i = 0;
        uint16_t j = 0;
        while (i < 64) {
            TxBuffer[0][j] = OutputBuffer[0][i];
            TxBuffer[0][j+1] = OutputBuffer[1][i];
            i++;
            j=j+2;
        }
        i2s0State=2;
    }
    //Copy second segment to output buffers
    if (i2s0State==1) {
            uint16_t i = 0;
            uint16_t j = 128;
            while (i < 64) {
                TxBuffer[0][j] = OutputBuffer[0][i];
                TxBuffer[0][j+1] = OutputBuffer[1][i];
                i++;
                j=j+2;
            }
            i2s0State=2;
        }
*/
 
 
}
 
void DSP_EnableExchange(void) {
    EnableExchange = 1;
 
}
 
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
    if (EnableExchange==0) return;
    if (hi2s == i2sHandle0) i2s0State=0;
    if (hi2s == i2sHandle1) i2s1State=0;
    return;
}
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s){
    if (EnableExchange==0) return;
    if (hi2s == i2sHandle0) i2s0State=1;
    if (hi2s == i2sHandle1) i2s1State=1;
 
    return;
}
void HAL_I2S_TxCpltCallback (I2S_HandleTypeDef *hi2s) {
    return;
}
void HAL_I2STxHalfCpltCallback (I2S_HandleTypeDef *hi2s) {
    return;
}
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) {
    return;
}
 
 
 
 
 
#endif /* APPLICATION_USER_DSP_H_ */



Outcomes