diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 71ba9f5c..10542b6c 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -117,6 +117,10 @@ void rffc5071_setup(rffc5071_driver_t* const drv) /* GPOs are active at all times */ set_RFFC5071_GATE(drv, 1); + /* Output LOCK status on GPO4 and enable lock detect */ + set_RFFC5071_LOCK(drv, 1); + set_RFFC5071_LDEN(drv, 1); + rffc5071_regs_commit(drv); } @@ -254,13 +258,6 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) { tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) / (lodiv * (1 << 24ULL)); - /* Path 1 */ - set_RFFC5071_P1LODIV(drv, n_lo); - set_RFFC5071_P1N(drv, n); - set_RFFC5071_P1PRESC(drv, fbkdiv >> 1); - set_RFFC5071_P1NMSB(drv, p1nmsb); - set_RFFC5071_P1NLSB(drv, p1nlsb); - /* Path 2 */ set_RFFC5071_P2LODIV(drv, n_lo); set_RFFC5071_P2N(drv, n); diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 7c3d9da2..5699f93c 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -94,10 +94,7 @@ void rffc5071_spi_stop(spi_bus_t* const bus) { static void rffc5071_spi_serial_delay(spi_bus_t* const bus) { (void)bus; - volatile uint32_t i; - - for (i = 0; i < 2; i++) - __asm__("nop"); + __asm__("nop"); } static void rffc5071_spi_sck(spi_bus_t* const bus) { diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 5f2252aa..29272b79 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC_M4 usb_api_transceiver.c "${PATH_HACKRF_FIRMWARE_COMMON}/operacake.c" usb_api_operacake.c + usb_api_sweep.c "${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c" "${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c" "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 2d5fd2ff..046934c7 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -22,12 +22,12 @@ #include -#include - #include #include +#include "tuning.h" + #include "usb.h" #include "usb_standard_request.h" @@ -42,75 +42,11 @@ #include "usb_api_spiflash.h" #include "usb_api_operacake.h" #include "operacake.h" +#include "usb_api_sweep.h" #include "usb_api_transceiver.h" -#include "sgpio_isr.h" #include "usb_bulk_buffer.h" -static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF; - -void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { - baseband_streaming_disable(&sgpio_config); - - usb_endpoint_disable(&usb_endpoint_bulk_in); - usb_endpoint_disable(&usb_endpoint_bulk_out); - - _transceiver_mode = new_transceiver_mode; - - if( _transceiver_mode == TRANSCEIVER_MODE_RX ) { - led_off(LED3); - led_on(LED2); - usb_endpoint_init(&usb_endpoint_bulk_in); - rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; - } else if (_transceiver_mode == TRANSCEIVER_MODE_TX) { - led_off(LED2); - led_on(LED3); - usb_endpoint_init(&usb_endpoint_bulk_out); - rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx; - } else { - led_off(LED2); - led_off(LED3); - rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; - } - - if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) { - si5351c_activate_best_clock_source(&clock_gen); - baseband_streaming_enable(&sgpio_config); - } -} - -transceiver_mode_t transceiver_mode(void) { - return _transceiver_mode; -} - -usb_request_status_t usb_vendor_request_set_transceiver_mode( - usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage -) { - if( stage == USB_TRANSFER_STAGE_SETUP ) { - switch( endpoint->setup.value ) { - case TRANSCEIVER_MODE_OFF: - case TRANSCEIVER_MODE_RX: - case TRANSCEIVER_MODE_TX: - set_transceiver_mode(endpoint->setup.value); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - case TRANSCEIVER_MODE_CPLD_UPDATE: - usb_endpoint_init(&usb_endpoint_bulk_out); - start_cpld_update = true; - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - default: - return USB_REQUEST_STATUS_STALL; - } - } else { - return USB_REQUEST_STATUS_OK; - } -} - static const usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, @@ -142,6 +78,7 @@ static const usb_request_handler_fn vendor_request_handler[] = { #endif usb_vendor_request_set_freq_explicit, usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ + usb_vendor_request_init_sweep, usb_vendor_request_operacake_get_boards, usb_vendor_request_operacake_set_ports }; @@ -244,11 +181,18 @@ int main(void) { operacake_init(); unsigned int phase = 0; + while(true) { // Check whether we need to initiate a CPLD update if (start_cpld_update) cpld_update(); + // Check whether we need to initiate sweep mode + if (start_sweep_mode) { + start_sweep_mode = false; + sweep_mode(); + } + // Set up IN transfer of buffer 0. if ( usb_bulk_buffer_offset >= 16384 && phase == 1 @@ -262,7 +206,7 @@ int main(void) { ); phase = 0; } - + // Set up IN transfer of buffer 1. if ( usb_bulk_buffer_offset < 16384 && phase == 0 @@ -277,6 +221,6 @@ int main(void) { phase = 1; } } - + return 0; } diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c new file mode 100644 index 00000000..581faacc --- /dev/null +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -0,0 +1,109 @@ +/* + * Copyright 2016 Mike Walters, Dominic Spill + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "usb_api_sweep.h" +#include "usb_queue.h" +#include +#include +#include "usb_api_transceiver.h" +#include "usb_bulk_buffer.h" +#include "tuning.h" +#include "usb_endpoint.h" + +#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 + +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 uint32_t dwell_blocks = 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; + 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); + } else if (stage == USB_TRANSFER_STAGE_DATA) { + sweep_freq = frequencies[0]; + set_freq(sweep_freq*FREQ_GRANULARITY); + start_sweep_mode = true; + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} + +void sweep_mode(void) { + unsigned int blocks_queued = 0; + unsigned int phase = 0; + unsigned int ifreq = 0; + + uint8_t *buffer; + bool transfer = false; + + while(transceiver_mode() != TRANSCEIVER_MODE_OFF) { + // Set up IN transfer of buffer 0. + if ( usb_bulk_buffer_offset >= 16384 && phase == 1) { + transfer = true; + buffer = &usb_bulk_buffer[0x0000]; + phase = 0; + blocks_queued++; + } + + // Set up IN transfer of buffer 1. + if ( usb_bulk_buffer_offset < 16384 && phase == 0) { + transfer = true; + buffer = &usb_bulk_buffer[0x4000]; + phase = 1; + blocks_queued++; + } + + if (transfer) { + *(uint16_t*)buffer = 0x7F7F; + *(uint16_t*)(buffer+2) = sweep_freq; + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + buffer, + 0x4000, + NULL, NULL + ); + transfer = false; + } + + if (blocks_queued >= dwell_blocks) { + if(++ifreq >= frequency_count) + ifreq = 0; + sweep_freq = frequencies[ifreq]; + set_freq(sweep_freq*FREQ_GRANULARITY); + blocks_queued = 0; + } + } +} diff --git a/firmware/hackrf_usb/usb_api_sweep.h b/firmware/hackrf_usb/usb_api_sweep.h new file mode 100644 index 00000000..828647cd --- /dev/null +++ b/firmware/hackrf_usb/usb_api_sweep.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Mike Walters, Dominic Spill + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_API_SCAN_H__ +#define __USB_API_SCAN_H__ + +#include +#include +#include + +extern volatile bool start_sweep_mode; + +usb_request_status_t usb_vendor_request_init_sweep( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); + +void sweep_mode(void); + +#endif /* __USB_API_SPCAN_H__ */ diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index e8bac410..d86de7db 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -22,9 +22,16 @@ #include "usb_api_transceiver.h" +#include +#include +#include "sgpio_isr.h" + +#include "usb_api_cpld.h" // Remove when CPLD update is handled elsewhere + #include #include #include +#include #include #include @@ -221,3 +228,68 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( return USB_REQUEST_STATUS_OK; } } + +static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF; + + +transceiver_mode_t transceiver_mode(void) { + return _transceiver_mode; +} + +void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { + baseband_streaming_disable(&sgpio_config); + + usb_endpoint_disable(&usb_endpoint_bulk_in); + usb_endpoint_disable(&usb_endpoint_bulk_out); + + _transceiver_mode = new_transceiver_mode; + + if( _transceiver_mode == TRANSCEIVER_MODE_RX ) { + led_off(LED3); + led_on(LED2); + usb_endpoint_init(&usb_endpoint_bulk_in); + rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX); + vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; + } else if (_transceiver_mode == TRANSCEIVER_MODE_TX) { + led_off(LED2); + led_on(LED3); + usb_endpoint_init(&usb_endpoint_bulk_out); + rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX); + vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx; + } else { + led_off(LED2); + led_off(LED3); + rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); + vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; + } + + if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) { + si5351c_activate_best_clock_source(&clock_gen); + baseband_streaming_enable(&sgpio_config); + } +} + +usb_request_status_t usb_vendor_request_set_transceiver_mode( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + switch( endpoint->setup.value ) { + case TRANSCEIVER_MODE_OFF: + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_TX: + set_transceiver_mode(endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + case TRANSCEIVER_MODE_CPLD_UPDATE: + usb_endpoint_init(&usb_endpoint_bulk_out); + start_cpld_update = true; + usb_transfer_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + default: + return USB_REQUEST_STATUS_STALL; + } + } else { + return USB_REQUEST_STATUS_OK; + } +} \ No newline at end of file diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index 24244025..59f85778 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -53,4 +53,9 @@ usb_request_status_t usb_vendor_request_set_antenna_enable( usb_request_status_t usb_vendor_request_set_freq_explicit( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +transceiver_mode_t transceiver_mode(void); +void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode); +usb_request_status_t usb_vendor_request_set_transceiver_mode( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); + #endif/*__USB_API_TRANSCEIVER_H__*/ diff --git a/host/cmake/modules/FindFFTW.cmake b/host/cmake/modules/FindFFTW.cmake new file mode 100644 index 00000000..00c3401c --- /dev/null +++ b/host/cmake/modules/FindFFTW.cmake @@ -0,0 +1,22 @@ +# - Find FFTW +# Find the native FFTW includes and library +# +# FFTW_INCLUDES - where to find fftw3.h +# FFTW_LIBRARIES - List of libraries when using FFTW. +# FFTW_FOUND - True if FFTW found. + +if (FFTW_INCLUDES) + # Already in cache, be silent + set (FFTW_FIND_QUIETLY TRUE) +endif (FFTW_INCLUDES) + +find_path (FFTW_INCLUDES fftw3.h) + +find_library (FFTW_LIBRARIES NAMES fftw3) + +# handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if +# all listed variables are TRUE +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES) + +mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES) diff --git a/host/hackrf-tools/CMakeLists.txt b/host/hackrf-tools/CMakeLists.txt index cc7ff9be..82ea47d8 100644 --- a/host/hackrf-tools/CMakeLists.txt +++ b/host/hackrf-tools/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) project(hackrf-tools C) set(MAJOR_VERSION 0) -set(MINOR_VERSION 4) +set(MINOR_VERSION 5) set(PACKAGE hackrf-tools) set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}) set(VERSION ${VERSION_STRING}) diff --git a/host/hackrf-tools/src/CMakeLists.txt b/host/hackrf-tools/src/CMakeLists.txt index a006c6ac..692e843f 100644 --- a/host/hackrf-tools/src/CMakeLists.txt +++ b/host/hackrf-tools/src/CMakeLists.txt @@ -38,8 +38,12 @@ SET(TOOLS hackrf_cpldjtag hackrf_info hackrf_operacake + hackrf_sweep ) +add_executable(hackrf_sweep hackrf_sweep.c) +install(TARGETS hackrf_sweep RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR}) + if(NOT libhackrf_SOURCE_DIR) include_directories(${LIBHACKRF_INCLUDE_DIR}) LIST(APPEND TOOLS_LINK_LIBS ${LIBHACKRF_LIBRARIES}) @@ -51,6 +55,8 @@ if(MSVC) LIST(APPEND TOOLS_LINK_LIBS libgetopt_static) endif() +LIST(APPEND TOOLS_LINK_LIBS m fftw3f) + foreach(tool ${TOOLS}) add_executable(${tool} ${tool}.c) target_link_libraries(${tool} ${TOOLS_LINK_LIBS}) diff --git a/host/hackrf-tools/src/hackrf_sweep.c b/host/hackrf-tools/src/hackrf_sweep.c new file mode 100644 index 00000000..220c1d2c --- /dev/null +++ b/host/hackrf-tools/src/hackrf_sweep.c @@ -0,0 +1,547 @@ +/* + * Copyright 2016 Dominic Spill + * Copyright 2016 Mike Walters + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef bool +typedef int bool; +#define true 1 +#define false 0 +#endif + +#ifdef _WIN32 +#include + +#ifdef _MSC_VER + +#ifdef _WIN64 +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif + +#define strtoull _strtoui64 +#define snprintf _snprintf + +int gettimeofday(struct timeval *tv, void* ignored) { + FILETIME ft; + unsigned __int64 tmp = 0; + if (NULL != tv) { + GetSystemTimeAsFileTime(&ft); + tmp |= ft.dwHighDateTime; + tmp <<= 32; + tmp |= ft.dwLowDateTime; + tmp /= 10; + tmp -= 11644473600000000Ui64; + tv->tv_sec = (long)(tmp / 1000000UL); + tv->tv_usec = (long)(tmp % 1000000UL); + } + return 0; +} + +#endif +#endif + +#if defined(__GNUC__) +#include +#include +#endif + +#include + +#define FD_BUFFER_SIZE (8*1024) + +#define FREQ_ONE_MHZ (1000000ull) + +#define FREQ_MIN_HZ (0ull) /* 0 Hz */ +#define FREQ_MAX_HZ (7250000000ull) /* 7250MHz */ + +#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 MAX_FREQ_COUNT 1000 + +#define DEFAULT_SAMPLE_COUNT 0x4000 + +#if defined _WIN32 + #define sleep(a) Sleep( (a*1000) ) +#endif + +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); +} + +int parse_u32(char* s, uint32_t* const value) { + uint_fast8_t base = 10; + char* s_end; + uint64_t ulong_value; + + if( strlen(s) > 2 ) { + if( s[0] == '0' ) { + if( (s[1] == 'x') || (s[1] == 'X') ) { + base = 16; + s += 2; + } else if( (s[1] == 'b') || (s[1] == 'B') ) { + base = 2; + s += 2; + } + } + } + + s_end = s; + ulong_value = strtoul(s, &s_end, base); + if( (s != s_end) && (*s_end == 0) ) { + *value = (uint32_t)ulong_value; + return HACKRF_SUCCESS; + } else { + return HACKRF_ERROR_INVALID_PARAM; + } +} + +int parse_u32_range(char* s, uint32_t* const value_min, uint32_t* const value_max) { + int result; + + char *sep = strchr(s, ':'); + if (!sep) + return HACKRF_ERROR_INVALID_PARAM; + + *sep = 0; + + result = parse_u32(s, value_min); + if (result != HACKRF_SUCCESS) + return result; + result = parse_u32(sep + 1, value_max); + if (result != HACKRF_SUCCESS) + return result; + + return HACKRF_SUCCESS; +} + +volatile bool do_exit = false; + +FILE* fd = NULL; +volatile uint32_t byte_count = 0; + +struct timeval time_start; +struct timeval t_start; + +bool amp = false; +uint32_t amp_enable; + +bool antenna = false; +uint32_t antenna_enable; + +uint32_t freq_min; +uint32_t freq_max; + +int fftSize; +fftwf_complex *fftwIn = NULL; +fftwf_complex *fftwOut = NULL; +fftwf_plan fftwPlan = NULL; +float* pwr; +float* window; + +float logPower(fftwf_complex in, float scale) +{ + float re = in[0] * scale; + float im = in[1] * scale; + float magsq = re * re + im * im; + return log2f(magsq) * 10.0f / log2(10.0f); +} + +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 + */ + 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++) { + if(buf[0] == 0x7F && buf[1] == 0x7F) { + frequency = *(uint16_t*)&buf[2]; + } + /* copy to fftwIn as floats */ + buf += 16384 - (fftSize * 2); + for(i=0; i < fftSize; i++) { + fftwIn[i][0] = buf[i*2] * window[i] * 1.0f / 128.0f; + fftwIn[i][1] = buf[i*2+1] * window[i] * 1.0f / 128.0f; + } + 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 + int k = i ^ (fftSize >> 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; + } + } else { + return -1; + } +} + +static void usage() { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF.\n"); + fprintf(stderr, "\t[-a amp_enable] # RX/TX 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[-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[-x gain_db] # TX VGA (IF) gain, 0-47dB, 1dB steps\n"); + fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 0-%lu\n", (uint64_t)1<<32); +} + +static hackrf_device* device = NULL; + +#ifdef _MSC_VER +BOOL WINAPI +sighandler(int signum) { + if (CTRL_C_EVENT == signum) { + fprintf(stderr, "Caught signal %d\n", signum); + do_exit = true; + return TRUE; + } + return FALSE; +} +#else +void sigint_callback_handler(int signum) { + fprintf(stderr, "Caught signal %d\n", signum); + do_exit = true; +} +#endif + +int main(int argc, char** argv) { + int opt, i, result, ifreq = 0; + bool odd; + 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, txvga_gain=0; + uint16_t frequencies[MAX_FREQ_COUNT]; + uint32_t num_samples = DEFAULT_SAMPLE_COUNT; + + while( (opt = getopt(argc, argv, "a:f:p:l:g:x:d:n:")) != EOF ) { + result = HACKRF_SUCCESS; + switch( opt ) + { + case 'd': + serial_number = optarg; + break; + + case 'a': + amp = true; + result = parse_u32(optarg, &_enable); + break; + + 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': + antenna = true; + result = parse_u32(optarg, &antenna_enable); + break; + + case 'l': + result = parse_u32(optarg, &lna_gain); + break; + + case 'g': + result = parse_u32(optarg, &vga_gain); + break; + + case 'x': + result = parse_u32(optarg, &txvga_gain); + break; + + case 'n': + result = parse_u32(optarg, &num_samples); + break; + + default: + fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg); + usage(); + return EXIT_FAILURE; + } + + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "argument error: '-%c %s' %s (%d)\n", opt, optarg, hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + } + + if (lna_gain % 8) + fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n"); + + if (vga_gain % 2) + fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n"); + + if (num_samples % 0x4000) { + fprintf(stderr, "warning: num_samples (-s) must be a multiple of 16384\n"); + return EXIT_FAILURE; + } + + if( amp ) { + if( amp_enable > 1 ) { + fprintf(stderr, "argument error: amp_enable shall be 0 or 1.\n"); + usage(); + return EXIT_FAILURE; + } + } + + if (antenna) { + if (antenna_enable > 1) { + fprintf(stderr, "argument error: antenna_enable shall be 0 or 1.\n"); + usage(); + return EXIT_FAILURE; + } + } + + if (ifreq == 0) { + fprintf(stderr, "argument error: must specify sweep frequency range (-f).\n"); + usage(); + return EXIT_FAILURE; + } + + fftSize = 64; + 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); + pwr = (float*)fftwf_malloc(sizeof(float) * fftSize); + window = (float*)fftwf_malloc(sizeof(float) * fftSize); + for (i = 0; i < fftSize; i++) { + window[i] = 0.5f * (1.0f - cos(2 * M_PI * i / (fftSize - 1))); + } + + result = hackrf_init(); + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + result = hackrf_open_by_serial(serial_number, &device); + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + fd = fopen(path, "wb"); + if( fd == NULL ) { + fprintf(stderr, "Failed to open file: %s\n", path); + return EXIT_FAILURE; + } + /* Change fd buffer to have bigger one to store or read data on/to HDD */ + result = setvbuf(fd , NULL , _IOFBF , FD_BUFFER_SIZE); + if( result != 0 ) { + fprintf(stderr, "setvbuf() failed: %d\n", result); + usage(); + return EXIT_FAILURE; + } + +#ifdef _MSC_VER + SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); +#else + signal(SIGINT, &sigint_callback_handler); + signal(SIGILL, &sigint_callback_handler); + signal(SIGFPE, &sigint_callback_handler); + signal(SIGSEGV, &sigint_callback_handler); + signal(SIGTERM, &sigint_callback_handler); + signal(SIGABRT, &sigint_callback_handler); +#endif + fprintf(stderr, "call hackrf_sample_rate_set(%.03f MHz)\n", + ((float)DEFAULT_SAMPLE_RATE_HZ/(float)FREQ_ONE_MHZ)); + result = hackrf_set_sample_rate_manual(device, DEFAULT_SAMPLE_RATE_HZ, 1); + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "hackrf_sample_rate_set() failed: %s (%d)\n", + hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%.03f MHz)\n", + ((float)DEFAULT_BASEBAND_FILTER_BANDWIDTH/(float)FREQ_ONE_MHZ)); + result = hackrf_set_baseband_filter_bandwidth(device, DEFAULT_BASEBAND_FILTER_BANDWIDTH); + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", + hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + result = hackrf_set_vga_gain(device, vga_gain); + result |= hackrf_set_lna_gain(device, lna_gain); + result |= hackrf_start_rx(device, rx_callback, NULL); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + result = hackrf_init_sweep(device, frequencies, ifreq, num_samples); + if( result != HACKRF_SUCCESS ) { + fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n", + hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + + if (amp) { + fprintf(stderr, "call hackrf_set_amp_enable(%u)\n", amp_enable); + result = hackrf_set_amp_enable(device, (uint8_t)amp_enable); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_set_amp_enable() failed: %s (%d)\n", + hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + } + + if (antenna) { + fprintf(stderr, "call hackrf_set_antenna_enable(%u)\n", antenna_enable); + result = hackrf_set_antenna_enable(device, (uint8_t)antenna_enable); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_set_antenna_enable() failed: %s (%d)\n", + hackrf_error_name(result), result); + usage(); + return EXIT_FAILURE; + } + } + + gettimeofday(&t_start, NULL); + gettimeofday(&time_start, NULL); + + fprintf(stderr, "Stop with Ctrl-C\n"); + while((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) { + uint32_t byte_count_now; + struct timeval time_now; + float time_difference, rate; + sleep(1); + + gettimeofday(&time_now, NULL); + + byte_count_now = byte_count; + byte_count = 0; + + time_difference = TimevalDiff(&time_now, &time_start); + rate = (float)byte_count_now / time_difference; + fprintf(stderr, "%4.1f MiB / %5.3f sec = %4.1f MiB/second\n", + (byte_count_now / 1e6f), time_difference, (rate / 1e6f) ); + + time_start = time_now; + + if (byte_count_now == 0) { + exit_code = EXIT_FAILURE; + fprintf(stderr, "\nCouldn't transfer any bytes for one second.\n"); + break; + } + } + + result = hackrf_is_streaming(device); + if (do_exit) { + fprintf(stderr, "\nUser cancel, exiting...\n"); + } else { + fprintf(stderr, "\nExiting... hackrf_is_streaming() result: %s (%d)\n", + hackrf_error_name(result), result); + } + + gettimeofday(&t_end, NULL); + time_diff = TimevalDiff(&t_end, &t_start); + fprintf(stderr, "Total time: %5.5f s\n", time_diff); + + if(device != NULL) { + result = hackrf_stop_rx(device); + if(result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_stop_rx() failed: %s (%d)\n", + hackrf_error_name(result), result); + } else { + fprintf(stderr, "hackrf_stop_rx() done\n"); + } + + result = hackrf_close(device); + if(result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_close() failed: %s (%d)\n", + hackrf_error_name(result), result); + } else { + fprintf(stderr, "hackrf_close() done\n"); + } + + hackrf_exit(); + fprintf(stderr, "hackrf_exit() done\n"); + } + + if(fd != NULL) { + fclose(fd); + fd = NULL; + fprintf(stderr, "fclose(fd) done\n"); + } + fprintf(stderr, "exit\n"); + return exit_code; +} diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 61824cf1..3b57a5a6 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -67,9 +67,10 @@ typedef enum { HACKRF_VENDOR_REQUEST_SET_TXVGA_GAIN = 21, HACKRF_VENDOR_REQUEST_ANTENNA_ENABLE = 23, HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24, - HACKRF_VENDOR_REQUEST_READ_WCID = 25, - HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS = 26, - HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 27, + // USB_WCID_VENDOR_REQ = 25 + HACKRF_VENDOR_REQUEST_INIT_SWEEP = 26, + HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS = 27, + HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 28, } hackrf_vendor_request; typedef enum { @@ -1420,6 +1421,7 @@ static int create_transfer_thread(hackrf_device* device, if( device->transfer_thread_started == false ) { device->streaming = false; + do_exit = false; result = prepare_transfers( device, endpoint_address, @@ -1698,6 +1700,33 @@ uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz) return p->bandwidth_hz; } +/* Initialise sweep mode with alist of frequencies and dwell time in samples */ +int ADDCALL hackrf_init_sweep(hackrf_device* device, uint16_t* frequency_list, int length, uint32_t dwell_time) +{ + int result, i; + int size = length * sizeof(frequency_list[0]); + + for(i=0; iusb_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, + size, + 0 + ); + + if (result < size) { + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + /* Retrieve list of Operacake board addresses * boards must be *uint8_t[8] */ @@ -1750,8 +1779,7 @@ int ADDCALL hackrf_set_operacake_ports(hackrf_device* device, 0 ); - if (result != 0) - { + if (result != 0) { return HACKRF_ERROR_LIBUSB; } else { return HACKRF_SUCCESS; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index ef7f0958..584dd292 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -207,6 +207,10 @@ extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_fil extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz); /* Compute best default value depending on sample rate (auto filter) */ extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz); +/* Start scan mode */ +extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device, + uint16_t* frequency_list, + int length, uint32_t dwell_time); /* Operacake functions */ int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards); diff --git a/host/python/max2837_dump.py b/host/python/max2837_dump.py deleted file mode 100755 index 6624737b..00000000 --- a/host/python/max2837_dump.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012 Jared Boone -# -# This file is part of HackRF. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import usb -import struct -import sys - -device = usb.core.find(idVendor=0x1d50, idProduct=0x604b) -if device: - print 'Find: HackRF Jawbreaker' -else: - device = usb.core.find(idVendor=0x1d50, idProduct=0x6089) - if device: - print 'Find: HackRF One' - else: - device = usb.core.find(idVendor=0x1d50, idProduct=0xcc15) - if device: - print 'Find: rad1o' - else: - print 'Not find any HackRF device.' - sys.exit() -device.set_configuration() - -def read_max2837_register(register_number): - return struct.unpack('