Frequency Resolution (pun intended)

Hacking multi-tool. Get one for $30, including worldwide shipping.

Frequency Resolution (pun intended)

Postby mrmr » Fri Jan 04, 2013 7:36 pm

Despite double sampling in firmware, an earlier attempt to improve frequency resolution by measuring the period(s) proved to intermittently fail for frequencies above 775Hz. More frequent failures occurred at 2 KHz especially when a high jitter sourced clock signal (DLL generated) was used. During failure either a timer timeout failed to set the interrupt flag or the reading IFS1bits.T5IF failed. This resulted in a long pause during frequency measurement, requiring the timer to loop, before code execution continued.

To workaround this problem, a new method of measuring the period(s) was developed. PIC input capture logic was used to capture timer values at the rising edge of the AUX signal. Since 16-bit values are captured, two input capture units were used. IC2 and IC1 were used to capture the 32-bit timer value composed of TMR5 and TMR4.

To eliminate the effects of jitter during the time allocated, the initial frequency count was used to determine the number of periods, "n", to measure over before returning a period count.

This routine was used when it provided a finer resolution then existing bpFreq_count() routine:

Code: Select all
unsigned long bpPeriod_count(unsigned int n){
        static unsigned int i;
        static unsigned long j, k, l, m, d, s;

        IFS0bits.IC2IF=0; // clear input capture interrupt flag
        IFS0bits.IC1IF=0; // clear input capture interrupt flag

        // configure IC1 to RP20 (AUX)
        RPINR7bits.IC2R=AUXPIN_RPIN;
        RPINR7bits.IC1R=AUXPIN_RPIN;

        //timer 4 internal, measures interval
        TMR5HLD=0x00;
        TMR4=0x00;
        T4CON=0b1000; //.T32=1, bit 3
        //start timer4
        T4CONbits.TON=1;

        // unimplemented: [15:14]=0b00,
        // ICSIDL:        [13]=0b0, input capture module continues to operate in CPU idle mode
        // ICTSEL[2:0]:   [12:10]=0b010=TMR4, 0b011=TMR5 (unimplemented for 16-bit capture)
        // unimplemented: [9:8]=0b00
        // ICTMR:         [7]=0b0=TMR3, 0b1=TMR2 (unimplemented for 32-bit capture)
        // ICI[1:0]:      [6:5]=0b00, 1 capture per interrupt
        // ICOV,ICBNE:    [4:3]=0b00, read-only buffer overflow and not empty
        // ICM[2:0]:      [2:0]=0b011, capture every rising edge
        IC2CON1=0x0C03; // fails with ICM 0 or 3 (0 always read from IC2BUF)

        IC1CON1=0x0803;

        // unimplemented: [15:9]=0b0000000
        // IC32:          [8]=0b0
        // ICTRIG:        [7]=0b0, synchronize with SYNCSEL specified source
        // TRIGSTAT:      [6]=0b0, cleared by SW, holds timer in reset when low, trigger chosen by syncsel sets bit and releases timer from reset.
        // unimplemented: [5]=0b0
        // SYNCSEL[4:0]:  [4:0]=0b10100, selects trigger/synchronization source to be IC1.
        IC2CON2=0x0014;

        IC1CON2=0x0014;

        // read input capture bits n times
        while(IC1CON1bits.ICBNE) // clear buffer
                j = IC1BUF;

        while(IC2CON1bits.ICBNE) // clear buffer
                k = IC2BUF;

        while(!IC1CON1bits.ICBNE); // wait for ICBNE

        k = IC1BUF;
        m = IC2BUF;
        for(i=s=0; i<n; i++) {
                while(!IC1CON1bits.ICBNE); // wait for ICBNE
                j = IC1BUF;
                l = IC2BUF;
                d = ((l-m)<<16) + (j-k);
                s = s + d;
                m = l;
                k = j;
        }

        // turn off input capture modules, reset control to POR state
        IC1CON1=0;
        IC1CON2=0;
        T4CONbits.TON=0;

        return s/n;
}

To determine the finer resolution, a comparison was done between the frequency resolution provided by bpFreq_count(), which counts AUX signal edges over a 1 second interval, and the frequency resolution provided by the new routine, bpPeriod_count(), which captures 16MHz timer values each AUX signal edge.

Since we count frequency over a 1 second interval:
Frequency = f
where "f" is the frequency measurement count by the existing method.

And how fine this resolution is can be calculated over an increment as:
(f - (f-1))/f
or simply the expected 1/f.

Since the period is measured with a 16MHz clocked timer:
Frequency = 16e6/p
Where "p" is the period count of a captured 16MHz timer.

And how fine this resolution is can be calculated over an increment as:
(16e6/(p-1) - 16e6/p) / 16e6/(p-1)
which reduces to 1 - (p-1)/p.

The crossing point where 1-bit of frequency resolution provided by a period count is equivalent to 1-bit of
frequency resolution provided by a frequency count is given by the equation:
1 - (p-1)/p = 1/f

