We don't need a DAC on the ESP32-S3
atomic14.substack.com
atomic14.substack.com
The only external components were a simple passive RC filter.
https://hackaday.com/2005/10/25/audio-output-from-a-serial-p...
(Looks like somebody mirrored it to github at https://github.com/koniu/ttyplay)
Aparently very high quality audio.
https://www.reddit.com/r/minidisc/s/OTHQJwSt92
They used ΔΣ as their logo.
Nope, that's what they're actually doing. Congrats, you've built a very simple external DAC.
Low-effort clickbait? Or an innocent misunderstanding by someone who thinks DACs have to be expensive?
Probably the latter. Things like Arduino and cheap ESP modules from china have made electronics vastly more accessible than they were previously. Given that, it makes sense that somebody wouldn't really understand _how_ a DAC works but would understand what one does, what it's used for and that the datasheet for $currentModule says there is none present.
People like me. I think I can call myself tolerably good at programming, but I can easily tell I'm much more newb at EE and I can really only operate with things that have clearly defined outputs that match up to some other input. Where you may see trivial conversions you could bash together in your sleep, I see an output that doesn't match the input and don't immediately know where to go with that.
In my case, I'm able to follow the post just fine, but if I had to put that circuit together from scratch from first principles I'd be looking at weeks of learning more about EE. And as a result, as I am blundering about an unfamiliar landscape in some personal projects I've got going on, I appreciate posts like this.
But when I opened up the post and saw a 2nd order (probably) Sallen-key (or is this a MFB? I always get my topologies confused...) with a full-bore OpAmp and capacitors up the wazoo... erm... yeah, they're basically hand-building a DAC at this point.
---------------
A lot of stuff is wishy-washy definitions anyway. What's the difference from an analog-comparator and a ADC anyway? An analog-comparator is just a 1-bit ADC after all.
So a lot of "what is a DAC" exactly is up to opinion around the edges. But if you've got op-amps and signal conditioning, you're getting pretty darn close to "proper DAC" except you know, not as good (ie: cheap, fast, or simple) as a proper professional solution.
-------
EDIT: Reread blogpost. It looks like the RC-filter is in fact, being used. The Espressif docs __suggest__ the OpAmp based 2nd-order filter, but the blogpost is strictly with the simple 1st order RC-filter.
So yeah, I'd say that RC-filter is "not a DAC", due to being too simple. (It functions as a DAC in this case, but we got to draw the line somewhere).
I would claim that 70% of software engineers would love taking an electronics course. It's like programing, with electrons.
I suspect the next link in the cycle will be how you can make music on an old AM radio, if you attach a length of unterminated wire instead of a cap!
I very much think all software engineers should take an electronics course. At least an introductory one. Knowing how things work will improve your code, and will give you an alternate way of thinking about programming problems.
But I'll admit my bias: I came to programming by way of a digital electronics course as a child. Since I was a child of a poor family, I couldn't afford to actually do electronics projects at home, though (this was well before everything got so inexpensive), and shifted to programming because you could do that for free if you had access to a computer.
On the other hand, FPGAs and really fast microcontrollers are a thing now, so you could probably get a chip with a nice internal ADC, digitize the output voltage, and use an actual computer program to drive the H bridges, thus making an extremely non-cost-effective class D amplifier :)
Issue with doing what I tried to do and FPGAs is that the overall architecture of this kind of DSP is perfect example of a thing that does not match the FPGA architecture. It boils down to ridiculously long shift register, few bits per tap of parameter data and reducing tree for the result, ie. most of that is ridiculous amount of 1bit SRAM cells.
And well, in the end I realized that idea, in not-even-that-fast-for-the-time ARM11TDMI and software and 24b samples at 96kSps (both of which is realistically a total overkill for this application), but without the DSD input (in theory the code that produced the output can be inverted and used to convert DSD to some sane representation, but well, I did not really care)
Those micros were much weaker than the ESP, so the audio was all synthesized with a roughly nintendo-parity waveform selection rather than samples. In fact the earliest version was on an attiny85 which had no hardware multiplication, so.. lots of fixed point arithmetic and lookup tables were involved.
My pet project was DuinoTune, which would convert tracker-music into ready-to-compile code.
https://www.youtube.com/watch?v=rFqvPWnolfY
This sounds like tricks demo scene coders use to coax sampled audio out of unlikely things like apple IIs and XT-era hardware.
Here's a blog post[1] showing how to do something very similar with the Raspberry Pi Pico, which also doesn't have a DAC. I wrote a very simple 4-channel MOD player[2] for the Pico using his sound output code.
[1] https://gregchadwick.co.uk/blog/playing-with-the-pico-pt3/
https://gist.github.com/phkahler/1ddddb79fc57072c4269fdd6716...
I just drop that in my 20khz isr and point to the GPIO with the LED.
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 0 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 1 0 1 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
1.0035971164599362
0.9085335060080786
0.9035432831636958
0.7979082616868238
0.7167128607342428
0.5957569676023409
0.49808942875852646
0.4009797804151446
0.3308973662512045
0.1857546947996519
0.07410762115348818
Here's a plot of the original data and low pass filtered: https://imgur.com/a/kCxA7XKUmmmm...
What happened here? I know that low-pass filters can "ring" and therefore have some gains in some cases. But any simple FIR digital filter won't ring like this and end up with a value above 1.00
What filter did you (erm, ChatGPT) decide to use that (1 1 1 1 1 1 1 1 0 1 1 1 1) or so averaged out to a value above 1.00 ?
All in constant execution time too!
For an ADC, you can get back useful bits via Oversampling & Decimation, at the expense of bandwidth.
For most use cases PWM or PDM is sufficient. For more complex cases you are probably looking for some very specific performance characteristics and an external IC probably makes more sense.
If the built in vcr stinks or doesn't quite meet expectations you're either stuck with its subpar performance, or with the sunk cost of an unused or unusable feature.
Many people might want an audio quality dac.. but 8 bit? 16? 24? Or maybe 4 bit is fine but you need 12 of them... Best to just have good peripheral support.
I guess you can't really trust the raw PDM output from an MCU which might not be very well designed or shaped.
Maybe better to convert back to analog and then apply whatever secret sauce you have to make the class D amplifier work really well.
Here’s a white paper of his specifically about direct PWM amplification.
https://www.researchgate.net/publication/242013327_All_ampli...
Very high fidelity sigma delta DACs are filtered PDM, they just use high modulation rate and good filters.
However, having an actual on-board DAC is best in general. You get better results and a lower parts count.
I'm not sure which is the hard part you're referring to- implementing the amplifier itself, or the board around it. I don't think an amateur would want to build their own class-D from raw components except for pedagogical purposes.
(i've been pretty happy with the results, I used the board to drive a couple speakers and the amplifier is not the first thing I'd fix to improve the audio quality.
Besides, I don't think it actually uses substantially more CPU than an external DAC. You'd be feeding a DMA buffer into the I2S peripheral either way. If you precompute the PDM waveform from the audio sample it's essentially free. Using a LUT or even computing it realtime should only take a dozen or so cycles per sample, at 44.1kHz.
Considering that the ESP32-S3 has two cores running at 240MHz, even taking an excessive 500 cycles per sample would only be a 5% CPU load.
> has two cores running at 240MHz
Yeah ok that is manageable.
So you can get 100 (bad) analog outputs out of an FPGA. There has to be an application for that. :D
I went back and played it on my Apple //e, it holds up pretty well. The source code for the sequel was released by the authors widow, around 2004. https://archive.org/details/BeyondCastleWolfenstein_source
Oh, now I see it's just decompiled, not the original source. But you'd still be able to find the data and code for the audio.