I have a 32.768 kHz oscillator which produces a 1-Hz pulse. I'm measuring this pulse with a 40MHz clock. I am trying to measure the actual frequency of the oscillator by comparing the expected results with the obtained one.
computedFreq = (uint32) ( (float32)32768u / ( ( (float32)measuredPeriod / (float32)40,000,000 ) / (float32)10u ) );
computedFreq = ( 32768*10*40,000,000 ) / measuredPeriod;
Your problem is that measured range goes up to 40010000 Hz, while you are only interested in 20000 Hz range. So the solution is to limit the range.
You can do this with linear interpolation using 2 points.
Select 2 input values. Min/max points might do:
inMin = 40,000,000 - 10,000 inMax = 40,000,000 + 10,000
Precalculate respective output values using your formula (values here are rough values, calculate your own): You can store these as constants in your code.
outMin = ( 32768*10*40,000,000 ) / inMin = 327761 outMax = ( 32768*10*40,000,000 ) / inMax = 327598
Notice how max is smaller than min, due the nature of your formula. This is important when selecting types below.
Use linear interpolation to calculate result using both previous points:
out = (in - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
You have to use signed integers for this, because
(outMax - outMin) is negative.
Upper limit of the multiplication is
(inMax - inMin) * (outMax - outMin), which should fit into int32.
You can pick any 2 points, but you should pick ones that will not produce too big values to overflow on multiplication. Also, if points are too near each other, answer may be less accurate.
If you you have extra precision to spare, you could use bigger multiplier than 10 on outMin/outMax and round afterwards to keep more precision.