Skip to content

Support synchronized ADC capture #55

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

Closed

Conversation

jmdodd95682
Copy link
Contributor

@jmdodd95682 jmdodd95682 commented Feb 6, 2024

The begin() function takes about 106us to execute. If you're trying to start two ADCs, this will mean the first ADC will already be capturing for at least 106us when you execute the ADC.begin() on the second one.

The changes proposed here allow the following semantics:

adc1.ready(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers);
adc2.ready(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers);

adc1.start(sample_rate);
adc2.start(sample_rate);

This reduces the skew between the two captures to about 4us.

ready() and start() are just the begin() function split into two pieces so you can setup the DMA and ADC without starting until later.
ready() and start() are just the begin() function split into two pieces.  ready() does everything except start the ADC capture. 

clear() is calling the DMABufferPool routine to flush out anything in the DMA buffers.
@CLAassistant
Copy link

CLAassistant commented Feb 6, 2024

CLA assistant check
All committers have signed the CLA.

Copy link

github-actions bot commented Feb 6, 2024

Memory usage change @ a76e0e4

Board flash % RAM for global variables %
arduino:mbed_giga:giga 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
Click for full report table
Board examples/Advanced/ADC_Multi
flash
% examples/Advanced/ADC_Multi
RAM for global variables
% examples/Advanced/ADC_Multi_Channel
flash
% examples/Advanced/ADC_Multi_Channel
RAM for global variables
% examples/Advanced/ADC_Multi_Channel_Dynamic
flash
% examples/Advanced/ADC_Multi_Channel_Dynamic
RAM for global variables
% examples/Advanced/ADC_Multi_To_DAC
flash
% examples/Advanced/ADC_Multi_To_DAC
RAM for global variables
% examples/Advanced/ADC_Serial_Plotter
flash
% examples/Advanced/ADC_Serial_Plotter
RAM for global variables
% examples/Advanced/ADC_To_DAC
flash
% examples/Advanced/ADC_To_DAC
RAM for global variables
% examples/Advanced/DAC_One_Channel
flash
% examples/Advanced/DAC_One_Channel
RAM for global variables
% examples/Advanced/DAC_Sine_wave
flash
% examples/Advanced/DAC_Sine_wave
RAM for global variables
% examples/Advanced/DAC_Two_Channels
flash
% examples/Advanced/DAC_Two_Channels
RAM for global variables
% examples/Beginner/Audio_Playback
flash
% examples/Beginner/Audio_Playback
RAM for global variables
% examples/Beginner/Waveform_Generator
flash
% examples/Beginner/Waveform_Generator
RAM for global variables
%
arduino:mbed_giga:giga 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
Click for full report CSV
Board,examples/Advanced/ADC_Multi<br>flash,%,examples/Advanced/ADC_Multi<br>RAM for global variables,%,examples/Advanced/ADC_Multi_Channel<br>flash,%,examples/Advanced/ADC_Multi_Channel<br>RAM for global variables,%,examples/Advanced/ADC_Multi_Channel_Dynamic<br>flash,%,examples/Advanced/ADC_Multi_Channel_Dynamic<br>RAM for global variables,%,examples/Advanced/ADC_Multi_To_DAC<br>flash,%,examples/Advanced/ADC_Multi_To_DAC<br>RAM for global variables,%,examples/Advanced/ADC_Serial_Plotter<br>flash,%,examples/Advanced/ADC_Serial_Plotter<br>RAM for global variables,%,examples/Advanced/ADC_To_DAC<br>flash,%,examples/Advanced/ADC_To_DAC<br>RAM for global variables,%,examples/Advanced/DAC_One_Channel<br>flash,%,examples/Advanced/DAC_One_Channel<br>RAM for global variables,%,examples/Advanced/DAC_Sine_wave<br>flash,%,examples/Advanced/DAC_Sine_wave<br>RAM for global variables,%,examples/Advanced/DAC_Two_Channels<br>flash,%,examples/Advanced/DAC_Two_Channels<br>RAM for global variables,%,examples/Beginner/Audio_Playback<br>flash,%,examples/Beginner/Audio_Playback<br>RAM for global variables,%,examples/Beginner/Waveform_Generator<br>flash,%,examples/Beginner/Waveform_Generator<br>RAM for global variables,%
arduino:mbed_giga:giga,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

