stm32 SAI / SPDIF_TX issue - Page 1
Forum section: electronics / general

author: jmf11
author_rank: Contributor
timestamp: November 20, 2016, 05:07:03 pm
content: Hello,I'm trying to develop an application to drive multiamplified speakers from USB (async), applying DSP for crossover and EQ on a Nucleo F746ZG. The project is therehttps://github.com/jmf13/F7USBAudio/tree/master.I'm almost there but I have strange glitches as explained herehttps://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fGlitches%20with%20SAISPDIF%2e%20Different%20behaviour%20on%20LR%20channels&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https%3A%2F%2Fmy%2Est%2Ecom%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex%5Fmx%5Fstm32%2FAllItems%2Easpx&currentviews=0. Please refer to that thread for detailed explanation. execept if you think that it is better to copy paste here.I'm not sure to have support from the ST forum. If somebody here had some experience with the stm32 SAI, especially using the SPDIF protocol, or have ideas about possible causes, I would be highly interested. i don't have more ideas for debut, nor idea to follow... Sad when so near from achieving the goal.Best regards,JMF

author: Scrts
author_rank: Frequent Contributor
timestamp: November 21, 2016, 01:39:33 pm
content: How big is your buffer? I suspect buffer issues where it under/over runs.

author: jmf11
author_rank: Contributor
timestamp: November 21, 2016, 08:17:08 pm
content: Quote from: Scrts on November 21, 2016, 01:39:33 pmThis was my first idea. However, I changes the length of the different buffers to see if it would have an impact on the issue, and it had not.Currently the buffer size to the SAI is 256 samples (> 5ms), but I tried with 1024 samples and had the same thing.You can also see in the big zoom that the signal is perfectly continuous. In cfase of buffer underrun/overrun, you expect some discontinuity in the signal...Looking at the specs of the SPDIF interface, I wonder if it could be related to some protection scheme of the consumer interface. I currently don' t manage the Channel Status bits. Could it trigger some faults in my SPDIF receiver?JMF

author: cv007
author_rank: Frequent Contributor
timestamp: November 22, 2016, 04:25:47 am
content: First, I know very little so consider the source.I doubt leaving the (vu)c bits as 0 would be a problem- (I can spit out raw spdif on a pic32 through the spi and my old receiver is happy with all the control bytes/bits as 0- at 44.1k and 48k) - BUTare you sure you are not inadvertently putting info in those vuc bits ?you have this-Audio_output_bufferA[AUDIO_OUTPUT_BUF_SIZE*buffer+2*i]= (((int32_t)Audio_buffer_2) <<8 );I'm no C guru, but casting an int16 to an int32 then left shifting 8 could be setting those upper vuc bits (?)Although if that was the case you would think the V bit would be set quite often and cause major problems.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2016, 05:14:19 am
content: I would put money on that you are tickling the "pre-emphasis" bit in the channel status information of the S/PDIF stream, and the de-emphasis filter is switching on and off. See if the 'glitch' is always a multiple of blocks of about 192 samples, and at different frequencies it has different levels. Just making sure that your channel status bits are valid would be a start to eliminating this.Maybe debug the stream with a Logic Analyzer - look for the block start (11101000 or 00010111) to identify frame 0, and then have a look at the channel status bit in frame 3 to check that it is the case. It is in bit 30 of the sample data, so maybe mask that bit off?

author: jmf11
author_rank: Contributor
timestamp: November 22, 2016, 06:40:15 am
content: I will try this evening to add a first CS bit to 1 to set the "Pro" interface and then zeros. it is the minimum implementation from the spec.On the Stm32 SAI module, the data are fed through a 32bit register:- 0..23 = data,- 24 = Validity bit,- 25 = User bit,- 26 = CS bit.There is no "function" to set the CS bits chain and then merge it to the data, so it has to be done manually at application level, which is not very convenient.By doing: Audio_output_bufferA[AUDIO_OUTPUT_BUF_SIZE*buffer+2*i]= (((int32_t)Audio_buffer_2) <<8 );I expect to fill my 32bit samples buffer with my 16 bits data, shifted to get the 24 bits SPDIF data.I'm not a C guru, but I shouldn't set any CS, V, U bits in that process...JMF

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2016, 10:39:37 am
content: Quote from: jmf11 on November 22, 2016, 06:40:15 amUm, maybeDoesn't that code shift the data in bits 18,17 & 16 into bits 26,25 & 24? Unless Audio_buffer_2 is uint16_t You might want to & it with 0xFFFFFF just to be sure that sign is not being extended...

