2015-09-16 06:03 PM
2015-09-23 12:16 AM
> I've read erratum and never related that issue with my case. I asume I'm the master (and erratum is for slave). I don't take in account that Tx on ext pin is slave.
It's the unfortunate (to put it politely) way of how full-duplex I2S is implemented in the 'F4 - it's two simplex I2S units (one of them - the ''ext'' - crippled to be only I2S and only slave), with internally connected clocks (there is one more I2S erratum for '405/407 witnessing that this connection went wrong in one case).> So I will try to implement double buffer DMA transfer. The buffer exchange is made on RX/TX compleat interrupt? or is it a register configuration and part of the uC hardware?
Hardware - see Double buffer mode sub-chapter of DMA chapter in RM. DMA_SxCR.DBM switches on the double-buffer mode; you'll need to set the second buffer's address into DMA_SxM1AR and DMA_SxCR.CT indicates which buffer is in use by DMA (i.e. the other buffer is available for the software to be manupulated with). The double-buffer mode is not a necessary precondition. You can use a single buffer and write ahead of the DMA's read pointer, indicated by current NDTR value. JW2015-09-23 04:41 AM
It will be a little tricky.... My device need to make several test on the pacient ear. For example, I need to send 2 tones and record the ear response at the same time. Each TransmitReceive will be for about 46mseg and I will need 100 or more TransmitReceive experiment. But the thing is that this is not the only thing the equioment will do. So I will need turn off and on several time the I2S interface...
I think on move to 407, but if the I2S implementation is the same.... I will not move.... I search on TI and they don't have M4 with I2S. Freescale do have M4 with full I2S implementation... Time to think how to continue... Thank Jan2015-09-23 01:58 PM
There is little tricky in using I2S, it's a fairly simple interface. You can stop both Rx and Tx and then restart them. Or you can stop Tx and wait for WS to become the proper level before restart. Or you can leave both running and just fill the buffers. Or you can set the double-buffer mode and only switch memory address of the inactive buffer to one of previously prepared buffers, even buffers in FLASH. There are so many ways to skin the cat...
JW2015-09-23 04:54 PM
Jan, I want to thank you so much for your answers!
It help me a lot. Now my project is working ok!!!! I just do this:void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
f_mitad_buffer = 0;
}
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
f_mitad_buffer = 1;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_I2S2_Init();
MX_USB_DEVICE_Init();
uint16_t i;
int32_t tmp=0;
int32_t tmp1=0;
// uint8_t cnt_PromSincr = 0;
/*
* Creo la señal de a sacar por los parlantes. Las frecuencias son Fsin1 y Fsin2
*/
for(i=0;i<
2
*SAMPLES;i+=2)
{
//Multiplico por 2^24/2 - 1. el -1 es fundamental para evitar overflow en algunos casos
tmp= ( sin(2*M_PI*(i/2)*Fsin1/Fs) ) * (int32_t)6088607;
tmp1= ( sin(2*M_PI*(i/2)*Fsin2/Fs) ) * (int32_t)6088607;
// Paso los 24bits como MSb
tmp <<= 8;
tmp1 <<= 8;
//Canal L
OutputBuffer[i] = ((tmp&0x0000FFFF)<<16) | ((tmp&0xFFFF0000)>>16);
//Canal R
OutputBuffer[i+1] = ((tmp1&0x0000FFFF)<<
16
) | ((tmp1&0xFFFF0000)>>16);
}
for(i=2*SAMPLES;i<
2
*2*SAMPLES;i++)
{
//Canal L y R
OutputBuffer[i] = 0;
}
/*
* Configuro el Audio Codec
* Al finalizar necesito un delay para asegurar que esté funcionando estable. 2000 es mucho, ir achicando
*/
codec_init();
HAL_Delay(2000);
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*2*SAMPLES);
while(1)
{
if(fUSB_rcv) //Si se ha recivido un dato por el USB
{
switch (msg[0]) //Verifico que caracter me envió la PC
{
case 'Z':
while(f_mitad_buffer == 0);
for(
i
=
0
;i<2*SAMPLES;i+=2)
{
tmp
=
InputBuffer
[i+140];
tmp = ((tmp&0x0000FFFF)<<16) | ((tmp&0xFFFF0000)>>16);
tmp >>= 8;
Input[i/2] = tmp;
fftInpSignal[i] = tmp; ///80;
fftInpSignal[i+1] = 0.0;
}
/* Process the data through the CFFT/CIFFT module */
arm_cfft_f32(&arm_cfft_sR_f32_len2048, fftInpSignal, ifftFlag, doBitReverse);
/* Process the data through the Complex Magnitude Module for
calculating the magnitude at each bin */
arm_cmplx_mag_f32(fftInpSignal, fftSignal, fftSize);
CDC_Transmit_FS((uint8_t *)&Input[0], SAMPLES*4);
HAL_Delay(100);
CDC_Transmit_FS((uint8_t *)&fftSignal[0], SAMPLES*4);
break;
}
fUSB_rcv=0;
} //Fin de la verificacion de recepcion de dato por USB
}
}
and configure DMA on Circular mode.
The magic is on the flag that tells me that I just send half buffer (the sound I'm interested on) and the
while(f_mitad_buffer == 0);
before procees the buffer. There is more elegant way to do this, but this just work ok for now. BR