Shop OBEX P1 Docs P2 Docs Learn Events
Frequency calculation for NCO counter — Parallax Forums

Frequency calculation for NCO counter

Andrew E MileskiAndrew E Mileski Posts: 77
edited 2016-01-01 03:46 in Propeller 1
My Christmas 2015 present to myself was a frequency counter (TTi TF960), as I've been fiddling a lot with oscillator design & RF lately.

Like getting a new set of tools, I'm going around the house and fixing measuring everything whether it needs it or not. This of course lead me to my Propeller boards.

The math for NCO frequency initially looks like it is a 32-bit divisor and a 64-bit dividend. I wanted to avoid that, and keep things limited to SPIN's 32-bit signed integers.

The following is the result, but of course I'd love to hear if there is a faster or simpler method that I'm overlooking that is also accurate. I excel at finding the most complex solutions to simple problems (e.g. I considered successive approximation).
PUB NCO(_ctr, _freq, _pin) | _frqx
{{
Purpose:  Set a counter to output at the specified frequency.
Results:  Always succeeds.
Parameters:
_ctr            The counter to use (0 = counter 'A', 1 = counter 'B').
_freq           The frequency to output, in Hertz.
_pin            The pin to output on.
}}
        ' Set pin to output
        DIRA[_pin]~~
        
        _frqx := 0

        ' _frqx = (_freq << 32) / CLKFREQ        
        repeat 32

                _freq := (_freq // CLKFREQ) << 1
                _frqx := (_frqx << 1) + (_freq / CLKFREQ)

        ' Round to nearest (round quotient up if remainder > half of divisor)
        if ((_freq << 1) => CLKFREQ)

                _frqx++

        ' Start counter                
        if (_ctr)

                CTRB := 0
                PHSB := 0
                FRQB := _frqx
                CTRB := (%00100 << 26) | _pin

        else        

                CTRA := 0
                PHSA := 0
                FRQA := _frqx
                CTRA := (%00100 << 26) | _pin
                

Comments

  • AribaAriba Posts: 2,690
    The CTR.SPIN fom the propeller tool library contains a methode: fraction(a,b,s) which is very handy for NCO frequency computation.

    For a fixed propeller clock of 80 MHz and 1 hertz resolution, I use this simple formula:
    FRQA := hertz * 161 / 3    'for 80 MHz sysclock
    

    Andy
  • I use the following:
    ' enter with frequency in Hz
    ' exit with frqx value needed to produce that NCO frequency 
    ' (not using PLL)
    PRI frqxVal(hertz)  | cf    ' calculate hertz/clkfreq * 2^32
      cf := clkfreq
      repeat 32              
        hertz <<= 1
        result <<= 1
        if hertz => cf
          hertz -= cf
          result++         ' returns the frqx as result
    

    That uses only shift/add so it will be faster than the method that uses division / and remainder //. Note that 2^32 / 80_000_000 = 53.687, which is close to 161/3.
  • Great!! Thanks for the tips!
  • jmgjmg Posts: 15,173
    I. Note that 2^32 / 80_000_000 = 53.687, which is close to 161/3.

    That 'close' is ~ 381ppm error, which may be good enough for many applications.

    Another approach is to use 2^32/64 =67.108864MHz and a 4.194304MHz Xtal, and then you have an exact and simple 64 ( << 6).



Sign In or Register to comment.