-
-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use DMA for ADC and DAC #85
base: master
Are you sure you want to change the base?
Conversation
Thanks a lot for this interesting pull request! I am currently very busy, but I plan to have an AIOC maintenance week at end of September. Lower noise floor sounds nice. How much can you reduce the ppm errors on some sample rates? From what I can tell, all sample rates can be achieved perfectly, after downsampling? |
I might plan to add the same thing to the DAC side also. The only error left is probably only the error of the crystal. |
Some notes while implementing this: Setting the DAC DMA buffer too large results in the usb audio buffer in The sigma-delta modulator might be quite expensive for the CPU. At 480ksps, we have around 150 clock cycles per sample. The most expensive part is the saturating addition. |
I have had a look at this and while I like the idea, I am not sure if this is too much added complexity while I am still not sure about the benefit. Lower sampling noise is nice, but usually the radio channel trumps the noise floor by a huge margin, when the squelch opens. The errors in the sample rate have not yet resulted in any complaints, so not sure about that either. I would like to keep this here, because I imagine it was a lot of work, and it may be that the situation arises in the future where this code could come in handy. |
Thanks for looking at this! I have been using this code since oversampling eliminated a weird ~1KHz tone on both transmit and receive side. Receiving a clean signal will result in an additional 1KHz tone received in the computer and transmitting will cause a 1KHz tone to be transmitted out in the RF signal. I am not sure what causes it, but it is probably the microcontroller since oversampling attenuates it by a lot. As for the noise floor, I have noticed a increase in SNR for voice signals after doing ADC oversampling, and better audio quality during transmit. This is probably because due to the code we effectively get a 16bit ADC and DAC which is what the computer will provide in the usb audio stream. One way to reduce complexity will be to do away with the fractional side and simply do integer rate, that would remove a lot of the code to keep track of fractional samples. |
I was doing some more work on the analog part of the AIOC (see PR #93) and was remembered to this. After some time I have passed, I reread your text with a clear mind. The 1kHz tone is very probably from the USB interface (and it was even more noticeable when I had only a single 3.3V regulator for analog and digital power). I think (not sure though) the reason, why it disappears with the oversampling is due to the fractional decimator. I might be more inclined to have a look at a simpler integer decimation solution. What's would be the drawback? Your notes about the noise made me curious. I could imagine producing some testing firmwares with the oversampling included and let a group of people test this to see if the effort for this is warranted. If it is, it might be interesting to implement this. |
@rhgndf can you supply a .bin file that I can flash with dfu-util? I would like to measure the performance gain. |
I think oversampling on the ADC side sort of 'smooths' out its internal noise. For the DAC side, the sample frequently changes, which also does something similar. This is my guess anyway, not too sure also.
The biggest drawback is that the sample rate becomes much more inaccurate. Compare 2.4MHz/54 and 72MHz/1632. This is the main reason why I implemented the fractional decimator. The code can be made simpler if the fractional scaling of the single sample when the value changes is removed. Another approach would be to change the ADC frequency and adjust the divisors.
You could try using a spectrum analyzer and compare the peaks with the noise floor. I used gnuradio's frequency and waterfall sink. Github doesn't allow grc extension files so I put it in a zip: analyzer.zip
If you use check the waterfall of the received audio, you will see it is still there but very very weak which makes it inaudible. |
@das-Iro I have put them into the releases page. I have used the v1.2.0 successfully, but haven't tested the v1.3.0 as much. |
Thanks a bunch for testing..I will have a closer look next time I have some spare time. Just to note, it is not surprising that you can get better ADC resolution (i.e. less quantization noise) with oversampling. My argument earlier was, if this method actually brings any improvement in the noise if you are actually using a radio. This would only be the case if the noise floor of the radio is actually better than the AIOC quantization noise. Still, any improvement is nice and if it comes essentially for free, it is even better. Feel free to try eliminating the USB SOF disturbance. I have sunk a lot of time into this in the very beginning and the only thing I found that actually helped was to provide AVDD and DVDD from two separate regulators. In my m memory it should actually hide in the noise floor of the radio. |
Hehe, okay, well played 😁
Did I really put the led frequency right in the middle of the audio range? Can't believe it, will add it to my to-do list |
This is probably the CPU waking up during the DMA interrupt to do work since it interrupts every half buffer and the buffer size is 256: 2.4MHz/128 = 18750Hz Reducing the buffer size to 128 should help, but I think we need to check whether there can be missed interrupts when the rate is higher. |
Uses the DMA with the ADC to get 2.4MSPS for oversampling and DAC at 480KSPS. I observed a lower noise floor with higher sampling rate for ADC and a reduced 1KHz tone and lower noise on the DAC. This also reduces the ppm error for non integer decimation ratios.
The 2.4MSPS for ADC is obtained by: PLL clock 72MHz, ADC prescaler 2, sampling time 2.5 clock cycles, total 15 clock cycle per sample.
The 480KSPS for DAC is obtained by: PLL clock 72MHz, TIM6 divides by 150.
Its probably possible to get to 4.8MSPS. That would require 15 clock cycles per sample at 72MHz.
This runs per sample:
https://github.com/rhgndf/AIOC/blob/f95b47d4669d32a8a14b0feb2888d116414072de/stm32/aioc-fw/Src/audio_dsp.c#L52
and compiles to two instructions, probably with the extra code around it its 3-4 instructions per sample, which should run fast enough