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

applet.interface.freq_counter: implement a frequency and duty-cycle counter #216

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

attie
Copy link
Member

@attie attie commented Oct 11, 2020

This implements a basic frequency and duty-cycle counter...

It counts n (according to --count) rising or falling edges (according to --edge), and produces basic analysis of the signal, as below.

This will only produce sensible results for a periodic / stable signal.

venv:$ glasgow run freq-counter -V 3.3
I: g.device.hardware: device already has bitstream ID 105ecaf020abed3b9e44b92ca7afa398
I: g.cli: running handler for applet 'freq-counter'
I: g.applet.interface.freq_counter: port(s) A, B voltage set to 3.3 V
Duration:          42.688 us  /     256 cycles
Frequency:          5.997 MHz / 166.748 ns
Time High / Low:   41.667 ns  / 125.081 ns
Duty Cycle:        24.988 %

@attie attie force-pushed the freq-counter branch 3 times, most recently from 5fc5921 to 6f5c590 Compare October 11, 2020 15:13
@electroniceel
Copy link
Member

This will only produce sensible results for a periodic / stable signal.

Just an idea: add a feature to also report maximum deviation to give the user an idea how stable the signal was. If there was for example a glitch in the signal, or a flaky connection, the results would be off without the user noticing.

How I think this could be implemented:
for high time and low time each:

  • store the length of the first cycle
  • init max-longer, max-shorter to 0
  • on the following cycles, calculate length difference to the first cycle
  • compare the length difference to max-longer, max-shorter, update if maximum diff up to this point is exceeded

In the python part of the applet you calculate the difference of the first cycle to the average and shift max-longer/max-shorter by this amount. then report the bigger of the two as max deviation.

This is just an enhancement idea, no feature requirement. If you don't want to complicate the code any further, I'm totally ok with merging it without this addition.

@attie
Copy link
Member Author

attie commented Oct 11, 2020

Just an idea: add a feature to also report maximum deviation to give the user an idea how stable the signal was

I like this idea, and the implementation you outlined might typically give a good indication if it's not a stable signal... however if the average matches up with the first cycle, then that indication is somewhat lost.

Additionally, the major reason I opted for averaging over n-cycles, is that for higher frequencies, we'll start to get a bit of aliasing due to the sys_clk_freq over a single cycle of the input.


I'm looking at collecting the lo/hi cycles for each of min_lo / max_lo / min_hi / max_hi, in addition to the total counts that I'm already collecting... this would let us give better indication of outliers or glitches, but it increases the complexity quite a bit...

Let me have a play?

@attie
Copy link
Member Author

attie commented Oct 12, 2020

I've reworked this somewhat, and have produced the following output from a 2MHz input signal, with 300kHz FM @ 1kHz.

Frequency  :    1.778 MHz  <    2.001 MHz  <    2.526 MHz
Duty       :   47.368  %   <   52.665  %   <   55.000  %
Time Lo    :  187.500 ns   <  236.605 ns   <  291.667 ns
Time Hi    :  187.500 ns   <  263.250 ns   <  291.667 ns

... and the following from a "glitch clock training signal". (Note the outliers: ~1% duty cycle, and ~21ns time hi).

Frequency  :  338.028 kHz  <  499.963 kHz  <  505.263 kHz
Duty       :    1.031  %   <   48.705  %   <   48.421  %
Time Lo    :    1.021 us   <    1.026 us   <    2.000 us
Time Hi    :   20.833 ns   <  974.170 ns   <  958.333 ns

This is becoming a data presentation problem... I'd like to include +/- percentages, but it's already fairly messy.
I'm going to look at using color to help differentiate it, but any other input would be appreciated.


There is additionally, the unfortunate situation where the "minimum X over a single cycle" is reported as more than the average. This is the aliasing I was referring to earlier. (this is the same "glitch clock training signal", but with no glitch over the n-cycles).

Frequency  :  500.000 kHz  <  499.967 kHz  <  505.263 kHz
Duty       :   47.368  %   <   48.706  %   <   48.421  %
Time Lo    :    1.021 us   <    1.026 us   <    1.042 us
Time Hi    :  937.500 ns   <  974.184 ns   <  958.333 ns

Actually, no: this is because I'm not storing the min/max period... and I'm thus calculating the "min frequency" from the available data, rather than using grounded / actual data...

@attie attie force-pushed the freq-counter branch 3 times, most recently from 6a04e9e to fee7fd6 Compare October 12, 2020 21:56
@attie
Copy link
Member Author

attie commented Oct 12, 2020

This is the aliasing I was referring to earlier

Actually, no: this is because I'm not storing the min/max period...

Acually, yes... this is aliasing... what a ride.

I implemented min/max for the whole cycle too, and it didn't improve the results:

--- 8< ---
 'max_t': {'count': 1,
           'cyc_hi': 46,
           'cyc_lo': 50,
           'cyc_total': 96,
           'duration': 2.0000000000000003e-06,
           'duty': 47.91666666666667,
           'frequency': 500000.0,
           't_hi': 9.583333333333334e-07,
           't_lo': 1.0416666666666667e-06,
           't_total': 2.0000000000000003e-06},
--- 8< ---
 'min_t': {'count': 1,
           'cyc_hi': 45,
           'cyc_lo': 49,
           'cyc_total': 94,
           'duration': 1.9583333333333334e-06,
           'duty': 47.87234042553192,
           'frequency': 510638.2978723404,
           't_hi': 9.375e-07,
           't_lo': 1.0208333333333334e-06,
           't_total': 1.9583333333333334e-06},
 'total': {'count': 1000,
           'cyc_hi': 46763,
           'cyc_lo': 49245,
           'cyc_total': 96008,
           'duration': 0.0020001666666666666,
           'duty': 48.70739938338472,
           'frequency': 499958.33680526627,
           't_hi': 9.742291666666667e-07,
           't_lo': 1.0259375e-06,
           't_total': 2.0001666666666665e-06}}

I think at this point, it's better to "lie" about the figures, by not excluding the total key from the min/max search (patch)... thoughts?

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.

3 participants