Skip to content
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

Adding documentation, updating DAC output timing #208

Merged
merged 16 commits into from
Jan 18, 2021
Merged

Adding documentation, updating DAC output timing #208

merged 16 commits into from
Jan 18, 2021

Conversation

ryan-summers
Copy link
Member

@ryan-summers ryan-summers commented Dec 17, 2020

This PR adds extensive documentation to the asynchronous IO modules on stabilizer. This fixes #171

This PR also updates the DAC codes so that DAC + ADC batches are always synchronous (DAC codes are exactly 2 batches after the ADC sample that generated them). In this implementation, DAC batches are always delayed by exactly 1 additional batch size from the original ADC sample batch that generated them.

There are thus two DAC batches with fixed output-zero codes at the very start of stabilizer processing.

This PR fixes #185

TODO:

  • Verify timing on stabilizer hardware
  • Investigate updating DAC DMA to use DBM to prevent potential sample loss

@jordens
Copy link
Member

jordens commented Dec 17, 2020

Pretty sure the delay is two batches, not one. You'd measure from first sample of an ADC batch to (corresponding) first sample of a DAC batch.

src/adc.rs Show resolved Hide resolved
src/adc.rs Outdated Show resolved Hide resolved
///! such, one of the ADCs will be sampled marginally earlier before the other because the DMA
///! requests are generated simultaneously. This can be avoided by providing a known offset to the
///! sample DMA requests, which can be completed by setting e.g. ADC0's comparison to a counter
///! value of 0 and ADC1's comparison to a counter value of 1.
Copy link
Member

Choose a reason for hiding this comment

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

We should do that by default. The risk of having the sequence of ADC0/1 winning the bus arbitration race change between samples is worse than the constant skew.

Copy link
Member Author

Choose a reason for hiding this comment

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

The ADC0/ADC1 never race for the bus because of natural priority of the DMA transfers (since they are using the same DMA peripheral). This means the DMA peripheral arbitrates between ADC0 and ADC1 internally in a deterministic manner.

src/adc.rs Outdated Show resolved Hide resolved
src/dac.rs Outdated Show resolved Hide resolved
src/dac.rs Outdated Show resolved Hide resolved
///! simultaneously. If only a single ADC is used, it must always be ADC0, as ADC1 will not generate
///! transfer-complete interrupts.
///!
///! There is a very small amount of latency between sampling of ADCs due to bus matrix priority. As
Copy link
Collaborator

Choose a reason for hiding this comment

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

How might we be able to calculate this latency?

Copy link
Member Author

Choose a reason for hiding this comment

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

The latency is 1 bus matrix clock. However, since the bus might be used by for example the CPU, it might get delayed further. Because this latency is in the range of a handful of AXI bus clocks, that's what I used the phrase "a very small amount"

Copy link
Member Author

Choose a reason for hiding this comment

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

Essentially, the latency is not deterministic, hence why it's not clearly specified here

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we specify some sort of worst case number? This allows someone to make the determination of "I don't care about this latency".

src/dac.rs Outdated Show resolved Hide resolved
///!
///! # Note
///!
///! There is a very small amount of latency between updating the two DACs due to bus matrix
Copy link
Collaborator

Choose a reason for hiding this comment

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

How much latency? We describe it in terms of "timer ticks" below, but nano- or microseconds would also be nice.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is the same as with the ADCs. It's actually an undeterministic number of AXI bus cycles, hence why it's unspecified.

@irwineffect
Copy link
Collaborator

irwineffect commented Dec 18, 2020

Something that is implied but not plainly explained is how the ADC/DAC constraints sum up to create the constraints of the DSP application code. Something like:

Processing time for the DSP application code is bounded by the following constraints:

DSP application code starts after the ADC has generated a batch of samples, and must be completed by the time the next batch of ADC samples has been acquired (plus the FIFO buffer time). If this constraint is not met, <what will happen?>.

The DSP application code must also fill out the next DAC output buffer in time such that the DAC can switch to it when it has completed the current buffer. If this constraint is not met <what will happen?>

Because the ADC and DAC operate at the same rate, these two constraints actually implement the same time bounds, meeting one also means the other is also met.

How will the end user know that their DSP application code meets these constraints? Once this code is stabilized I imagine that we can provide equations to estimate how much time the DSP application has based on parameters like sampling rate and batch size.

Will we eventually have some sort of burden reporting mechanism so the end user can test code and see how much more they can add before hitting one of the limits?

@irwineffect
Copy link
Collaborator

Concerning my burden question, it seems like #166 might address it?

@ryan-summers
Copy link
Member Author

@irwineffect I've added the blurb you provided to describe the DSP timing constraints - thanks for writing it up. In regard to knowing whether an application is meeting timing:

The ADC inputs listen for an overrun on the SPI peripheral, which generates an interrupt that panics. Thus, if timing is not met, the firmware will panic and make it obvious to the end user that timing is not being met. Ultimately, #166 will also aid with this as you point out.

///! simultaneously. If only a single ADC is used, it must always be ADC0, as ADC1 will not generate
///! transfer-complete interrupts.
///!
///! There is a very small amount of latency between sampling of ADCs due to bus matrix priority. As
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we specify some sort of worst case number? This allows someone to make the determination of "I don't care about this latency".

@ryan-summers
Copy link
Member Author

Timing for batch sizes > 1 was verified. It was found that batch_size = 1 results in an extra batch delay from input -> output, and I haven't been able to figure out the cause. I spawned an issue in #229 so we can track it as necessary.

@ryan-summers ryan-summers merged commit d447501 into quartiq:master Jan 18, 2021
@ryan-summers ryan-summers deleted the feature/io-docs branch January 26, 2021 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

First DAC output code may not be synchronized with the sampling timer Document IO architecture
3 participants