From: Keith Packard Date: Sat, 4 May 2019 04:51:28 +0000 (-0700) Subject: altos: Directly compute radio tuning values from frequency X-Git-Tag: 1.9.1~1^2~86 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=a6e8b739c47c50fa472e3f2a41cf13abb8d82c07 altos: Directly compute radio tuning values from frequency 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 --- diff --git a/src/kernel/ao_freq.c b/src/kernel/ao_freq.c index 81640ce8..5a701b91 100644 --- a/src/kernel/ao_freq.c +++ b/src/kernel/ao_freq.c @@ -21,36 +21,24 @@ /* * 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; }