I try to connect a audio codec to the STM32 Primer. I want to use a TLV320aic23B, but unfortunatly the uC on the Primer cannot generate I2S on the SPI. Is there an other way to connect a (different) audio codec? 16 bit mono in/out are o.k., but dma ist a must. Full duplex would be nice.
If not, I am thinking of unsing the 12 bit ADC on chip and generate my mono output with the PWM. What resolution can I expect? (I have to dig deeper in the datasheet...)
Thanks in advance, -Klaus
PS: If you are thinking of a Primer Vers. 2, use one with I2S!
I have actually did the trick on LPC214x, but I think it would also work on STM (sorry - I did not study SPI/SSP modes on STM yet). I have configured LPC214x as SLAVE, and connect SSEL signal to LRCLK signal of TLV320AIC23B. Then TLV320 is configured as a MASTER with Left-Justified mode (you do not have to select I2S). The disadvantage of that solution is, that I receive only channel transmitted when L/R clock is low (which actually works as Slave Select signal). Further on, you have to configure SPI mode to 16 bits word lengt to read full audio sample. For SPI configuration CPOL = 0, CPHA = 0.
I have used interrupt of SSP when RX FIFO is half full, so every 4 received soud sample I receive interrupt (FIFO is 8 words long/deep). As LPC has no DMA for SSP (that's actually very bad for me) I have to grab everything on the fly and implement software FIFO.
Nevertheless it works without problems. The same should work when you're going to play sound - the difference is, that after each 4 samples received, you should load next 4 samples to SSP TX FIFO, it will be automatically clocked by TLV320 to DAC. In this case, you can of course ignore content you're receiving from TLV320.
When you play sound, you can of course use interrupt of TX FIFO is half empty, but I have observed better sound quality, when I loaded content to be playes on RX FIFO half empty interrupt.
Now you have to look on STM manual to adopt that to your hardware. Anyhow please do remeber, that when STM is configured as SLAVE, you have to exchange lines of MISO and MOSI. I write it clearly, because I spend 2 hours to figure out, why there is no sound (before, LPC214x was designed to be MASTER and TLV320 as a SLAVE).
In case of using SSP interrupts, I go for 32kHz without problems, I think 44,1kHz is not a problem as well. The biggest advantage od using microcontroller as a SLAVE is that you do not have to generate precise BCLK and LRCLK signals according to 256 x samplin frequency. You only have to provide next samples when TLV320 need them, without care when it should be done. All clocking issues are resolved by TLV320 internal dividers.
Please also take care: when 12MHz crystal and USB mode is used in TLV320, BCLK and DI/DO pulse on TLV320 are 4 times shorter, than in non-USB modes. I observed that on the scope, because LPC214x was sometimes got lost with so short data pulses. Next issue with LPC214x is that in case of SLAVE mode it can accept only PCLK/12 maximum frequency of SPI clock. For higher sampling frequency it can be a problem.
In case of further questions just drop me an email.
I have actually did the trick on LPC214x, but I think it would also work on STM (sorry - I did not study SPI/SSP modes on STM yet). I have configured LPC214x as SLAVE, and connect SSEL signal to LRCLK signal of TLV320AIC23B. Then TLV320 is configured as a MASTER with Left-Justified mode (you do not have to select I2S). The disadvantage of that solution is, that I receive only channel transmitted when L/R clock is low (which actually works as Slave Select signal). Further on, you have to configure SPI mode to 16 bits word lengt to read full audio sample. For SPI configuration CPOL = 0, CPHA = 0.
To get you right: Does this mean, I can only receive one channel? It would be o.k.!
stefan :
I have used interrupt of SSP when RX FIFO is half full, so every 4 received soud sample I receive interrupt (FIFO is 8 words long/deep). As LPC has no DMA for SSP (that's actually very bad for me) I have to grab everything on the fly and implement software FIFO.
AFAIK, the STM32 can use dma for SPI. I hope I can try it next week.
stefan :
Nevertheless it works without problems. The same should work when you're going to play sound - the difference is, that after each 4 samples received, you should load next 4 samples to SSP TX FIFO, it will be automatically clocked by TLV320 to DAC. In this case, you can of course ignore content you're receiving from TLV320.
So it should be able to play two channels?
Now you have to look on STM manual to adopt that to your hardware. Anyhow please do remeber, that when STM is configured as SLAVE, you have to exchange lines of MISO and MOSI. I write it clearly, because I spend 2 hours to figure out, why there is no sound (before, LPC214x was designed to be MASTER and TLV320 as a SLAVE).
Ah, yes... I would have forgotten that!
In case of using SSP interrupts, I go for 32kHz without problems, I think 44,1kHz is not a problem as well.
32 kHz ist enough for my first two applications. Later I will try 44.1 kHz. A lot of great infos!
Yes, I play/record only one (right if I am not wrong) channel, the problem is that as long as you haven't true I2S interface, you're not able to send from micro sample for the other channel. The ONLY way to do this is to internally generate all clocks for TLV320 (in this case micro MUST be a MASTER) two times faster, than required sampling frequency. To give you an example (I test it - so I know it works):
Imagine you have to play 16kHz, 16 bit samples. Then you have period of 62,5uS for each subsequent frame (2 channels!). Therefore I setup timer interrupt every 32,25 uS, "manually" generate LRCLK signal on one of GPIO pins and send one 16bit-wide word to SPI output buffer for L and R channel respectively (I was not using SSP FIFO halfe empty interrupt of course).
But actually this is the bad thing with this design - you're in interrupt service every 32,25uS - it's really not comfortable for the rest of the application.
In the same example, when using SSP FIFO you have to do the job every 4 x 62,5 us = 250uS which gives much more processing time for main application thread.
I have seen several ideas on the net, exaple using of PWM channel to generate LRCLK and BCLK and so on, but I didn't try them. Mainly because I need only one channel to be sampled/played.
I think having DMA is a big advantage in your case - you can setup two ping-pong buffers for playing audio: one is played, while the opposite is being loaded from MMC card or whatever.