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
This commit is contained in:
Jonathan Suite
2023-11-02 08:25:13 -07:00
committed by GitHub
parent 1fd67f66ca
commit 799d9ad158

View File

@ -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;
}