Merge branch 'master' into rad1o

This commit is contained in:
schneider42
2017-02-11 18:02:51 +01:00
committed by GitHub
21 changed files with 1058 additions and 949 deletions

View File

@ -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.
![HackRF One](https://raw.github.com/mossmann/hackrf/master/doc/HackRF-One-fd0-0009.jpeg) ![HackRF One](https://raw.github.com/mossmann/hackrf/master/doc/HackRF-One-fd0-0009.jpeg)

View File

@ -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

View File

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

View File

@ -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;
} }
} }

View File

@ -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__ */

View 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()

View File

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

View File

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

View File

@ -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) {

View 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, &register_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, &register_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, &parameters[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, &parameters[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, &register_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, &register_number);
break;
case 'w':
write = true;
result = parse_int(optarg, &register_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;
}

View File

@ -44,6 +44,10 @@ int main(void)
hackrf_error_name(result), result); hackrf_error_name(result), result);
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();

View File

@ -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, &register_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, &register_number);
break;
case 'w':
write = true;
result = parse_int(optarg, &register_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;
}

View File

@ -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) {

View File

@ -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, &register_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, &register_number);
break;
case 'w':
write = true;
result = parse_int(optarg, &register_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;
}

View File

@ -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, &register_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, &parameters[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, &parameters[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, &register_number);
break;
case 'w':
write = true;
result = parse_int(optarg, &register_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;
}

View File

@ -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",

View File

@ -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;
} }

View File

@ -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 {

View File

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

View File

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

View File

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