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[-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[-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 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[-1] # one shot mode\n"
|
||||||
"\t[-N num_sweeps] # Number of sweeps to perform\n"
|
"\t[-N num_sweeps] # Number of sweeps to perform\n"
|
||||||
"\t[-B] # binary output\n"
|
"\t[-B] # binary output\n"
|
||||||
@ -411,6 +413,36 @@ void sigint_callback_handler(int signum)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int opt, i, result = 0;
|
int opt, i, result = 0;
|
||||||
@ -425,8 +457,10 @@ int main(int argc, char** argv)
|
|||||||
uint32_t freq_min = 0;
|
uint32_t freq_min = 0;
|
||||||
uint32_t freq_max = 6000;
|
uint32_t freq_max = 6000;
|
||||||
uint32_t requested_fft_bin_width;
|
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;
|
result = HACKRF_SUCCESS;
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'd':
|
case 'd':
|
||||||
@ -488,6 +522,25 @@ int main(int argc, char** argv)
|
|||||||
fftSize = DEFAULT_SAMPLE_RATE_HZ / requested_fft_bin_width;
|
fftSize = DEFAULT_SAMPLE_RATE_HZ / requested_fft_bin_width;
|
||||||
break;
|
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':
|
case '1':
|
||||||
one_shot = true;
|
one_shot = true;
|
||||||
break;
|
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) {
|
if (lna_gain % 8) {
|
||||||
fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n");
|
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);
|
fftwIn = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||||
fftwOut = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
fftwOut = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||||
fftwPlan =
|
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);
|
pwr = (float*) fftwf_malloc(sizeof(float) * fftSize);
|
||||||
window = (float*) fftwf_malloc(sizeof(float) * fftSize);
|
window = (float*) fftwf_malloc(sizeof(float) * fftSize);
|
||||||
for (i = 0; i < fftSize; i++) {
|
for (i = 0; i < fftSize; i++) {
|
||||||
window[i] = (float) (0.5f * (1.0f - cos(2 * M_PI * i / (fftSize - 1))));
|
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
|
#ifdef _MSC_VER
|
||||||
if (binary_output) {
|
if (binary_output) {
|
||||||
_setmode(_fileno(stdout), _O_BINARY);
|
_setmode(_fileno(stdout), _O_BINARY);
|
||||||
@ -725,7 +791,12 @@ int main(int argc, char** argv)
|
|||||||
ifftwIn,
|
ifftwIn,
|
||||||
ifftwOut,
|
ifftwOut,
|
||||||
FFTW_BACKWARD,
|
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(
|
result = hackrf_init_sweep(
|
||||||
@ -858,6 +929,7 @@ int main(int argc, char** argv)
|
|||||||
fftwf_free(window);
|
fftwf_free(window);
|
||||||
fftwf_free(ifftwIn);
|
fftwf_free(ifftwIn);
|
||||||
fftwf_free(ifftwOut);
|
fftwf_free(ifftwOut);
|
||||||
|
export_wisdom(fftwWisdomPath);
|
||||||
fprintf(stderr, "exit\n");
|
fprintf(stderr, "exit\n");
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user