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:
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user