sensorium / Mozzi

sound synthesis library for Arduino

Home Page:https://sensorium.github.io/Mozzi/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

I2S dac with a nano.

poetaster opened this issue · comments

I've been looking through the docs on external I2S and there is enough info on the ESP boards, but it's unclear if I can get a nano to do I2S with a board like: https://github.com/dwhinham/mt32-pi/wiki/GY-PCM5102-DAC-module

I just have a lot of PCM5102 modules from pi development (bare metal minidex and the like).

I did just test (knowing probably wrong) with:
| 5102 | PT8211 | Connect to:
|Vin | Vdd | V+
|BCK | BCK | SCK
|LCK | WS | any digital pin (defined by WS_pin here, pin 5)
|DIN | DIN | MOSI
|GND | GND | GND

I wasn't sure where setup like that in AudioConfigESP32.h should go? I'll give it a try with a nodeMCU, but the nano is my preference (since I have a bunch and have an own build shield, etc).

This is a tangent, but I just tested https://github.com/andykarpov/VS1003 with an LC VS1003 board (line and mic inputs, headphone out). Works great. This chip has a DAC mode, among many other (rt midi, ogg encoding) things.

https://www.vlsi.fi/en/support/software/vs10xxapplications.html
https://www.vlsi.fi/fileadmin/software/VS10XX/dacmode.pdf

Hi,

Nano does not have I2S by default, but luckily it can be emulated using SPI or another protocol.

I think the best shot is to use a external audio output function which take care of transmitting the orders to the DAC.

There are a few examples in the External_Audio_Output example folder, using SPI to emulate I2S for instance but the same technique can be done with any protocol, you just have to:

  • set mozzi to use an external audio output function: #define EXTERNAL_AUDIO_OUTPUT true should be uncommented in mozzi_config.h.
  • define this function in your sketch. There are a few examples given with Mozzi.

Do not hesitate to report back if you have problems of if it works well!

Hi, I've taken a crack at using the the external audio output function, but I can't get it to compile :)

https://github.com/poetaster/VS1003/blob/master/examples/vs1003_mozzi_stereo_16bits/vs1003_mozzi_stereo_16bits.ino

I think trying to feed the chunk playing function f.l() is , well, a hack at best.

/home/mwa/Arduino/libraries/Mozzi-1.1.0/tables/cos2048_int8.h:14:28: error: COS2048_DATA causes a section type conflict with reg_name_AICTRL3
 CONSTTABLE_STORAGE(int8_t) COS2048_DATA []  =
                            ^
/home/mwa/Arduino/libraries/VS1003/VS1003.cpp:89:6: note: 'reg_name_AICTRL3' was declared here
 char reg_name_AICTRL3[] PROGMEM  = "AICTRL3";

But I get this name space like clash.

Hi,
Thanks for the example and the report! I indeed managed to reproduce.

It seems to originate in a conflict in the usage of PROGMEM which both Mozzi and the VS1003 libraries are using.

There is a fix described here, that could be implemented in both libraries. As we have control over Mozzi's code, I tried implemented that fix in this branch.

I might not be aware of the full implications of it, assembler is complaining a bit, but it does compile and standard sketches still work, at least on the UNO. Could you maybe give it a try?

PS: given the way this DAC works, there are probably way nicer way to connect Mozzi to it, for instance by branching it straight inside Mozzi's buffers. This might not be easy with the current version of Mozzi but might be easier with Mozzi2.0 which is in preparation. In all cases, first things first, the conflict ;). Your solution should be working, at least somehow.

Finally, the initial DAC you suggested should also work, also somehow (always depends how low-level you are wishing to go…), but this is fundamentally a I2S DAC, a protocol than can be emulated by SPI.

In case you are wondering, the LRCK is equivalent to WS in our denomination, selecting right or left channel. This DAC seems to accept different format, there might be a small amount of fiddling with the SPI_MODE to have the correct one depending on which configuration you chose, but there are only 4 modes so should be quite manageable!

