mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-09-11 18:30:14 -07:00
perf(lf): drop double-precision sqrt from FSK demod hot path
The build targets the Cortex-M4F single-precision FPU (-mfpu=fpv4-sp-d16), which has no double-precision hardware. goertzel_mag() used sqrt() (double): the float result was promoted to double for the call and converted back, and a software double-sqrt routine ran -- twice per decoded bit. The bit decision only compares the two Goertzel outputs, and power is monotonic with magnitude, so the sqrt is unnecessary. goertzel_power() returns the squared magnitude and fsk_feed() compares that directly. This also removes a latent sqrt(NaN): the magnitude argument can round slightly negative near zero signal, which sqrt() turned into NaN (and NaN comparisons make the bit decision unreliable); comparing the raw power is well-defined. The old goertzel_mag() had no callers anywhere and was not declared in the header, so it is removed rather than kept. Shared by all FSK readers (HID Prox, ioProx, Pyramid): bit decisions are identical, the soft-float double dependency is gone, and the time-sensitive demod loop is slightly faster. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6e2a902d0e
commit
ab59e7af00
@@ -7,7 +7,7 @@
|
||||
#define PI 3.14159265358979f
|
||||
#define GOERTZEL(FREQ, SAMPLE_RATE) (2.0 * cos((2.0 * PI * FREQ) / (SAMPLE_RATE)))
|
||||
|
||||
float goertzel_mag(float coef, uint16_t samples[], int n) {
|
||||
static float goertzel_power(float coef, const uint16_t samples[], int n) {
|
||||
float z1 = 0;
|
||||
float z2 = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -15,7 +15,11 @@ float goertzel_mag(float coef, uint16_t samples[], int n) {
|
||||
z2 = z1;
|
||||
z1 = z0;
|
||||
}
|
||||
return sqrt(z1 * z1 + z2 * z2 - coef * z1 * z2);
|
||||
// Squared magnitude (|X|^2). The bit decision only compares two of these,
|
||||
// and power is monotonic with magnitude, so the sqrt is dropped entirely.
|
||||
// Result can be slightly negative from rounding; harmless for a comparison
|
||||
// (and avoids the sqrt(NaN) the old magnitude version could hit near zero).
|
||||
return z1 * z1 + z2 * z2 - coef * z1 * z2;
|
||||
}
|
||||
|
||||
void fsk_free(fsk_t *m) {
|
||||
@@ -33,8 +37,8 @@ bool fsk_feed(fsk_t *m, uint16_t sample, bool *bit) {
|
||||
if (m->c < m->bitrate) {
|
||||
return false;
|
||||
}
|
||||
float bit0 = goertzel_mag(m->goertzel_fc_8, m->samples, m->bitrate);
|
||||
float bit1 = goertzel_mag(m->goertzel_fc_10, m->samples, m->bitrate);
|
||||
float bit0 = goertzel_power(m->goertzel_fc_8, m->samples, m->bitrate);
|
||||
float bit1 = goertzel_power(m->goertzel_fc_10, m->samples, m->bitrate);
|
||||
*bit = (bit1 > bit0);
|
||||
|
||||
// Reset counter and clear sample buffer for the next bit
|
||||
|
||||
Reference in New Issue
Block a user