Hi Dewster -
I have been obsessing over how one determines the difference frequency accurately for a digital heterodyning system without having to go via an analogue integrator and comparator.. The inaccuracy of my D-Latch scheme really pissed me off!
Been playing with all sorts of complex logic schemes which I think could be implemented in a FPGA or PSoC quite easily - but the basic idea boiled down to this.. Rather than just using the Reference and Variable oscillators, the logic also takes the counter clock - by using these 2 oscillator and a (much) higher frequency clock I believe it may be possible to derive the frequency to the accuracy of one (HF) clock cycle.
If we take the output of an XOR that's driven from the oscillators, the pulse width from this output will be exactly 50:50 twice during every (difference frequency) cycle - this corresponds to the zero crossing point of the integrated PWM (triangle) -
If we use the (counter) clock (or a faster clock) to count the low time and high time output from the XOR, then when these times are equal, we have determined the zero crossing point.
And one has eliminated the need for any analogue, but still have the advantages of heterodyning.
Fred.
(my simulated logic involved an up/down counter, resetting this counter on the rising edge from the XOR (after having captured the value of the counter), incrementing the counter with the count clock when the XOR output was high, decrementing the counter when the XOR output was low, and using the captured counts to determine zero crossing. I used a 200MHz clock to count the XOR output so as to capture high difference frequencies - one can calculate required count rate and bounds (as in, whether to accept say a span of -1 to +1 as a "0") to ensure that one captures the zero crossing for whatever maximum difference frequency one needs to work with)
I played with a PSoC 5 implementation of the above, where I didnt use an up-down counter but used a pair of "timer" UMs, one to count the EXOR low time, one to count the high time - these counters were not reset, but the counts were captured on rising and falling edges from the XOR, and an interrupt was generated on each capture event - the interrupt handlers taking care of determining the zero crossing.. This is a safer way of dealing with things because one does not need to hit an exactly equal M/S from the XOR - one can determine if one has gone through a zero crossing event by comparing the previous interrupts data to the current one. Doing this one does not need as fast a clock (The PSoC UM's operate at maximum 48MHz) but can be sure of detecting every zero crossing.
Once a zero crossing is detected, one can disable the timer UM interrupts for say 20us to prevent any spurious triggering and to give the processor time for other tasks / pending interrupts. (2 interrupts coming in every 4us for oscillators running at ~250kHz isnt too difficult to deal with by the PSoC 5 processor, but if the oscillators were to go up to 1MHz and a slower processor was used, it could get tight - I am sort of toying with using a PSoC 1 and this scheme for implementing CV output ;-)
ADDED ->
Writing things often makes them clearer to myself.. Following writing the above I realised the process could be greatly simplified.
One does not need to look for "Zero Crossing" - If one is only looking at one edge of the triangle, this can be performed with one counter, and one can look at this counters value while it is going in one direction (incrementing or decrementing) and compare the count to some constant to determine a crossing point.
Even if looking at both slopes one can use a single counter - Probably the simplest (fastest IRQ handler) would be as follows:
When PWM is (say) high, hold the clock counter in reset.
when PWM is low, the counter counts the high speed clock.
On the rising edge of the PWM, capture the count value and generate an interrupt..
One each interrupt check whether acquired count is incrementing or decrementing (Check whether the previous captured count was greater or less than the present captured count, after calculating any roll-over if the counter is not reset after each capture*) and flag a 1/2 cycle when "direction" changes (as in, if captured counts had been increasing but change to decreasing), or a cycle when direction changes one way (change from say increasing count to decreasing one).
The interrupt handler only needs to look at the count values and determine whether these are increasing or decreasing - a change in direction would be correspond to the peaks of the triangle wave.* Not a good scheme - see update
*(one does not actually need to reset the counter - could use the PWM to gate the count clock, and process the count / roll-over in the IRQ handler)
UPDATE -->
Having now run a load more simulations, the peak detection scheme is probably not the best - PWM pulses get extremely narrow at the peaks (actually, they vanish altogether at the +Ve and -Ve peak), and it becomes difficult to capture the exact point of transition.
The best schemes seem to be crossover detection somewhere near the mid count - the best is probably comparing the mark to the space, as one is increasing while the other decreasing and VV, giving a sharper detection of crossover.
A constant against which the count is compared also works well, particularly if placed near the mid-count - its simpler to implement, but results in unequal spacing of the output pulses.. so one needs to only use output from either the rising or the falling counts - this method is identical to using an analogue comparator looking at a triangle waveform and comparing it to a fixed voltage - you can only use either the rising or the falling edges from this comparator unless you can maintain the reference at exactly the mid point.
If at all possible, my choice would be to compare mark to space - As I see it, if a clock >= 2* the frequency of the period clock is used for the "PWM MS Counter" then one should get the same or better timing accuracy as one gets from analogue integration and analog comparator - But, in fact, I believe the resolution will be better - one does not have any analogue noise or HF leakage into or out of the analogue comparator, there is no frequency dependent or temperature dependent analogue stuff to worry about at the integrator / filter (you dont need a filter or any analogue stuff to do the heterodyning).
The "PWM MS Counter" can be small - 8 bits is probably more than enough for most situations.. With oscillator frequencies at ~250kHz, the longest PWM period will be 4us, so would only overflow an 8 bit counter unrecoverably if the clock exceeded 63MHz.