Hi, Thanks for the example and the report! I indeed managed to reproduce.

It seems to originate in a conflict in the usage of PROGMEM which both Mozzi and the VS1003 libraries are using.

There is a fix described here, that could be implemented in both libraries. As we have control over Mozzi's code, I tried implemented that fix in this branch.

I might not be aware of the full implications of it, assembler is complaining a bit, but it does compile and standard sketches still work, at least on the UNO. Could you maybe give it a try?

That compiles but I think I'm feeding the playchunk function data incorrectly.
It's expecting:

void VS1003::playChunk(const uint8_t* data, size_t len)
{
  spi_saver_t spi_saver;
  set_our_spi();
  sdi_send_buffer(data,len);
}

The 1003 and 1053 both require user programs (encoder/decoder, realtime midi, PCM input, DAC) to be pushed to the device and soft reset is required to operate in that mode. The lib does not support the DAC mode of the 1003 which is kind of the point here ;) So I think I may need to to that first.

To see the SPI operations one can skip the library and use the approach here: https://github.com/diyelectromusic/sdemp/blob/f4688e7e4cca5bc9b8f5a7967eeb1ea71159de5e/src/SDEMP/ArduinoVS10xxDrumMachine/ArduinoVS10xxDrumMachine.ino He's including a header file from the manufacturer. And does all the setup and communication in the sketch itself.

This might not be easy with the current version of Mozzi but might be easier with Mozzi2.0 which is in preparation.

Ah, that might indeed be worth the wait!

might be easier

Might only ;), at least maybe a bit cleaner but take it with a pinch of salt as I am not that experienced with codecs.

That compiles but I think I'm feeding the playchunk function data incorrectly.

As the library expects a pointer, I would put my bet on something like:

player.playChunk(&f.l(), sizeof(f.l()));

But as you said, maybe easier to feed in the order a bit more manually like the example you linked. If it is pure SPI/I2S there is no reason for it not to work. I would suggest trying to get the DAC working in a manual way first without Mozzi, and then using the same codes in Mozzi external audio function.

Hope this help!


I might have lost track a bit, but all this is concerning the VS10XX DACs series right? The PCM5102 has not been tested?

might be easier

Might only ;), at least maybe a bit cleaner but take it with a pinch of salt as I am not that experienced with codecs.

That compiles but I think I'm feeding the playchunk function data incorrectly.

As the library expects a pointer, I would put my bet on something like:

player.playChunk(&f.l(), sizeof(f.l()));

Ah, should have spotted that variant. I'll take a crack at that.

But as you said, maybe easier to feed in the order a bit more manually like the example you linked. If it is pure SPI/I2S there is no reason for it not to work. I would suggest trying to get the DAC working in a manual way first without Mozzi, and then using the same codes in Mozzi external audio function.

Yes, I have enough data and the required mode programs, I just got distracted implementing a euclidean drum midi synth on the chip to see what it could do :)

Hope this help!

I might have lost track a bit, but all this is concerning the VS10XX DACs series right? The PCM5102 has not been tested?

No, I confused things but introducing the second dac. I'm working on 3 audio things in parallel, so I tend to confound the issue. But getting either dac running would be a good thing. I'll report here on my findings and submit a sketch.

Ah, forgot to mention that there is a bunch of information at: https://github.com/pschatzmann/arduino-audio-tools/wiki/External-DAC where the PCM5012A makes an appearance.

Hi! Just a quick update. I'm going to split out the VS10XX topic into another ticket.

I managed, after getting the PT8211 running on a nano (which did not provide an improvement in audio quality over pwm on pin 9) to get I2S running with both the PT8211 and PCM5102 but ONLY using an RP2040 and the pschatzmann fork of mozzi. It's a bit bitchy to get (the 5102) running but that's all a matter of configuration (I referred to the default pin assigments in the AudioConfigRP2040.h and used config params in schatzmann;s objects).

I may revisit this since it's possible to get I2S running via SPI on the nano, but It seems to 'work' under some conditions so it's not an 'Issue' per se.