From 799d9ad1588556db38b2d11bee1a1bd0e05227a8 Mon Sep 17 00:00:00 2001 From: Jonathan Suite Date: Thu, 2 Nov 2023 08:25:13 -0700 Subject: [PATCH] Run fftw_execute() once on an empty buffer (Fix #1366), add option to save wisdom and specify plan (#863) (#1368) * Call fftw_execute once prior to starting IQ streaming * Add options to use/save to an FFTW wisdom file and specify plan * Fix bug where using -P would also enable one-shot mode Fixes #1366 Fixes #1260 Addresses #863 --- host/hackrf-tools/src/hackrf_sweep.c | 78 ++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index a38675a13..826589f95 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -381,6 +381,8 @@ static void usage() "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n" "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n" "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz, 2445-5000000\n" + "\t[-W wisdom_file] # Use FFTW wisdom file (will be created if necessary)\n" + "\t[-P estimate|measure|patient|exhaustive] # FFTW plan type, default is 'measure'\n" "\t[-1] # one shot mode\n" "\t[-N num_sweeps] # Number of sweeps to perform\n" "\t[-B] # binary output\n" @@ -411,6 +413,36 @@ void sigint_callback_handler(int signum) } #endif +int import_wisdom(const char* path) +{ + // Returns nonzero + if (!fftwf_import_wisdom_from_filename(path)) { + fprintf(stderr, + "Wisdom file %s not found; will attempt to create it\n", + path); + return 0; + } + + return 1; +} + +int import_default_wisdom() +{ + return fftwf_import_system_wisdom(); +} + +int export_wisdom(const char* path) +{ + if (path != NULL) { + if (!fftwf_export_wisdom_to_filename(path)) { + fprintf(stderr, "Could not write FFTW wisdom file to %s", path); + return 0; + } + } + + return 1; +} + int main(int argc, char** argv) { int opt, i, result = 0; @@ -425,8 +457,10 @@ int main(int argc, char** argv) uint32_t freq_min = 0; uint32_t freq_max = 6000; uint32_t requested_fft_bin_width; + const char* fftwWisdomPath = NULL; + int fftw_plan_type = FFTW_MEASURE; - while ((opt = getopt(argc, argv, "a:f:p:l:g:d:n:N:w:1BIr:h?")) != EOF) { + while ((opt = getopt(argc, argv, "a:f:p:l:g:d:n:N:w:W:P:1BIr:h?")) != EOF) { result = HACKRF_SUCCESS; switch (opt) { case 'd': @@ -488,6 +522,25 @@ int main(int argc, char** argv) fftSize = DEFAULT_SAMPLE_RATE_HZ / requested_fft_bin_width; break; + case 'W': + fftwWisdomPath = optarg; + break; + + case 'P': + if (strcmp("estimate", optarg) == 0) { + fftw_plan_type = FFTW_ESTIMATE; + } else if (strcmp("measure", optarg) == 0) { + fftw_plan_type = FFTW_MEASURE; + } else if (strcmp("patient", optarg) == 0) { + fftw_plan_type = FFTW_PATIENT; + } else if (strcmp("exhaustive", optarg) == 0) { + fftw_plan_type = FFTW_EXHAUSTIVE; + } else { + fprintf(stderr, "Unknown FFTW plan type '%s'\n", optarg); + return EXIT_FAILURE; + } + break; + case '1': one_shot = true; break; @@ -527,6 +580,14 @@ int main(int argc, char** argv) } } + // Try to load a wisdom file if specified, otherwise + // try to load the system-wide wisdom file + if (fftwWisdomPath) { + import_wisdom(fftwWisdomPath); + } else { + import_default_wisdom(); + } + if (lna_gain % 8) { fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n"); } @@ -607,13 +668,18 @@ int main(int argc, char** argv) fftwIn = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); fftwOut = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); fftwPlan = - fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE); + fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, fftw_plan_type); pwr = (float*) fftwf_malloc(sizeof(float) * fftSize); window = (float*) fftwf_malloc(sizeof(float) * fftSize); for (i = 0; i < fftSize; i++) { window[i] = (float) (0.5f * (1.0f - cos(2 * M_PI * i / (fftSize - 1)))); } + /* Execute the plan once to make sure it's ready to go when real + * data starts to flow. See issue #1366 + */ + fftwf_execute(fftwPlan); + #ifdef _MSC_VER if (binary_output) { _setmode(_fileno(stdout), _O_BINARY); @@ -725,7 +791,12 @@ int main(int argc, char** argv) ifftwIn, ifftwOut, FFTW_BACKWARD, - FFTW_MEASURE); + fftw_plan_type); + + /* Execute the plan once to make sure it's ready to go when real + * data starts to flow. See issue #1366 + */ + fftwf_execute(ifftwPlan); } result = hackrf_init_sweep( @@ -858,6 +929,7 @@ int main(int argc, char** argv) fftwf_free(window); fftwf_free(ifftwIn); fftwf_free(ifftwOut); + export_wisdom(fftwWisdomPath); fprintf(stderr, "exit\n"); return exit_code; }