2015-07-17 01:58 AM
Hello, I'd like to know if there is a 'magical' way to syncronize the bit stream with the channel signal in the i2s receivers. I don't have control on the external stream ( slave mode), so the serial clock is free running, and the only way I've found to use the interface is to wait for the correct time to enable it.
Perhaps there is some way to do it using the receiver but I've been unable to find it.If this is a 'feature', perhaps it would be wise to modify the silicon on next iterations/products to allow for an automatical way to sync the receiver with the data stream.Thank you very much.Albert #i2s #stm32f407 #syncSolved! Go to Solution.
2018-05-07 12:37 AM
I answer myself. I forgot about this question pending here.
There is an easy way to synchronize the enable. The appropiate levels of the WS signal depend on the exact protocol you're using. Change as needed.
You must do the following procedure:
-disable the interface
-reset the interface
-wait for a rising edge of the ws signal
-disable interrupts
-count the clock cycles that you're using (bits) less 1, using the rising/falling edges of the clock signal
-enable the interface
-enable interrupts
this way, on the next bit clock, the interface will start with the first bit correctly clocked.
I have impolemented it this way and its working flawlessly.
Albert
2015-07-17 08:05 AM
Isn't that the purpose of the WS signal?
2015-07-19 11:18 PM
2018-05-06 10:20 PM
Hello
I have the same problem.
The only way is to control the timing of enable I2S.
But it is not exact about 1 bit.
1 bit is very large sound because it means the sound is 2 times louder.
2018-05-07 12:37 AM
I answer myself. I forgot about this question pending here.
There is an easy way to synchronize the enable. The appropiate levels of the WS signal depend on the exact protocol you're using. Change as needed.
You must do the following procedure:
-disable the interface
-reset the interface
-wait for a rising edge of the ws signal
-disable interrupts
-count the clock cycles that you're using (bits) less 1, using the rising/falling edges of the clock signal
-enable the interface
-enable interrupts
this way, on the next bit clock, the interface will start with the first bit correctly clocked.
I have impolemented it this way and its working flawlessly.
Albert
2018-05-07 02:51 AM
I'd put the 'disable interrupts' before 'wait for a rising edge of the WS signal' (and, as you've said before, it may be 'wait for a falling edge' in some protocols).
The reason is that there's a hardware bug in the I2S module implementation in the 'classic' 'F2xx/'F4xx in that the
https://community.st.com/0D50X00009XkW2ISAV
circuit is level-sensitive instead of being properly edge-sensitive. It is described in the errata and corrected in the newer 'Fxx.JW
2018-05-07 03:47 AM
Thank you for your reply
This is my code that starts I2S.
The delay is unstable.
Some times 1bit(1clock) earlier some times 1bit
(1clock)
later.What do you mean '
count the clock cycles'?
Is it different from the while loop delay(
while(counter--);)
?void I2S_Fit(){ __disable_irq(); I2S_Cmd(SPI2, DISABLE); Init_I2S();uint32_t counter = 26;
while(1){ if(!I2S_WS_IN_PIN_READ) break; } while(1){ if(I2S_WS_IN_PIN_READ) break; } while(I2S_WS_IN_PIN_READ){ }while(counter--);//Delay
SPI2->I2SCFGR |= 0x0400;//enables I2S
// I2S_Cmd(SPI2, ENABLE);__enable_irq();
XXX(11, ('I2S_Fit\n'));}2018-05-07 04:50 AM
Count the clock cycles:
while(counter--){
while(I2S_CLOCK_PIN_READ);//waits until the clock signal is low
while(!I2S_CLOCK_PIN_READ);
//waits until the clock signal is high
}
Depending on the clock polarity you're using you may need to change the order.
2018-05-07 02:08 PM
I don't think it's necessary. I believe it's enough to wait until the 'inactive' level of WS, and then enable the I2S.
JW
2018-05-07 06:20 PM
I have tested to count the I2S clock.
But still the timing is unstable by 1 bit.
The I2S clock is too fast to count by pin reading.
My MCU is STM32F105RB with 25mHz(internal 72mhz).
I put the test code like this.
//Count the clock cycles:
while(counter--){TEST1_PIN_SET; while(I2S_CK_PIN_READ);//waits until the clock signal is lowTEST1_PIN_RESET; while(!I2S_CK_PIN_READ);//waits until the clock signal is high}As the oscilloscope wave, reading the clock pin do not catch up the I2S clock speed.
I think the best way is that ST release the bug fixed version which supports I2S WS signal sync.
Any body knows that ST have released the I2S WS sync bug fixed version MCU?
If not, I need to make TTL circuit to read the I2S correctly.
It is too wast of PCB space. T.T