@facchinm
Copy link
Collaborator

facchinm commented Feb 6, 2024

Hi @jmdodd95682 ,
if start() and then ready() is equivalent to begin() I'd change the PR to do that in order to avoid code duplication.

Copy link
Collaborator

@facchinm facchinm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change begin() to call start() and then ready() (if equivalent)

@per1234 per1234 changed the title Jmdodd95682 patch 1 Support synchronized ADC capture Feb 6, 2024
@per1234 per1234 added type: enhancement Proposed improvement topic: code Related to content of the project itself labels Feb 6, 2024
@per1234 per1234 linked an issue Feb 6, 2024 that may be closed by this pull request
@leonardocavagnis
Copy link
Contributor

leonardocavagnis commented Feb 6, 2024

I'd change begin() to call start() and then ready() (if equivalent)

My proposal:

  • The current begin() function has been removed.
  • The ready() function will be renamed to begin().
  • The start() function has been added. There is no need to pass sample_rate as input; it could become a private object variable initialized by the begin() function.

With these changes, you would use begin() to configure the ADC and start() to initiate the conversion process.

@facchinm @iabdalkader Sounds good for you?
Please, @iabdalkader could you take a look and give a spin?

Thanks

@iabdalkader
Copy link
Collaborator

I can take a look at the issue and PR next week. In the meantime @jmdodd95682 please sign the CLA.

@jmdodd95682
Copy link
Contributor Author

jmdodd95682 commented Feb 6, 2024

Signed the CLA.

I agree with not having code duplication. I didn't want to just remove begin() if there was some other purpose (e.g. ease of use).

So we just have start() followed by begin() to do ADC capture. Do you want me to make those changes to my branch?

@jmdodd95682
Copy link
Contributor Author

jmdodd95682 commented Feb 7, 2024

I had another thought. Rather than getting rid of the existing begin() we should just keep it for backward compatibility with people's existing code. Instead, add a new bool flag to begin with a default of false. When this flag is set true, it does all the setup, but does not start. If the flag is false, it does the legacy behavior of doing the setup and start.

To avoid duplicate code, the begin() will call the new start() routine when the flag is false. So, we get full backward compatibility and get the new functionality with no duplicated code.

@leonardocavagnis
Copy link
Contributor

I had another thought. Rather than getting rid of the existing begin() we should just keep it for backward compatibility with people's existing code. Instead, add a new bool flag to begin with a default of false. When this flag is set true, it does all the setup, but does not start. If the flag is false, it does the legacy behavior of doing the setup and start.

To avoid duplicate code, the begin() will call the new start() routine when the flag is false. So, we get full backward compatibility and get the new functionality with no duplicated code.

Your proposal sounds good!
Do the changes and add commits to this branch

Added bool noStart with default of false to allow backward compatibility with existing code.
@jmdodd95682
Copy link
Contributor Author

Made proposed changes. Tested on my application, works as expected.

Copy link

github-actions bot commented Feb 7, 2024

Memory usage change @ 13e9f0e

