diff --git a/Makefile b/Makefile index c41ad14..a6c96be 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ override CFLAGS += -isystem third_party -I src -std=gnu2x \ -Wnull-dereference -Wvector-operation-performance -Wformat-signedness \ -Wwrite-strings -Wlogical-op -Wjump-misses-init -Wcast-align \ -Wconversion -Wsign-conversion \ - -Wdouble-promotion -Wfloat-conversion -Wfloat-equal \ - -fanalyzer + -Wdouble-promotion -Wfloat-conversion -Wfloat-equal #\ + # -fanalyzer override LDFLAGS += -lm -lasound -lfftw3 diff --git a/src/config.c b/src/config.c index e488da9..3c72c72 100644 --- a/src/config.c +++ b/src/config.c @@ -26,8 +26,10 @@ static CONFIG_T defaults = { .capture_gain = 1, .dc_alpha = 0.999, .x_window = false, + .dbm_cal = 0, .refl = 0, .refh = 20, + .ref_interval = 1, .sgam_spread = 1, .sgam_drag = 0.9, .wfall_zoom = 5, @@ -64,8 +66,10 @@ struct {"capture_gain", DOUBLE, .DOUBLE = &config.capture_gain}, {"dc_alpha", DOUBLE, .DOUBLE = &config.dc_alpha}, {"x_window", BOOL, .BOOL = &config.x_window}, + {"dbm_cal", DOUBLE, .DOUBLE = &config.dbm_cal}, {"refl", DOUBLE, .DOUBLE = &config.refl}, {"refh", DOUBLE, .DOUBLE = &config.refh}, + {"ref_interval", UINT, .UINT = &config.ref_interval}, {"sgam_spread", UINT, .UINT = &config.sgam_spread}, {"sgam_drag", DOUBLE, .DOUBLE = &config.sgam_drag}, {"wfall_zoom", UINT, .UINT = &config.wfall_zoom}, diff --git a/src/config.h b/src/config.h index 0451d41..bb57f26 100644 --- a/src/config.h +++ b/src/config.h @@ -23,8 +23,10 @@ typedef struct double capture_gain; double dc_alpha; bool x_window; + double dbm_cal; double refl; double refh; + unsigned ref_interval; unsigned sgam_spread; double sgam_drag; unsigned wfall_zoom; diff --git a/src/display.h b/src/display.h index e9d6c4f..d53badb 100644 --- a/src/display.h +++ b/src/display.h @@ -20,4 +20,4 @@ void display_open(unsigned sample_rate); void display_close(void); void display_update_bg(unsigned sample_rate); -void display_update(double *amplitudes); +void display_update(const double *dbm_values); diff --git a/src/display/display.c b/src/display/display.c index 368d2e3..09b16b5 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -114,10 +114,10 @@ void render_debug_line(void) render_text(fb.buf, debug_line, -7, -10, false, YELLOW); } -void display_update(double *amplitudes) +void display_update(const double *dbm_values) { - spectrogram_update(amplitudes); - waterfall_update(amplitudes); + spectrogram_update(dbm_values); + waterfall_update(dbm_values); static int64_t next_frame_due = 0; diff --git a/src/display/spectrogram.c b/src/display/spectrogram.c index 471dede..86fe7b1 100644 --- a/src/display/spectrogram.c +++ b/src/display/spectrogram.c @@ -43,7 +43,10 @@ void spectrogram_render_bg(fb_buf_t *bg) } // Horizontal reference lines - for (int y = (int)(floor(config.refl + 1)); y < config.refh; y++) + int start = (int)(floor(config.refl / config.ref_interval + 1)) * (int)config.ref_interval; + int stop = (int)ceil(config.refh); + + for (int y = start; y < stop; y += (int)config.ref_interval) { int yyy = (int)((y - config.refl) * SGAM_HEIGHT / (config.refh - config.refl)); for (int x = 8 + 8 + 8 + 1; (x + 3) < SGAM_WIDTH; x += 8) @@ -58,19 +61,19 @@ void spectrogram_render_bg(fb_buf_t *bg) } } -void spectrogram_update(const double *values) +void spectrogram_update(const double *dbm_values) { double sum = 0; for (unsigned i = 0; i < config.sgam_spread * 2; i++) { - sum += values[i]; + sum += dbm_values[i]; } for (unsigned i = config.sgam_spread; i < SGAM_WIDTH - config.sgam_spread; i++) { - sum += values[i + config.sgam_spread]; + sum += dbm_values[i + config.sgam_spread]; double this_amplitude = sum / (config.sgam_spread * 2 + 1); - sum -= values[i - config.sgam_spread]; + sum -= dbm_values[i - config.sgam_spread]; smoothed_values[i] = smoothed_values[i] * config.sgam_drag; smoothed_values[i] += this_amplitude * (1.0 - config.sgam_drag); @@ -84,9 +87,9 @@ void render_spectrogram(fb_buf_t *buf) { int col = SGAM_LEFT + x; - int amp = (int)(smoothed_values[x] * SGAM_HEIGHT); + double dbm_display = (smoothed_values[x] - config.refl) / (config.refh - config.refl); + int amp = (int)(dbm_display * SGAM_HEIGHT); - // amp *= 0.244140625 * SGAM_HEIGHT; EQMAX(amp, 0); EQMIN(amp, SGAM_HEIGHT); diff --git a/src/display/spectrogram.h b/src/display/spectrogram.h index 52517b6..4d3c46f 100644 --- a/src/display/spectrogram.h +++ b/src/display/spectrogram.h @@ -18,5 +18,5 @@ ******************************************************************************/ extern void spectrogram_render_bg(fb_buf_t *bg); -extern void spectrogram_update(const double *values); +extern void spectrogram_update(const double *dbm_values); extern void render_spectrogram(fb_buf_t *buf); diff --git a/src/display/waterfall.c b/src/display/waterfall.c index 2719505..aa606da 100644 --- a/src/display/waterfall.c +++ b/src/display/waterfall.c @@ -42,7 +42,7 @@ void waterfall_init(void) } } -void waterfall_update(const double *values) +void waterfall_update(const double *dbm_values) { static unsigned phase = 0; @@ -52,7 +52,8 @@ void waterfall_update(const double *values) for (unsigned x = 0; x < WFALL_WIDTH; x++) { - int intens = (int)(values[x] * INTENS_LEVELS); + double dbm_display = (dbm_values[x] - config.refl) / (config.refh - config.refl); + int intens = (int)(dbm_display * INTENS_LEVELS); EQMAX(intens, 0); waterfall[waterfall_i][x] = (intens >= INTENS_LEVELS) ? WHITE : wf_map[intens]; diff --git a/src/display/waterfall.h b/src/display/waterfall.h index 01b2ed1..da83b77 100644 --- a/src/display/waterfall.h +++ b/src/display/waterfall.h @@ -18,5 +18,5 @@ ******************************************************************************/ extern void waterfall_init(void); -extern void waterfall_update(const double *values); +extern void waterfall_update(const double *dbm_values); extern void render_waterfall(fb_buf_t *buf); diff --git a/src/dsp.c b/src/dsp.c index 9dcfb44..f25a66e 100644 --- a/src/dsp.c +++ b/src/dsp.c @@ -34,10 +34,11 @@ static double normalisation_db = 0; * Code ******************************************************************************/ -void dsp_init(unsigned init_fft_size) +void dsp_init(unsigned init_fft_size, unsigned input_scale) { fft_size = init_fft_size; - normalisation_db = 10 * log10(INT16_MAX * fft_size); + normalisation_db = 20 * log10(input_scale * fft_size); + fft_in = fftw_alloc_complex(fft_size); fft_out = fftw_alloc_complex(fft_size); @@ -52,12 +53,12 @@ void dsp_free(void) fftw_free(fft_out); } -void dsp_process(const complex double *samples, double *results) +void dsp_process(const complex double *iq_inputs, double *dbm_results) { // Prepare the samples for processing by FFTW: for (unsigned i = 0; i < fft_size; i++) { - complex double sample = samples[i]; + complex double sample = iq_inputs[i]; // Apply any configured input gain: sample *= config.capture_gain; @@ -78,23 +79,17 @@ void dsp_process(const complex double *samples, double *results) unsigned idx = ((fft_size / 2) + i) % fft_size; // Calculate the magnitude squared of the complex frequency bin - // There's no point performing an expensive square root as it's + // There's no point performing an expensive square root as it's // just a factor of two after the upcoming log(). double mag_sq = SQUARED(creal(fft_out[idx])) + SQUARED(cimag(fft_out[idx])); // Convert to dB and compensate for the missing square root - double db = (10 / 2) * log10(mag_sq); + double db = (20 / 2) * log10(mag_sq); // Normalize for the fft size and the scale of the original integer samples - double dbfs = db - normalisation_db; // 10 * log10(INT16_MAX * fft_size); - - // Shift and scale the result using the configured upper and lower reference - // values: - dbfs -= config.refl; - dbfs /= (config.refh - config.refl); + double db_fs = db - normalisation_db; // 20 * log10(input_scale * fft_size); - // Clip out any negative results at this stage to simplify downstream - // processing: - results[i] = MAX(dbfs, 0); + // Convert to dBm using the configured offset: + dbm_results[i] = db_fs + config.dbm_cal; } } diff --git a/src/dsp.h b/src/dsp.h index d528e84..5c4d4c1 100644 --- a/src/dsp.h +++ b/src/dsp.h @@ -17,6 +17,6 @@ * API ******************************************************************************/ -extern void dsp_init(unsigned init_fft_size); +extern void dsp_init(unsigned init_fft_size, unsigned input_scale); extern void dsp_free(void); -extern void dsp_process(const complex double *samples, double *results); +extern void dsp_process(const complex double *iq_inputs, double *dbm_results); diff --git a/src/main.c b/src/main.c index eee3785..8a4a242 100644 --- a/src/main.c +++ b/src/main.c @@ -51,7 +51,7 @@ int main(int argc, const char *argv[]) config_init(); sample_rate = config.sample_rate; - dsp_init(FFT_SIZE); + dsp_init(FFT_SIZE, INT16_MAX); display_open(sample_rate); @@ -61,13 +61,13 @@ int main(int argc, const char *argv[]) while (should_run) { - static complex double samples[FFT_SIZE]; - capture.get(samples, FFT_SIZE); + static complex double iq_samples[FFT_SIZE]; + capture.get(iq_samples, FFT_SIZE); - static double amplitudes[FFT_SIZE]; - dsp_process(samples, amplitudes); + static double dbm_values[FFT_SIZE]; + dsp_process(iq_samples, dbm_values); - display_update(amplitudes); + display_update(dbm_values); if (config_update()) {