summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-12 22:06:35 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-12 22:16:23 +0000
commit569660ada9383b3ba1119b212f3200e7e1876539 (patch)
treee9d1b51fe83b1309e9c5caf1657d3e4080a94da1
parent606c452bd88d8637febecdcd5106fbe8740b36f1 (diff)
util/spkmodem-decode: automatic tone calibration
current logic is hardcoded, as in the original spkmodem-recv. with this change, small differences are observed and averaged, then the detection thresholds are adjusted accordingly. the existing macros serve as a baseline, but real signals differ. with this change, we therefore account for possible drift in timings, which can change in real-time; the old code could possibly get out of sync beccause of that, which may have resulted in corrupt characters on the screen. this change therefore should make the output a bit more stable. the detection window is continually adjusted, so that the output timings don't drift. the tolerances are automatically adjusted based on base timings (see new define in patch) Signed-off-by: Leah Rowe <leah@libreboot.org>
-rw-r--r--util/spkmodem_decode/spkmodem-decode.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/util/spkmodem_decode/spkmodem-decode.c b/util/spkmodem_decode/spkmodem-decode.c
index 3c4b94c1..f08b1b52 100644
--- a/util/spkmodem_decode/spkmodem-decode.c
+++ b/util/spkmodem_decode/spkmodem-decode.c
@@ -128,6 +128,9 @@
#define SEP_TONE_MIN_HZ 1000
#define SEP_TONE_MAX_HZ 3000
+#define SEP_TOLERANCE_PULSES \
+ (((SEP_TONE_MAX_HZ) - (SEP_TONE_MIN_HZ)) / (2 * (FRAME_RATE)))
+
#define DATA_TONE_MIN_HZ 3000
#define DATA_TONE_MAX_HZ 12000
@@ -180,6 +183,12 @@ struct decoder_state {
int debug;
int swap_bytes;
+
+ /* dynamic separator calibration */
+ int sep_sum;
+ int sep_samples;
+ int sep_min;
+ int sep_max;
};
static const char *argv0;
@@ -228,6 +237,12 @@ main(int argc, char **argv)
break;
}
+ /*
+ * Used for separator calibration
+ */
+ st.sep_min = FREQ_SEP_MIN;
+ st.sep_max = FREQ_SEP_MAX;
+
st.ascii_bit = 7;
st.ringpos = 0;
@@ -254,6 +269,7 @@ host_is_big_endian(void)
static void
handle_audio(struct decoder_state *st)
{
+ int avg;
int sample;
/*
@@ -262,7 +278,30 @@ handle_audio(struct decoder_state *st)
*/
if (st->sample_count >= (3 * SAMPLES_PER_FRAME))
reset_char(st);
+
if (!valid_signal(st)) {
+
+ /*
+ * collect separator tone statistics
+ * (and auto-adjust tolerances)
+ */
+ if (st->sep_samples < 50 && st->freq_separator > 0) {
+ st->sep_sum += st->freq_separator;
+ st->sep_samples++;
+
+ if (st->sep_samples == 50) {
+ avg = st->sep_sum / st->sep_samples;
+
+ /* ±3 pulse window */
+ st->sep_min = avg - SEP_TOLERANCE_PULSES;
+ st->sep_max = avg + SEP_TOLERANCE_PULSES;
+
+ if (st->debug)
+ printf("separator calibrated: %dHz\n",
+ avg * FRAME_RATE);
+ }
+ }
+
decode_pulse(st);
return;
}
@@ -283,8 +322,8 @@ handle_audio(struct decoder_state *st)
static int
valid_signal(struct decoder_state *st)
{
- return (st->freq_separator > FREQ_SEP_MIN &&
- st->freq_separator < FREQ_SEP_MAX &&
+ return (st->freq_separator > st->sep_min &&
+ st->freq_separator < st->sep_max &&
st->freq_data > FREQ_DATA_MIN &&
st->freq_data < FREQ_DATA_MAX);
}
@@ -438,24 +477,30 @@ print_stats(struct decoder_state *st)
int data_hz = st->freq_data * FRAME_RATE;
int sep_hz = st->freq_separator * FRAME_RATE;
+ int sep_hz_min = st->sep_min * FRAME_RATE;
+ int sep_hz_max = st->sep_max * FRAME_RATE;
if ((pos = ftell(stdin)) == -1) {
- printf("%d %d %d data=%dHz sep=%dHz\n",
+ printf("%d %d %d data=%dHz sep=%dHz(min %dHz %dHz)\n",
st->freq_data,
st->freq_separator,
FREQ_DATA_THRESHOLD,
data_hz,
- sep_hz);
+ sep_hz,
+ sep_hz_min,
+ sep_hz_max);
return;
}
- printf("%d %d %d @%ld data=%dHz sep=%dHz\n",
+ printf("%d %d %d @%ld data=%dHz sep=%dHz(min %dHz %dHz)\n",
st->freq_data,
st->freq_separator,
FREQ_DATA_THRESHOLD,
pos - SAMPLE_OFFSET,
data_hz,
- sep_hz);
+ sep_hz,
+ sep_hz_min,
+ sep_hz_max);
}
static void