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);