altos: Directly compute radio tuning values from frequency
authorKeith Packard <keithp@keithp.com>
Sat, 4 May 2019 04:51:28 +0000 (21:51 -0700)
committerKeith Packard <keithp@keithp.com>
Sat, 4 May 2019 04:51:28 +0000 (21:51 -0700)
The 8051 compiler doesn't support 64-bit ints, so the old
code used an iterative method in 32-bit values. That could take
a long time when the frequency was mis-entered in Hz or MHz instead of
kHz.

This direct-computation uses 64-bit ints, but takes a fixed amount of
time for any inputs.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/kernel/ao_freq.c

index 81640ce..5a701b9 100644 (file)
 /*
  * The provided 'calibration' value is
  * that needed to tune the radio to precisely 434550kHz.
- * Use that to 'walk' to the target frequency by following
- * a 'bresenham' line from 434550kHz to the target
- * frequency, and updating the radio setting along the way
+ * The relation between value and freq is linear, so
+ * to get the value for an arbitrary frequency:
+ *
+ *     target_value   target_freq
+ *     ------------ = ------------
+ *      cal_value       cal_freq
+ *
+ *                     cal_value * target_freq
+ *     target_value = -----------------------
+ *                             cal_freq
  */
 
-int32_t ao_freq_to_set(int32_t freq, int32_t cal) 
+int32_t ao_freq_to_set(int32_t target_freq, int32_t cal_value)
 {
-       static int32_t  set;
-       static uint8_t  neg;
-       static int32_t  error;
+       int64_t prod = (int64_t) target_freq * (int64_t) cal_value;
 
-       set = 0;
-       neg = 0;
-       error = -434550 / 2;
+       /* Round to nearest */
+       int32_t target_value = (prod + (434550 / 2)) / 434550;
 
-       if ((freq -= 434550) < 0) {
-               neg = 1;
-               freq = -freq;
-       }
-       for (;;) {
-               if (error > 0) {
-                       error -= 434550;
-                       set++;
-               } else {
-                       error += cal;
-                       if (--freq < 0)
-                               break;
-               }
-       }
-       if (neg)
-               set = -set;
-       return cal + set;
+       return target_value;
 }