author: jmf11
author_rank: Contributor
timestamp: November 22, 2016, 01:01:24 pm
content: It is defined asCode:int16_t Audio_buffer_2[AUDIO_OUTPUT_BUF_SIZE/2];Can I have a problem (in your text you state that it should be uint16_t to not have issues? I'm very interested as below clues go in your direction. But I don't see yet But where in my code I would set bits in the 24..31 range to impact the CS bits...Additional answer to one of your questions: I use 48K samples. 48 samples = 1ms. 192 samples = 4 ms. Bingo?Additional potential clue. I had a look at the AK4113 datasheet and in the default config, they use the CS of the first subframe. That could explain the fact that feeding the data to one channel and zeros to the other has a different effect if we feed the data to the first or second subframe/channel.JMF

author: cv007
author_rank: Frequent Contributor
timestamp: November 22, 2016, 01:42:22 pm
content: QuoteYou are converting (casting) an int16 to an int32 before you shift- so for any negative number you are getting the upper bits set in the cast-int16 > -1 > 0xFFFF(int32) int16 > -1 > 0xFFFFFFFF0xFFFFFFFF << 8 = 0xFFFFFF00those vuc bits are now setbut what you wanted was 0x00FFFF00there is a lot of casting going on in that codeyou could do several things-cast appropriately- Audio_output_bufferA[AUDIO_OUTPUT_BUF_SIZE*buffer+2*i]= (int32_t)(((uint32_t)Audio_buffer_2) <<8 );or maybe change Audio_output_bufferA to an uint32_t (you aren't using those upper bits anyway)

author: jmf11
author_rank: Contributor
timestamp: November 22, 2016, 02:24:36 pm
content: Thanks al lot to all of you to point at my mistakes.This looks quite promising. I'll give a try this evening and post the results here. I will try to go to full unsigned datatypes.Best regards,JMF

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2016, 05:50:07 pm
content: Did a little test for you:Code:C:\Users\hamster\Desktop\audio>type test.c#include <stdio.h>int main(void) {uint32_t a,b;int16_t Audio_buffer_2 = -1;a = (((int32_t)Audio_buffer_2) <<8 );b = (((uint16_t)Audio_buffer_2) <<8 );printf("'a' is %08X\n", a);printf("'b' is %08X\n", b);return 0;}C:\Users\hamster\Desktop\audio>tcc\tcc test.cC:\Users\hamster\Desktop\audio>test'a' is FFFFFF00'b' is 00FFFF00C:\Users\hamster\Desktop\audio>

author: jmf11
author_rank: Contributor
timestamp: November 22, 2016, 06:43:29 pm
content: Bingo !!!!!Being "clean", using unsigned int, and controlling better the Cast solved the issue. I now only stream zeros as CS bits.Seems to confirm that I was are tickling "pre-emphasis" bit randomly, applying the filter for a block...Thanks a lot again to have pointed out my mistake :-) This helped a lot and it works much better now.Best regards,JMF

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2016, 08:25:31 pm
content: oh, and +1000 points for updating the ST forum post with the fix.

author: jmf11
author_rank: Contributor
timestamp: November 22, 2016, 08:41:55 pm
content: I like the stm32 product for audio applications, but the st forum does not looks so responsive. Very often, people seem to post the solutions to their problems on their own.I have been surprised to see how people here have been responsive and helpful.This has been much appreciated !Best regards,JMF

author: cv007
author_rank: Frequent Contributor
timestamp: November 22, 2016, 11:15:09 pm
content: in your other st forum post I saw this-QuoteI knew that couldn't be good (shifting signed int's), but it took me a little while to find where the actual code was. I wish I was capable of dealing with higher powered devices (along with the added code).Sounds like a neat project.

author: jmf11
author_rank: Contributor
timestamp: November 23, 2016, 07:42:47 am
content: My coding skills were far far in the past and quite rusted... I (re)learn a lot in this project.I spent part of the evening listening music.This works really very well !It delivers top quality with little budget and hardware:- only one clock domain thanks to the Async USB that decouples from the music server- DSP crossover and EQ that allow to skip the questions related to the quality, type, tolerance and sonic impact of condensators, coils, resistors of passive crossovers, the complex load on amplifiers,- one amplifier per driver,- those class D amplifiers deliver tremendous performance. Full Digital Amplifiers like the STA326 deliver very high performance even for audiophile crowd.- full digital chain from the music file to the amplifier chip.Very good options were existing relying on Linux machines or Raspberry Pi for stereo systems, but those systems don't expose several digital out systems. The Nucleo boards are a very good option to meet this multi channel requirement.I would be happy to experiment with the ST cape provided with a STA350 and direct I2S from the SAI to the chip: even simpler :-)But now lets enjoy the music for a while.JMF