To handle decoding and the overhead of moving bits around, it uses a dual-buffer DMA approach. It reads data from an SD card, running the decoding routine on the main CPU. The decoded samples are written into one of two buffers. While one buffer is being written to, the other is read via DMA and sent to the PWM buffer (more on PWM audio here: https://x.com/beala/status/1826147833168408738). Because DMA is used, data transfer can occur in parallel with decoding, without involving the main processor. When the bits have all been written to the PWM buffer, an interrupt triggers a buffer swap, and the process repeats.
I'm leaving out many details. Tuning the pwm speed to achieve correct playback speed was quite an adventure. And when I needed to increase the clock speed to play higher sample rates, this caused I/O errors with the SD card that I never managed to solve. Although I learned a lot from this process, I ultimately opted to use an MP3 module in my final build: https://store-usa.arduino.cc/products/dfplayer-a-mini-mp3-pl...
This is probably routine for an experienced embedded engineer, but it was quite a learning experience for me!
> And when I needed to increase the clock speed to play higher sample rates, this caused I/O errors with the SD card that I never managed to solve.
Presumably if a RP2040 could almost do it, a RP2350 could do it no problem. Unless you were limited by PWM speed. Even then you might be able to accept less resolution and filter and dither.
I've got music-player on my short list of projects as well. I anticipate using a Teensy though. I'm pretty sure there are good libraries to handle everything you would need.
The RP2040 can output 24 bit (or technically 32-bit), 48kHz stereo audio over I2S. Combine that with a DAC like the PCM1502 (which has plenty of dev boards) and you've got yourself a high quality audio setup.
I have a Rust crate for outputting I2S data, or retrieving it from something like a mic or ADC. You can hook it up to DMA and make your audio go brrrr
I feel like the flaws of the Pico 2/RP2350 should be advertised better. The Pico is great. I waisted half of an extremely frustrating day with a Pico 2 before suspecting the board itself was the problem, and confirming it with very specific searches that brought up threads about the issue. The internal pull-downs don't work.
Maybe it's my fault for not making it to page 1357 (!) of the datasheet, where the issue is described as "RP2350-E9".
This is unfortunately not emphasized with many breakout boards. It pays off to skim errata sections at the start of a project. All hardware has errata, and it ranges from incorrect details and minor malfunctions all the way through to broken peripherals and all manner of critical malfunctions.
Something is just not right in the Raspberry Pi design team if at this point ESP32 have less unpleasant surprises. New RP micros always turn out have disappointing bugs that make them just shy of considering using for actual embedded projects.
I think schematics are easier to read than looking at a (fritzing?) breadboard layout.
Discrete resistors aren't necessary for the buttons if you enable the internal pullups on the RP2040.
If you want to do a similar audio player I can recommend the DY-SV5W module family, this is essentially a micro-SD playback chip with a headphone amp and a 5W (mono) amplifier, the whole thing can be powered from 5V/USB. Really great for art projects where you just need a single track to play/loop on the press of a button and can't be bothered to program.
It has thre DIP switches that set the mode, you can use them to set the playback modes, one of which is serial control, meaning you can easily beef this up using a microcontroller.
Similarly, the dfplayer mini is fine if you want some sound to scream back at you. Works on button press, but also rx/TX for track management from micro SD card. Small amplifier built in.
I built motion activated playback speakers - good for hiding them in the bushes on halloween.
For headphone audio it's plenty to just PWM, inductance of the headphones and mechanical low pass characteristic of the speaker itself will mostly do the rest.
If you want to smooth the things out because you target a line input, simple LC filter will work just fine here.
I've got a Pico 2 (2035) playing mono 22kHz MP3 using built-in 12-bit PWM, sounds pretty good. This would probably work on the 2040. However, as this is C code I'm not sure if this ports to MicroPython easily.
I did a lot of research for building my own little iPod Nano sized player, which should also have the ability to be controlled by a wired headphone remote.
So here are my results up until now:
- The best device I found is a LicheeRV Nano[1] - also used in NanoKVM.
- It has enough CPU+RAM to support more complex formats like FLAC while still being very small.
- It has a full featured MIPI 31-pin / 6-pin touch display port, although I could not find any available display smaller than 7" to order without hassle (there is an unavailable official 3" though[4]).
- It also has USB-C, where it should be possible to use one of these external USB-C to audiojack adapters with mic support.
- Some of these adapters should support headset control buttons out of the box (via kernel usbsound) - on my notebook this works flawlessly.
- There also is a full featured configurable buildroot[2], so, less work to get started with an optimized build.
- Combining a TP4057 battery charger and a battery gauge (MAX17043) you should be able to support a 1200mah battery, read out battery status via I2C and recharge within a < 3" 3D printed case.
- All you would have to do is create a custom buildroot and a nice user interface via LVGL, they already have a music player sample on there samples listing[3]. Unfortunately this is where the workload is huge ;)
I setup a project somewhat along these lines with a Raspberry Pi, a USB DAC, and spotifyd. Now I have a decent and convenient audio player hooked up to my sound system. May not pass all the bars for an audiophile but the sound quality is actually fairly decent - much better than my previous Alexa setup - which is all I needed.
I mean, we're in an age where the processing power that used to be in large expensive lab equipment is easily emulated for pocket change or even free from thrift store scraps.
[+] [-] beala|1 year ago|reply
To handle decoding and the overhead of moving bits around, it uses a dual-buffer DMA approach. It reads data from an SD card, running the decoding routine on the main CPU. The decoded samples are written into one of two buffers. While one buffer is being written to, the other is read via DMA and sent to the PWM buffer (more on PWM audio here: https://x.com/beala/status/1826147833168408738). Because DMA is used, data transfer can occur in parallel with decoding, without involving the main processor. When the bits have all been written to the PWM buffer, an interrupt triggers a buffer swap, and the process repeats.
I'm leaving out many details. Tuning the pwm speed to achieve correct playback speed was quite an adventure. And when I needed to increase the clock speed to play higher sample rates, this caused I/O errors with the SD card that I never managed to solve. Although I learned a lot from this process, I ultimately opted to use an MP3 module in my final build: https://store-usa.arduino.cc/products/dfplayer-a-mini-mp3-pl...
This is probably routine for an experienced embedded engineer, but it was quite a learning experience for me!
[+] [-] mlyle|1 year ago|reply
Presumably if a RP2040 could almost do it, a RP2350 could do it no problem. Unless you were limited by PWM speed. Even then you might be able to accept less resolution and filter and dither.
[+] [-] JKCalhoun|1 year ago|reply
[+] [-] bschwindHN|1 year ago|reply
I have a Rust crate for outputting I2S data, or retrieving it from something like a mic or ADC. You can hook it up to DMA and make your audio go brrrr
https://github.com/bschwind/rp2040-i2s
[+] [-] bschwindHN|1 year ago|reply
https://github.com/bschwind/sleep-machine/blob/main/src/main...
[+] [-] hippospark|1 year ago|reply
[+] [-] TacticalCoder|1 year ago|reply
[deleted]
[+] [-] 34679|1 year ago|reply
Maybe it's my fault for not making it to page 1357 (!) of the datasheet, where the issue is described as "RP2350-E9".
https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.p...
[+] [-] slabity|1 year ago|reply
They don't work at all? How the heck did something that important get past testing?
Guess I'm not moving on from the RP2040 anytime soon...
[+] [-] wilted-iris|1 year ago|reply
[+] [-] RicoElectrico|1 year ago|reply
[+] [-] stavros|1 year ago|reply
[+] [-] nerdralph|1 year ago|reply
[+] [-] boznz|1 year ago|reply
[+] [-] atoav|1 year ago|reply
It has thre DIP switches that set the mode, you can use them to set the playback modes, one of which is serial control, meaning you can easily beef this up using a microcontroller.
[+] [-] schobi|1 year ago|reply
I built motion activated playback speakers - good for hiding them in the bushes on halloween.
[+] [-] JansjoFromIkea|1 year ago|reply
[+] [-] stavros|1 year ago|reply
[+] [-] hoc|1 year ago|reply
Great that the author chose one and finished (and published) the project instead of stopping at that annoying junction :)
[+] [-] mordae|1 year ago|reply
If you want to smooth the things out because you target a line input, simple LC filter will work just fine here.
Like this: https://shorturl.at/z3eYG (link to Falstad's Analog Filter Tool)
If you want to get better bit depth, you should use PDM instead of PWM.
[+] [-] josteink|1 year ago|reply
Not to talk down anyone’s hobby project, but that kinda limits the appeal for most other people I would think?
[+] [-] relwin|1 year ago|reply
[+] [-] duped|1 year ago|reply
[+] [-] smitelli|1 year ago|reply
[+] [-] sandreas|1 year ago|reply
So here are my results up until now:
- The best device I found is a LicheeRV Nano[1] - also used in NanoKVM.
- It has enough CPU+RAM to support more complex formats like FLAC while still being very small.
- It has a full featured MIPI 31-pin / 6-pin touch display port, although I could not find any available display smaller than 7" to order without hassle (there is an unavailable official 3" though[4]).
- It also has USB-C, where it should be possible to use one of these external USB-C to audiojack adapters with mic support.
- Some of these adapters should support headset control buttons out of the box (via kernel usbsound) - on my notebook this works flawlessly.
- There also is a full featured configurable buildroot[2], so, less work to get started with an optimized build.
- Combining a TP4057 battery charger and a battery gauge (MAX17043) you should be able to support a 1200mah battery, read out battery status via I2C and recharge within a < 3" 3D printed case.
- All you would have to do is create a custom buildroot and a nice user interface via LVGL, they already have a music player sample on there samples listing[3]. Unfortunately this is where the workload is huge ;)
1: https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.h...
2: https://github.com/sipeed/LicheeRV-Nano-Build
3: https://github.com/lvgl/lv_demos/tree/master/src/lv_demo_mus...
4: https://aliexpress.com/item/1005006519668532.html
[+] [-] dangelov|1 year ago|reply
[+] [-] slig|1 year ago|reply
[+] [-] BizarroLand|1 year ago|reply
[+] [-] tyre|1 year ago|reply
https://github.com/mikebrady/shairport-sync
[+] [-] oliwarner|1 year ago|reply
[+] [-] kali_00|1 year ago|reply
[deleted]