Merge branch 'master' into rad1o
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
This repository contains hardware designs and software for HackRF, a project to
|
This repository contains hardware designs and software for HackRF,
|
||||||
produce a low cost, open source software radio platform.
|
a low cost, open source Software Defined Radio platform.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -27,22 +27,28 @@ To build and install a standard firmware image for HackRF One:
|
|||||||
$ cd hackrf_usb
|
$ cd hackrf_usb
|
||||||
$ mkdir build
|
$ mkdir build
|
||||||
$ cd build
|
$ cd build
|
||||||
$ cmake .. -DBOARD=HACKRF_ONE
|
$ cmake ..
|
||||||
$ make
|
$ make
|
||||||
$ hackrf_spiflash -w hackrf_usb.bin
|
$ hackrf_spiflash -w hackrf_usb.bin
|
||||||
|
|
||||||
If you have a Jawbreaker, use -DBOARD=JAWBREAKER instead.
|
If you have a Jawbreaker, add -DBOARD=JAWBREAKER to the cmake command.
|
||||||
If you have a rad1o, use -DBOARD=RAD1O instead.
|
If you have a rad1o, use -DBOARD=RAD1O instead.
|
||||||
|
|
||||||
For loading firmware into RAM with DFU you will also need:
|
|
||||||
|
|
||||||
http://dfu-util.gnumonks.org/
|
It is possible to use a USB Device Firmware Upgrade (DFU) method to load
|
||||||
|
firmware into RAM. This is normally only required to recover a device that has
|
||||||
|
had faulty firmware loaded, but it can also be useful for firmware developers.
|
||||||
|
|
||||||
|
For loading firmware into RAM with DFU you will need:
|
||||||
|
|
||||||
|
http://dfu-util.sourceforge.net/
|
||||||
|
|
||||||
To start up HackRF One in DFU mode, hold down the DFU button while powering it
|
To start up HackRF One in DFU mode, hold down the DFU button while powering it
|
||||||
on or while pressing and releasing the RESET button. Release the DFU button
|
on or while pressing and releasing the RESET button. Release the DFU button
|
||||||
after the 3V3 LED illuminates.
|
after the 3V3 LED illuminates.
|
||||||
|
|
||||||
A .dfu file is built by default when building firmware. Alternatively you can
|
A .dfu file is built by default when building firmware. Alternatively you can
|
||||||
load a known good .dfu file from a release package with:
|
use a known good .dfu file from a release package. Load the firmware into RAM
|
||||||
|
with:
|
||||||
|
|
||||||
$ dfu-util --device 1fc9:000c --alt 0 --download hackrf_usb.dfu
|
$ dfu-util --device 1fc9:000c --alt 0 --download hackrf_usb.dfu
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "i2c_bus.h"
|
#include "i2c_bus.h"
|
||||||
#include "i2c_lpc.h"
|
#include "i2c_lpc.h"
|
||||||
#include <libopencm3/lpc43xx/cgu.h>
|
#include <libopencm3/lpc43xx/cgu.h>
|
||||||
|
#include <libopencm3/lpc43xx/ccu.h>
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
#include <libopencm3/lpc43xx/ssp.h>
|
||||||
|
|
||||||
@ -743,6 +744,72 @@ void cpu_clock_init(void)
|
|||||||
|
|
||||||
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1)
|
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1)
|
||||||
| CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
|
| CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||||
|
|
||||||
|
/* Disable unused clocks */
|
||||||
|
/* Start with PLLs */
|
||||||
|
CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1);
|
||||||
|
|
||||||
|
/* Dividers */
|
||||||
|
CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1);
|
||||||
|
CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1);
|
||||||
|
CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1);
|
||||||
|
CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1);
|
||||||
|
CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1);
|
||||||
|
|
||||||
|
/* Base clocks */
|
||||||
|
CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */
|
||||||
|
CGU_BASE_USB1_CLK = CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */
|
||||||
|
CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1);
|
||||||
|
CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1);
|
||||||
|
CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1);
|
||||||
|
CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1);
|
||||||
|
CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1);
|
||||||
|
CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1);
|
||||||
|
CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1);
|
||||||
|
CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1);
|
||||||
|
CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1);
|
||||||
|
CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1);
|
||||||
|
CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1);
|
||||||
|
CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1);
|
||||||
|
CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1);
|
||||||
|
|
||||||
|
/* Disable unused peripheral clocks */
|
||||||
|
CCU1_CLK_APB1_CAN1_CFG = 0;
|
||||||
|
CCU1_CLK_APB1_I2S_CFG = 0;
|
||||||
|
CCU1_CLK_APB1_MOTOCONPWM_CFG = 0;
|
||||||
|
CCU1_CLK_APB3_ADC0_CFG = 0;
|
||||||
|
CCU1_CLK_APB3_ADC1_CFG = 0;
|
||||||
|
CCU1_CLK_APB3_CAN0_CFG = 0;
|
||||||
|
CCU1_CLK_APB3_DAC_CFG = 0;
|
||||||
|
CCU1_CLK_M4_DMA_CFG = 0;
|
||||||
|
CCU1_CLK_M4_EMC_CFG = 0;
|
||||||
|
CCU1_CLK_M4_EMCDIV_CFG = 0;
|
||||||
|
CCU1_CLK_M4_ETHERNET_CFG = 0;
|
||||||
|
CCU1_CLK_M4_LCD_CFG = 0;
|
||||||
|
CCU1_CLK_M4_QEI_CFG = 0;
|
||||||
|
CCU1_CLK_M4_RITIMER_CFG = 0;
|
||||||
|
CCU1_CLK_M4_SCT_CFG = 0;
|
||||||
|
CCU1_CLK_M4_SDIO_CFG = 0;
|
||||||
|
CCU1_CLK_M4_SPIFI_CFG = 0;
|
||||||
|
CCU1_CLK_M4_TIMER0_CFG = 0;
|
||||||
|
CCU1_CLK_M4_TIMER1_CFG = 0;
|
||||||
|
CCU1_CLK_M4_TIMER2_CFG = 0;
|
||||||
|
CCU1_CLK_M4_TIMER3_CFG = 0;
|
||||||
|
CCU1_CLK_M4_UART1_CFG = 0;
|
||||||
|
CCU1_CLK_M4_USART0_CFG = 0;
|
||||||
|
CCU1_CLK_M4_USART2_CFG = 0;
|
||||||
|
CCU1_CLK_M4_USART3_CFG = 0;
|
||||||
|
CCU1_CLK_M4_USB1_CFG = 0;
|
||||||
|
CCU1_CLK_M4_VADC_CFG = 0;
|
||||||
|
// CCU1_CLK_SPIFI_CFG = 0;
|
||||||
|
// CCU1_CLK_USB1_CFG = 0;
|
||||||
|
// CCU1_CLK_VADC_CFG = 0;
|
||||||
|
// CCU2_CLK_APB0_UART1_CFG = 0;
|
||||||
|
// CCU2_CLK_APB0_USART0_CFG = 0;
|
||||||
|
// CCU2_CLK_APB2_USART2_CFG = 0;
|
||||||
|
// CCU2_CLK_APB2_USART3_CFG = 0;
|
||||||
|
// CCU2_CLK_APLL_CFG = 0;
|
||||||
|
// CCU2_CLK_SDIO_CFG = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -868,10 +935,6 @@ void pin_setup(void) {
|
|||||||
|
|
||||||
scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_NOPULL);
|
scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_NOPULL);
|
||||||
|
|
||||||
/* Disable unused clock outputs. They generate noise. */
|
|
||||||
scu_pinmux(CLK0, SCU_CLK_IN | SCU_CONF_FUNCTION7);
|
|
||||||
scu_pinmux(CLK2, SCU_CLK_IN | SCU_CONF_FUNCTION7);
|
|
||||||
|
|
||||||
/* Configure USB indicators */
|
/* Configure USB indicators */
|
||||||
#if (defined JELLYBEAN || defined JAWBREAKER)
|
#if (defined JELLYBEAN || defined JAWBREAKER)
|
||||||
scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3);
|
scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3);
|
||||||
|
@ -31,31 +31,53 @@
|
|||||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||||
#define FREQ_GRANULARITY 1000000
|
#define FREQ_GRANULARITY 1000000
|
||||||
#define MIN_FREQ 1
|
#define MAX_RANGES 10
|
||||||
#define MAX_FREQ 6000
|
|
||||||
#define MAX_FREQ_COUNT 1000
|
|
||||||
#define THROWAWAY_BUFFERS 2
|
#define THROWAWAY_BUFFERS 2
|
||||||
|
|
||||||
volatile bool start_sweep_mode = false;
|
volatile bool start_sweep_mode = false;
|
||||||
static uint64_t sweep_freq;
|
static uint64_t sweep_freq;
|
||||||
bool odd = true;
|
static uint16_t frequencies[MAX_RANGES * 2];
|
||||||
static uint16_t frequencies[MAX_FREQ_COUNT];
|
static unsigned char data[9 + MAX_RANGES * 2 * sizeof(frequencies[0])];
|
||||||
static uint16_t frequency_count = 0;
|
static uint16_t num_ranges = 0;
|
||||||
static uint32_t dwell_blocks = 0;
|
static uint32_t dwell_blocks = 0;
|
||||||
|
static uint32_t step_width = 0;
|
||||||
|
static uint32_t offset = 0;
|
||||||
|
static enum sweep_style style = LINEAR;
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_init_sweep(
|
usb_request_status_t usb_vendor_request_init_sweep(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
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) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
dwell_time = (endpoint->setup.index << 16) | endpoint->setup.value;
|
num_samples = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||||
dwell_blocks = dwell_time / 0x4000;
|
dwell_blocks = num_samples / 0x4000;
|
||||||
frequency_count = endpoint->setup.length / sizeof(uint16_t);
|
if(1 > dwell_blocks) {
|
||||||
usb_transfer_schedule_block(endpoint->out, &frequencies,
|
return USB_REQUEST_STATUS_STALL;
|
||||||
endpoint->setup.length, NULL, NULL);
|
}
|
||||||
|
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) {
|
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||||
sweep_freq = frequencies[0];
|
step_width = ((uint32_t)(data[3]) << 24) | ((uint32_t)(data[2]) << 16)
|
||||||
set_freq(sweep_freq*FREQ_GRANULARITY);
|
| ((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 = (uint64_t)frequencies[0] * FREQ_GRANULARITY;
|
||||||
|
set_freq(sweep_freq + offset);
|
||||||
start_sweep_mode = true;
|
start_sweep_mode = true;
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
}
|
}
|
||||||
@ -64,8 +86,9 @@ usb_request_status_t usb_vendor_request_init_sweep(
|
|||||||
|
|
||||||
void sweep_mode(void) {
|
void sweep_mode(void) {
|
||||||
unsigned int blocks_queued = 0;
|
unsigned int blocks_queued = 0;
|
||||||
unsigned int phase = 0;
|
unsigned int phase = 1;
|
||||||
unsigned int ifreq = 0;
|
bool odd = true;
|
||||||
|
uint16_t range = 0;
|
||||||
|
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
bool transfer = false;
|
bool transfer = false;
|
||||||
@ -88,8 +111,16 @@ void sweep_mode(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (transfer) {
|
if (transfer) {
|
||||||
*(uint16_t*)buffer = 0x7F7F;
|
*buffer = 0x7f;
|
||||||
*(uint16_t*)(buffer+2) = sweep_freq;
|
*(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) {
|
if (blocks_queued > THROWAWAY_BUFFERS) {
|
||||||
usb_transfer_schedule_block(
|
usb_transfer_schedule_block(
|
||||||
&usb_endpoint_bulk_in,
|
&usb_endpoint_bulk_in,
|
||||||
@ -102,10 +133,27 @@ void sweep_mode(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((dwell_blocks + THROWAWAY_BUFFERS) <= blocks_queued) {
|
if ((dwell_blocks + THROWAWAY_BUFFERS) <= blocks_queued) {
|
||||||
if(++ifreq >= frequency_count)
|
if(INTERLEAVED == style) {
|
||||||
ifreq = 0;
|
if(!odd && ((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY))) {
|
||||||
sweep_freq = frequencies[ifreq];
|
range = (range + 1) % num_ranges;
|
||||||
set_freq(sweep_freq*FREQ_GRANULARITY);
|
sweep_freq = (uint64_t)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 = (uint64_t)frequencies[range*2] * FREQ_GRANULARITY;
|
||||||
|
} else {
|
||||||
|
sweep_freq += step_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_freq(sweep_freq + offset);
|
||||||
blocks_queued = 0;
|
blocks_queued = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __USB_API_SCAN_H__
|
#ifndef __USB_API_SWEEP_H__
|
||||||
#define __USB_API_SCAN_H__
|
#define __USB_API_SWEEP_H__
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <usb_type.h>
|
#include <usb_type.h>
|
||||||
@ -28,9 +28,14 @@
|
|||||||
|
|
||||||
extern volatile bool start_sweep_mode;
|
extern volatile bool start_sweep_mode;
|
||||||
|
|
||||||
|
enum sweep_style {
|
||||||
|
LINEAR = 0,
|
||||||
|
INTERLEAVED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_init_sweep(
|
usb_request_status_t usb_vendor_request_init_sweep(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||||
|
|
||||||
void sweep_mode(void);
|
void sweep_mode(void);
|
||||||
|
|
||||||
#endif /* __USB_API_SPCAN_H__ */
|
#endif /* __USB_API_SWEEP_H__ */
|
||||||
|
26
host/cmake/set_release.cmake
Normal file
26
host/cmake/set_release.cmake
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#set(RELEASE "")
|
||||||
|
|
||||||
|
if(NOT DEFINED RELEASE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git log -n 1 --format=%h
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
RESULT_VARIABLE GIT_EXIT_VALUE
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_VARIABLE GIT_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if (GIT_EXIT_VALUE)
|
||||||
|
set(RELEASE "unknown")
|
||||||
|
else (GIT_EXIT_VALUE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git status -s --untracked-files=no
|
||||||
|
OUTPUT_VARIABLE DIRTY
|
||||||
|
)
|
||||||
|
if ( NOT "${DIRTY}" STREQUAL "" )
|
||||||
|
set(DIRTY_FLAG "*")
|
||||||
|
else()
|
||||||
|
set(DIRTY_FLAG "")
|
||||||
|
endif()
|
||||||
|
set(RELEASE "git-${GIT_VERSION}${DIRTY_FLAG}")
|
||||||
|
endif (GIT_EXIT_VALUE)
|
||||||
|
endif()
|
@ -23,11 +23,9 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(hackrf-tools C)
|
project(hackrf-tools C)
|
||||||
set(MAJOR_VERSION 0)
|
|
||||||
set(MINOR_VERSION 5)
|
|
||||||
set(PACKAGE hackrf-tools)
|
set(PACKAGE hackrf-tools)
|
||||||
set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION})
|
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
|
||||||
set(VERSION ${VERSION_STRING})
|
add_definitions(-DTOOL_RELEASE="${RELEASE}")
|
||||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -26,14 +26,11 @@ set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX"
|
|||||||
INCLUDE(FindPkgConfig)
|
INCLUDE(FindPkgConfig)
|
||||||
|
|
||||||
SET(TOOLS
|
SET(TOOLS
|
||||||
hackrf_max2837
|
|
||||||
hackrf_si5351c
|
|
||||||
hackrf_transfer
|
hackrf_transfer
|
||||||
hackrf_rffc5071
|
|
||||||
hackrf_spiflash
|
hackrf_spiflash
|
||||||
hackrf_cpldjtag
|
hackrf_cpldjtag
|
||||||
hackrf_info
|
hackrf_info
|
||||||
hackrf_operacake
|
hackrf_debug
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -120,13 +120,6 @@ int main(int argc, char** argv)
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != HACKRF_SUCCESS) {
|
|
||||||
fprintf(stderr, "argument error: %s (%d)\n",
|
|
||||||
hackrf_error_name(result), result);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
|
490
host/hackrf-tools/src/hackrf_debug.c
Normal file
490
host/hackrf-tools/src/hackrf_debug.c
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||||
|
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||||
|
* Copyright 2017 Dominic Spill <dominicgs@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <hackrf.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#ifndef bool
|
||||||
|
typedef int bool;
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REGISTER_INVALID 32767
|
||||||
|
|
||||||
|
int parse_int(char* s, uint16_t* const value) {
|
||||||
|
uint_fast8_t base = 10;
|
||||||
|
char* s_end;
|
||||||
|
long long_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;
|
||||||
|
long_value = strtol(s, &s_end, base);
|
||||||
|
if( (s != s_end) && (*s_end == 0) ) {
|
||||||
|
*value = (uint16_t)long_value;
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int max2837_read_register(hackrf_device* device, const uint16_t register_number) {
|
||||||
|
uint16_t register_value;
|
||||||
|
int result = hackrf_max2837_read(device, (uint8_t)register_number, ®ister_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("[%2d] -> 0x%03x\n", register_number, register_value);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_max2837_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max2837_read_registers(hackrf_device* device) {
|
||||||
|
uint16_t register_number;
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
|
||||||
|
for(register_number=0; register_number<32; register_number++) {
|
||||||
|
result = max2837_read_register(device, register_number);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max2837_write_register(
|
||||||
|
hackrf_device* device,
|
||||||
|
const uint16_t register_number,
|
||||||
|
const uint16_t register_value
|
||||||
|
) {
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
result = hackrf_max2837_write(device, (uint8_t)register_number, register_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("0x%03x -> [%2d]\n", register_value, register_number);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si5351c_read_register(hackrf_device* device, const uint16_t register_number) {
|
||||||
|
uint16_t register_value;
|
||||||
|
int result = hackrf_si5351c_read(device, register_number, ®ister_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("[%3d] -> 0x%02x\n", register_number, register_value);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_si5351c_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si5351c_read_registers(hackrf_device* device) {
|
||||||
|
uint16_t register_number;
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
|
||||||
|
for(register_number=0; register_number<256; register_number++) {
|
||||||
|
result = si5351c_read_register(device, register_number);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si5351c_write_register(
|
||||||
|
hackrf_device* device,
|
||||||
|
const uint16_t register_number,
|
||||||
|
const uint16_t register_value
|
||||||
|
) {
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
result = hackrf_si5351c_write(device, register_number, register_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("0x%2x -> [%3d]\n", register_value, register_number);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) {
|
||||||
|
uint_fast8_t i;
|
||||||
|
uint_fast8_t reg_base;
|
||||||
|
uint16_t parameters[8];
|
||||||
|
uint32_t p1,p2,p3,r_div;
|
||||||
|
uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128};
|
||||||
|
|
||||||
|
printf("MS%d:", ms_number);
|
||||||
|
if(ms_number <6){
|
||||||
|
reg_base = 42 + (ms_number * 8);
|
||||||
|
for(i=0; i<8; i++) {
|
||||||
|
uint_fast8_t reg_number = reg_base + i;
|
||||||
|
int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p1 = ((parameters[2] & 0x03) << 16)
|
||||||
|
| (parameters[3] << 8)
|
||||||
|
| parameters[4];
|
||||||
|
p2 = ((parameters[5] & 0x0F) << 16)
|
||||||
|
| (parameters[6] << 8)
|
||||||
|
| parameters[7];
|
||||||
|
p3 = ((parameters[5] & 0xF0) << 12)
|
||||||
|
| (parameters[0] << 8)
|
||||||
|
| parameters[1];
|
||||||
|
r_div = (parameters[2] >> 4) & 0x7;
|
||||||
|
|
||||||
|
printf("\tp1 = %u\n", p1);
|
||||||
|
printf("\tp2 = %u\n", p2);
|
||||||
|
printf("\tp3 = %u\n", p3);
|
||||||
|
if(p3)
|
||||||
|
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] );
|
||||||
|
} else {
|
||||||
|
// MS6 and 7 are integer only
|
||||||
|
unsigned int parms;
|
||||||
|
reg_base = 90;
|
||||||
|
|
||||||
|
for(i=0; i<3; i++) {
|
||||||
|
uint_fast8_t reg_number = reg_base + i;
|
||||||
|
int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ;
|
||||||
|
parms = (ms_number == 6) ? parameters[0] : parameters[1];
|
||||||
|
printf("\tp1_int = %u\n", parms);
|
||||||
|
if(parms)
|
||||||
|
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] );
|
||||||
|
}
|
||||||
|
printf("\toutput divider = %u\n", div_lut[r_div]);
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si5351c_read_configuration(hackrf_device* device) {
|
||||||
|
uint_fast8_t ms_number;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
for(ms_number=0; ms_number<8; ms_number++) {
|
||||||
|
result = si5351c_read_multisynth_config(device, ms_number);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFFC5071 and RFFC5072 are similar components with a compatible control
|
||||||
|
* interface. RFFC5071 was used on some early prototypes, so the libhackrf API
|
||||||
|
* calls are named that way. Because we use RFFC5072 on production hardware,
|
||||||
|
* we use that name here and present it to the user.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int rffc5072_read_register(hackrf_device* device, const uint16_t register_number) {
|
||||||
|
uint16_t register_value;
|
||||||
|
int result = hackrf_rffc5071_read(device, (uint8_t)register_number, ®ister_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("[%2d] -> 0x%03x\n", register_number, register_value);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_rffc5071_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rffc5072_read_registers(hackrf_device* device) {
|
||||||
|
uint16_t register_number;
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
|
||||||
|
for(register_number=0; register_number<31; register_number++) {
|
||||||
|
result = rffc5072_read_register(device, register_number);
|
||||||
|
if( result != HACKRF_SUCCESS ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rffc5072_write_register(
|
||||||
|
hackrf_device* device,
|
||||||
|
const uint16_t register_number,
|
||||||
|
const uint16_t register_value
|
||||||
|
) {
|
||||||
|
int result = HACKRF_SUCCESS;
|
||||||
|
result = hackrf_rffc5071_write(device, (uint8_t)register_number, register_value);
|
||||||
|
|
||||||
|
if( result == HACKRF_SUCCESS ) {
|
||||||
|
printf("0x%03x -> [%2d]\n", register_value, register_number);
|
||||||
|
} else {
|
||||||
|
printf("hackrf_rffc5071_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum parts {
|
||||||
|
PART_NONE = 0,
|
||||||
|
PART_MAX2837 = 1,
|
||||||
|
PART_SI5351C = 2,
|
||||||
|
PART_RFFC5072 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
int read_register(hackrf_device* device, uint8_t part,
|
||||||
|
const uint16_t register_number) {
|
||||||
|
switch (part) {
|
||||||
|
case PART_MAX2837:
|
||||||
|
return max2837_read_register(device, register_number);
|
||||||
|
case PART_SI5351C:
|
||||||
|
return si5351c_read_register(device, register_number);
|
||||||
|
case PART_RFFC5072:
|
||||||
|
return rffc5072_read_register(device, register_number);
|
||||||
|
}
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_registers(hackrf_device* device, uint8_t part) {
|
||||||
|
switch (part) {
|
||||||
|
case PART_MAX2837:
|
||||||
|
return max2837_read_registers(device);
|
||||||
|
case PART_SI5351C:
|
||||||
|
return si5351c_read_registers(device);
|
||||||
|
case PART_RFFC5072:
|
||||||
|
return rffc5072_read_registers(device);
|
||||||
|
}
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_register(hackrf_device* device, uint8_t part,
|
||||||
|
const uint16_t register_number,
|
||||||
|
const uint16_t register_value) {
|
||||||
|
switch (part) {
|
||||||
|
case PART_MAX2837:
|
||||||
|
return max2837_write_register(device, register_number, register_value);
|
||||||
|
case PART_SI5351C:
|
||||||
|
return si5351c_write_register(device, register_number, register_value);
|
||||||
|
case PART_RFFC5072:
|
||||||
|
return rffc5072_write_register(device, register_number, register_value);
|
||||||
|
}
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
printf("\nUsage:\n");
|
||||||
|
printf("\t-h, --help: this help\n");
|
||||||
|
printf("\t-n, --register <n>: set register number for read/write operations\n");
|
||||||
|
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
|
||||||
|
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
|
||||||
|
printf("\t-c, --config: print SI5351C multisynth configuration information\n");
|
||||||
|
printf("\t-d, --device <s>: specify a particular device by serial number\n");
|
||||||
|
printf("\t-m, --max2837: target MAX2837\n");
|
||||||
|
printf("\t-s, --si5351c: target SI5351C\n");
|
||||||
|
printf("\t-f, --rffc5072: target RFFC5072\n");
|
||||||
|
printf("\nExamples:\n");
|
||||||
|
printf("\thackrf_debug --si5351c -n 0 -r # reads from si5351c register 0\n");
|
||||||
|
printf("\thackrf_debug --si5351c -c # displays si5351c multisynth configuration\n");
|
||||||
|
printf("\thackrf_debug --rffc5072 -r # reads all rffc5072 registers\n");
|
||||||
|
printf("\thackrf_debug --max2837 -n 10 -w 22 # writes max2837 register 10 with 22 decimal\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{ "config", no_argument, 0, 'c' },
|
||||||
|
{ "register", required_argument, 0, 'n' },
|
||||||
|
{ "write", required_argument, 0, 'w' },
|
||||||
|
{ "read", no_argument, 0, 'r' },
|
||||||
|
{ "device", no_argument, 0, 'd' },
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ "max2837", no_argument, 0, 'm' },
|
||||||
|
{ "si5351c", no_argument, 0, 's' },
|
||||||
|
{ "rffc5072", no_argument, 0, 'f' },
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int opt;
|
||||||
|
uint16_t register_number = REGISTER_INVALID;
|
||||||
|
uint16_t register_value;
|
||||||
|
hackrf_device* device = NULL;
|
||||||
|
int option_index = 0;
|
||||||
|
bool read = false;
|
||||||
|
bool write = false;
|
||||||
|
bool dump_config = false;
|
||||||
|
uint8_t part = PART_NONE;
|
||||||
|
const char* serial_number = NULL;
|
||||||
|
|
||||||
|
int result = hackrf_init();
|
||||||
|
if(result) {
|
||||||
|
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfh?", long_options, &option_index)) != EOF ) {
|
||||||
|
switch( opt ) {
|
||||||
|
case 'n':
|
||||||
|
result = parse_int(optarg, ®ister_number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
write = true;
|
||||||
|
result = parse_int(optarg, ®ister_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
read = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
dump_config = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
serial_number = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
if(part != PART_NONE) {
|
||||||
|
fprintf(stderr, "Only one part can be specified.'\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
part = PART_MAX2837;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if(part != PART_NONE) {
|
||||||
|
fprintf(stderr, "Only one part can be specified.'\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
part = PART_SI5351C;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
if(part != PART_NONE) {
|
||||||
|
fprintf(stderr, "Only one part can be specified.'\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
part = PART_RFFC5072;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
usage();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != HACKRF_SUCCESS) {
|
||||||
|
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(write && read) {
|
||||||
|
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(write && dump_config) {
|
||||||
|
fprintf(stderr, "Config and write options are mutually exclusive.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dump_config && part != PART_SI5351C) {
|
||||||
|
fprintf(stderr, "Config option is only valid for SI5351C.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(write || read || dump_config)) {
|
||||||
|
fprintf(stderr, "Specify read, write, or config option.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(part == PART_NONE) {
|
||||||
|
fprintf(stderr, "Specify a part to read, write, or print config from.\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = hackrf_open_by_serial(serial_number, &device);
|
||||||
|
if(result) {
|
||||||
|
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(write) {
|
||||||
|
result = write_register(device, part, register_number, register_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(read) {
|
||||||
|
if(register_number == REGISTER_INVALID) {
|
||||||
|
result = read_registers(device, part);
|
||||||
|
} else {
|
||||||
|
result = read_register(device, part, register_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dump_config) {
|
||||||
|
si5351c_read_configuration(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = hackrf_close(device);
|
||||||
|
if(result) {
|
||||||
|
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hackrf_exit();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
@ -45,6 +45,10 @@ int main(void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("hackrf_info version: %s\n", TOOL_RELEASE);
|
||||||
|
printf("libhackrf version: %s (%s)\n", hackrf_library_release(),
|
||||||
|
hackrf_library_version());
|
||||||
|
|
||||||
list = hackrf_device_list();
|
list = hackrf_device_list();
|
||||||
|
|
||||||
if (list->devicecount < 1 ) {
|
if (list->devicecount < 1 ) {
|
||||||
|
@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
|
||||||
*
|
|
||||||
* 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 <hackrf.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#ifndef bool
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usage() {
|
|
||||||
printf("\nUsage:\n");
|
|
||||||
printf("\t-h, --help: this help\n");
|
|
||||||
printf("\t-n, --register <n>: set register number for read/write operations\n");
|
|
||||||
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
|
|
||||||
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
|
|
||||||
printf("\nExamples:\n");
|
|
||||||
printf("\t<command> -n 12 -r # reads from register 12\n");
|
|
||||||
printf("\t<command> -r # reads all registers\n");
|
|
||||||
printf("\t<command> -n 10 -w 22 # writes register 10 with 22 decimal\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{ "register", required_argument, 0, 'n' },
|
|
||||||
{ "write", required_argument, 0, 'w' },
|
|
||||||
{ "read", no_argument, 0, 'r' },
|
|
||||||
{ "help", no_argument, 0, 'h' },
|
|
||||||
{ 0, 0, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
int parse_int(char* s, uint16_t* const value) {
|
|
||||||
uint_fast8_t base = 10;
|
|
||||||
char* s_end;
|
|
||||||
long long_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;
|
|
||||||
long_value = strtol(s, &s_end, base);
|
|
||||||
if( (s != s_end) && (*s_end == 0) ) {
|
|
||||||
*value = (uint16_t)long_value;
|
|
||||||
return HACKRF_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return HACKRF_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_register(hackrf_device* device, const uint16_t register_number) {
|
|
||||||
uint16_t register_value;
|
|
||||||
int result = hackrf_max2837_read(device, (uint8_t)register_number, ®ister_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("[%2d] -> 0x%03x\n", register_number, register_value);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_max2837_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_registers(hackrf_device* device) {
|
|
||||||
uint16_t register_number;
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
|
|
||||||
for(register_number=0; register_number<32; register_number++) {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_register(
|
|
||||||
hackrf_device* device,
|
|
||||||
const uint16_t register_number,
|
|
||||||
const uint16_t register_value
|
|
||||||
) {
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
result = hackrf_max2837_write(device, (uint8_t)register_number, register_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("0x%03x -> [%2d]\n", register_value, register_number);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define REGISTER_INVALID 32767
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
int opt;
|
|
||||||
uint16_t register_number = REGISTER_INVALID;
|
|
||||||
uint16_t register_value;
|
|
||||||
hackrf_device* device = NULL;
|
|
||||||
int option_index = 0;
|
|
||||||
bool read = false;
|
|
||||||
bool write = false;
|
|
||||||
|
|
||||||
int result = hackrf_init();
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "n:rw:h?", long_options, &option_index)) != EOF ) {
|
|
||||||
switch( opt ) {
|
|
||||||
case 'n':
|
|
||||||
result = parse_int(optarg, ®ister_number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
write = true;
|
|
||||||
result = parse_int(optarg, ®ister_value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
read = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
usage();
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write && read) {
|
|
||||||
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(write || read)) {
|
|
||||||
fprintf(stderr, "Specify either read or write option.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_open(&device);
|
|
||||||
if(result) {
|
|
||||||
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write) {
|
|
||||||
result = write_register(device, register_number, register_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(read) {
|
|
||||||
if(register_number == REGISTER_INVALID) {
|
|
||||||
result = dump_registers(device);
|
|
||||||
} else {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_close(device);
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hackrf_exit();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -34,8 +34,7 @@ typedef int bool;
|
|||||||
static void usage() {
|
static void usage() {
|
||||||
printf("\nUsage:\n");
|
printf("\nUsage:\n");
|
||||||
printf("\t-h, --help: this help\n");
|
printf("\t-h, --help: this help\n");
|
||||||
printf("\t-s, --serial <s>: specify a particular device by serial number\n");
|
printf("\t-d, --device <n>: specify a particular device by serial number\n");
|
||||||
printf("\t-d, --device <n>: specify a particular device by number\n");
|
|
||||||
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
|
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
|
||||||
printf("\t-a <n>: set port A connection\n");
|
printf("\t-a <n>: set port A connection\n");
|
||||||
printf("\t-b <n>: set port B connection\n");
|
printf("\t-b <n>: set port B connection\n");
|
||||||
@ -44,7 +43,6 @@ static void usage() {
|
|||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{ "device", no_argument, 0, 'd' },
|
{ "device", no_argument, 0, 'd' },
|
||||||
{ "serial", no_argument, 0, 's' },
|
|
||||||
{ "address", no_argument, 0, 'o' },
|
{ "address", no_argument, 0, 'o' },
|
||||||
{ "list", no_argument, 0, 'v' },
|
{ "list", no_argument, 0, 'v' },
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
@ -65,7 +63,6 @@ int parse_int(char* const s, uint16_t* const value) {
|
|||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int opt;
|
int opt;
|
||||||
const char* serial_number = NULL;
|
const char* serial_number = NULL;
|
||||||
int device_index = 0;
|
|
||||||
int operacake_address = 0;
|
int operacake_address = 0;
|
||||||
int port_a = 0;
|
int port_a = 0;
|
||||||
int port_b = 0;
|
int port_b = 0;
|
||||||
@ -83,13 +80,9 @@ int main(int argc, char** argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "d:s:o:a:b:lh?", long_options, &option_index)) != EOF ) {
|
while( (opt = getopt_long(argc, argv, "d:o:a:b:lh?", long_options, &option_index)) != EOF ) {
|
||||||
switch( opt ) {
|
switch( opt ) {
|
||||||
case 'd':
|
case 'd':
|
||||||
device_index = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
serial_number = optarg;
|
serial_number = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -119,11 +112,6 @@ int main(int argc, char** argv) {
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(list || set_ports)) {
|
if(!(list || set_ports)) {
|
||||||
@ -132,20 +120,11 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serial_number != NULL) {
|
result = hackrf_open_by_serial(serial_number, &device);
|
||||||
result = hackrf_open_by_serial(serial_number, &device);
|
if (result != HACKRF_SUCCESS) {
|
||||||
} else {
|
fprintf(stderr, "hackrf_open() failed: %s (%d)\n",
|
||||||
hackrf_device_list_t* device_list = hackrf_device_list();
|
hackrf_error_name(result), result);
|
||||||
if(device_list->devicecount <= 0) {
|
return EXIT_FAILURE;
|
||||||
result = HACKRF_ERROR_NOT_FOUND;
|
|
||||||
} else {
|
|
||||||
result = hackrf_device_list_open(device_list, device_index, &device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(list) {
|
if(list) {
|
||||||
|
@ -1,212 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
|
||||||
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <hackrf.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#ifndef bool
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usage() {
|
|
||||||
printf("\nUsage:\n");
|
|
||||||
printf("\t-h, --help: this help\n");
|
|
||||||
printf("\t-n, --register <n>: set register number for read/write operations\n");
|
|
||||||
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
|
|
||||||
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
|
|
||||||
printf("\nExamples:\n");
|
|
||||||
printf("\t<command> -n 12 -r # reads from register 12\n");
|
|
||||||
printf("\t<command> -r # reads all registers\n");
|
|
||||||
printf("\t<command> -n 10 -w 514 # writes register 10 with 514 decimal\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{ "register", required_argument, 0, 'n' },
|
|
||||||
{ "write", required_argument, 0, 'w' },
|
|
||||||
{ "read", no_argument, 0, 'r' },
|
|
||||||
{ "help", no_argument, 0, 'h' },
|
|
||||||
{ 0, 0, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
int parse_int(char* s, uint16_t* const value) {
|
|
||||||
uint_fast8_t base = 10;
|
|
||||||
char* s_end;
|
|
||||||
long long_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;
|
|
||||||
long_value = strtol(s, &s_end, base);
|
|
||||||
if( (s != s_end) && (*s_end == 0) ) {
|
|
||||||
*value = (uint16_t)long_value;
|
|
||||||
return HACKRF_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return HACKRF_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_register(hackrf_device* device, const uint16_t register_number) {
|
|
||||||
uint16_t register_value;
|
|
||||||
int result = hackrf_rffc5071_read(device, (uint8_t)register_number, ®ister_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("[%2d] -> 0x%03x\n", register_number, register_value);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_rffc5071_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_registers(hackrf_device* device) {
|
|
||||||
uint16_t register_number;
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
|
|
||||||
for(register_number=0; register_number<31; register_number++) {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_register(
|
|
||||||
hackrf_device* device,
|
|
||||||
const uint16_t register_number,
|
|
||||||
const uint16_t register_value
|
|
||||||
) {
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
result = hackrf_rffc5071_write(device, (uint8_t)register_number, register_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("0x%03x -> [%2d]\n", register_value, register_number);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_rffc5071_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define REGISTER_INVALID 32767
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
int opt;
|
|
||||||
uint16_t register_number = REGISTER_INVALID;
|
|
||||||
uint16_t register_value;
|
|
||||||
hackrf_device* device = NULL;
|
|
||||||
int option_index = 0;
|
|
||||||
bool read = false;
|
|
||||||
bool write = false;
|
|
||||||
|
|
||||||
int result = hackrf_init();
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "n:rw:h?", long_options, &option_index)) != EOF ) {
|
|
||||||
switch( opt ) {
|
|
||||||
case 'n':
|
|
||||||
result = parse_int(optarg, ®ister_number);
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
write = true;
|
|
||||||
result = parse_int(optarg, ®ister_value);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
read = true;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
usage();
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write && read) {
|
|
||||||
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(write || read)) {
|
|
||||||
fprintf(stderr, "Specify either read or write option.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_open(&device);
|
|
||||||
if(result) {
|
|
||||||
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write) {
|
|
||||||
result = write_register(device, register_number, register_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(read) {
|
|
||||||
if(register_number == REGISTER_INVALID) {
|
|
||||||
result = dump_registers(device);
|
|
||||||
} else {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_close(device);
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hackrf_exit();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -1,321 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
|
||||||
*
|
|
||||||
* 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 <hackrf.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#ifndef bool
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usage() {
|
|
||||||
printf("\nUsage:\n");
|
|
||||||
printf("\t-h, --help: this help\n");
|
|
||||||
printf("\t-c, --config: print textual configuration information\n");
|
|
||||||
printf("\t-n, --register <n>: set register number for read/write operations\n");
|
|
||||||
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
|
|
||||||
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
|
|
||||||
printf("\t-s, --serial <s>: specify a particular device by serial number\n");
|
|
||||||
printf("\t-d, --device <n>: specify a particular device by number\n");
|
|
||||||
printf("\nExamples:\n");
|
|
||||||
printf("\t<command> -n 12 -r # reads from register 12\n");
|
|
||||||
printf("\t<command> -r # reads all registers\n");
|
|
||||||
printf("\t<command> -n 10 -w 22 # writes register 10 with 22 decimal\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{ "config", no_argument, 0, 'c' },
|
|
||||||
{ "register", required_argument, 0, 'n' },
|
|
||||||
{ "write", required_argument, 0, 'w' },
|
|
||||||
{ "read", no_argument, 0, 'r' },
|
|
||||||
{ "device", no_argument, 0, 'd' },
|
|
||||||
{ "serial", no_argument, 0, 's' },
|
|
||||||
{ "help", no_argument, 0, 'h' },
|
|
||||||
{ 0, 0, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
int parse_int(char* const s, uint16_t* const value) {
|
|
||||||
char* s_end = s;
|
|
||||||
const long long_value = strtol(s, &s_end, 10);
|
|
||||||
if( (s != s_end) && (*s_end == 0) ) {
|
|
||||||
*value = (uint16_t)long_value;
|
|
||||||
return HACKRF_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return HACKRF_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_register(hackrf_device* device, const uint16_t register_number) {
|
|
||||||
uint16_t register_value;
|
|
||||||
int result = hackrf_si5351c_read(device, register_number, ®ister_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("[%3d] -> 0x%02x\n", register_number, register_value);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_max2837_read() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_registers(hackrf_device* device) {
|
|
||||||
uint16_t register_number;
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
|
|
||||||
for(register_number=0; register_number<256; register_number++) {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_register(
|
|
||||||
hackrf_device* device,
|
|
||||||
const uint16_t register_number,
|
|
||||||
const uint16_t register_value
|
|
||||||
) {
|
|
||||||
int result = HACKRF_SUCCESS;
|
|
||||||
result = hackrf_si5351c_write(device, register_number, register_value);
|
|
||||||
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
printf("0x%2x -> [%3d]\n", register_value, register_number);
|
|
||||||
} else {
|
|
||||||
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define REGISTER_INVALID 32767
|
|
||||||
|
|
||||||
int dump_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) {
|
|
||||||
uint_fast8_t i;
|
|
||||||
uint_fast8_t reg_base;
|
|
||||||
uint16_t parameters[8];
|
|
||||||
uint32_t p1,p2,p3,r_div;
|
|
||||||
uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128};
|
|
||||||
|
|
||||||
printf("MS%d:", ms_number);
|
|
||||||
if(ms_number <6){
|
|
||||||
reg_base = 42 + (ms_number * 8);
|
|
||||||
for(i=0; i<8; i++) {
|
|
||||||
uint_fast8_t reg_number = reg_base + i;
|
|
||||||
int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p1 =
|
|
||||||
((parameters[2] & 0x03) << 16)
|
|
||||||
| (parameters[3] << 8)
|
|
||||||
| parameters[4]
|
|
||||||
;
|
|
||||||
p2 =
|
|
||||||
((parameters[5] & 0x0F) << 16)
|
|
||||||
| (parameters[6] << 8)
|
|
||||||
| parameters[7]
|
|
||||||
;
|
|
||||||
p3 =
|
|
||||||
((parameters[5] & 0xF0) << 12)
|
|
||||||
| (parameters[0] << 8)
|
|
||||||
| parameters[1]
|
|
||||||
;
|
|
||||||
r_div =
|
|
||||||
(parameters[2] >> 4) & 0x7
|
|
||||||
;
|
|
||||||
|
|
||||||
printf("\tp1 = %u\n", p1);
|
|
||||||
printf("\tp2 = %u\n", p2);
|
|
||||||
printf("\tp3 = %u\n", p3);
|
|
||||||
if(p3)
|
|
||||||
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] );
|
|
||||||
} else {
|
|
||||||
// MS6 and 7 are integer only
|
|
||||||
unsigned int parms;
|
|
||||||
reg_base = 90;
|
|
||||||
|
|
||||||
for(i=0; i<3; i++) {
|
|
||||||
uint_fast8_t reg_number = reg_base + i;
|
|
||||||
int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ;
|
|
||||||
parms = (ms_number == 6) ? parameters[0] : parameters[1];
|
|
||||||
printf("\tp1_int = %u\n", parms);
|
|
||||||
if(parms)
|
|
||||||
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] );
|
|
||||||
}
|
|
||||||
printf("\toutput divider = %u\n", div_lut[r_div]);
|
|
||||||
|
|
||||||
return HACKRF_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_configuration(hackrf_device* device) {
|
|
||||||
uint_fast8_t ms_number;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
for(ms_number=0; ms_number<8; ms_number++) {
|
|
||||||
result = dump_multisynth_config(device, ms_number);
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HACKRF_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
int opt;
|
|
||||||
|
|
||||||
uint16_t register_number = REGISTER_INVALID;
|
|
||||||
uint16_t register_value;
|
|
||||||
bool read = false;
|
|
||||||
bool write = false;
|
|
||||||
bool dump_config = false;
|
|
||||||
const char* serial_number = NULL;
|
|
||||||
int device_index = 0;
|
|
||||||
|
|
||||||
hackrf_device* device = NULL;
|
|
||||||
int option_index = 0;
|
|
||||||
|
|
||||||
int result = hackrf_init();
|
|
||||||
if( result ) {
|
|
||||||
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "d:s:cn:rw:h?", long_options, &option_index)) != EOF ) {
|
|
||||||
switch( opt ) {
|
|
||||||
case 'n':
|
|
||||||
result = parse_int(optarg, ®ister_number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
write = true;
|
|
||||||
result = parse_int(optarg, ®ister_value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
read = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
dump_config = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
device_index = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
serial_number = optarg;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
usage();
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( result != HACKRF_SUCCESS ) {
|
|
||||||
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write && read) {
|
|
||||||
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write && dump_config) {
|
|
||||||
fprintf(stderr, "Config and write options are mutually exclusive.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(write || read || dump_config)) {
|
|
||||||
fprintf(stderr, "Specify read, write, or config option.\n");
|
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(serial_number != NULL) {
|
|
||||||
result = hackrf_open_by_serial(serial_number, &device);
|
|
||||||
} else {
|
|
||||||
hackrf_device_list_t* device_list = hackrf_device_list();
|
|
||||||
if(device_list->devicecount <= 0) {
|
|
||||||
result = HACKRF_ERROR_NOT_FOUND;
|
|
||||||
} else {
|
|
||||||
result = hackrf_device_list_open(device_list, device_index, &device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result) {
|
|
||||||
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write) {
|
|
||||||
if( result == HACKRF_SUCCESS ) {
|
|
||||||
result = write_register(device, register_number, register_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(read) {
|
|
||||||
if( register_number == REGISTER_INVALID ) {
|
|
||||||
result = dump_registers(device);
|
|
||||||
} else {
|
|
||||||
result = dump_register(device, register_number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dump_config) {
|
|
||||||
dump_configuration(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_close(device);
|
|
||||||
if(result) {
|
|
||||||
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hackrf_exit();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
@ -226,11 +226,6 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((read || write) && (fd == NULL)) {
|
|
||||||
fprintf(stderr, "Failed to open file: %s\n", path);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_init();
|
result = hackrf_init();
|
||||||
if (result != HACKRF_SUCCESS) {
|
if (result != HACKRF_SUCCESS) {
|
||||||
fprintf(stderr, "hackrf_init() failed: %s (%d)\n",
|
fprintf(stderr, "hackrf_init() failed: %s (%d)\n",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 Dominic Spill <dominicgs@gmail.com>
|
* Copyright 2016 Dominic Spill <dominicgs@gmail.com>
|
||||||
* Copyright 2016 Mike Walters <mike@flomp.net>
|
* Copyright 2016 Mike Walters <mike@flomp.net>
|
||||||
|
* Copyright 2017 Michael Ossmann <mike@ossmann.com>
|
||||||
*
|
*
|
||||||
* This file is part of HackRF.
|
* This file is part of HackRF.
|
||||||
*
|
*
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fftw3.h>
|
#include <fftw3.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
@ -87,21 +89,25 @@ int gettimeofday(struct timeval *tv, void* ignored) {
|
|||||||
|
|
||||||
#define FREQ_ONE_MHZ (1000000ull)
|
#define FREQ_ONE_MHZ (1000000ull)
|
||||||
|
|
||||||
#define FREQ_MIN_HZ (0ull) /* 0 Hz */
|
#define FREQ_MIN_MHZ (0) /* 0 MHz */
|
||||||
#define FREQ_MAX_HZ (7250000000ull) /* 7250MHz */
|
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
|
||||||
|
|
||||||
#define DEFAULT_SAMPLE_RATE_HZ (20000000) /* 20MHz default sample rate */
|
#define DEFAULT_SAMPLE_RATE_HZ (20000000) /* 20MHz default sample rate */
|
||||||
#define DEFAULT_BASEBAND_FILTER_BANDWIDTH (15000000) /* 5MHz default */
|
#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 OFFSET 7500000
|
||||||
|
|
||||||
#define DEFAULT_SAMPLE_COUNT 0x4000
|
#define DEFAULT_SAMPLE_COUNT 0x4000
|
||||||
|
#define BLOCKS_PER_TRANSFER 16
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32
|
||||||
#define sleep(a) Sleep( (a*1000) )
|
#define sleep(a) Sleep( (a*1000) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int num_ranges = 0;
|
||||||
|
uint16_t frequencies[MAX_SWEEP_RANGES*2];
|
||||||
|
|
||||||
static float TimevalDiff(const struct timeval *a, const struct timeval *b) {
|
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);
|
return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec);
|
||||||
}
|
}
|
||||||
@ -166,15 +172,20 @@ uint32_t amp_enable;
|
|||||||
bool antenna = false;
|
bool antenna = false;
|
||||||
uint32_t antenna_enable;
|
uint32_t antenna_enable;
|
||||||
|
|
||||||
uint32_t freq_min;
|
bool binary_output = false;
|
||||||
uint32_t freq_max;
|
bool one_shot = false;
|
||||||
|
volatile bool sweep_started = false;
|
||||||
|
|
||||||
int fftSize;
|
int fftSize = 20;
|
||||||
|
uint32_t fft_bin_width;
|
||||||
fftwf_complex *fftwIn = NULL;
|
fftwf_complex *fftwIn = NULL;
|
||||||
fftwf_complex *fftwOut = NULL;
|
fftwf_complex *fftwOut = NULL;
|
||||||
fftwf_plan fftwPlan = NULL;
|
fftwf_plan fftwPlan = NULL;
|
||||||
float* pwr;
|
float* pwr;
|
||||||
float* window;
|
float* window;
|
||||||
|
time_t time_now;
|
||||||
|
struct tm *fft_time;
|
||||||
|
char time_str[50];
|
||||||
|
|
||||||
float logPower(fftwf_complex in, float scale)
|
float logPower(fftwf_complex in, float scale)
|
||||||
{
|
{
|
||||||
@ -185,65 +196,121 @@ float logPower(fftwf_complex in, float scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rx_callback(hackrf_transfer* transfer) {
|
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;
|
int8_t* buf;
|
||||||
float frequency;
|
uint8_t* ubuf;
|
||||||
|
uint64_t frequency; /* in Hz */
|
||||||
|
uint64_t band_edge;
|
||||||
|
uint32_t record_length;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if( fd != NULL ) {
|
if(NULL == fd) {
|
||||||
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte_count += transfer->valid_length;
|
||||||
|
buf = (int8_t*) transfer->buffer;
|
||||||
|
for(j=0; j<BLOCKS_PER_TRANSFER; j++) {
|
||||||
|
if(do_exit) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ubuf = (uint8_t*) buf;
|
||||||
|
if(ubuf[0] == 0x7F && ubuf[1] == 0x7F) {
|
||||||
|
frequency = ((uint64_t)(ubuf[9]) << 56) | ((uint64_t)(ubuf[8]) << 48) | ((uint64_t)(ubuf[7]) << 40)
|
||||||
|
| ((uint64_t)(ubuf[6]) << 32) | ((uint64_t)(ubuf[5]) << 24) | ((uint64_t)(ubuf[4]) << 16)
|
||||||
|
| ((uint64_t)(ubuf[3]) << 8) | ubuf[2];
|
||||||
|
} else {
|
||||||
|
buf += SAMPLES_PER_BLOCK;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* copy to fftwIn as floats */
|
||||||
|
buf += SAMPLES_PER_BLOCK - (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++) {
|
||||||
|
pwr[i] = logPower(fftwOut[i], 1.0f / fftSize);
|
||||||
|
}
|
||||||
|
if(binary_output) {
|
||||||
|
record_length = 2 * sizeof(band_edge)
|
||||||
|
+ (fftSize/4) * sizeof(float);
|
||||||
|
|
||||||
|
fwrite(&record_length, sizeof(record_length), 1, stdout);
|
||||||
|
band_edge = frequency;
|
||||||
|
fwrite(&band_edge, sizeof(band_edge), 1, stdout);
|
||||||
|
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 4;
|
||||||
|
fwrite(&band_edge, sizeof(band_edge), 1, stdout);
|
||||||
|
fwrite(&pwr[1+(fftSize*5)/8], sizeof(float), fftSize/4, stdout);
|
||||||
|
|
||||||
|
fwrite(&record_length, sizeof(record_length), 1, stdout);
|
||||||
|
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 2;
|
||||||
|
fwrite(&band_edge, sizeof(band_edge), 1, stdout);
|
||||||
|
band_edge = frequency + (DEFAULT_SAMPLE_RATE_HZ * 3) / 4;
|
||||||
|
fwrite(&band_edge, sizeof(band_edge), 1, stdout);
|
||||||
|
fwrite(&pwr[1+fftSize/8], sizeof(float), fftSize/4, 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, %" PRIu64 ", %" PRIu64 ", %.2f, %u",
|
||||||
|
time_str,
|
||||||
|
(uint64_t)(frequency),
|
||||||
|
(uint64_t)(frequency+DEFAULT_SAMPLE_RATE_HZ/4),
|
||||||
|
(float)fft_bin_width,
|
||||||
|
fftSize);
|
||||||
|
for(i=1+(fftSize*5)/8; (1+(fftSize*7)/8) > 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");
|
||||||
|
}
|
||||||
|
if(one_shot && ((uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4))
|
||||||
|
>= (uint64_t)(FREQ_ONE_MHZ*frequencies[num_ranges*2-1]))) {
|
||||||
|
do_exit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
fprintf(stderr, "Usage:\n");
|
fprintf(stderr, "Usage:\n");
|
||||||
fprintf(stderr, "\t[-h] # this help\n");
|
fprintf(stderr, "\t[-h] # this help\n");
|
||||||
fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF.\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[-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] # minimum and maximum frequencies in MHz\n");
|
||||||
fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable.\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[-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[-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, 16384-4294967296\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");
|
||||||
|
fprintf(stderr, "\tdate, time, hz_low, hz_high, hz_bin_width, num_samples, dB, dB, . . .\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static hackrf_device* device = NULL;
|
static hackrf_device* device = NULL;
|
||||||
@ -266,18 +333,20 @@ void sigint_callback_handler(int signum) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int opt, i, result, ifreq = 0;
|
int opt, i, result = 0;
|
||||||
bool odd;
|
|
||||||
const char* path = "/dev/null";
|
const char* path = "/dev/null";
|
||||||
const char* serial_number = NULL;
|
const char* serial_number = NULL;
|
||||||
int exit_code = EXIT_SUCCESS;
|
int exit_code = EXIT_SUCCESS;
|
||||||
struct timeval t_end;
|
struct timeval t_end;
|
||||||
float time_diff;
|
float time_diff;
|
||||||
unsigned int lna_gain=16, vga_gain=20, txvga_gain=0;
|
unsigned int lna_gain=16, vga_gain=20;
|
||||||
uint16_t frequencies[MAX_FREQ_COUNT];
|
|
||||||
uint32_t num_samples = DEFAULT_SAMPLE_COUNT;
|
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:x:d:n:h?")) != EOF ) {
|
|
||||||
|
while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:w:1Bh?")) != EOF ) {
|
||||||
result = HACKRF_SUCCESS;
|
result = HACKRF_SUCCESS;
|
||||||
switch( opt )
|
switch( opt )
|
||||||
{
|
{
|
||||||
@ -292,17 +361,29 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
result = parse_u32_range(optarg, &freq_min, &freq_max);
|
result = parse_u32_range(optarg, &freq_min, &freq_max);
|
||||||
fprintf(stderr, "Scanning %uMHz to %uMHz\n", freq_min, freq_max);
|
if(freq_min >= freq_max) {
|
||||||
frequencies[ifreq++] = freq_min;
|
fprintf(stderr,
|
||||||
odd = true;
|
"argument error: freq_max must be greater than freq_min.\n");
|
||||||
while(frequencies[ifreq-1] <= freq_max) {
|
usage();
|
||||||
if (odd)
|
return EXIT_FAILURE;
|
||||||
frequencies[ifreq] = frequencies[ifreq-1] + FREQ_STEP / 4;
|
|
||||||
else
|
|
||||||
frequencies[ifreq] = frequencies[ifreq-1] + 3*(FREQ_STEP/4);
|
|
||||||
ifreq++;
|
|
||||||
odd = !odd;
|
|
||||||
}
|
}
|
||||||
|
if(FREQ_MAX_MHZ <freq_max) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"argument error: freq_max may not be higher than %u.\n",
|
||||||
|
FREQ_MAX_MHZ);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if(MAX_SWEEP_RANGES <= num_ranges) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"argument error: specify a maximum of %u frequency ranges.\n",
|
||||||
|
MAX_SWEEP_RANGES);
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
frequencies[2*num_ranges] = (uint16_t)freq_min;
|
||||||
|
frequencies[2*num_ranges+1] = (uint16_t)freq_max;
|
||||||
|
num_ranges++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
@ -318,14 +399,23 @@ int main(int argc, char** argv) {
|
|||||||
result = parse_u32(optarg, &vga_gain);
|
result = parse_u32(optarg, &vga_gain);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
|
||||||
result = parse_u32(optarg, &txvga_gain);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
result = parse_u32(optarg, &num_samples);
|
result = parse_u32(optarg, &num_samples);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
result = parse_u32(optarg, &fft_bin_width);
|
||||||
|
fftSize = DEFAULT_SAMPLE_RATE_HZ / fft_bin_width;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
one_shot = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
binary_output = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
usage();
|
usage();
|
||||||
@ -350,12 +440,12 @@ int main(int argc, char** argv) {
|
|||||||
if (vga_gain % 2)
|
if (vga_gain % 2)
|
||||||
fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n");
|
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");
|
fprintf(stderr, "warning: num_samples (-n) must be a multiple of 16384\n");
|
||||||
return EXIT_FAILURE;
|
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");
|
fprintf(stderr, "warning: num_samples (-n) must be at least 16384\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -376,16 +466,36 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifreq == 0) {
|
if (0 == num_ranges) {
|
||||||
fprintf(stderr, "argument error: must specify sweep frequency range (-f).\n");
|
frequencies[0] = (uint16_t)freq_min;
|
||||||
usage();
|
frequencies[1] = (uint16_t)freq_max;
|
||||||
|
num_ranges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fftSize = 64;
|
if(16368 < fftSize) {
|
||||||
fftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
fprintf(stderr,
|
||||||
fftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
"argument error: FFT bin width (-w) too small, resulted in more than 16368 FFT bins\n");
|
||||||
fftwPlan = fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE);
|
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);
|
||||||
pwr = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
pwr = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
||||||
window = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
window = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
||||||
for (i = 0; i < fftSize; i++) {
|
for (i = 0; i < fftSize; i++) {
|
||||||
@ -458,7 +568,21 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = hackrf_init_sweep(device, frequencies, ifreq, num_samples);
|
/*
|
||||||
|
* For each range, plan a whole number of tuning steps of a certain
|
||||||
|
* bandwidth. Increase high end of range if necessary to accommodate a
|
||||||
|
* whole number of steps, minimum 1.
|
||||||
|
*/
|
||||||
|
for(i = 0; i < num_ranges; i++) {
|
||||||
|
step_count = 1 + (frequencies[2*i+1] - frequencies[2*i] - 1)
|
||||||
|
/ TUNE_STEP;
|
||||||
|
frequencies[2*i+1] = frequencies[2*i] + step_count * TUNE_STEP;
|
||||||
|
fprintf(stderr, "Sweeping from %u MHz to %u MHz\n",
|
||||||
|
frequencies[2*i], frequencies[2*i+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = hackrf_init_sweep(device, frequencies, num_ranges, num_samples,
|
||||||
|
TUNE_STEP * FREQ_ONE_MHZ, OFFSET, INTERLEAVED);
|
||||||
if( result != HACKRF_SUCCESS ) {
|
if( result != HACKRF_SUCCESS ) {
|
||||||
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n",
|
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n",
|
||||||
hackrf_error_name(result), result);
|
hackrf_error_name(result), result);
|
||||||
@ -554,6 +678,10 @@ int main(int argc, char** argv) {
|
|||||||
fd = NULL;
|
fd = NULL;
|
||||||
fprintf(stderr, "fclose(fd) done\n");
|
fprintf(stderr, "fclose(fd) done\n");
|
||||||
}
|
}
|
||||||
|
fftwf_free(fftwIn);
|
||||||
|
fftwf_free(fftwOut);
|
||||||
|
fftwf_free(pwr);
|
||||||
|
fftwf_free(window);
|
||||||
fprintf(stderr, "exit\n");
|
fprintf(stderr, "exit\n");
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
@ -311,6 +311,7 @@ bool signalsource = false;
|
|||||||
uint32_t amplitude = 0;
|
uint32_t amplitude = 0;
|
||||||
|
|
||||||
bool hw_sync = false;
|
bool hw_sync = false;
|
||||||
|
uint32_t hw_sync_enable;
|
||||||
|
|
||||||
bool receive = false;
|
bool receive = false;
|
||||||
bool receive_wav = false;
|
bool receive_wav = false;
|
||||||
@ -434,7 +435,7 @@ int tx_callback(hackrf_transfer* transfer) {
|
|||||||
}
|
}
|
||||||
if (bytes_read != bytes_to_read) {
|
if (bytes_read != bytes_to_read) {
|
||||||
if (repeat) {
|
if (repeat) {
|
||||||
printf("Input file end reached. Rewind to beginning.\n");
|
fprintf(stderr, "Input file end reached. Rewind to beginning.\n");
|
||||||
rewind(fd);
|
rewind(fd);
|
||||||
fread(transfer->buffer + bytes_read, 1, bytes_to_read - bytes_read, fd);
|
fread(transfer->buffer + bytes_read, 1, bytes_to_read - bytes_read, fd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -503,7 +504,7 @@ static void usage() {
|
|||||||
printf("\t[-R] # Repeat TX mode (default is off) \n");
|
printf("\t[-R] # Repeat TX mode (default is off) \n");
|
||||||
printf("\t[-b baseband_filter_bw_hz] # Set baseband filter bandwidth in Hz.\n\tPossible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz, default <= 0.75 * sample_rate_hz.\n" );
|
printf("\t[-b baseband_filter_bw_hz] # Set baseband filter bandwidth in Hz.\n\tPossible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz, default <= 0.75 * sample_rate_hz.\n" );
|
||||||
printf("\t[-C ppm] # Set Internal crystal clock error in ppm.\n");
|
printf("\t[-C ppm] # Set Internal crystal clock error in ppm.\n");
|
||||||
printf("\t[-H] # Synchronise USB transfer using GPIO pins.\n");
|
printf("\t[-H hw_sync_enable] # Synchronise USB transfer using GPIO pins.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static hackrf_device* device = NULL;
|
static hackrf_device* device = NULL;
|
||||||
@ -547,13 +548,14 @@ int main(int argc, char** argv) {
|
|||||||
float time_diff;
|
float time_diff;
|
||||||
unsigned int lna_gain=8, vga_gain=20, txvga_gain=0;
|
unsigned int lna_gain=8, vga_gain=20, txvga_gain=0;
|
||||||
|
|
||||||
while( (opt = getopt(argc, argv, "Hwr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:C:RS:h?")) != EOF )
|
while( (opt = getopt(argc, argv, "H:wr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:C:RS:h?")) != EOF )
|
||||||
{
|
{
|
||||||
result = HACKRF_SUCCESS;
|
result = HACKRF_SUCCESS;
|
||||||
switch( opt )
|
switch( opt )
|
||||||
{
|
{
|
||||||
case 'H':
|
case 'H':
|
||||||
hw_sync = true;
|
hw_sync = true;
|
||||||
|
result = parse_u32(optarg, &hw_sync_enable);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
receive_wav = true;
|
receive_wav = true;
|
||||||
@ -807,9 +809,6 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if( baseband_filter_bw )
|
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) {
|
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",
|
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));
|
BASEBAND_FILTER_BW_MAX, (float)(BASEBAND_FILTER_BW_MAX/FREQ_ONE_MHZ));
|
||||||
@ -823,6 +822,9 @@ int main(int argc, char** argv) {
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
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) {
|
if(requested_mode_count > 1) {
|
||||||
@ -961,11 +963,13 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", hw_sync);
|
if(hw_sync) {
|
||||||
result = hackrf_set_hw_sync_mode(device, hw_sync ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF);
|
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", hw_sync);
|
||||||
if( result != HACKRF_SUCCESS ) {
|
result = hackrf_set_hw_sync_mode(device, hw_sync_enable ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF);
|
||||||
fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result);
|
if( result != HACKRF_SUCCESS ) {
|
||||||
return EXIT_FAILURE;
|
fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
if( transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
||||||
@ -1056,14 +1060,14 @@ int main(int argc, char** argv) {
|
|||||||
len=stream_size-stream_head;
|
len=stream_size-stream_head;
|
||||||
bytes_written = fwrite(stream_buf+stream_head, 1, len, fd);
|
bytes_written = fwrite(stream_buf+stream_head, 1, len, fd);
|
||||||
if (len != bytes_written) {
|
if (len != bytes_written) {
|
||||||
printf("write failed");
|
fprintf(stderr, "write failed");
|
||||||
do_exit=true;
|
do_exit=true;
|
||||||
};
|
};
|
||||||
stream_head=(stream_head+len)%stream_size;
|
stream_head=(stream_head+len)%stream_size;
|
||||||
}
|
}
|
||||||
if(stream_drop>0) {
|
if(stream_drop>0) {
|
||||||
uint32_t drops= __atomic_exchange_n (&stream_drop,0,__ATOMIC_SEQ_CST);
|
uint32_t drops= __atomic_exchange_n (&stream_drop,0,__ATOMIC_SEQ_CST);
|
||||||
printf("dropped frames: [%d]\n",drops);
|
fprintf(stderr, "dropped frames: [%d]\n", drops);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,10 +24,13 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(libhackrf C)
|
project(libhackrf C)
|
||||||
set(MAJOR_VERSION 0)
|
set(MAJOR_VERSION 0)
|
||||||
set(MINOR_VERSION 4)
|
set(MINOR_VERSION 5)
|
||||||
set(PACKAGE libhackrf)
|
set(PACKAGE libhackrf)
|
||||||
set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION})
|
set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION})
|
||||||
set(VERSION ${VERSION_STRING})
|
set(VERSION ${VERSION_STRING})
|
||||||
|
add_definitions(-DLIBRARY_VERSION="${VERSION_STRING}")
|
||||||
|
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
|
||||||
|
add_definitions(-DLIBRARY_RELEASE="${RELEASE}")
|
||||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -145,6 +145,7 @@ static const uint16_t hackrf_one_usb_pid = 0x6089;
|
|||||||
static const uint16_t rad1o_usb_pid = 0xcc15;
|
static const uint16_t rad1o_usb_pid = 0xcc15;
|
||||||
|
|
||||||
static libusb_context* g_libusb_context = NULL;
|
static libusb_context* g_libusb_context = NULL;
|
||||||
|
int last_libusb_error = LIBUSB_SUCCESS;
|
||||||
|
|
||||||
static void request_exit(void)
|
static void request_exit(void)
|
||||||
{
|
{
|
||||||
@ -249,6 +250,7 @@ static int prepare_transfers(
|
|||||||
error = libusb_submit_transfer(device->transfers[transfer_index]);
|
error = libusb_submit_transfer(device->transfers[transfer_index]);
|
||||||
if( error != 0 )
|
if( error != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = error;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,6 +271,7 @@ static int detach_kernel_drivers(libusb_device_handle* usb_device_handle)
|
|||||||
result = libusb_get_active_config_descriptor(dev, &config);
|
result = libusb_get_active_config_descriptor(dev, &config);
|
||||||
if( result < 0 )
|
if( result < 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,11 +285,13 @@ static int detach_kernel_drivers(libusb_device_handle* usb_device_handle)
|
|||||||
if( result == LIBUSB_ERROR_NOT_SUPPORTED ) {
|
if( result == LIBUSB_ERROR_NOT_SUPPORTED ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else if( result == 1 ) {
|
} else if( result == 1 ) {
|
||||||
result = libusb_detach_kernel_driver(usb_device_handle, i);
|
result = libusb_detach_kernel_driver(usb_device_handle, i);
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,6 +305,7 @@ static int set_hackrf_configuration(libusb_device_handle* usb_device, int config
|
|||||||
result = libusb_get_configuration(usb_device, &curr_config);
|
result = libusb_get_configuration(usb_device, &curr_config);
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +319,7 @@ static int set_hackrf_configuration(libusb_device_handle* usb_device, int config
|
|||||||
result = libusb_set_configuration(usb_device, config);
|
result = libusb_set_configuration(usb_device, config);
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,6 +347,7 @@ int ADDCALL hackrf_init(void)
|
|||||||
libusb_error = libusb_init(&g_libusb_context);
|
libusb_error = libusb_init(&g_libusb_context);
|
||||||
if( libusb_error != 0 )
|
if( libusb_error != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = libusb_error;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -357,6 +365,22 @@ int ADDCALL hackrf_exit(void)
|
|||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LIBRARY_VERSION
|
||||||
|
#define LIBRARY_VERSION "unknown"
|
||||||
|
#endif
|
||||||
|
const char* ADDCALL hackrf_library_version()
|
||||||
|
{
|
||||||
|
return LIBRARY_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef LIBRARY_RELEASE
|
||||||
|
#define LIBRARY_RELEASE "unknown"
|
||||||
|
#endif
|
||||||
|
const char* ADDCALL hackrf_library_release()
|
||||||
|
{
|
||||||
|
return LIBRARY_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
hackrf_device_list_t* ADDCALL hackrf_device_list()
|
hackrf_device_list_t* ADDCALL hackrf_device_list()
|
||||||
{
|
{
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
@ -511,6 +535,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d
|
|||||||
result = libusb_claim_interface(usb_device, 0);
|
result = libusb_claim_interface(usb_device, 0);
|
||||||
if( result != LIBUSB_SUCCESS )
|
if( result != LIBUSB_SUCCESS )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
libusb_close(usb_device);
|
libusb_close(usb_device);
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
@ -601,7 +626,7 @@ int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackr
|
|||||||
int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device)
|
int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device)
|
||||||
{
|
{
|
||||||
libusb_device_handle* usb_device;
|
libusb_device_handle* usb_device;
|
||||||
int i;
|
int i, result;
|
||||||
|
|
||||||
if( device == NULL || list == NULL || idx < 0 || idx >= list->devicecount )
|
if( device == NULL || list == NULL || idx < 0 || idx >= list->devicecount )
|
||||||
{
|
{
|
||||||
@ -610,8 +635,10 @@ int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_
|
|||||||
|
|
||||||
i = list->usb_device_index[idx];
|
i = list->usb_device_index[idx];
|
||||||
|
|
||||||
if( libusb_open(list->usb_devices[i], &usb_device) != 0 ) {
|
result = libusb_open(list->usb_devices[i], &usb_device);
|
||||||
|
if(result != 0) {
|
||||||
usb_device = NULL;
|
usb_device = NULL;
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,6 +661,7 @@ int ADDCALL hackrf_set_transceiver_mode(hackrf_device* device, hackrf_transceive
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -662,6 +690,7 @@ int ADDCALL hackrf_max2837_read(hackrf_device* device, uint8_t register_number,
|
|||||||
|
|
||||||
if( result < 2 )
|
if( result < 2 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -694,6 +723,7 @@ int ADDCALL hackrf_max2837_write(hackrf_device* device, uint8_t register_number,
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -724,6 +754,7 @@ int ADDCALL hackrf_si5351c_read(hackrf_device* device, uint16_t register_number,
|
|||||||
|
|
||||||
if( result < 1 )
|
if( result < 1 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
*value = temp_value;
|
*value = temp_value;
|
||||||
@ -756,6 +787,7 @@ int ADDCALL hackrf_si5351c_write(hackrf_device* device, uint16_t register_number
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -778,6 +810,7 @@ int ADDCALL hackrf_set_baseband_filter_bandwidth(hackrf_device* device, const ui
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -807,6 +840,7 @@ int ADDCALL hackrf_rffc5071_read(hackrf_device* device, uint8_t register_number,
|
|||||||
|
|
||||||
if( result < 2 )
|
if( result < 2 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -835,6 +869,7 @@ int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -857,6 +892,7 @@ int ADDCALL hackrf_spiflash_erase(hackrf_device* device)
|
|||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -886,6 +922,7 @@ int ADDCALL hackrf_spiflash_write(hackrf_device* device, const uint32_t address,
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -915,6 +952,7 @@ int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address,
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -944,6 +982,7 @@ int ADDCALL hackrf_cpld_write(hackrf_device* device,
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (result != LIBUSB_SUCCESS) {
|
if (result != LIBUSB_SUCCESS) {
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -967,6 +1006,7 @@ int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value)
|
|||||||
|
|
||||||
if (result < 1)
|
if (result < 1)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -990,6 +1030,7 @@ int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version,
|
|||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
version[result] = '\0';
|
version[result] = '\0';
|
||||||
@ -1005,8 +1046,10 @@ extern ADDAPI int ADDCALL hackrf_usb_api_version_read(hackrf_device* device,
|
|||||||
struct libusb_device_descriptor desc;
|
struct libusb_device_descriptor desc;
|
||||||
dev = libusb_get_device(device->usb_device);
|
dev = libusb_get_device(device->usb_device);
|
||||||
result = libusb_get_device_descriptor(dev, &desc);
|
result = libusb_get_device_descriptor(dev, &desc);
|
||||||
if (result < 0)
|
if (result < 0) {
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
|
}
|
||||||
|
|
||||||
*version = desc.bcdDevice;
|
*version = desc.bcdDevice;
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1053,6 +1096,7 @@ int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz)
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1104,6 +1148,7 @@ int ADDCALL hackrf_set_freq_explicit(hackrf_device* device,
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1145,6 +1190,7 @@ int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device,
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return hackrf_set_baseband_filter_bandwidth(device,
|
return hackrf_set_baseband_filter_bandwidth(device,
|
||||||
@ -1214,6 +1260,7 @@ int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value)
|
|||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1239,6 +1286,7 @@ int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid
|
|||||||
|
|
||||||
if (result < length)
|
if (result < length)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -1358,6 +1406,7 @@ int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value
|
|||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1389,12 +1438,12 @@ static void hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer
|
|||||||
if(usb_transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
if(usb_transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
||||||
{
|
{
|
||||||
hackrf_transfer transfer = {
|
hackrf_transfer transfer = {
|
||||||
transfer.device = device,
|
.device = device,
|
||||||
transfer.buffer = usb_transfer->buffer,
|
.buffer = usb_transfer->buffer,
|
||||||
transfer.buffer_length = usb_transfer->length,
|
.buffer_length = usb_transfer->length,
|
||||||
transfer.valid_length = usb_transfer->actual_length,
|
.valid_length = usb_transfer->actual_length,
|
||||||
transfer.rx_ctx = device->rx_ctx,
|
.rx_ctx = device->rx_ctx,
|
||||||
transfer.tx_ctx = device->tx_ctx
|
.tx_ctx = device->tx_ctx
|
||||||
};
|
};
|
||||||
|
|
||||||
if( device->callback(&transfer) == 0 )
|
if( device->callback(&transfer) == 0 )
|
||||||
@ -1606,6 +1655,10 @@ const char* ADDCALL hackrf_error_name(enum hackrf_error errcode)
|
|||||||
return "insufficient memory";
|
return "insufficient memory";
|
||||||
|
|
||||||
case HACKRF_ERROR_LIBUSB:
|
case HACKRF_ERROR_LIBUSB:
|
||||||
|
#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000103)
|
||||||
|
if(last_libusb_error != LIBUSB_SUCCESS)
|
||||||
|
return libusb_strerror(last_libusb_error);
|
||||||
|
#endif
|
||||||
return "USB error";
|
return "USB error";
|
||||||
|
|
||||||
case HACKRF_ERROR_THREAD:
|
case HACKRF_ERROR_THREAD:
|
||||||
@ -1750,34 +1803,83 @@ int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value)
|
|||||||
|
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
* Initialize sweep mode:
|
||||||
{
|
* frequency_list is a list of start/stop pairs of frequencies in MHz.
|
||||||
|
* num_ranges is the number of pairs in frequency_list (1 to 10)
|
||||||
|
* num_samples is the number of samples to capture after each tuning.
|
||||||
|
* step_width is the width in Hz of the tuning step.
|
||||||
|
* offset is a number of Hz added to every tuning frequency.
|
||||||
|
* Use to select center frequency based on the expected usable bandwidth.
|
||||||
|
* sweep_mode
|
||||||
|
* LINEAR means step_width is added to the current frequency at each step.
|
||||||
|
* INTERLEAVED invokes a scheme in which each step is divided into two
|
||||||
|
* interleaved sub-steps, allowing the host to select the best portions
|
||||||
|
* of the FFT of each sub-step and discard the rest.
|
||||||
|
*/
|
||||||
|
int ADDCALL hackrf_init_sweep(hackrf_device* device,
|
||||||
|
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) {
|
||||||
USB_API_REQUIRED(device, 0x0102)
|
USB_API_REQUIRED(device, 0x0102)
|
||||||
int result, i;
|
int result, i;
|
||||||
int size = length * sizeof(frequency_list[0]);
|
unsigned char data[9 + MAX_SWEEP_RANGES * 2 * sizeof(frequency_list[0])];
|
||||||
|
int size = 9 + num_ranges * 2 * sizeof(frequency_list[0]);
|
||||||
|
|
||||||
for(i=0; i<length; i++)
|
if((num_ranges < 1) || (num_ranges > MAX_SWEEP_RANGES)){
|
||||||
frequency_list[i] = TO_LE(frequency_list[i]);
|
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(
|
result = libusb_control_transfer(
|
||||||
device->usb_device,
|
device->usb_device,
|
||||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||||
HACKRF_VENDOR_REQUEST_INIT_SWEEP,
|
HACKRF_VENDOR_REQUEST_INIT_SWEEP,
|
||||||
dwell_time & 0xffff,
|
num_samples & 0xffff,
|
||||||
(dwell_time >> 16) & 0xffff,
|
(num_samples >> 16) & 0xffff,
|
||||||
(unsigned char*)frequency_list,
|
data,
|
||||||
size,
|
size,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result < size) {
|
if (result < size) {
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1804,6 +1906,7 @@ int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards)
|
|||||||
|
|
||||||
if (result < 8)
|
if (result < 8)
|
||||||
{
|
{
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1839,6 +1942,7 @@ int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
@ -1859,6 +1963,7 @@ int ADDCALL hackrf_reset(hackrf_device* device) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if( result != 0 ) {
|
if( result != 0 ) {
|
||||||
|
last_libusb_error = result;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
|
@ -47,6 +47,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SAMPLES_PER_BLOCK 16384
|
||||||
|
#define MAX_SWEEP_RANGES 10
|
||||||
|
|
||||||
enum hackrf_error {
|
enum hackrf_error {
|
||||||
HACKRF_SUCCESS = 0,
|
HACKRF_SUCCESS = 0,
|
||||||
HACKRF_TRUE = 1,
|
HACKRF_TRUE = 1,
|
||||||
@ -95,6 +98,11 @@ enum operacake_ports {
|
|||||||
OPERACAKE_PB4 = 7,
|
OPERACAKE_PB4 = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sweep_style {
|
||||||
|
LINEAR = 0,
|
||||||
|
INTERLEAVED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct hackrf_device hackrf_device;
|
typedef struct hackrf_device hackrf_device;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -133,6 +141,9 @@ extern "C"
|
|||||||
extern ADDAPI int ADDCALL hackrf_init();
|
extern ADDAPI int ADDCALL hackrf_init();
|
||||||
extern ADDAPI int ADDCALL hackrf_exit();
|
extern ADDAPI int ADDCALL hackrf_exit();
|
||||||
|
|
||||||
|
extern ADDAPI const char* ADDCALL hackrf_library_version();
|
||||||
|
extern ADDAPI const char* ADDCALL hackrf_library_release();
|
||||||
|
|
||||||
extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
|
extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
|
||||||
extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device);
|
extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device);
|
||||||
extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list);
|
extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list);
|
||||||
@ -215,10 +226,11 @@ extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t
|
|||||||
/* set hardware sync mode */
|
/* set hardware sync mode */
|
||||||
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
|
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,
|
extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
|
||||||
uint16_t* frequency_list,
|
const uint16_t* frequency_list, const int num_ranges,
|
||||||
int length, uint32_t dwell_time);
|
const uint32_t num_samples, const uint32_t step_width,
|
||||||
|
const uint32_t offset, const enum sweep_style style);
|
||||||
|
|
||||||
/* Operacake functions */
|
/* Operacake functions */
|
||||||
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
|
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
|
||||||
|
Reference in New Issue
Block a user