Board flash % RAM for global variables %
arduino:mbed_giga:giga ❔ -64 - +64 -0.0 - 0.0 0 - 0 0.0 - 0.0
Click for full report table
Board examples/Advanced/ADC_Multi
flash
% examples/Advanced/ADC_Multi
RAM for global variables
% examples/Advanced/ADC_Multi_Channel
flash
% examples/Advanced/ADC_Multi_Channel
RAM for global variables
% examples/Advanced/ADC_Multi_Channel_Dynamic
flash
% examples/Advanced/ADC_Multi_Channel_Dynamic
RAM for global variables
% examples/Advanced/ADC_Multi_To_DAC
flash
% examples/Advanced/ADC_Multi_To_DAC
RAM for global variables
% examples/Advanced/ADC_Serial_Plotter
flash
% examples/Advanced/ADC_Serial_Plotter
RAM for global variables
% examples/Advanced/ADC_To_DAC
flash
% examples/Advanced/ADC_To_DAC
RAM for global variables
% examples/Advanced/DAC_One_Channel
flash
% examples/Advanced/DAC_One_Channel
RAM for global variables
% examples/Advanced/DAC_Sine_wave
flash
% examples/Advanced/DAC_Sine_wave
RAM for global variables
% examples/Advanced/DAC_Two_Channels
flash
% examples/Advanced/DAC_Two_Channels
RAM for global variables
% examples/Beginner/Audio_Playback
flash
% examples/Beginner/Audio_Playback
RAM for global variables
% examples/Beginner/Waveform_Generator
flash
% examples/Beginner/Waveform_Generator
RAM for global variables
%
arduino:mbed_giga:giga -64 -0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 64 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
Click for full report CSV
Board,examples/Advanced/ADC_Multi<br>flash,%,examples/Advanced/ADC_Multi<br>RAM for global variables,%,examples/Advanced/ADC_Multi_Channel<br>flash,%,examples/Advanced/ADC_Multi_Channel<br>RAM for global variables,%,examples/Advanced/ADC_Multi_Channel_Dynamic<br>flash,%,examples/Advanced/ADC_Multi_Channel_Dynamic<br>RAM for global variables,%,examples/Advanced/ADC_Multi_To_DAC<br>flash,%,examples/Advanced/ADC_Multi_To_DAC<br>RAM for global variables,%,examples/Advanced/ADC_Serial_Plotter<br>flash,%,examples/Advanced/ADC_Serial_Plotter<br>RAM for global variables,%,examples/Advanced/ADC_To_DAC<br>flash,%,examples/Advanced/ADC_To_DAC<br>RAM for global variables,%,examples/Advanced/DAC_One_Channel<br>flash,%,examples/Advanced/DAC_One_Channel<br>RAM for global variables,%,examples/Advanced/DAC_Sine_wave<br>flash,%,examples/Advanced/DAC_Sine_wave<br>RAM for global variables,%,examples/Advanced/DAC_Two_Channels<br>flash,%,examples/Advanced/DAC_Two_Channels<br>RAM for global variables,%,examples/Beginner/Audio_Playback<br>flash,%,examples/Beginner/Audio_Playback<br>RAM for global variables,%,examples/Beginner/Waveform_Generator<br>flash,%,examples/Beginner/Waveform_Generator<br>RAM for global variables,%
arduino:mbed_giga:giga,-64,-0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,64,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

leonardocavagnis and others added 7 commits February 8, 2024 09:57
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Co-authored-by: Ibrahim Abdelkader <[email protected]>
Copy link
Contributor

@leonardocavagnis leonardocavagnis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmdodd95682
I removed sample_rate parameter from start() to avoid duplication.

Please, apply these changes:

@iabdalkader
Copy link
Collaborator

This change is fine on its own, and it probably wouldn't hurt to merge it (after the issues are fixed) but it doesn't really fix the issue, the 2 ADCs will still be out of sync. I think, if we have time and if this is high priority, we should look into supporting "Dual Mode". In dual mode, one ADC controls the other and sampling is triggered simultaneously. I haven't tested it before but it sounds exactly like what's needed here.

@jmdodd95682
Copy link
Contributor Author

I agree. This was a quick fix and gets them with about 4us of each other. Not great, but okay as a short-term fix.
I read about the Dual-Mode as well. Adc1 and Adc2 can be bound together, with Adc1 being the master. This seems like a longer effort, but probably worth it. I thought about doing that enhancement, but I don't have enough experience with the HAL code.

The applications where it would be useful is things like:

  1. Capturing two analog signals and using one as a capture trigger (e.g. capture scope application)
  2. Recording two correlated signals for low-frequency radar or lidar.

@per1234
Copy link
Contributor

per1234 commented Mar 14, 2024

we should look into supporting "Dual Mode".

This is now tracked at #59 (thanks @jmdodd95682!).

@iabdalkader
Copy link
Collaborator

Superseded by #60.

@per1234 per1234 added the conclusion: duplicate Has already been submitted label Mar 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conclusion: duplicate Has already been submitted topic: code Related to content of the project itself type: enhancement Proposed improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Synchronized ADC Capture
6 participants