Noting f = Frequency = 16e6/p, we can determine the crossing point count by solving:
1 - (p-1)/p = p/16e6
which reduces to p=4000

Therefore, frequency measurement resolution can be improved using the new period measurement routine for p>4000.

For p slightly greater the 4000, it makes sense to output an additional fractional decimal digit. An equation very similar to the
above can be used to determine when it makes sense to output yet another fractional decimal digit, i.e. when p is greater then
the crossing point where an increment of period count resolution is 1/10 of an increment of frequency resolution:
1 - (p-1)/p = 0.1*p/16e6
which reduces to p=4*10^(7/2) or p=1.264911e4

For our measurements, recall that recalculating using a period count to improve the measurement resolution was roughly limited to 1 second (p=16e6), limited by the initial frequency count>=1. For period counts less the 16e6, Additional equations were solved for decimal digit crossing points resulting in the following table:

Code: Select all
| Frequency Resolution | Period Count (p)       | Frequency |
|----------------------+------------------------+-----------|
|                    1 | 4*10^(6/2) =4000       |      4000 |
|                   .1 | 4*10^(7/2) =1.264911e4 |  1264.911 |
|                  .01 | 4*10^(8/2) =4e4        |       400 |
|                 .001 | 4*10^(9/2) =1.264911e5 |  126.4911 |
|                .0001 | 4*10^(10/2)=4e5        |        40 |
|               .00001 | 4*10^(11/2)=1.264911e6 |  12.64911 |
|              .000001 | 4*10^(12/2)=4e6        |         4 |
|             .0000001 | 4*10^(13/2)=1.264911e7 |  1.264911 |

Experimentally it was determined, that it didn't make sense to output resolutions less then 1e-5 due to oscillator accuracy;
although, the commented code was retained should a more accurate timer clock source be used.
mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm

Re: Frequency Resolution (pun intended)

Postby arakis » Tue Jan 08, 2013 9:55 am

The BPv3 (64GA002) chip doesn't support IC with dedicated timers, it can only support tmr2 and tmr3. I'll try to change the code around so the method above is implemented for v4, and the tmr2 nad tmr3 is implemented for BPv3, with the use of #if defined...

BPv3 has only a ICxCON register, so no SYNC can be implemented with it...
best regards FIlip.
arakis
Crew
Crew
 
Posts: 1044
Joined: Wed May 25, 2011 11:15 am
Location: Belgrade, Serbia

Re: Frequency Resolution (pun intended)

Postby arakis » Wed Jan 09, 2013 9:51 am

Hi i added the patch to the current SVN, r2082. I modified it slightly to work on both Bpv3, and BPv4, it now compiles with no problem on both versions, I'll test it out tomorow with 2 BPs V4 generating the PWM signal and BPv3 reading it, and vice versa...

I adde the patch below..., I also implemented your baseIO.c patch as wall, and committed it to SVN rev2082..
Attachments
AUXpin.c.20130901.patch
(11.65 KiB) Downloaded 97 times
best regards FIlip.
arakis
Crew
Crew
 
Posts: 1044
Joined: Wed May 25, 2011 11:15 am
Location: Belgrade, Serbia

Re: Frequency Resolution (pun intended)

Postby mrmr » Wed Jan 09, 2013 6:44 pm

Hi Filip,
A compare against the new svn r2082 showed AUXpin.c is missing an earlier patch I submitted to correct the behavior of AUX1 and AUX2 (issue #65). Can you add this to svn also. While there, it looks like a couple lines of of white space and an indentation was inadvertently added at line 482 of AUXpin.c. Also, its customary to use YYYYMMDD (not YYYYDDMM) for chronological sorting.
Thx!
mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm

Re: Frequency Resolution (pun intended)

Postby arakis » Thu Jan 10, 2013 2:52 am

mrmr wrote:Hi Filip,
A compare against the new svn r2082 showed AUXpin.c is missing an earlier patch I submitted to correct the behavior of AUX1 and AUX2 (issue #65). Can you add this to svn also. While there, it looks like a couple lines of of white space and an indentation was inadvertently added at line 482 of AUXpin.c. Also, its customary to use YYYYMMDD (not YYYYDDMM) for chronological sorting.
Thx!

Hi,
Thanks for taking your time to check it out. I'll fix the issues later today. Thanks again..
best regards FIlip.
arakis
Crew
Crew
 
Posts: 1044
Joined: Wed May 25, 2011 11:15 am
Location: Belgrade, Serbia

Re: Frequency Resolution (pun intended)

Postby arakis » Thu Jan 10, 2013 8:46 am

HI, I made the update and am uploading it now to the SVN, I removed the huge ugly commented out section, and fixed the indents in one of the functions, there simply were none..
also added the AUX fix you metioned...
now at rev 2083..
Attachments
AUXpin.c.20130110.patch
(7.56 KiB) Downloaded 90 times
best regards FIlip.
arakis
Crew
Crew
 
Posts: 1044
Joined: Wed May 25, 2011 11:15 am
Location: Belgrade, Serbia


Return to Bus Pirate Support