From 8ee70526601fb58bfd80cb4994529037c8818b39 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 3 Feb 2017 16:38:06 -0700 Subject: [PATCH 01/24] Added csv text output to hackrf_sweep. Added -B option for binary output. Text output is now the default. Removed binary dump of raw samples between FFTs. --- host/hackrf-tools/src/hackrf_sweep.c | 53 ++++++++++++++++++---------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index dca716cf..8d0727a1 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -36,6 +36,10 @@ #include #define _FILE_OFFSET_BITS 64 +#define BLOCKS_PER_TRANSFER 16 +#define SAMPLES_PER_BLOCK 16384 +#define STEP_SIZE_IN_HZ 312500 +#define FFT_SIZE 64 #ifndef bool typedef int bool; @@ -169,12 +173,17 @@ uint32_t antenna_enable; uint32_t freq_min; uint32_t freq_max; +bool binary_output = false; + int fftSize; fftwf_complex *fftwIn = NULL; fftwf_complex *fftwOut = NULL; fftwf_plan fftwPlan = NULL; float* pwr; float* window; +time_t time_now; +struct tm *fft_time; +char time_str[50]; float logPower(fftwf_complex in, float scale) { @@ -190,22 +199,19 @@ int rx_callback(hackrf_transfer* transfer) { * Throw away unused bins * write output to pipe */ - ssize_t bytes_to_write; - ssize_t bytes_written; int8_t* buf; float frequency; int i, j; if( fd != NULL ) { byte_count += transfer->valid_length; - bytes_to_write = transfer->valid_length; buf = (int8_t*) transfer->buffer; - for(j=0; j<16; j++) { + for(j=0; j> 1); pwr[i] = logPower(fftwOut[k], 1.0f / fftSize); } - fwrite(&frequency, sizeof(float), 1, stdout); - fwrite(pwr, sizeof(float), fftSize, stdout); - } - - bytes_written = fwrite(transfer->buffer, 1, bytes_to_write, fd); - if (bytes_written != bytes_to_write) { - return -1; - } else { - return 0; + if(binary_output) { + fwrite(&frequency, sizeof(float), 1, stdout); + fwrite(pwr, sizeof(float), fftSize, stdout); + } else { + time_now = time(NULL); + fft_time = localtime(&time_now); + strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); + printf("%s, hz_low, hz_high, hz_step, num_samples, ", time_str); + for(i=0; i < (fftSize - 1); i++) { + printf("%.2f, ", pwr[i]); + } + printf("%.2f\n", pwr[fftSize - 1]); + } } + return 0; } else { return -1; } @@ -243,6 +255,7 @@ static void usage() { fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 16384-4294967296\n"); + fprintf(stderr, "\t[-B] # binary output\n"); } static hackrf_device* device = NULL; @@ -276,7 +289,7 @@ int main(int argc, char** argv) { uint16_t frequencies[MAX_FREQ_COUNT]; uint32_t num_samples = DEFAULT_SAMPLE_COUNT; - while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:h?")) != EOF ) { + while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:Bh?")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) { @@ -321,6 +334,10 @@ int main(int argc, char** argv) { result = parse_u32(optarg, &num_samples); break; + case 'B': + binary_output = true; + break; + case 'h': case '?': usage(); @@ -345,12 +362,12 @@ int main(int argc, char** argv) { if (vga_gain % 2) fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n"); - if (num_samples % 0x4000) { + if (num_samples % SAMPLES_PER_BLOCK) { fprintf(stderr, "warning: num_samples (-n) must be a multiple of 16384\n"); return EXIT_FAILURE; } - if (num_samples < 0x4000) { + if (num_samples < SAMPLES_PER_BLOCK) { fprintf(stderr, "warning: num_samples (-n) must be at least 16384\n"); return EXIT_FAILURE; } @@ -377,7 +394,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - fftSize = 64; + fftSize = FFT_SIZE; 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); From a51f06350eaf45cf19805059d38e37e321638085 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 3 Feb 2017 17:08:11 -0700 Subject: [PATCH 02/24] print actual values for all fields in hackrf_sweep csv output --- host/hackrf-tools/src/hackrf_sweep.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 8d0727a1..03ae392c 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -34,6 +34,7 @@ #include #include #include +#include #define _FILE_OFFSET_BITS 64 #define BLOCKS_PER_TRANSFER 16 @@ -232,7 +233,12 @@ int rx_callback(hackrf_transfer* transfer) { time_now = time(NULL); fft_time = localtime(&time_now); strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); - printf("%s, hz_low, hz_high, hz_step, num_samples, ", time_str); + printf("%s, %" PRIu64 ", %" PRIu64 ", %f, %d, ", + time_str, + (uint64_t)((FREQ_ONE_MHZ*frequency)-STEP_SIZE_IN_HZ*(FFT_SIZE/2)), + (uint64_t)((FREQ_ONE_MHZ*frequency)+STEP_SIZE_IN_HZ*(FFT_SIZE/2)), + (float)STEP_SIZE_IN_HZ, + FFT_SIZE); for(i=0; i < (fftSize - 1); i++) { printf("%.2f, ", pwr[i]); } From bb350dccc0e7d6bd404f8448cdcd380a984fc62c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 3 Feb 2017 17:44:10 -0700 Subject: [PATCH 03/24] fixed off-by-one error in hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 03ae392c..d50122eb 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -235,7 +235,7 @@ int rx_callback(hackrf_transfer* transfer) { strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); printf("%s, %" PRIu64 ", %" PRIu64 ", %f, %d, ", time_str, - (uint64_t)((FREQ_ONE_MHZ*frequency)-STEP_SIZE_IN_HZ*(FFT_SIZE/2)), + (uint64_t)((FREQ_ONE_MHZ*frequency)+1-STEP_SIZE_IN_HZ*(FFT_SIZE/2)), (uint64_t)((FREQ_ONE_MHZ*frequency)+STEP_SIZE_IN_HZ*(FFT_SIZE/2)), (float)STEP_SIZE_IN_HZ, FFT_SIZE); From 586082e3e5067fce0fb937f03cc9970eebcd874e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 3 Feb 2017 17:48:16 -0700 Subject: [PATCH 04/24] fixed off-by-one error in hackrf_sweep again --- host/hackrf-tools/src/hackrf_sweep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index d50122eb..cc71059c 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -235,7 +235,7 @@ int rx_callback(hackrf_transfer* transfer) { strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); printf("%s, %" PRIu64 ", %" PRIu64 ", %f, %d, ", time_str, - (uint64_t)((FREQ_ONE_MHZ*frequency)+1-STEP_SIZE_IN_HZ*(FFT_SIZE/2)), + (uint64_t)((FREQ_ONE_MHZ*frequency)-STEP_SIZE_IN_HZ*((FFT_SIZE/2)-1)), (uint64_t)((FREQ_ONE_MHZ*frequency)+STEP_SIZE_IN_HZ*(FFT_SIZE/2)), (float)STEP_SIZE_IN_HZ, FFT_SIZE); From 74aea3266ee7c0a7a27a55ad2392e6979ed03f46 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 4 Feb 2017 09:58:04 -0700 Subject: [PATCH 05/24] Made hackrf_sweep output more like rtl_power's. --- host/hackrf-tools/src/hackrf_sweep.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index cc71059c..399799b9 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -201,7 +201,8 @@ int rx_callback(hackrf_transfer* transfer) { * write output to pipe */ int8_t* buf; - float frequency; + uint16_t frequency; + float float_freq; int i, j; if( fd != NULL ) { @@ -210,6 +211,13 @@ int rx_callback(hackrf_transfer* transfer) { for(j=0; j Date: Sat, 4 Feb 2017 10:07:17 -0700 Subject: [PATCH 06/24] consolidated a little code in hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 399799b9..5a93daea 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -242,16 +242,16 @@ int rx_callback(hackrf_transfer* transfer) { time_now = time(NULL); fft_time = localtime(&time_now); strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); - printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d, ", + printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d", time_str, (uint64_t)((FREQ_ONE_MHZ*frequency)-(DEFAULT_SAMPLE_RATE_HZ/2)), (uint64_t)((FREQ_ONE_MHZ*frequency)+(DEFAULT_SAMPLE_RATE_HZ/2)), (float)STEP_SIZE_IN_HZ, FFT_SIZE); - for(i=0; i < (fftSize - 1); i++) { - printf("%.2f, ", pwr[i]); + for(i=0; i < fftSize; i++) { + printf(", %.2f", pwr[i]); } - printf("%.2f\n", pwr[fftSize - 1]); + printf("\n"); } } return 0; From 8ec1fb32741a89b3bf35d487958155eb2844a811 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 4 Feb 2017 10:09:26 -0700 Subject: [PATCH 07/24] too many Hz --- host/hackrf-tools/src/hackrf_sweep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 5a93daea..f0ae1389 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -215,7 +215,7 @@ int rx_callback(hackrf_transfer* transfer) { buf += SAMPLES_PER_BLOCK; break; } - if((FREQ_MAX_HZ*FREQ_ONE_MHZ < frequency)) { + if((FREQ_MAX_HZ < frequency)) { buf += SAMPLES_PER_BLOCK; break; } From 93201702d66ab1e3c3a9a4a23a3c7ece8d52c796 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 4 Feb 2017 10:30:33 -0700 Subject: [PATCH 08/24] too few Hz --- host/hackrf-tools/src/hackrf_sweep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index f0ae1389..06e4441b 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -201,7 +201,7 @@ int rx_callback(hackrf_transfer* transfer) { * write output to pipe */ int8_t* buf; - uint16_t frequency; + uint16_t frequency; /* in MHz */ float float_freq; int i, j; @@ -215,7 +215,7 @@ int rx_callback(hackrf_transfer* transfer) { buf += SAMPLES_PER_BLOCK; break; } - if((FREQ_MAX_HZ < frequency)) { + if(FREQ_MAX_HZ < (FREQ_ONE_MHZ*frequency)) { buf += SAMPLES_PER_BLOCK; break; } From 3ad5113201df7624ae25da5c67b3de62aca8760d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 4 Feb 2017 10:43:33 -0700 Subject: [PATCH 09/24] Select only the best sections of the FFT output. Skip the lowest 1/8 of the band, the middle 1/4 of the band, and the highest 1/8 of the band. This provides full coverage of the selected frequency range because the hopping pattern was designed with this in mind. --- host/hackrf-tools/src/hackrf_sweep.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 06e4441b..910d6b84 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -244,11 +244,21 @@ int rx_callback(hackrf_transfer* transfer) { strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d", time_str, - (uint64_t)((FREQ_ONE_MHZ*frequency)-(DEFAULT_SAMPLE_RATE_HZ/2)), - (uint64_t)((FREQ_ONE_MHZ*frequency)+(DEFAULT_SAMPLE_RATE_HZ/2)), + (uint64_t)((FREQ_ONE_MHZ*frequency)-((DEFAULT_SAMPLE_RATE_HZ*3)/8)), + (uint64_t)((FREQ_ONE_MHZ*frequency)-(DEFAULT_SAMPLE_RATE_HZ/8)), (float)STEP_SIZE_IN_HZ, FFT_SIZE); - for(i=0; i < fftSize; i++) { + for(i=fftSize/8; (fftSize*3)/8 > i; i++) { + printf(", %.2f", pwr[i]); + } + printf("\n"); + printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d", + time_str, + (uint64_t)((FREQ_ONE_MHZ*frequency)+(DEFAULT_SAMPLE_RATE_HZ/8)), + (uint64_t)((FREQ_ONE_MHZ*frequency)+((DEFAULT_SAMPLE_RATE_HZ*3)/8)), + (float)STEP_SIZE_IN_HZ, + FFT_SIZE); + for(i=(fftSize*5)/8; (fftSize*7)/8 > i; i++) { printf(", %.2f", pwr[i]); } printf("\n"); From d3b30eca594c647488d43dccce1b97d5a8105517 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 6 Feb 2017 20:39:14 -0700 Subject: [PATCH 10/24] default frequency range and error checking of frequency range in hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 59 +++++++++++++++++----------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 910d6b84..719a44a2 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -92,13 +92,13 @@ int gettimeofday(struct timeval *tv, void* ignored) { #define FREQ_ONE_MHZ (1000000ull) -#define FREQ_MIN_HZ (0ull) /* 0 Hz */ -#define FREQ_MAX_HZ (7250000000ull) /* 7250MHz */ +#define FREQ_MIN_MHZ (0) /* 0 MHz */ +#define FREQ_MAX_MHZ (7250) /* 7250 MHz */ #define DEFAULT_SAMPLE_RATE_HZ (20000000) /* 20MHz default sample rate */ #define DEFAULT_BASEBAND_FILTER_BANDWIDTH (15000000) /* 5MHz default */ -#define FREQ_STEP (DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ) +#define TUNE_STEP (DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ) #define MAX_FREQ_COUNT 1000 #define DEFAULT_SAMPLE_COUNT 0x4000 @@ -171,8 +171,8 @@ uint32_t amp_enable; bool antenna = false; uint32_t antenna_enable; -uint32_t freq_min; -uint32_t freq_max; +uint32_t freq_min = 10; +uint32_t freq_max = 6000; bool binary_output = false; @@ -215,7 +215,7 @@ int rx_callback(hackrf_transfer* transfer) { buf += SAMPLES_PER_BLOCK; break; } - if(FREQ_MAX_HZ < (FREQ_ONE_MHZ*frequency)) { + if(FREQ_MAX_MHZ < frequency) { buf += SAMPLES_PER_BLOCK; break; } @@ -242,7 +242,7 @@ int rx_callback(hackrf_transfer* transfer) { time_now = time(NULL); fft_time = localtime(&time_now); strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); - printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d", + printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %u", time_str, (uint64_t)((FREQ_ONE_MHZ*frequency)-((DEFAULT_SAMPLE_RATE_HZ*3)/8)), (uint64_t)((FREQ_ONE_MHZ*frequency)-(DEFAULT_SAMPLE_RATE_HZ/8)), @@ -252,7 +252,7 @@ int rx_callback(hackrf_transfer* transfer) { printf(", %.2f", pwr[i]); } printf("\n"); - printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %d", + printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %u", time_str, (uint64_t)((FREQ_ONE_MHZ*frequency)+(DEFAULT_SAMPLE_RATE_HZ/8)), (uint64_t)((FREQ_ONE_MHZ*frequency)+((DEFAULT_SAMPLE_RATE_HZ*3)/8)), @@ -275,7 +275,7 @@ static void usage() { fprintf(stderr, "\t[-h] # this help\n"); fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF.\n"); fprintf(stderr, "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable.\n"); - fprintf(stderr, "\t[-f freq_min:freq_max # Specify minimum & maximum sweep frequencies (MHz).\n"); + fprintf(stderr, "\t[-f freq_min:freq_max] # Specify minimum & maximum sweep frequencies (MHz).\n"); fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable.\n"); fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); @@ -313,6 +313,7 @@ int main(int argc, char** argv) { unsigned int lna_gain=16, vga_gain=20; uint16_t frequencies[MAX_FREQ_COUNT]; uint32_t num_samples = DEFAULT_SAMPLE_COUNT; + int step_count; while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:Bh?")) != EOF ) { result = HACKRF_SUCCESS; @@ -329,17 +330,6 @@ int main(int argc, char** argv) { case 'f': result = parse_u32_range(optarg, &freq_min, &freq_max); - fprintf(stderr, "Scanning %uMHz to %uMHz\n", freq_min, freq_max); - frequencies[ifreq++] = freq_min; - odd = true; - while(frequencies[ifreq-1] <= freq_max) { - if (odd) - frequencies[ifreq] = frequencies[ifreq-1] + FREQ_STEP / 4; - else - frequencies[ifreq] = frequencies[ifreq-1] + 3*(FREQ_STEP/4); - ifreq++; - odd = !odd; - } break; case 'p': @@ -413,12 +403,35 @@ int main(int argc, char** argv) { } } - if (ifreq == 0) { - fprintf(stderr, "argument error: must specify sweep frequency range (-f).\n"); + if (freq_min >= freq_max) { + fprintf(stderr, "argument error: freq_max must be greater than freq_min.\n"); usage(); return EXIT_FAILURE; } - + + /* Plan a whole number of steps with bandwidth equal to the sample rate. */ + step_count = 1 + (freq_max - freq_min - 1) / TUNE_STEP; + freq_max = freq_min + step_count * TUNE_STEP; + + if (FREQ_MAX_MHZ Date: Tue, 7 Feb 2017 13:57:49 -0700 Subject: [PATCH 11/24] Moved sweep mode frequency computation into firmware. Changed from long list of tuning frequencies to short list of ranges. --- firmware/hackrf_usb/usb_api_sweep.c | 90 +++++++++++++++++++++------- firmware/hackrf_usb/usb_api_sweep.h | 9 ++- host/hackrf-tools/src/hackrf_sweep.c | 70 +++++++++++----------- host/libhackrf/src/hackrf.c | 65 +++++++++++++++++--- host/libhackrf/src/hackrf.h | 15 ++++- 5 files changed, 179 insertions(+), 70 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 503e7f6a..c1a5f2b4 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -31,31 +31,55 @@ #define MIN(x,y) ((x)<(y)?(x):(y)) #define MAX(x,y) ((x)>(y)?(x):(y)) #define FREQ_GRANULARITY 1000000 -#define MIN_FREQ 1 -#define MAX_FREQ 6000 -#define MAX_FREQ_COUNT 1000 +#define MAX_RANGES 10 #define THROWAWAY_BUFFERS 2 volatile bool start_sweep_mode = false; static uint64_t sweep_freq; -bool odd = true; -static uint16_t frequencies[MAX_FREQ_COUNT]; -static uint16_t frequency_count = 0; +static bool odd = true; +static uint16_t frequencies[MAX_RANGES * 2]; +static unsigned char data[9 + MAX_RANGES * 2 * sizeof(frequencies[0])]; +static uint16_t num_ranges = 0; static uint32_t dwell_blocks = 0; +static uint32_t step_width = 0; +static uint32_t offset = 0; +static enum sweep_style style = LINEAR; +static uint16_t range = 0; usb_request_status_t usb_vendor_request_init_sweep( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - uint32_t dwell_time; + uint32_t num_samples; + int i; if (stage == USB_TRANSFER_STAGE_SETUP) { - dwell_time = (endpoint->setup.index << 16) | endpoint->setup.value; - dwell_blocks = dwell_time / 0x4000; - frequency_count = endpoint->setup.length / sizeof(uint16_t); - usb_transfer_schedule_block(endpoint->out, &frequencies, - endpoint->setup.length, NULL, NULL); + num_samples = (endpoint->setup.index << 16) | endpoint->setup.value; + dwell_blocks = num_samples / 0x4000; + if(1 > dwell_blocks) { + return USB_REQUEST_STATUS_STALL; + } + num_ranges = (endpoint->setup.length - 9) / (2 * sizeof(frequencies[0])); + if((1 > num_ranges) || (MAX_RANGES < num_ranges)) { + return USB_REQUEST_STATUS_STALL; + } + usb_transfer_schedule_block(endpoint->out, &data, + endpoint->setup.length, NULL, NULL); } else if (stage == USB_TRANSFER_STAGE_DATA) { - sweep_freq = frequencies[0]; - set_freq(sweep_freq*FREQ_GRANULARITY); + step_width = ((uint32_t)(data[3]) << 24) | ((uint32_t)(data[2]) << 16) + | ((uint32_t)(data[1]) << 8) | data[0]; + if(1 > step_width) { + return USB_REQUEST_STATUS_STALL; + } + offset = ((uint32_t)(data[7]) << 24) | ((uint32_t)(data[6]) << 16) + | ((uint32_t)(data[5]) << 8) | data[4]; + style = data[8]; + if(INTERLEAVED < style) { + return USB_REQUEST_STATUS_STALL; + } + for(i=0; i<(num_ranges*2); i++) { + frequencies[i] = ((uint16_t)(data[10+i*2]) << 8) + data[9+i*2]; + } + sweep_freq = frequencies[0] * FREQ_GRANULARITY; + set_freq(sweep_freq + offset); start_sweep_mode = true; usb_transfer_schedule_ack(endpoint->in); } @@ -65,7 +89,6 @@ usb_request_status_t usb_vendor_request_init_sweep( void sweep_mode(void) { unsigned int blocks_queued = 0; unsigned int phase = 0; - unsigned int ifreq = 0; uint8_t *buffer; bool transfer = false; @@ -88,8 +111,16 @@ void sweep_mode(void) { } if (transfer) { - *(uint16_t*)buffer = 0x7F7F; - *(uint16_t*)(buffer+2) = sweep_freq; + *buffer = 0x7f; + *(buffer+1) = 0x7f; + *(buffer+2) = sweep_freq & 0xff; + *(buffer+3) = (sweep_freq >> 8) & 0xff; + *(buffer+4) = (sweep_freq >> 16) & 0xff; + *(buffer+5) = (sweep_freq >> 24) & 0xff; + *(buffer+6) = (sweep_freq >> 32) & 0xff; + *(buffer+7) = (sweep_freq >> 40) & 0xff; + *(buffer+8) = (sweep_freq >> 48) & 0xff; + *(buffer+9) = (sweep_freq >> 56) & 0xff; if (blocks_queued > THROWAWAY_BUFFERS) { usb_transfer_schedule_block( &usb_endpoint_bulk_in, @@ -102,10 +133,27 @@ void sweep_mode(void) { } if ((dwell_blocks + THROWAWAY_BUFFERS) <= blocks_queued) { - if(++ifreq >= frequency_count) - ifreq = 0; - sweep_freq = frequencies[ifreq]; - set_freq(sweep_freq*FREQ_GRANULARITY); + if(INTERLEAVED == style) { + if(!odd && ((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY))) { + range = (range + 1) % num_ranges; + sweep_freq = frequencies[range*2] * FREQ_GRANULARITY; + } else { + if(odd) { + sweep_freq += step_width/4; + } else { + sweep_freq += 3*step_width/4; + } + } + odd = !odd; + } else { + if((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY)) { + range = (range + 1) % num_ranges; + sweep_freq = frequencies[range*2] * FREQ_GRANULARITY; + } else { + sweep_freq += step_width; + } + } + set_freq(sweep_freq + offset); blocks_queued = 0; } } diff --git a/firmware/hackrf_usb/usb_api_sweep.h b/firmware/hackrf_usb/usb_api_sweep.h index 828647cd..427c1cb2 100644 --- a/firmware/hackrf_usb/usb_api_sweep.h +++ b/firmware/hackrf_usb/usb_api_sweep.h @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_SCAN_H__ -#define __USB_API_SCAN_H__ +#ifndef __USB_API_SWEEP_H__ +#define __USB_API_SWEEP_H__ #include #include @@ -28,6 +28,11 @@ extern volatile bool start_sweep_mode; +enum sweep_style { + LINEAR = 0, + INTERLEAVED = 1, +}; + usb_request_status_t usb_vendor_request_init_sweep( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 719a44a2..a5c0489c 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -37,10 +37,6 @@ #include #define _FILE_OFFSET_BITS 64 -#define BLOCKS_PER_TRANSFER 16 -#define SAMPLES_PER_BLOCK 16384 -#define STEP_SIZE_IN_HZ 312500 -#define FFT_SIZE 64 #ifndef bool typedef int bool; @@ -99,9 +95,12 @@ int gettimeofday(struct timeval *tv, void* ignored) { #define DEFAULT_BASEBAND_FILTER_BANDWIDTH (15000000) /* 5MHz default */ #define TUNE_STEP (DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ) -#define MAX_FREQ_COUNT 1000 +#define OFFSET 7500000 #define DEFAULT_SAMPLE_COUNT 0x4000 +#define BLOCKS_PER_TRANSFER 16 +#define FFT_BIN_WIDTH_HZ 312500 +#define FFT_SIZE 64 #if defined _WIN32 #define sleep(a) Sleep( (a*1000) ) @@ -201,7 +200,8 @@ int rx_callback(hackrf_transfer* transfer) { * write output to pipe */ int8_t* buf; - uint16_t frequency; /* in MHz */ + uint8_t* ubuf; + uint64_t frequency; /* in Hz */ float float_freq; int i, j; @@ -209,13 +209,16 @@ int rx_callback(hackrf_transfer* transfer) { byte_count += transfer->valid_length; buf = (int8_t*) transfer->buffer; for(j=0; j i; i++) { printf(", %.2f", pwr[i]); @@ -254,9 +258,9 @@ int rx_callback(hackrf_transfer* transfer) { printf("\n"); printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %u", time_str, - (uint64_t)((FREQ_ONE_MHZ*frequency)+(DEFAULT_SAMPLE_RATE_HZ/8)), - (uint64_t)((FREQ_ONE_MHZ*frequency)+((DEFAULT_SAMPLE_RATE_HZ*3)/8)), - (float)STEP_SIZE_IN_HZ, + (uint64_t)(frequency+(DEFAULT_SAMPLE_RATE_HZ/2)), + (uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)), + (float)FFT_BIN_WIDTH_HZ, FFT_SIZE); for(i=(fftSize*5)/8; (fftSize*7)/8 > i; i++) { printf(", %.2f", pwr[i]); @@ -303,15 +307,14 @@ void sigint_callback_handler(int signum) { #endif int main(int argc, char** argv) { - int opt, i, result, ifreq = 0; - bool odd; + int opt, i, result = 0; const char* path = "/dev/null"; const char* serial_number = NULL; int exit_code = EXIT_SUCCESS; struct timeval t_end; float time_diff; unsigned int lna_gain=16, vga_gain=20; - uint16_t frequencies[MAX_FREQ_COUNT]; + uint16_t frequencies[MAX_SWEEP_RANGES*2]; uint32_t num_samples = DEFAULT_SAMPLE_COUNT; int step_count; @@ -409,10 +412,6 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - /* Plan a whole number of steps with bandwidth equal to the sample rate. */ - step_count = 1 + (freq_max - freq_min - 1) / TUNE_STEP; - freq_max = freq_min + step_count * TUNE_STEP; - if (FREQ_MAX_MHZ MAX_SWEEP_RANGES)){ + return HACKRF_ERROR_INVALID_PARAM; + } + + if(num_samples % SAMPLES_PER_BLOCK) { + return HACKRF_ERROR_INVALID_PARAM; + } + + if(SAMPLES_PER_BLOCK < num_samples) { + return HACKRF_ERROR_INVALID_PARAM; + } + + if(1 > step_width) { + return HACKRF_ERROR_INVALID_PARAM; + } + + if(INTERLEAVED < style) { + return HACKRF_ERROR_INVALID_PARAM; + } + + data[0] = step_width & 0xff; + data[1] = (step_width >> 8) & 0xff; + data[2] = (step_width >> 16) & 0xff; + data[3] = (step_width >> 24) & 0xff; + data[4] = offset & 0xff; + data[5] = (offset >> 8) & 0xff; + data[6] = (offset >> 16) & 0xff; + data[7] = (offset >> 24) & 0xff; + data[8] = style; + for(i=0; i<(num_ranges*2); i++) { + data[9+i*2] = frequency_list[i] & 0xff; + data[10+i*2] = (frequency_list[i] >> 8) & 0xff; + } result = libusb_control_transfer( device->usb_device, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, HACKRF_VENDOR_REQUEST_INIT_SWEEP, - dwell_time & 0xffff, - (dwell_time >> 16) & 0xffff, - (unsigned char*)frequency_list, + num_samples & 0xffff, + (num_samples >> 16) & 0xffff, + data, size, 0 ); diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 904207e0..a92f5051 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -47,6 +47,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #endif +#define SAMPLES_PER_BLOCK 16384 +#define MAX_SWEEP_RANGES 10 + enum hackrf_error { HACKRF_SUCCESS = 0, HACKRF_TRUE = 1, @@ -95,6 +98,11 @@ enum operacake_ports { OPERACAKE_PB4 = 7, }; +enum sweep_style { + LINEAR = 0, + INTERLEAVED = 1, +}; + typedef struct hackrf_device hackrf_device; typedef struct { @@ -218,10 +226,11 @@ extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t /* set hardware sync mode */ extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value); -/* Start scan mode */ +/* Start sweep mode */ extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device, - uint16_t* frequency_list, - int length, uint32_t dwell_time); + const uint16_t* frequency_list, const int num_ranges, + const uint32_t num_samples, const uint32_t step_width, + const uint32_t offset, const enum sweep_style style); /* Operacake functions */ extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards); From 4b6de820efd95b0ee290123ad761692a33184eae Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 15:37:26 -0700 Subject: [PATCH 12/24] support multiple frequency ranges in hackrf_sweep --- firmware/hackrf_usb/usb_api_sweep.h | 2 +- host/hackrf-tools/src/hackrf_sweep.c | 69 ++++++++++++++++++---------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.h b/firmware/hackrf_usb/usb_api_sweep.h index 427c1cb2..20c27859 100644 --- a/firmware/hackrf_usb/usb_api_sweep.h +++ b/firmware/hackrf_usb/usb_api_sweep.h @@ -38,4 +38,4 @@ usb_request_status_t usb_vendor_request_init_sweep( void sweep_mode(void); -#endif /* __USB_API_SPCAN_H__ */ +#endif /* __USB_API_SWEEP_H__ */ diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index a5c0489c..4514b5f9 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -106,6 +106,9 @@ int gettimeofday(struct timeval *tv, void* ignored) { #define sleep(a) Sleep( (a*1000) ) #endif +int num_ranges = 0; +uint16_t frequencies[MAX_SWEEP_RANGES*2]; + static float TimevalDiff(const struct timeval *a, const struct timeval *b) { return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec); } @@ -170,9 +173,6 @@ uint32_t amp_enable; bool antenna = false; uint32_t antenna_enable; -uint32_t freq_min = 10; -uint32_t freq_max = 6000; - bool binary_output = false; int fftSize; @@ -314,9 +314,11 @@ int main(int argc, char** argv) { struct timeval t_end; float time_diff; unsigned int lna_gain=16, vga_gain=20; - uint16_t frequencies[MAX_SWEEP_RANGES*2]; uint32_t num_samples = DEFAULT_SAMPLE_COUNT; int step_count; + uint32_t freq_min = 0; + uint32_t freq_max = 6000; + while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:Bh?")) != EOF ) { result = HACKRF_SUCCESS; @@ -333,6 +335,29 @@ int main(int argc, char** argv) { case 'f': result = parse_u32_range(optarg, &freq_min, &freq_max); + if(freq_min >= freq_max) { + fprintf(stderr, + "argument error: freq_max must be greater than freq_min.\n"); + usage(); + return EXIT_FAILURE; + } + if(FREQ_MAX_MHZ = freq_max) { - fprintf(stderr, "argument error: freq_max must be greater than freq_min.\n"); - usage(); - return EXIT_FAILURE; - } - - if (FREQ_MAX_MHZ Date: Tue, 7 Feb 2017 16:00:20 -0700 Subject: [PATCH 13/24] fixed firmware bug with sweep ranges that start at high frequencies --- firmware/hackrf_usb/usb_api_sweep.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index c1a5f2b4..102bac69 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -78,7 +78,7 @@ usb_request_status_t usb_vendor_request_init_sweep( for(i=0; i<(num_ranges*2); i++) { frequencies[i] = ((uint16_t)(data[10+i*2]) << 8) + data[9+i*2]; } - sweep_freq = frequencies[0] * FREQ_GRANULARITY; + sweep_freq = (uint64_t)frequencies[0] * FREQ_GRANULARITY; set_freq(sweep_freq + offset); start_sweep_mode = true; usb_transfer_schedule_ack(endpoint->in); @@ -136,7 +136,7 @@ void sweep_mode(void) { if(INTERLEAVED == style) { if(!odd && ((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY))) { range = (range + 1) % num_ranges; - sweep_freq = frequencies[range*2] * FREQ_GRANULARITY; + sweep_freq = (uint64_t)frequencies[range*2] * FREQ_GRANULARITY; } else { if(odd) { sweep_freq += step_width/4; @@ -148,7 +148,7 @@ void sweep_mode(void) { } else { if((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY)) { range = (range + 1) % num_ranges; - sweep_freq = frequencies[range*2] * FREQ_GRANULARITY; + sweep_freq = (uint64_t)frequencies[range*2] * FREQ_GRANULARITY; } else { sweep_freq += step_width; } From a32dedf1a795122485054ad6628bec6bb3961ef2 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 16:18:30 -0700 Subject: [PATCH 14/24] fixed bug in bandwidth filter option error checking in hackrf_transfer --- host/hackrf-tools/src/hackrf_transfer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 88221716..1d52a54d 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -807,9 +807,6 @@ int main(int argc, char** argv) { if( baseband_filter_bw ) { - /* Compute nearest freq for bw filter */ - baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw(baseband_filter_bw_hz); - if (baseband_filter_bw_hz > BASEBAND_FILTER_BW_MAX) { fprintf(stderr, "argument error: baseband_filter_bw_hz must be less or equal to %u Hz/%.03f MHz\n", BASEBAND_FILTER_BW_MAX, (float)(BASEBAND_FILTER_BW_MAX/FREQ_ONE_MHZ)); @@ -823,6 +820,9 @@ int main(int argc, char** argv) { usage(); return EXIT_FAILURE; } + + /* Compute nearest freq for bw filter */ + baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw(baseband_filter_bw_hz); } if(requested_mode_count > 1) { From 0c45d65dc3fc7bc1952f4b99cd03f39365d33cec Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 17:12:16 -0700 Subject: [PATCH 15/24] allow selection of FFT bin width in hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 47 +++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 4514b5f9..4627b8b0 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -99,8 +99,6 @@ int gettimeofday(struct timeval *tv, void* ignored) { #define DEFAULT_SAMPLE_COUNT 0x4000 #define BLOCKS_PER_TRANSFER 16 -#define FFT_BIN_WIDTH_HZ 312500 -#define FFT_SIZE 64 #if defined _WIN32 #define sleep(a) Sleep( (a*1000) ) @@ -175,7 +173,8 @@ uint32_t antenna_enable; bool binary_output = false; -int fftSize; +int fftSize = 20; +uint32_t fft_bin_width; fftwf_complex *fftwIn = NULL; fftwf_complex *fftwOut = NULL; fftwf_plan fftwPlan = NULL; @@ -250,9 +249,9 @@ int rx_callback(hackrf_transfer* transfer) { time_str, (uint64_t)(frequency), (uint64_t)(frequency+DEFAULT_SAMPLE_RATE_HZ/4), - (float)FFT_BIN_WIDTH_HZ, - FFT_SIZE); - for(i=fftSize/8; (fftSize*3)/8 > i; i++) { + (float)fft_bin_width, + fftSize); + for(i=1+fftSize/8; (1+(fftSize*3)/8) > i; i++) { printf(", %.2f", pwr[i]); } printf("\n"); @@ -260,9 +259,9 @@ int rx_callback(hackrf_transfer* transfer) { time_str, (uint64_t)(frequency+(DEFAULT_SAMPLE_RATE_HZ/2)), (uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)), - (float)FFT_BIN_WIDTH_HZ, - FFT_SIZE); - for(i=(fftSize*5)/8; (fftSize*7)/8 > i; i++) { + (float)fft_bin_width, + fftSize); + for(i=1+(fftSize*5)/8; (1+(fftSize*7)/8) > i; i++) { printf(", %.2f", pwr[i]); } printf("\n"); @@ -284,6 +283,7 @@ static void usage() { fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 16384-4294967296\n"); + fprintf(stderr, "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz\n"); fprintf(stderr, "\t[-B] # binary output\n"); } @@ -320,7 +320,7 @@ int main(int argc, char** argv) { uint32_t freq_max = 6000; - while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:Bh?")) != EOF ) { + while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:w:Bh?")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) { @@ -377,6 +377,11 @@ int main(int argc, char** argv) { result = parse_u32(optarg, &num_samples); break; + case 'w': + result = parse_u32(optarg, &fft_bin_width); + fftSize = DEFAULT_SAMPLE_RATE_HZ / fft_bin_width; + break; + case 'B': binary_output = true; break; @@ -437,7 +442,27 @@ int main(int argc, char** argv) { num_ranges++; } - fftSize = FFT_SIZE; + if(4 > fftSize) { + fprintf(stderr, + "argument error: FFT bin width (-w) must be no more than one quarter the sample rate\n"); + return EXIT_FAILURE; + } + + if(65536 < fftSize) { + fprintf(stderr, + "argument error: FFT bin width (-w) resulted in more than 65536 FFT bins\n"); + return EXIT_FAILURE; + } + + /* In interleaved mode, the FFT bin selection works best if the total + * number of FFT bins is equal to an odd multiple of four. + * (e.g. 4, 12, 20, 28, 36, . . .) + */ + while((fftSize + 4) % 8) { + fftSize++; + } + + fft_bin_width = DEFAULT_SAMPLE_RATE_HZ / fftSize; 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); From 813f540e94100e5be3b80a72703fb6fb5ac2adea Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 17:48:24 -0700 Subject: [PATCH 16/24] fixed FFT bin reordering bug in hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 4627b8b0..d1707896 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -230,11 +230,7 @@ int rx_callback(hackrf_transfer* transfer) { buf += fftSize * 2; fftwf_execute(fftwPlan); for (i=0; i < fftSize; i++) { - // Start from the middle of the FFTW array and wrap - // to rearrange the data - //FIXME only works when fftSize = 2**n - int k = i ^ (fftSize >> 1); - pwr[i] = logPower(fftwOut[k], 1.0f / fftSize); + pwr[i] = logPower(fftwOut[i], 1.0f / fftSize); } if(binary_output) { float_freq = frequency; @@ -251,7 +247,7 @@ int rx_callback(hackrf_transfer* transfer) { (uint64_t)(frequency+DEFAULT_SAMPLE_RATE_HZ/4), (float)fft_bin_width, fftSize); - for(i=1+fftSize/8; (1+(fftSize*3)/8) > i; i++) { + for(i=1+(fftSize*5)/8; (1+(fftSize*7)/8) > i; i++) { printf(", %.2f", pwr[i]); } printf("\n"); @@ -261,7 +257,7 @@ int rx_callback(hackrf_transfer* transfer) { (uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)), (float)fft_bin_width, fftSize); - for(i=1+(fftSize*5)/8; (1+(fftSize*7)/8) > i; i++) { + for(i=1+fftSize/8; (1+(fftSize*3)/8) > i; i++) { printf(", %.2f", pwr[i]); } printf("\n"); From 00d5b1c5754b6872810dffb33ff3d4792d2dce79 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 17:52:09 -0700 Subject: [PATCH 17/24] don't send first buffer to host in sweep mode until it is full --- firmware/hackrf_usb/usb_api_sweep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 102bac69..0c0b06fa 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -88,7 +88,7 @@ usb_request_status_t usb_vendor_request_init_sweep( void sweep_mode(void) { unsigned int blocks_queued = 0; - unsigned int phase = 0; + unsigned int phase = 1; uint8_t *buffer; bool transfer = false; From 05759ce1c8f879e9d032da01ecdc03025746b39c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 18:02:52 -0700 Subject: [PATCH 18/24] fft bin selection in hackrf_sweep binary output, similar to text output --- host/hackrf-tools/src/hackrf_sweep.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index d1707896..91cf5cf6 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -233,10 +233,14 @@ int rx_callback(hackrf_transfer* transfer) { pwr[i] = logPower(fftwOut[i], 1.0f / fftSize); } if(binary_output) { - float_freq = frequency; + float_freq = frequency + DEFAULT_SAMPLE_RATE_HZ / 4; float_freq /= FREQ_ONE_MHZ; fwrite(&float_freq, sizeof(float), 1, stdout); - fwrite(pwr, sizeof(float), fftSize, stdout); + fwrite(&pwr[1+(fftSize*5)/8], sizeof(float), fftSize/4, stdout); + float_freq = frequency + DEFAULT_SAMPLE_RATE_HZ / 2; + float_freq /= FREQ_ONE_MHZ; + fwrite(&float_freq, sizeof(float), 1, stdout); + fwrite(&pwr[1+fftSize/8], sizeof(float), fftSize/4, stdout); } else { time_now = time(NULL); fft_time = localtime(&time_now); From c68aedef314dd0cbf9b112e1073211ffe9236d6a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 20:25:21 -0700 Subject: [PATCH 19/24] added output description to hackrf_sweep help --- host/hackrf-tools/src/hackrf_sweep.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 91cf5cf6..dfc66954 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -276,15 +276,18 @@ int rx_callback(hackrf_transfer* transfer) { static void usage() { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t[-h] # this help\n"); - fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF.\n"); - fprintf(stderr, "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable.\n"); - fprintf(stderr, "\t[-f freq_min:freq_max] # Specify minimum & maximum sweep frequencies (MHz).\n"); - fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable.\n"); + fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF\n"); + fprintf(stderr, "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable\n"); + fprintf(stderr, "\t[-f freq_min:freq_max] # minimum and maximum frequencies in MHz\n"); + fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable\n"); fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 16384-4294967296\n"); fprintf(stderr, "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz\n"); fprintf(stderr, "\t[-B] # binary output\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output fields:\n"); + fprintf(stderr, "\tdate, time, hz_low, hz_high, hz_bin_width, num_samples, dB, dB, . . .\n"); } static hackrf_device* device = NULL; From 5ab315a73acb5d48e71ffa4dd2ed73b3e00311d8 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 7 Feb 2017 21:11:50 -0700 Subject: [PATCH 20/24] code cleanup --- host/hackrf-tools/src/hackrf_sweep.c | 136 +++++++++++++-------------- 1 file changed, 66 insertions(+), 70 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index dfc66954..40bdb6eb 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -1,6 +1,7 @@ /* * Copyright 2016 Dominic Spill * Copyright 2016 Mike Walters + * Copyright 2017 Michael Ossmann * * This file is part of HackRF. * @@ -193,84 +194,79 @@ float logPower(fftwf_complex in, float scale) } int rx_callback(hackrf_transfer* transfer) { - /* This is where we need to do interesting things with the samples - * FFT - * Throw away unused bins - * write output to pipe - */ int8_t* buf; uint8_t* ubuf; uint64_t frequency; /* in Hz */ float float_freq; int i, j; - if( fd != NULL ) { - byte_count += transfer->valid_length; - buf = (int8_t*) transfer->buffer; - for(j=0; j i; i++) { - printf(", %.2f", pwr[i]); - } - printf("\n"); - printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %u", - time_str, - (uint64_t)(frequency+(DEFAULT_SAMPLE_RATE_HZ/2)), - (uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)), - (float)fft_bin_width, - fftSize); - for(i=1+fftSize/8; (1+(fftSize*3)/8) > i; i++) { - printf(", %.2f", pwr[i]); - } - printf("\n"); - } - } - return 0; - } else { + if(NULL == fd) { return -1; } + + byte_count += transfer->valid_length; + buf = (int8_t*) transfer->buffer; + for(j=0; j i; i++) { + printf(", %.2f", pwr[i]); + } + printf("\n"); + printf("%s, %" PRIu64 ", %" PRIu64 ", %.2f, %u", + time_str, + (uint64_t)(frequency+(DEFAULT_SAMPLE_RATE_HZ/2)), + (uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)), + (float)fft_bin_width, + fftSize); + for(i=1+fftSize/8; (1+(fftSize*3)/8) > i; i++) { + printf(", %.2f", pwr[i]); + } + printf("\n"); + } + } + return 0; } static void usage() { From 5e6e70659bf520af56d09053c88efecfc07ab072 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Feb 2017 00:37:42 -0700 Subject: [PATCH 21/24] hackrf_sweep: suppress processing and output until the first expected frequency is seen --- host/hackrf-tools/src/hackrf_sweep.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 40bdb6eb..de08f7e2 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -173,6 +173,7 @@ bool antenna = false; uint32_t antenna_enable; bool binary_output = false; +volatile bool sweep_started = false; int fftSize = 20; uint32_t fft_bin_width; @@ -216,6 +217,14 @@ int rx_callback(hackrf_transfer* transfer) { buf += SAMPLES_PER_BLOCK; break; } + if(!sweep_started) { + if (frequency == (uint64_t)(FREQ_ONE_MHZ*frequencies[0])) { + sweep_started = true; + } else { + buf += SAMPLES_PER_BLOCK; + continue; + } + } if((FREQ_MAX_MHZ * FREQ_ONE_MHZ) < frequency) { buf += SAMPLES_PER_BLOCK; break; From c9c70f7adb8fcaebb06f9ccc0adfc1e7cd89b783 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Feb 2017 00:42:13 -0700 Subject: [PATCH 22/24] hackrf_sweep: don't skip more input than necessary when waiting for valid data --- host/hackrf-tools/src/hackrf_sweep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index de08f7e2..1947a36a 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -215,7 +215,7 @@ int rx_callback(hackrf_transfer* transfer) { | ((uint64_t)(ubuf[3]) << 8) | ubuf[2]; } else { buf += SAMPLES_PER_BLOCK; - break; + continue; } if(!sweep_started) { if (frequency == (uint64_t)(FREQ_ONE_MHZ*frequencies[0])) { @@ -227,7 +227,7 @@ int rx_callback(hackrf_transfer* transfer) { } if((FREQ_MAX_MHZ * FREQ_ONE_MHZ) < frequency) { buf += SAMPLES_PER_BLOCK; - break; + continue; } /* copy to fftwIn as floats */ buf += SAMPLES_PER_BLOCK - (fftSize * 2); From 5b881e1d5451b860fcc0db392ed9ff0a1e2c7e72 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Feb 2017 10:44:16 -0700 Subject: [PATCH 23/24] fixed bug that caused tuning glitches in interleaved sweep mode --- firmware/hackrf_usb/usb_api_sweep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 0c0b06fa..35656e81 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -36,7 +36,6 @@ volatile bool start_sweep_mode = false; static uint64_t sweep_freq; -static bool odd = true; static uint16_t frequencies[MAX_RANGES * 2]; static unsigned char data[9 + MAX_RANGES * 2 * sizeof(frequencies[0])]; static uint16_t num_ranges = 0; @@ -44,7 +43,6 @@ static uint32_t dwell_blocks = 0; static uint32_t step_width = 0; static uint32_t offset = 0; static enum sweep_style style = LINEAR; -static uint16_t range = 0; usb_request_status_t usb_vendor_request_init_sweep( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -89,6 +87,8 @@ usb_request_status_t usb_vendor_request_init_sweep( void sweep_mode(void) { unsigned int blocks_queued = 0; unsigned int phase = 1; + bool odd = true; + uint16_t range = 0; uint8_t *buffer; bool transfer = false; From 03d93c1369a64718cd5c89b422bde72537c8564e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Feb 2017 10:46:08 -0700 Subject: [PATCH 24/24] added one shot mode to hackrf_sweep --- host/hackrf-tools/src/hackrf_sweep.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c index 1947a36a..2edd68cf 100644 --- a/host/hackrf-tools/src/hackrf_sweep.c +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -173,6 +173,7 @@ bool antenna = false; uint32_t antenna_enable; bool binary_output = false; +bool one_shot = false; volatile bool sweep_started = false; int fftSize = 20; @@ -208,6 +209,9 @@ int rx_callback(hackrf_transfer* transfer) { byte_count += transfer->valid_length; buf = (int8_t*) transfer->buffer; for(j=0; j= (uint64_t)(FREQ_ONE_MHZ*frequencies[num_ranges*2-1]))) { + do_exit = true; + } } return 0; } @@ -289,6 +297,7 @@ static void usage() { fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 16384-4294967296\n"); fprintf(stderr, "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz\n"); + fprintf(stderr, "\t[-1] # one shot mode\n"); fprintf(stderr, "\t[-B] # binary output\n"); fprintf(stderr, "\n"); fprintf(stderr, "Output fields:\n"); @@ -328,7 +337,7 @@ int main(int argc, char** argv) { uint32_t freq_max = 6000; - while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:w:Bh?")) != EOF ) { + while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:w:1Bh?")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) { @@ -390,6 +399,10 @@ int main(int argc, char** argv) { fftSize = DEFAULT_SAMPLE_RATE_HZ / fft_bin_width; break; + case '1': + one_shot = true; + break; + case 'B': binary_output = true; break; @@ -456,9 +469,9 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - if(65536 < fftSize) { + if(16368 < fftSize) { fprintf(stderr, - "argument error: FFT bin width (-w) resulted in more than 65536 FFT bins\n"); + "argument error: FFT bin width (-w) too small, resulted in more than 16368 FFT bins\n"); return EXIT_FAILURE; }