arduino-libraries / Arduino_AdvancedAnalog

Advanced Analog Library
GNU Lesser General Public License v2.1
7 stars 5 forks source link

Programming >2M Samples/sec on DAC seems to cause Giga board to hang #32

Closed jmdodd95682 closed 1 year ago

jmdodd95682 commented 1 year ago

I've been able to reproduce this a couple of times. If I take the example program for generating a sinewave and change the frequency to 48000*lut_size (about 3M samples per second), the program compiles and uploads with no error. About two seconds later the board disconnects from the USB serial port and is no longer recognizable by my PC. I have to double-tap the reset and reload a program in order to get out of this. I see no "SOS" pattern on the LED. Just silence.

What is the maximum samples per second for the DAC outputs? Obviously for audio 2M samples per second is plenty. I was just wondering. If there is a hard limit, it might be good to either put a check in the code for values > 2M or at least something in the documentations saying "Don't do that".

I'm including the failing code below, but its just the sinewave example with the frequency increased to 48000*lut_size.

// This example outputs a 32KHz sine wave on A12/DAC1.
#include <Arduino_AdvancedAnalog.h>

AdvancedDAC dac1(A13);

uint16_t lut[] = {
    0x0800,0x08c8,0x098f,0x0a52,0x0b0f,0x0bc5,0x0c71,0x0d12,0x0da7,0x0e2e,0x0ea6,0x0f0d,0x0f63,0x0fa7,0x0fd8,0x0ff5,
    0x0fff,0x0ff5,0x0fd8,0x0fa7,0x0f63,0x0f0d,0x0ea6,0x0e2e,0x0da7,0x0d12,0x0c71,0x0bc5,0x0b0f,0x0a52,0x098f,0x08c8,
    0x0800,0x0737,0x0670,0x05ad,0x04f0,0x043a,0x038e,0x02ed,0x0258,0x01d1,0x0159,0x00f2,0x009c,0x0058,0x0027,0x000a,
    0x0000,0x000a,0x0027,0x0058,0x009c,0x00f2,0x0159,0x01d1,0x0258,0x02ed,0x038e,0x043a,0x04f0,0x05ad,0x0670,0x0737
};

static size_t lut_size = sizeof(lut) / sizeof(lut[0]);

void setup() {
    Serial.begin(9600);
    if (!dac1.begin(AN_RESOLUTION_12, 48000 * lut_size, 64, 128)) {
        Serial.println("Failed to start DAC1 !");
        while (1);
    }
}

void loop() {
    static size_t lut_offs = 0;
    if (dac1.available()) {
        // Get a free buffer for writing.
        SampleBuffer buf = dac1.dequeue();
        // Write data to buffer.
        for (size_t i=0; i<buf.size(); i++, lut_offs++) {
            buf[i] =  lut[lut_offs % lut_size];
        }
        // Write the buffer to DAC.
        dac1.write(buf);
    }
}
aentinger commented 1 year ago

Hi @iabdalkader :coffee: :wave: can you please perhaps take a look at this? :pray: :bow:

iabdalkader commented 1 year ago

What is the maximum samples per second for the DAC outputs?

The DAC can run pretty fast, maybe up to 40 Msps, currently it might be limited by the max frequency we can configure the timer for (timer needs to be configurable from very low frequencies to high frequencies) and possibly some other factors, but I tried up to 200KHz (~12 Msps) for example and it works fine. I'm not sure what the issue is, I can't reproduce it consistently, but yes I can confirm there seems to be some issue, will look into it.

jmdodd95682 commented 1 year ago

Thanks. I've noticed a number of funny behaviors playing around with it. Sometimes the DAC stops working and I have to power cycle the board to get it back. Could all be an MBED OS issue.

Get Outlook for Androidhttps://aka.ms/AAb9ysg


