Hi Kristian, why don't you try Pulse Density Modulation or PDM? I know there is hardware within a MCU that performs PWM, and I don't know any MCU that outputs PDM via hardware, but the algorithm is as easy so that can be emulated using timers interrupts. I will explain the algorithm using words because there is chance that if i write pseudocode, my comment would be censored by yt. The general algo for PWM is: -Let CNT be a counter var that increases from 0 to N where N is the PWM period. Typically N is a power of two. Let D be the target sample data. -PWM output is 0 when CNT is below D, elss is 1. -CNT resets to 0 when the cycle finishes and D is updated to the next sample. The algo for PDM is not much complicated. Let be ACC an accumulator with an arbitrary value, but for convencience, the start value is 0. Then for every increment in CNT, D is added to ACC. If ACC is above N, output is 1 and N is substracted to ACC, else output 0. When CNT reaches N, it becomes 0 and D is updated. No other action required for ACC. This way, a 50 percent duty PWM something like 0000000011111111 while in PDM is 010101010101010. This is like PWM but ones and zeros are interleaved, thus filtering is much easy because energy of the signal is concentrated in high frequencies.
@mariobv9474 ай бұрын
Forgot to say that if N is a power of two, then PDM is even easier. You add D to ACC in every step, and let's say that you have a PDM of N equal to 2 to the 12th power. Then in each step you output the 12th bit of ACC and after that you reset such bit in the ACC variable. In PDM, linear interpolation is trivial. Let ∆ the difference of current sample and the next sample in the sequence. Then you shift D so that you multiply the value by N. If 12 bits, then you shift D by 12 at first. Then, for every PDM step you add ∆ to D, and D to ACC. Instead of outputting and resetting bit 12 of ACC, you output and then reset bit 24 because D is shifted 12 places.
@zexusdexus41934 ай бұрын
Does CNT increase from 0 to N or from 0 to N-1 ?
@mariobv9474 ай бұрын
@@zexusdexus4193 For both PWM and PDM, the counter counts up to N because the analog range of the output includes Vcc (that is, N+1 values from 0 to Vcc) while in a regular DAC the range goes from 0 to N-1 because the output can't reach Vcc as there is always a resistor tied to ground. Thus the Max value of the output in a resistor DAC is Vcc*(1-1/N). However, for large N it doesn't matter so much.
4 ай бұрын
It sounds interesting and I get it in denser values. However 0000000000000001 will still be a large gap won’t it?. So in those edge cases you still need the rc filter to be able to smooth this gap. Or am I thinking wrong? Also. Since this can’t be done in hardware it would be quite code intensive. ;) But a cool idea and something I haven’t heard of before thanks! :)
@mariobv9474 ай бұрын
Yes.... And not. The low frequency artifact's energy for edge values such as 0000000000000001 or 1111111111111110 is the same as in 1010101010101011 and it's close to the quantize noise, so the RC filter just have to lower those artifacts below the quantize noise level. But... In PDM it is really easy to dither such artifacts without losing bits resolution. Do you remember that i said that, for each cycle, ACC can have an arbitrary initial value but for convenience could be 0? Such initial value controls where the pulses are spread throught the full cycle, although the amount of pulses doesn't change. Let's say that you have a stream of samples of the same value (so you have a DC level) such as 0x0001. If you randomize the initial value of ACC in each cycle, you get a sequence at the output like this: 0000000000000001 0001000000000000 0000000010000000 0000000000100000 0100000000000000... Here the sample cycle tone disappears even being below 20kHz. You are right that implementing this in code can be very "runtime consuming", but the ISR is so simple that can be done with just a few assembly lines, and modern MCUs such as the family STM32G0xx... Have a fast TRNG hardware, so the dithering comes almost free.