I'm experimenting with very fine frequency measurements (i.e. uHz resolution) at high sample rates. For instance, down-converting all the WWV signals from a 100 Msps chunk of HF spectrum to near 0 Hz then comparing their drift.
I have a handle on the DDC within the USRP and the sig_source_c within GR, both of which use fixed point, 32-bit NCOs, thus the frequency accuracy is quantifiable, for example: nco_freq = int(target_freq/(samp_rate/2**32)) * (samp_rate/2**32) Now the Frequency Translating FIR filter uses a rotator, and from what I can tell by looking at the source (and I may be wrong), that rotator uses VOLK or falls back to the normal code, both of which use a floating point phase accumulator, with the latter being double precision. So is there anyway to quantify the frequency, over a long number of cycles, with the floating point phase accumulator? I ran this GRC experiment: https://dl.dropboxusercontent.com/u/49570443/rotator_test_grc.png I generated a 1 Hz tone at 100 Msps with both the sig_source_c and rotator, decimating down to 10 sps, and analysing with Baudline FFT to 8 digits of precision. The sig_source_c was spot on at 0.97788870 Hz, i.e. int(1/(100E6/2**32))*(100E6/2**32) For the rotator I used a phase increment of (1/100E6)*2*numpy.pi, which resulted in 0.99917424 Hz via Baudline. So I concluded the rotator has higher actuary to the target frequency of 1 Hz, but... Does it converge, or does it slowly drift away? Does it have more phase noise than the fixed point NCO? I noticed it has some spurs whereas the fixed point was spur-free? I suppose in cases like this I should use an separate NCO and decimating FIR for down conversion, instead of the Frequency Translating FIR? As a side experiment I tried the following python code, which shows shows an accumulating error over 10 cycles, but I'm not sure if this is even a valid experiment: import numpy as np target_freq = np.float64(1) samp_rate = np.float64(100E6) two_pi = np.float64(2*np.pi) phase = np.float64(0) cycles = 10 phase_inc = target_freq/samp_rate*two_pi for cycle in range(cycles): samp = 0 while samp < samp_rate: samp = samp + 1 phase = phase + phase_inc freq = phase/two_pi/(cycle+1) print "The frequency over %i cycles is %.15g" % (cycle+1, freq) ################################################# The frequency over 1 cycles is 1.00000000229562 The frequency over 2 cycles is 1.00000000453839 The frequency over 3 cycles is 1.00000000101206 The frequency over 4 cycles is 0.999999995386438 The frequency over 5 cycles is 0.999999992011064 The frequency over 6 cycles is 0.999999989760814 The frequency over 7 cycles is 0.999999988153493 The frequency over 8 cycles is 0.999999986948002 The frequency over 9 cycles is 0.999999986010398 The frequency over 10 cycles is 0.999999985260315 -- View this message in context: http://gnuradio.4.n7.nabble.com/fxpt-nco-vs-rotator-tp51750.html Sent from the GnuRadio mailing list archive at Nabble.com. _______________________________________________ Discuss-gnuradio mailing list [email protected] https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