From: Ibrahim Abdelkader @.> Sent: Monday, March 27, 2023 6:43:07 AM To: arduino-libraries/Arduino_AdvancedAnalog @.> Cc: jmdodd95682 @.>; Author @.> Subject: Re: [arduino-libraries/Arduino_AdvancedAnalog] Programming >2M Samples/sec on DAC seems to cause Giga board to hang (Issue #32)

What is the maximum samples per second for the DAC outputs?

The DAC can run pretty fast, maybe up to 40 Mspshttps://www.st.com/resource/en/application_note/an4566-extending-the-dac-performance-of-stm32-microcontrollers-stmicroelectronics.pdf, currently it might be limited by the max frequency we can configure the timer for (timer needs to be configurable from very low frequencies to high frequencies) and possibly some other factors, but I tried up to 200KHz (~12 Msps) for example and it works fine. I'm not sure what the issue is, I can't reproduce it consistently, but yes I can confirm there seems to be some issue, will look into it.

— Reply to this email directly, view it on GitHubhttps://github.com/arduino-libraries/Arduino_AdvancedAnalog/issues/32#issuecomment-1484915260, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ALCX2KF4QTMDA44IXR325Z3W6FVLXANCNFSM6AAAAAAWBTZ77Q. You are receiving this because you authored the thread.Message ID: @.***>

iabdalkader commented 1 year ago

Thanks. I've noticed a number of funny behaviors playing around with it. Sometimes the DAC stops working and I have to power cycle the board to get it back. Could all be an MBED OS issue.

I think it may have something to do with the read/write queues getting corrupted when DAC stops/restarts, the higher frequency triggers that issue because it's more likely to underrun and stop the DAC. I'm still investigating but I think the queues are not thread-safe the way they are used, we switched to those queues to save some memory but seem they're causing trouble.

jmdodd95682 commented 1 year ago

That would make a lot of sense. It seemed much more unstable at high rates.

Get Outlook for Androidhttps://aka.ms/AAb9ysg


From: Ibrahim Abdelkader @.> Sent: Wednesday, March 29, 2023 2:55:13 PM To: arduino-libraries/Arduino_AdvancedAnalog @.> Cc: jmdodd95682 @.>; Author @.> Subject: Re: [arduino-libraries/Arduino_AdvancedAnalog] Programming >2M Samples/sec on DAC seems to cause Giga board to hang (Issue #32)

Thanks. I've noticed a number of funny behaviors playing around with it. Sometimes the DAC stops working and I have to power cycle the board to get it back. Could all be an MBED OS issue.

I think it may have something to do with the read/write queues getting corrupted when DAC stops/restarts, the higher frequency triggers that issue because it's more likely to underrun and stop the DAC. I'm still investigating but I think the queues are not thread-safe the way they are used, we switched to those queues to save some memory but seem they're causing trouble.

— Reply to this email directly, view it on GitHubhttps://github.com/arduino-libraries/Arduino_AdvancedAnalog/issues/32#issuecomment-1489134706, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ALCX2KF4CNZ3HSQMS5P7HODW6SARDANCNFSM6AAAAAAWBTZ77Q. You are receiving this because you authored the thread.Message ID: @.***>

jmdodd95682 commented 1 year ago

One other thing that I had to realize. Even though the sample rate can be 2M samp/sec or higher on the DAC, the resulting analog signal really cannot have a higher frequency component than about 40KHz. I tried 64KHz output sinewave (I doubled the frequency of the lut[] data so that it was two periods in 64 samples) and the output is very bad. It does not look much like a sinewave. This makes sense to me since the DAC outputs are intended for audio which is only 20KHz. This is probably due to limitations on the slew-rate of the DAC analog outputs. So, 2M sample/sec is pretty much overkill. That's about 100X oversampling for a full audio spectrum. You really only need about 8X for high-quality audio reproduction. So, I'll probably keep my sample rate low. Perhaps 128KHz or 160KHz.

Its worth considering if you want to limit the sample rate in the dac.begin() routine to something like 250K Samp/sec. This might improve stability.

jmdodd95682 commented 1 year ago

I take it back. Ignore my previous comment. I found a bug in my sketch (I was not keeping the input to 12-bits). I can actually get an analog output which is 128KHz. I've stopped testing above that because that is way higher than I need. I could do full Dolby Surround with a single DAC channel. That's insanely good. Can't think how I would use that, but wow.

iabdalkader commented 1 year ago

@jmdodd95682 I fixed all of the memory issues, and some other edge cases, and it seems to be working fine now. I've also updated some of the examples, the waveform generator can now output 1KHz -> 128KHz, the sine wave example works up to 160KHz, it's probably possible to get 256KHz but we're not queuing buffers fast enough, maybe if the SDRAM is used to allocate large buffers it would work. I'm still testing things then will push the changes, but I'm attaching the library in its current state if you want to test it.

Arduino_AdvancedAnalog.zip

Note if you set a higher frequency, and add a very short delay maybe 1ms, and have a scope of course, you can see that the DAC outputs, stops, then restarts, this is just to confirm things are working as they should.

jmdodd95682 commented 1 year ago

I’ve downloaded and am running the ADC and DAC at 96Khz full resolution with no crashes or errors. Looking good.