Merge remote-tracking branch 'mossmann/master' into opera-merge
Conflicts: firmware/common/hackrf_core.c firmware/common/rf_path.c firmware/hackrf-common.cmake firmware/hackrf_usb/hackrf_usb.c firmware/hackrf_usb/usb_api_transceiver.c host/hackrf-tools/src/hackrf_transfer.c
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@
|
||||
*.hex
|
||||
*.srec
|
||||
host/build/
|
||||
host/**/build
|
||||
|
||||
# Operating system spew
|
||||
.DS_Store
|
||||
|
43
.travis.yml
43
.travis.yml
@ -3,6 +3,7 @@ language: c
|
||||
cache: apt
|
||||
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- linux
|
||||
@ -10,32 +11,48 @@ os:
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
# - clang
|
||||
- clang
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
- os: linux
|
||||
compiler: clang
|
||||
|
||||
before_script:
|
||||
# - wget https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q1-update/+download/gcc-arm-none-eabi-5_3-2016q1-20160330-linux.tar.bz2 -O /tmp/gcc-arm.tar.bz2
|
||||
# - tar -xvf /tmp/gcc-arm.tar.bz2
|
||||
# - export PATH=$PWD/gcc-arm-none-eabi-5_3-2016q1/bin:$PATH
|
||||
- export CFLAGS="-Wall -Wextra -Werror"
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libusb; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew tap PX4/homebrew-px4; brew update; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libusb fftw gcc-arm-none-eabi dfu-util; fi
|
||||
# For virtualenv(?) reasons we can't apt-get install python-yaml
|
||||
- pip install PyYAML
|
||||
|
||||
script:
|
||||
- mkdir host/build
|
||||
- cd host/build
|
||||
- cmake ..
|
||||
- make
|
||||
# - cd ../../firmware/hackrf_usb
|
||||
# - mkdir build
|
||||
# - cd build
|
||||
# - export CC="arm-none-eabi-gcc"
|
||||
# - export CXX="arm-none-eabi-g++"
|
||||
# - cmake ..
|
||||
# - make
|
||||
- cd ../..
|
||||
- mkdir firmware/build-hackrf-one
|
||||
- mkdir firmware/build-jawbreaker
|
||||
- cd firmware/libopencm3
|
||||
- make
|
||||
- cd ../build-hackrf-one
|
||||
- cmake ..
|
||||
- make
|
||||
- cd ../build-jawbreaker
|
||||
- cmake -DBOARD=JAWBREAKER ..
|
||||
- make
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- debian-sid
|
||||
packages:
|
||||
- libusb-1.0-0-dev
|
||||
- libfftw3-dev
|
||||
- gcc-arm-none-eabi
|
||||
- libnewlib-arm-none-eabi
|
||||
- dfu-util
|
||||
|
27
appveyor.yml
Normal file
27
appveyor.yml
Normal file
@ -0,0 +1,27 @@
|
||||
os: Visual Studio 2015
|
||||
clone_depth: 1
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
- Debug
|
||||
|
||||
install:
|
||||
- appveyor DownloadFile "https://downloads.sourceforge.net/project/libusb/libusb-1.0/libusb-1.0.21/libusb-1.0.21.7z?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Flibusb%2Ffiles%2Flibusb-1.0%2Flibusb-1.0.21%2F&ts=1485478643&use_mirror=cytranet" -FileName "C:\libusb.7z"
|
||||
- 7z x -y "C:\libusb.7z" -o"C:\libusb"
|
||||
- appveyor DownloadFile "http://mirrors.kernel.org/sourceware/pthreads-win32/pthreads-w32-2-9-1-release.zip" -FileName "C:\pthreads-w32-release.zip"
|
||||
- 7z x -y "C:\pthreads-w32-release.zip" -o"C:\pthreads"
|
||||
- appveyor DownloadFile "http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/pkg-config_0.26-1_win32.zip" -FileName "C:\pkg-config_win32.zip"
|
||||
- 7z x -y "C:\pkg-config_win32.zip" -o"C:\pkg-config"
|
||||
|
||||
|
||||
build_script:
|
||||
- mkdir c:\projects\hackrf\host\build
|
||||
- cd c:\projects\hackrf\host\build
|
||||
- cmake -G "Visual Studio 14 2015 Win64" \
|
||||
-DLIBUSB_LIBRARIES="C:\libusb\MS64\dll\libusb-1.0.lib" \
|
||||
-DLIBUSB_INCLUDE_DIR="C:\libusb\include\libusb-1.0" \
|
||||
-DTHREADS_PTHREADS_INCLUDE_DIR=c:\pthreads\Pre-built.2\include \
|
||||
-DTHREADS_PTHREADS_WIN32_LIBRARY=c:\pthreads\Pre-built.2\lib\x64\pthreadVC2.lib \
|
||||
-DPKG_CONFIG_EXECUTABLE="C:\pkg-config\bin\pkg-config.exe" \
|
||||
..
|
||||
- msbuild .\ALL_BUILD.vcxproj /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
@ -6,7 +6,7 @@ projects. The cpld directory contains HDL source for the CPLD.
|
||||
|
||||
The firmware is set up for compilation with the GCC toolchain available here:
|
||||
|
||||
https://launchpad.net/gcc-arm-embedded
|
||||
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
|
||||
|
||||
Required dependency:
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
pin_setup();
|
||||
|
||||
/* enable all power supplies */
|
||||
@ -36,15 +35,13 @@ int main(void)
|
||||
led_on(LED2);
|
||||
led_on(LED3);
|
||||
|
||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||
__asm__("nop");
|
||||
delay(2000000);
|
||||
|
||||
led_off(LED1);
|
||||
led_off(LED2);
|
||||
led_off(LED3);
|
||||
|
||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||
__asm__("nop");
|
||||
delay(2000000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -75,11 +75,24 @@ static struct gpio_t gpio_max2837_b7 = GPIO(2, 15);
|
||||
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
|
||||
static struct gpio_t gpio_max5864_select = GPIO(2, 7);
|
||||
|
||||
/* RF LDO control */
|
||||
#ifdef JAWBREAKER
|
||||
static struct gpio_t gpio_rf_ldo_enable = GPIO(2, 9);
|
||||
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
|
||||
/*
|
||||
static struct gpio_t gpio_sync_in_a = GPIO(3, 8);
|
||||
static struct gpio_t gpio_sync_in_b = GPIO(3, 9);
|
||||
static struct gpio_t gpio_sync_out_a = GPIO(3, 10);
|
||||
static struct gpio_t gpio_sync_out_b = GPIO(3, 11);
|
||||
*/
|
||||
static struct gpio_t gpio_sync_in_a = GPIO(3, 10);
|
||||
static struct gpio_t gpio_sync_in_b = GPIO(3, 11);
|
||||
static struct gpio_t gpio_sync_out_a = GPIO(3, 8);
|
||||
static struct gpio_t gpio_sync_out_b = GPIO(3, 9);
|
||||
#endif
|
||||
|
||||
/* RF LDO control */
|
||||
// #ifdef JAWBREAKER
|
||||
// static struct gpio_t gpio_rf_ldo_enable = GPIO(2, 9);
|
||||
// #endif
|
||||
|
||||
/* RF supply (VAA) control */
|
||||
#ifdef HACKRF_ONE
|
||||
static struct gpio_t gpio_vaa_disable = GPIO(2, 9);
|
||||
@ -886,6 +899,15 @@ void pin_setup(void) {
|
||||
|
||||
/* Safe state: start with VAA turned off: */
|
||||
disable_rf_power();
|
||||
|
||||
scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
|
||||
|
||||
gpio_input(&gpio_sync_in_a);
|
||||
gpio_input(&gpio_sync_in_b);
|
||||
|
||||
gpio_output(&gpio_sync_out_a);
|
||||
gpio_output(&gpio_sync_out_b);
|
||||
#endif
|
||||
|
||||
#ifdef RAD1O
|
||||
@ -894,6 +916,15 @@ void pin_setup(void) {
|
||||
|
||||
/* Safe state: start with VAA turned off: */
|
||||
disable_rf_power();
|
||||
|
||||
scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
|
||||
|
||||
gpio_input(&gpio_sync_in_a);
|
||||
gpio_input(&gpio_sync_in_b);
|
||||
|
||||
gpio_output(&gpio_sync_out_a);
|
||||
gpio_output(&gpio_sync_out_b);
|
||||
#endif
|
||||
|
||||
/* enable input on SCL and SDA pins */
|
||||
@ -950,3 +981,33 @@ void led_off(const led_t led) {
|
||||
void led_toggle(const led_t led) {
|
||||
gpio_toggle(&gpio_led[led]);
|
||||
}
|
||||
|
||||
void hw_sync_syn() {
|
||||
gpio_set(&gpio_sync_out_a);
|
||||
}
|
||||
|
||||
void hw_sync_stop() {
|
||||
gpio_clear(&gpio_sync_out_a);
|
||||
gpio_clear(&gpio_sync_out_b);
|
||||
}
|
||||
|
||||
void hw_sync_ack() {
|
||||
gpio_set(&gpio_sync_out_b);
|
||||
}
|
||||
|
||||
void hw_sync_copy_state() {
|
||||
if(gpio_read(&gpio_sync_in_a)) {
|
||||
gpio_set(&gpio_sync_out_a);
|
||||
} else {
|
||||
gpio_clear(&gpio_sync_out_a);
|
||||
}
|
||||
if(gpio_read(&gpio_sync_in_b)) {
|
||||
gpio_set(&gpio_sync_out_b);
|
||||
} else {
|
||||
gpio_clear(&gpio_sync_out_b);
|
||||
}
|
||||
}
|
||||
|
||||
bool hw_sync_ready() {
|
||||
return (gpio_read(&gpio_sync_in_a) && gpio_read(&gpio_sync_in_b));
|
||||
}
|
||||
|
@ -264,6 +264,11 @@ typedef enum {
|
||||
TRANSCEIVER_MODE_CPLD_UPDATE = 4
|
||||
} transceiver_mode_t;
|
||||
|
||||
typedef enum {
|
||||
HW_SYNC_MODE_OFF = 0,
|
||||
HW_SYNC_MODE_ON = 1,
|
||||
} hw_sync_mode_t;
|
||||
|
||||
void delay(uint32_t duration);
|
||||
|
||||
/* TODO: Hide these configurations */
|
||||
@ -279,6 +284,7 @@ extern w25q80bv_driver_t spi_flash;
|
||||
extern sgpio_config_t sgpio_config;
|
||||
extern rf_path_t rf_path;
|
||||
extern jtag_t jtag_cpld;
|
||||
extern i2c_bus_t i2c0;
|
||||
|
||||
void cpu_clock_init(void);
|
||||
void cpu_clock_pll1_low_speed(void);
|
||||
@ -311,6 +317,13 @@ void led_on(const led_t led);
|
||||
void led_off(const led_t led);
|
||||
void led_toggle(const led_t led);
|
||||
|
||||
void hw_sync_syn();
|
||||
void hw_sync_stop();
|
||||
void hw_sync_ack();
|
||||
bool hw_sync_ready();
|
||||
void hw_sync_copy_state();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -44,17 +44,23 @@ void i2c_lpc_transfer(i2c_bus_t* const bus,
|
||||
uint8_t* const data_rx, const size_t count_rx
|
||||
) {
|
||||
const uint32_t port = (uint32_t)bus->obj;
|
||||
i2c_tx_start(port);
|
||||
i2c_tx_byte(port, (slave_address << 1) | I2C_WRITE);
|
||||
for(size_t i=0; i<count_tx; i++) {
|
||||
i2c_tx_byte(port, data_tx[i]);
|
||||
size_t i;
|
||||
bool ack = false;
|
||||
if (data_tx && (count_tx > 0)) {
|
||||
i2c_tx_start(port);
|
||||
i2c_tx_byte(port, (slave_address << 1) | I2C_WRITE);
|
||||
for(i=0; i<count_tx; i++) {
|
||||
i2c_tx_byte(port, data_tx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if( data_rx ) {
|
||||
if (data_rx && (count_rx > 0)) {
|
||||
i2c_tx_start(port);
|
||||
i2c_tx_byte(port, (slave_address << 1) | I2C_READ);
|
||||
for(size_t i=0; i<count_rx; i++) {
|
||||
data_rx[i] = i2c_rx_byte(port);
|
||||
for(i=0; i<count_rx; i++) {
|
||||
/* ACK each byte except the last */
|
||||
ack = (i!=count_rx-1);
|
||||
data_rx[i] = i2c_rx_byte(port, ack);
|
||||
}
|
||||
}
|
||||
|
||||
|
147
firmware/common/operacake.c
Normal file
147
firmware/common/operacake.c
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2016 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 "operacake.h"
|
||||
#include "hackrf_core.h"
|
||||
|
||||
#define OPERACAKE_PIN_OE(x) (x<<7)
|
||||
#define OPERACAKE_PIN_U2CTRL1(x) (x<<6)
|
||||
#define OPERACAKE_PIN_U2CTRL0(x) (x<<5)
|
||||
#define OPERACAKE_PIN_U3CTRL1(x) (x<<4)
|
||||
#define OPERACAKE_PIN_U3CTRL0(x) (x<<3)
|
||||
#define OPERACAKE_PIN_U1CTRL(x) (x<<2)
|
||||
#define OPERACAKE_PIN_LEDEN2(x) (x<<1)
|
||||
#define OPERACAKE_PIN_LEDEN(x) (x<<0)
|
||||
|
||||
#define OPERACAKE_PORT_A1 (OPERACAKE_PIN_U2CTRL0(0) | OPERACAKE_PIN_U2CTRL1(0))
|
||||
#define OPERACAKE_PORT_A2 (OPERACAKE_PIN_U2CTRL0(1) | OPERACAKE_PIN_U2CTRL1(0))
|
||||
#define OPERACAKE_PORT_A3 (OPERACAKE_PIN_U2CTRL0(0) | OPERACAKE_PIN_U2CTRL1(1))
|
||||
#define OPERACAKE_PORT_A4 (OPERACAKE_PIN_U2CTRL0(1) | OPERACAKE_PIN_U2CTRL1(1))
|
||||
|
||||
#define OPERACAKE_PORT_B1 (OPERACAKE_PIN_U3CTRL0(0) | OPERACAKE_PIN_U3CTRL1(0))
|
||||
#define OPERACAKE_PORT_B2 (OPERACAKE_PIN_U3CTRL0(1) | OPERACAKE_PIN_U3CTRL1(0))
|
||||
#define OPERACAKE_PORT_B3 (OPERACAKE_PIN_U3CTRL0(0) | OPERACAKE_PIN_U3CTRL1(1))
|
||||
#define OPERACAKE_PORT_B4 (OPERACAKE_PIN_U3CTRL0(1) | OPERACAKE_PIN_U3CTRL1(1))
|
||||
|
||||
#define OPERACAKE_SAMESIDE OPERACAKE_PIN_U1CTRL(1)
|
||||
#define OPERACAKE_CROSSOVER OPERACAKE_PIN_U1CTRL(0)
|
||||
#define OPERACAKE_EN_LEDS (OPERACAKE_PIN_LEDEN2(1) | OPERACAKE_PIN_LEDEN2(0))
|
||||
#define OPERACAKE_GPIO_EN OPERACAKE_PIN_OE(0)
|
||||
#define OPERACAKE_GPIO_DISABLE OPERACAKE_PIN_OE(1)
|
||||
|
||||
#define OPERACAKE_REG_INPUT 0x00
|
||||
#define OPERACAKE_REG_OUTPUT 0x01
|
||||
#define OPERACAKE_REG_POLARITY 0x02
|
||||
#define OPERACAKE_REG_CONFIG 0x03
|
||||
|
||||
#define OPERACAKE_DEFAULT_OUTPUT (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE \
|
||||
| OPERACAKE_PORT_A1 | OPERACAKE_PORT_B1 \
|
||||
| OPERACAKE_EN_LEDS)
|
||||
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
|
||||
|
||||
#define OPERACAKE_DEFAULT_ADDRESS 0x18
|
||||
|
||||
i2c_bus_t* const oc_bus = &i2c0;
|
||||
uint8_t operacake_boards[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
/* read single register */
|
||||
uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg) {
|
||||
const uint8_t data_tx[] = { reg };
|
||||
uint8_t data_rx[] = { 0x00 };
|
||||
i2c_bus_transfer(bus, address, data_tx, 1, data_rx, 1);
|
||||
return data_rx[0];
|
||||
}
|
||||
|
||||
/* Write to one of the PCA9557 registers */
|
||||
void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value) {
|
||||
const uint8_t data[] = {reg, value};
|
||||
i2c_bus_transfer(bus, address, data, 2, NULL, 0);
|
||||
}
|
||||
|
||||
uint8_t operacake_init(void) {
|
||||
uint8_t reg, addr, i, j = 0;
|
||||
/* Find connected operacakes */
|
||||
for(i=0; i<8; i++) {
|
||||
addr = OPERACAKE_DEFAULT_ADDRESS | i;
|
||||
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_OUTPUT,
|
||||
OPERACAKE_DEFAULT_OUTPUT);
|
||||
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_CONFIG,
|
||||
OPERACAKE_CONFIG_ALL_OUTPUT);
|
||||
reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
|
||||
if(reg==OPERACAKE_CONFIG_ALL_OUTPUT)
|
||||
operacake_boards[j++] = addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t port_to_pins(uint8_t port) {
|
||||
switch(port) {
|
||||
case OPERACAKE_PA1:
|
||||
return OPERACAKE_PORT_A1;
|
||||
case OPERACAKE_PA2:
|
||||
return OPERACAKE_PORT_A2;
|
||||
case OPERACAKE_PA3:
|
||||
return OPERACAKE_PORT_A3;
|
||||
case OPERACAKE_PA4:
|
||||
return OPERACAKE_PORT_A4;
|
||||
|
||||
case OPERACAKE_PB1:
|
||||
return OPERACAKE_PORT_B1;
|
||||
case OPERACAKE_PB2:
|
||||
return OPERACAKE_PORT_B2;
|
||||
case OPERACAKE_PB3:
|
||||
return OPERACAKE_PORT_B3;
|
||||
case OPERACAKE_PB4:
|
||||
return OPERACAKE_PORT_B4;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB) {
|
||||
uint8_t side, pa, pb, reg;
|
||||
/* Start with some error checking,
|
||||
* which should have been done either
|
||||
* on the host or elsewhere in firmware
|
||||
*/
|
||||
if((PA > OPERACAKE_PB4) || (PB > OPERACAKE_PB4)) {
|
||||
return 1;
|
||||
}
|
||||
/* Check which side PA and PB are on */
|
||||
if(((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4))
|
||||
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(PA > OPERACAKE_PA4) {
|
||||
side = OPERACAKE_CROSSOVER;
|
||||
} else {
|
||||
side = OPERACAKE_SAMESIDE;
|
||||
}
|
||||
|
||||
pa = port_to_pins(PA);
|
||||
pb = port_to_pins(PB);
|
||||
|
||||
reg = (OPERACAKE_GPIO_DISABLE | side
|
||||
| pa | pb | OPERACAKE_EN_LEDS);
|
||||
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, reg);
|
||||
return 0;
|
||||
}
|
||||
|
53
firmware/common/operacake.h
Normal file
53
firmware/common/operacake.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPERACAKE_H
|
||||
#define __OPERACAKE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "i2c_bus.h"
|
||||
|
||||
#define OPERACAKE_PA1 0
|
||||
#define OPERACAKE_PA2 1
|
||||
#define OPERACAKE_PA3 2
|
||||
#define OPERACAKE_PA4 3
|
||||
|
||||
#define OPERACAKE_PB1 4
|
||||
#define OPERACAKE_PB2 5
|
||||
#define OPERACAKE_PB3 6
|
||||
#define OPERACAKE_PB4 7
|
||||
|
||||
/* Up to 8 Operacake boards can be used with one HackRF */
|
||||
extern uint8_t operacake_boards[8];
|
||||
|
||||
uint8_t operacake_init(void);
|
||||
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __OPERACAKE_H */
|
@ -230,6 +230,7 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) {
|
||||
|
||||
static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
|
||||
#ifdef JAWBREAKER
|
||||
(void) rf_path; /* silence unused param warning */
|
||||
mixer_set_gpo(&mixer, gpo);
|
||||
#elif HACKRF_ONE
|
||||
switchctrl_set_hackrf_one(rf_path, gpo);
|
||||
@ -274,9 +275,13 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
|
||||
gpio_output(rf_path->gpio_tx);
|
||||
gpio_output(rf_path->gpio_mix_bypass);
|
||||
gpio_output(rf_path->gpio_rx);
|
||||
#endif
|
||||
|
||||
#ifdef RAD1O
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and antenna port
|
||||
* power and enable both amp bypass and mixer bypass.
|
||||
*/
|
||||
switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
|
||||
#elif RAD1O
|
||||
/* Configure RF switch control signals */
|
||||
scu_pinmux(SCU_BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
@ -305,13 +310,15 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
|
||||
gpio_output(rf_path->gpio_low_high_filt_n);
|
||||
gpio_output(rf_path->gpio_tx_amp);
|
||||
gpio_output(rf_path->gpio_rx_lna);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and antenna port
|
||||
* power and enable both amp bypass and mixer bypass.
|
||||
*/
|
||||
switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
|
||||
#else
|
||||
(void) rf_path; /* silence unused param warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
void rf_path_init(rf_path_t* const rf_path) {
|
||||
|
@ -117,6 +117,10 @@ void rffc5071_setup(rffc5071_driver_t* const drv)
|
||||
/* GPOs are active at all times */
|
||||
set_RFFC5071_GATE(drv, 1);
|
||||
|
||||
/* Output LOCK status on GPO4 and enable lock detect */
|
||||
set_RFFC5071_LOCK(drv, 1);
|
||||
set_RFFC5071_LDEN(drv, 1);
|
||||
|
||||
rffc5071_regs_commit(drv);
|
||||
}
|
||||
|
||||
@ -254,13 +258,6 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
|
||||
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ)
|
||||
/ (lodiv * (1 << 24ULL));
|
||||
|
||||
/* Path 1 */
|
||||
set_RFFC5071_P1LODIV(drv, n_lo);
|
||||
set_RFFC5071_P1N(drv, n);
|
||||
set_RFFC5071_P1PRESC(drv, fbkdiv >> 1);
|
||||
set_RFFC5071_P1NMSB(drv, p1nmsb);
|
||||
set_RFFC5071_P1NLSB(drv, p1nlsb);
|
||||
|
||||
/* Path 2 */
|
||||
set_RFFC5071_P2LODIV(drv, n_lo);
|
||||
set_RFFC5071_P2N(drv, n);
|
||||
|
@ -94,10 +94,7 @@ void rffc5071_spi_stop(spi_bus_t* const bus) {
|
||||
|
||||
static void rffc5071_spi_serial_delay(spi_bus_t* const bus) {
|
||||
(void)bus;
|
||||
volatile uint32_t i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
static void rffc5071_spi_sck(spi_bus_t* const bus) {
|
||||
|
8
firmware/dfu.py
Normal file
8
firmware/dfu.py
Normal file
@ -0,0 +1,8 @@
|
||||
import os.path
|
||||
import struct
|
||||
import sys
|
||||
|
||||
with open("_header.bin", "wb") as f:
|
||||
x = struct.pack('<H', os.path.getsize(sys.argv[1] + '_dfu.bin') // 512 + 1)
|
||||
y = [0xda, 0xff, x[0], x[1], 0xff, 0xff, 0xff, 0xff]
|
||||
f.write(bytearray(y))
|
@ -42,6 +42,9 @@ set(SRC_M4
|
||||
usb_api_register.c
|
||||
usb_api_spiflash.c
|
||||
usb_api_transceiver.c
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/operacake.c"
|
||||
usb_api_operacake.c
|
||||
usb_api_sweep.c
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c"
|
||||
|
@ -22,12 +22,12 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <libopencm3/cm3/vector.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||
|
||||
#include <streaming.h>
|
||||
|
||||
#include "tuning.h"
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_standard_request.h"
|
||||
|
||||
@ -40,77 +40,14 @@
|
||||
#include "usb_api_cpld.h"
|
||||
#include "usb_api_register.h"
|
||||
#include "usb_api_spiflash.h"
|
||||
|
||||
#include "usb_api_operacake.h"
|
||||
#include "operacake.h"
|
||||
#include "usb_api_sweep.h"
|
||||
#include "usb_api_transceiver.h"
|
||||
#include "sgpio_isr.h"
|
||||
#include "usb_bulk_buffer.h"
|
||||
|
||||
#include "hackrf-ui.h"
|
||||
|
||||
static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;
|
||||
|
||||
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
baseband_streaming_disable(&sgpio_config);
|
||||
|
||||
usb_endpoint_disable(&usb_endpoint_bulk_in);
|
||||
usb_endpoint_disable(&usb_endpoint_bulk_out);
|
||||
|
||||
_transceiver_mode = new_transceiver_mode;
|
||||
|
||||
if( _transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
||||
led_off(LED3);
|
||||
led_on(LED2);
|
||||
usb_endpoint_init(&usb_endpoint_bulk_in);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||
} else if (_transceiver_mode == TRANSCEIVER_MODE_TX) {
|
||||
led_off(LED2);
|
||||
led_on(LED3);
|
||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx;
|
||||
} else {
|
||||
led_off(LED2);
|
||||
led_off(LED3);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||
}
|
||||
|
||||
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
||||
si5351c_activate_best_clock_source(&clock_gen);
|
||||
baseband_streaming_enable(&sgpio_config);
|
||||
}
|
||||
}
|
||||
|
||||
transceiver_mode_t transceiver_mode(void) {
|
||||
return _transceiver_mode;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
switch( endpoint->setup.value ) {
|
||||
case TRANSCEIVER_MODE_OFF:
|
||||
case TRANSCEIVER_MODE_RX:
|
||||
case TRANSCEIVER_MODE_TX:
|
||||
set_transceiver_mode(endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case TRANSCEIVER_MODE_CPLD_UPDATE:
|
||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||
start_cpld_update = true;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static const usb_request_handler_fn vendor_request_handler[] = {
|
||||
NULL,
|
||||
usb_vendor_request_set_transceiver_mode,
|
||||
@ -147,6 +84,11 @@ static const usb_request_handler_fn vendor_request_handler[] = {
|
||||
#endif
|
||||
usb_vendor_request_set_freq_explicit,
|
||||
usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ
|
||||
usb_vendor_request_init_sweep,
|
||||
usb_vendor_request_operacake_get_boards,
|
||||
usb_vendor_request_operacake_set_ports,
|
||||
usb_vendor_request_set_hw_sync_mode,
|
||||
usb_vendor_request_reset
|
||||
};
|
||||
|
||||
static const uint32_t vendor_request_handler_count =
|
||||
@ -247,13 +189,23 @@ int main(void) {
|
||||
usb_run(&usb_device);
|
||||
|
||||
rf_path_init(&rf_path);
|
||||
operacake_init();
|
||||
|
||||
unsigned int phase = 0;
|
||||
|
||||
while(true) {
|
||||
// Check whether we need to initiate a CPLD update
|
||||
if (start_cpld_update)
|
||||
cpld_update();
|
||||
|
||||
// Check whether we need to initiate sweep mode
|
||||
if (start_sweep_mode) {
|
||||
start_sweep_mode = false;
|
||||
sweep_mode();
|
||||
}
|
||||
|
||||
start_streaming_on_hw_sync();
|
||||
|
||||
// Set up IN transfer of buffer 0.
|
||||
if ( usb_bulk_buffer_offset >= 16384
|
||||
&& phase == 1
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <hackrf_core.h>
|
||||
#include <rom_iap.h>
|
||||
#include <usb_queue.h>
|
||||
#include <libopencm3/lpc43xx/wwdt.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
@ -91,3 +92,13 @@ usb_request_status_t usb_vendor_request_read_partid_serialno(
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_reset(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
wwdt_reset(100000);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
@ -39,5 +39,7 @@ usb_request_status_t usb_vendor_request_read_version_string(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_read_partid_serialno(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_reset(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif /* end of include guard: __USB_API_BOARD_INFO_H__ */
|
||||
|
49
firmware/hackrf_usb/usb_api_operacake.c
Normal file
49
firmware/hackrf_usb/usb_api_operacake.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2016 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 "usb_api_operacake.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
#include <operacake.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
usb_transfer_schedule_block(endpoint->in, operacake_boards, 8, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint8_t address, port_a, port_b;
|
||||
address = endpoint->setup.value & 0xFF;
|
||||
port_a = endpoint->setup.index & 0xFF;
|
||||
port_b = (endpoint->setup.index >> 8) & 0xFF;
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
operacake_set_ports(address, port_a, port_b);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
34
firmware/hackrf_usb/usb_api_operacake.h
Normal file
34
firmware/hackrf_usb/usb_api_operacake.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_OPERACAKE_H__
|
||||
#define __USB_API_OPERACAKE_H__
|
||||
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_get_boards(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
usb_request_status_t usb_vendor_request_operacake_set_ports(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif /* end of include guard: __USB_API_OPERACAKE_H__ */
|
109
firmware/hackrf_usb/usb_api_sweep.c
Normal file
109
firmware/hackrf_usb/usb_api_sweep.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2016 Mike Walters, Dominic Spill
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_sweep.h"
|
||||
#include "usb_queue.h"
|
||||
#include <stddef.h>
|
||||
#include <hackrf_core.h>
|
||||
#include "usb_api_transceiver.h"
|
||||
#include "usb_bulk_buffer.h"
|
||||
#include "tuning.h"
|
||||
#include "usb_endpoint.h"
|
||||
|
||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||
#define FREQ_GRANULARITY 1000000
|
||||
#define MIN_FREQ 1
|
||||
#define MAX_FREQ 6000
|
||||
#define MAX_FREQ_COUNT 1000
|
||||
|
||||
volatile bool start_sweep_mode = false;
|
||||
static uint64_t sweep_freq;
|
||||
bool odd = true;
|
||||
static uint16_t frequencies[MAX_FREQ_COUNT];
|
||||
static uint16_t frequency_count = 0;
|
||||
static uint32_t dwell_blocks = 0;
|
||||
|
||||
usb_request_status_t usb_vendor_request_init_sweep(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint32_t dwell_time;
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
dwell_time = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
dwell_blocks = dwell_time / 0x4000;
|
||||
frequency_count = endpoint->setup.length / sizeof(uint16_t);
|
||||
usb_transfer_schedule_block(endpoint->out, &frequencies,
|
||||
endpoint->setup.length, NULL, NULL);
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||
sweep_freq = frequencies[0];
|
||||
set_freq(sweep_freq*FREQ_GRANULARITY);
|
||||
start_sweep_mode = true;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
void sweep_mode(void) {
|
||||
unsigned int blocks_queued = 0;
|
||||
unsigned int phase = 0;
|
||||
unsigned int ifreq = 0;
|
||||
|
||||
uint8_t *buffer;
|
||||
bool transfer = false;
|
||||
|
||||
while(transceiver_mode() != TRANSCEIVER_MODE_OFF) {
|
||||
// Set up IN transfer of buffer 0.
|
||||
if ( usb_bulk_buffer_offset >= 16384 && phase == 1) {
|
||||
transfer = true;
|
||||
buffer = &usb_bulk_buffer[0x0000];
|
||||
phase = 0;
|
||||
blocks_queued++;
|
||||
}
|
||||
|
||||
// Set up IN transfer of buffer 1.
|
||||
if ( usb_bulk_buffer_offset < 16384 && phase == 0) {
|
||||
transfer = true;
|
||||
buffer = &usb_bulk_buffer[0x4000];
|
||||
phase = 1;
|
||||
blocks_queued++;
|
||||
}
|
||||
|
||||
if (transfer) {
|
||||
*(uint16_t*)buffer = 0x7F7F;
|
||||
*(uint16_t*)(buffer+2) = sweep_freq;
|
||||
usb_transfer_schedule_block(
|
||||
&usb_endpoint_bulk_in,
|
||||
buffer,
|
||||
0x4000,
|
||||
NULL, NULL
|
||||
);
|
||||
transfer = false;
|
||||
}
|
||||
|
||||
if (blocks_queued >= dwell_blocks) {
|
||||
if(++ifreq >= frequency_count)
|
||||
ifreq = 0;
|
||||
sweep_freq = frequencies[ifreq];
|
||||
set_freq(sweep_freq*FREQ_GRANULARITY);
|
||||
blocks_queued = 0;
|
||||
}
|
||||
}
|
||||
}
|
36
firmware/hackrf_usb/usb_api_sweep.h
Normal file
36
firmware/hackrf_usb/usb_api_sweep.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016 Mike Walters, Dominic Spill
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_SCAN_H__
|
||||
#define __USB_API_SCAN_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
extern volatile bool start_sweep_mode;
|
||||
|
||||
usb_request_status_t usb_vendor_request_init_sweep(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
void sweep_mode(void);
|
||||
|
||||
#endif /* __USB_API_SPCAN_H__ */
|
@ -23,10 +23,16 @@
|
||||
#include "usb_api_transceiver.h"
|
||||
|
||||
#include "hackrf-ui.h"
|
||||
#include <libopencm3/cm3/vector.h>
|
||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||
#include "sgpio_isr.h"
|
||||
|
||||
#include "usb_api_cpld.h" // Remove when CPLD update is handled elsewhere
|
||||
|
||||
#include <max2837.h>
|
||||
#include <rf_path.h>
|
||||
#include <tuning.h>
|
||||
#include <streaming.h>
|
||||
#include <usb.h>
|
||||
#include <usb_queue.h>
|
||||
|
||||
@ -226,3 +232,105 @@ usb_request_status_t usb_vendor_request_set_freq_explicit(
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;
|
||||
static volatile hw_sync_mode_t _hw_sync_mode = HW_SYNC_MODE_OFF;
|
||||
|
||||
void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode) {
|
||||
_hw_sync_mode = new_hw_sync_mode;
|
||||
}
|
||||
|
||||
transceiver_mode_t transceiver_mode(void) {
|
||||
return _transceiver_mode;
|
||||
}
|
||||
|
||||
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
baseband_streaming_disable(&sgpio_config);
|
||||
|
||||
usb_endpoint_disable(&usb_endpoint_bulk_in);
|
||||
usb_endpoint_disable(&usb_endpoint_bulk_out);
|
||||
|
||||
_transceiver_mode = new_transceiver_mode;
|
||||
|
||||
if( _transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
||||
led_off(LED3);
|
||||
led_on(LED2);
|
||||
usb_endpoint_init(&usb_endpoint_bulk_in);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||
} else if (_transceiver_mode == TRANSCEIVER_MODE_TX) {
|
||||
led_off(LED2);
|
||||
led_on(LED3);
|
||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx;
|
||||
} else {
|
||||
led_off(LED2);
|
||||
led_off(LED3);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF);
|
||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||
|
||||
hw_sync_stop();
|
||||
}
|
||||
|
||||
hw_sync_stop();
|
||||
|
||||
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
||||
si5351c_activate_best_clock_source(&clock_gen);
|
||||
|
||||
if( _hw_sync_mode != HW_SYNC_MODE_OFF) {
|
||||
hw_sync_syn();
|
||||
} else {
|
||||
baseband_streaming_enable(&sgpio_config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
switch( endpoint->setup.value ) {
|
||||
case TRANSCEIVER_MODE_OFF:
|
||||
case TRANSCEIVER_MODE_RX:
|
||||
case TRANSCEIVER_MODE_TX:
|
||||
set_transceiver_mode(endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case TRANSCEIVER_MODE_CPLD_UPDATE:
|
||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||
start_cpld_update = true;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_hw_sync_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
set_hw_sync_mode(endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void start_streaming_on_hw_sync()
|
||||
{
|
||||
if( _hw_sync_mode != HW_SYNC_MODE_OFF) {
|
||||
while(!hw_sync_ready()) { }
|
||||
hw_sync_ack();
|
||||
led_on(LED3);
|
||||
|
||||
baseband_streaming_enable(&sgpio_config);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode);
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
@ -52,5 +53,11 @@ usb_request_status_t usb_vendor_request_set_antenna_enable(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_freq_explicit(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_hw_sync_mode(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
transceiver_mode_t transceiver_mode(void);
|
||||
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode);
|
||||
void start_streaming_on_hw_sync();
|
||||
|
||||
#endif/*__USB_API_TRANSCEIVER_H__*/
|
||||
|
Submodule firmware/libopencm3 updated: 50c51c7b5f...d3d6f3e74b
@ -46,20 +46,20 @@ void tx_test() {
|
||||
}
|
||||
|
||||
void rx_test() {
|
||||
volatile uint32_t buffer[4096];
|
||||
uint32_t i = 0;
|
||||
volatile uint32_t buffer[4096];
|
||||
uint32_t i = 0;
|
||||
uint32_t magsq;
|
||||
int8_t sigi, sigq;
|
||||
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||
sgpio_cpld_stream_enable(&sgpio_config);
|
||||
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||
sgpio_cpld_stream_enable(&sgpio_config);
|
||||
|
||||
led_on(LED2);
|
||||
while(true) {
|
||||
while(SGPIO_STATUS_1 == 0);
|
||||
while(true) {
|
||||
while(SGPIO_STATUS_1 == 0);
|
||||
led_on(LED1);
|
||||
SGPIO_CLR_STATUS_1 = 1;
|
||||
buffer[i & 4095] = SGPIO_REG_SS(SGPIO_SLICE_A);
|
||||
SGPIO_CLR_STATUS_1 = 1;
|
||||
buffer[i & 4095] = SGPIO_REG_SS(SGPIO_SLICE_A);
|
||||
|
||||
/* find the magnitude squared */
|
||||
sigi = buffer[i & 4095] & 0xff;
|
||||
@ -72,7 +72,7 @@ void rx_test() {
|
||||
else
|
||||
led_off(LED3);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@ -86,7 +86,7 @@ int main(void) {
|
||||
enable_rf_power();
|
||||
#endif
|
||||
cpu_clock_init();
|
||||
rf_path_init(&rf_path);
|
||||
rf_path_init(&rf_path);
|
||||
|
||||
set_freq(freq);
|
||||
|
||||
|
109
host/README.md
109
host/README.md
@ -4,34 +4,34 @@ produce a low cost, open source software radio platform.
|
||||
##How to build the host software on Linux:
|
||||
|
||||
###Prerequisites for Linux (Debian/Ubuntu):
|
||||
|
||||
`sudo apt-get install build-essential cmake libusb-1.0-0-dev pkg-config`
|
||||
`sudo apt-get install build-essential cmake libusb-1.0-0-dev pkg-config libfftw3-dev`
|
||||
|
||||
###Build host software on Linux:
|
||||
```
|
||||
mkdir host/build
|
||||
cd host/build
|
||||
cmake ..
|
||||
make
|
||||
sudo make install
|
||||
sudo ldconfig
|
||||
```
|
||||
|
||||
`cd host`
|
||||
By defualt this will attempt to install a udev rule to '/etc/udev/rules.d` to
|
||||
provide the `usb` or `plugdev` group access to HackRF. If your setup requires
|
||||
the udev rule to be installed elsewhere you can modify the path with
|
||||
`-DUDEV_RULES_PATH=/path/to/udev`.
|
||||
|
||||
`mkdir build`
|
||||
|
||||
`cd build`
|
||||
|
||||
`cmake ../ -DINSTALL_UDEV_RULES=ON`
|
||||
|
||||
`make`
|
||||
|
||||
`sudo make install`
|
||||
|
||||
`sudo ldconfig`
|
||||
Note: The udev rule is not installed for by default for PyBOMBS installs as
|
||||
they do not ususally get installed with root privileges.
|
||||
|
||||
##Clean CMake temporary files/dirs:
|
||||
|
||||
`cd host/build`
|
||||
|
||||
`rm -rf *`
|
||||
```
|
||||
cd host/build
|
||||
rm -rf *
|
||||
```
|
||||
|
||||
##How to build host software on Windows:
|
||||
|
||||
###Prerequisites for cygwin or mingw:
|
||||
###Prerequisites for cygwin, mingw, or Visual Studio:
|
||||
|
||||
* cmake-2.8.12.1 or more see http://www.cmake.org/cmake/resources/software.html
|
||||
* libusbx-1.0.18 or more see http://sourceforge.net/projects/libusbx/files/latest/download?source=files
|
||||
@ -43,56 +43,45 @@ produce a low cost, open source software radio platform.
|
||||
Ctrl C is not managed correctly and especially for hackrf_transfer the Ctrl C(abort) will not stop correctly and will corrupt the file.
|
||||
|
||||
###For Cygwin:
|
||||
|
||||
`cd host`
|
||||
|
||||
`mkdir build`
|
||||
|
||||
`cd build`
|
||||
|
||||
`cmake ../ -G "Unix Makefiles" -DCMAKE_LEGACY_CYGWIN_WIN32=1 -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/`
|
||||
|
||||
`make`
|
||||
|
||||
`make install`
|
||||
|
||||
```
|
||||
mkdir host/build
|
||||
cd host/build
|
||||
cmake ../ -G "Unix Makefiles" -DCMAKE_LEGACY_CYGWIN_WIN32=1 -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
###For MinGW:
|
||||
```
|
||||
mkdir host/build
|
||||
cd host/build
|
||||
cmake ../ -G "MSYS Makefiles" -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
`cd host`
|
||||
###For Visual Studio 2015 x64
|
||||
```
|
||||
c:\hackrf\host\build> cmake ../ -G "Visual Studio 14 2015 Win64" \
|
||||
-DLIBUSB_INCLUDE_DIR=c:\libusb-1.0.18-win\include\libusb-1.0 \
|
||||
-DLIBUSB_LIBRARIES=c:\libusb-1.0.18-win\MS64\static\libusb-1.0.lib \
|
||||
-DTHREADS_PTHREADS_INCLUDE_DIR=c:\pthreads-w32-2-9-1-release\Pre-built.2\include \
|
||||
-DTHREADS_PTHREADS_WIN32_LIBRARY=c:\pthreads-w32-2-9-1-release\Pre-built.2\lib\x64\pthreadVC2.lib
|
||||
```
|
||||
|
||||
`mkdir build`
|
||||
|
||||
`cd build`
|
||||
|
||||
Normal version:
|
||||
|
||||
*
|
||||
`cmake ../ -G "MSYS Makefiles" -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/`
|
||||
|
||||
Debug version:
|
||||
|
||||
*
|
||||
`cmake ../ -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/`
|
||||
|
||||
`make`
|
||||
|
||||
`make install`
|
||||
|
||||
###For Visual Studio 2012 x64
|
||||
`c:\hackrf\host\cmake>cmake ../ -G "Visual Studio 11 2012 Win64" -DLIBUSB_INCLUDE_DIR=c:\libusb-1.0.18-win\include\libusb-1.0 -DLIBUSB_LIBRARIES=c:\libusb-1.0.18-win\MS64\static\libusb-1.0.lib -DTHREADS_PTHREADS_INCLUDE_DIR=c:\pthreads-w32-2-9-1-release\Pre-built.2\include -DTHREADS_PTHREADS_WIN32_LIBRARY=c:\pthreads-w32-2-9-1-release\Pre-built.2\lib\x64\pthreadVC2.lib`
|
||||
|
||||
Solution file: `c:\hackrf\host\cmake\hackrf_all.sln`
|
||||
Cmake will produce a solution file named `hackrf_all.sln` and a series of
|
||||
project files which can be used with msbuild as follows:
|
||||
`c:\hackrf\host\build> msbuild ALL_BUILD.vcxproj`
|
||||
|
||||
##How to build host the software on FreeBSD
|
||||
|
||||
You can use the binary package:
|
||||
`# pkg install hackrf`
|
||||
|
||||
You can build and install from ports:
|
||||
`# cd /usr/ports/comms/hackrf`
|
||||
`# make install`
|
||||
|
||||
```
|
||||
# cd /usr/ports/comms/hackrf
|
||||
# make install
|
||||
```
|
||||
|
||||
principal author: Michael Ossmann <mike@ossmann.com>
|
||||
|
||||
|
22
host/cmake/modules/FindFFTW.cmake
Normal file
22
host/cmake/modules/FindFFTW.cmake
Normal file
@ -0,0 +1,22 @@
|
||||
# - Find FFTW
|
||||
# Find the native FFTW includes and library
|
||||
#
|
||||
# FFTW_INCLUDES - where to find fftw3.h
|
||||
# FFTW_LIBRARIES - List of libraries when using FFTW.
|
||||
# FFTW_FOUND - True if FFTW found.
|
||||
|
||||
if (FFTW_INCLUDES)
|
||||
# Already in cache, be silent
|
||||
set (FFTW_FIND_QUIETLY TRUE)
|
||||
endif (FFTW_INCLUDES)
|
||||
|
||||
find_path (FFTW_INCLUDES fftw3.h)
|
||||
|
||||
find_library (FFTW_LIBRARIES NAMES fftw3)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES)
|
||||
|
||||
mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES)
|
@ -24,7 +24,7 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(hackrf-tools C)
|
||||
set(MAJOR_VERSION 0)
|
||||
set(MINOR_VERSION 4)
|
||||
set(MINOR_VERSION 5)
|
||||
set(PACKAGE hackrf-tools)
|
||||
set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION})
|
||||
set(VERSION ${VERSION_STRING})
|
||||
|
@ -1,34 +0,0 @@
|
||||
This repository contains hardware designs and software for HackRF, a project to
|
||||
produce a low cost, open source software radio platform.
|
||||
|
||||

|
||||
|
||||
How to build host software on Windows:
|
||||
prerequisite for cygwin or mingw:
|
||||
* cmake-2.8.10.2 or more see http://www.cmake.org/cmake/resources/software.html
|
||||
* libusbx-1.0.14 or more see http://sourceforge.net/projects/libusbx/files/latest/download?source=files
|
||||
* Install Windows driver for HackRF hardware or use Zadig see http://sourceforge.net/projects/libwdi/files/zadig
|
||||
- If you want to use Zadig select HackRF USB device and just install/replace it with WinUSB driver.
|
||||
* Build libhackrf before to build this library, see host/libhackrf/Readme.md.
|
||||
|
||||
For Cygwin:
|
||||
cmake -G "Unix Makefiles" -DCMAKE_LEGACY_CYGWIN_WIN32=1 -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
|
||||
For Mingw:
|
||||
#normal version
|
||||
cmake -G "MSYS Makefiles" -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
#debug version
|
||||
cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
|
||||
How to build host software on Linux:
|
||||
cmake ./
|
||||
make
|
||||
make install
|
||||
|
||||
principal author: Michael Ossmann <mike@ossmann.com>
|
||||
|
||||
http://greatscottgadgets.com/hackrf/
|
@ -23,10 +23,16 @@
|
||||
|
||||
set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX")
|
||||
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
if(MSVC)
|
||||
add_library(libgetopt_static STATIC
|
||||
../getopt/getopt.c
|
||||
)
|
||||
add_library(libgetopt_static STATIC
|
||||
../getopt/getopt.c
|
||||
)
|
||||
else()
|
||||
pkg_check_modules(FFTW REQUIRED fftw3f)
|
||||
LIST(APPEND TOOLS hackrf_sweep)
|
||||
LIST(APPEND TOOLS_LINK_LIBS m fftw3f)
|
||||
endif()
|
||||
|
||||
SET(TOOLS
|
||||
@ -37,6 +43,7 @@ SET(TOOLS
|
||||
hackrf_spiflash
|
||||
hackrf_cpldjtag
|
||||
hackrf_info
|
||||
hackrf_operacake
|
||||
)
|
||||
|
||||
if(NOT libhackrf_SOURCE_DIR)
|
||||
@ -55,4 +62,3 @@ foreach(tool ${TOOLS})
|
||||
target_link_libraries(${tool} ${TOOLS_LINK_LIBS})
|
||||
install(TARGETS ${tool} RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR})
|
||||
endforeach(tool)
|
||||
|
||||
|
@ -32,9 +32,10 @@ int main(void)
|
||||
uint8_t board_id = BOARD_ID_INVALID;
|
||||
char version[255 + 1];
|
||||
read_partid_serialno_t read_partid_serialno;
|
||||
uint8_t operacakes[8];
|
||||
hackrf_device_list_t *list;
|
||||
hackrf_device* device;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
result = hackrf_init();
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
@ -99,6 +100,19 @@ int main(void)
|
||||
read_partid_serialno.serial_no[2],
|
||||
read_partid_serialno.serial_no[3]);
|
||||
|
||||
result = hackrf_get_operacake_boards(device, &operacakes[0]);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
for(j=0; j<8; j++) {
|
||||
if(operacakes[j] == 0)
|
||||
break;
|
||||
printf("Operacake found, address: 0x%02x\n", operacakes[j]);
|
||||
|
||||
}
|
||||
|
||||
result = hackrf_close(device);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
|
||||
|
158
host/hackrf-tools/src/hackrf_operacake.c
Normal file
158
host/hackrf-tools/src/hackrf_operacake.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2016 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 <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-s, --serial <s>: 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-a <n>: set port A connection\n");
|
||||
printf("\t-b <n>: set port B connection\n");
|
||||
printf("\t-v: verbose, list available operacake boards\n");
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "device", no_argument, 0, 'd' },
|
||||
{ "serial", no_argument, 0, 's' },
|
||||
{ "address", no_argument, 0, 'o' },
|
||||
{ 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 main(int argc, char** argv) {
|
||||
int opt;
|
||||
const char* serial_number = NULL;
|
||||
int device_index = 0;
|
||||
int operacake_address = 0;
|
||||
int port_a = 0;
|
||||
int port_b = 0;
|
||||
int verbose = 0;
|
||||
uint8_t operacakes[8];
|
||||
int i = 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 -1;
|
||||
}
|
||||
|
||||
while( (opt = getopt_long(argc, argv, "d:s:o:a:b:v", long_options, &option_index)) != EOF ) {
|
||||
switch( opt ) {
|
||||
case 'd':
|
||||
device_index = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
serial_number = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
operacake_address = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
port_a = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
port_b = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
if(verbose) {
|
||||
hackrf_get_operacake_boards(device, operacakes);
|
||||
printf("Operacakes found:\n");
|
||||
for(i=0; i<8; i++) {
|
||||
if(operacakes[i] !=0)
|
||||
printf("%d\n", operacakes[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
result = hackrf_set_operacake_ports(device, operacake_address, port_a, port_b);
|
||||
if( result ) {
|
||||
printf("hackrf_set_operacake_ports() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = hackrf_close(device);
|
||||
if( result ) {
|
||||
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hackrf_exit();
|
||||
|
||||
return 0;
|
||||
}
|
@ -91,6 +91,7 @@ static void usage()
|
||||
printf("\t-r <filename>: Read data into file.\n");
|
||||
printf("\t-w <filename>: Write data from file.\n");
|
||||
printf("\t-d <serialnumber>: Serial number of device, if multiple devices\n");
|
||||
printf("\t-R: Reset HackRF after other operations.\n");
|
||||
printf("\t-v: Verbose output.\n");
|
||||
}
|
||||
|
||||
@ -112,8 +113,9 @@ int main(int argc, char** argv)
|
||||
bool read = false;
|
||||
bool write = false;
|
||||
bool verbose = false;
|
||||
bool reset = false;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "a:l:r:w:d:v", long_options,
|
||||
while ((opt = getopt_long(argc, argv, "a:l:r:w:d:vR", long_options,
|
||||
&option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
@ -142,8 +144,16 @@ int main(int argc, char** argv)
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
reset = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "opt error: %d\n", opt);
|
||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -156,18 +166,14 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (write == read) {
|
||||
if (write == true) {
|
||||
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Specify either read or write option.\n");
|
||||
}
|
||||
if(write && read) {
|
||||
fprintf(stderr, "Read and write options are mutually exclusive.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
fprintf(stderr, "Specify a path to a file.\n");
|
||||
if(!(write || read || reset)) {
|
||||
fprintf(stderr, "Specify either read, write, or reset option.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -177,7 +183,7 @@ int main(int argc, char** argv)
|
||||
fd = fopen(path, "rb");
|
||||
if(fd == NULL)
|
||||
{
|
||||
printf("Error to open file %s\n", path);
|
||||
printf("Error opening file %s\n", path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
/* Get size of the file */
|
||||
@ -214,7 +220,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == NULL) {
|
||||
if((read || write) && (fd == NULL)) {
|
||||
fprintf(stderr, "Failed to open file: %s\n", path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -233,8 +239,7 @@ int main(int argc, char** argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (read)
|
||||
{
|
||||
if(read) {
|
||||
ssize_t bytes_written;
|
||||
tmp_length = length;
|
||||
while (tmp_length)
|
||||
@ -261,7 +266,9 @@ int main(int argc, char** argv)
|
||||
fd = NULL;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if(write) {
|
||||
ssize_t bytes_read = fread(data, 1, length, fd);
|
||||
if (bytes_read != length) {
|
||||
fprintf(stderr, "Failed read file (read %d bytes).\n",
|
||||
@ -297,6 +304,17 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if(reset) {
|
||||
result = hackrf_reset(device);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_reset() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
fclose(fd);
|
||||
fd = NULL;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
result = hackrf_close(device);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
|
||||
|
549
host/hackrf-tools/src/hackrf_sweep.c
Normal file
549
host/hackrf-tools/src/hackrf_sweep.c
Normal file
@ -0,0 +1,549 @@
|
||||
/*
|
||||
* Copyright 2016 Dominic Spill <dominicgs@gmail.com>
|
||||
* Copyright 2016 Mike Walters <mike@flomp.net>
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <getopt.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <fftw3.h>
|
||||
#include <math.h>
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef int64_t ssize_t;
|
||||
#else
|
||||
typedef int32_t ssize_t;
|
||||
#endif
|
||||
|
||||
#define strtoull _strtoui64
|
||||
#define snprintf _snprintf
|
||||
|
||||
int gettimeofday(struct timeval *tv, void* ignored) {
|
||||
FILETIME ft;
|
||||
unsigned __int64 tmp = 0;
|
||||
if (NULL != tv) {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
tmp |= ft.dwHighDateTime;
|
||||
tmp <<= 32;
|
||||
tmp |= ft.dwLowDateTime;
|
||||
tmp /= 10;
|
||||
tmp -= 11644473600000000Ui64;
|
||||
tv->tv_sec = (long)(tmp / 1000000UL);
|
||||
tv->tv_usec = (long)(tmp % 1000000UL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#define FD_BUFFER_SIZE (8*1024)
|
||||
|
||||
#define FREQ_ONE_MHZ (1000000ull)
|
||||
|
||||
#define FREQ_MIN_HZ (0ull) /* 0 Hz */
|
||||
#define FREQ_MAX_HZ (7250000000ull) /* 7250MHz */
|
||||
|
||||
#define DEFAULT_SAMPLE_RATE_HZ (20000000) /* 20MHz default sample rate */
|
||||
#define DEFAULT_BASEBAND_FILTER_BANDWIDTH (15000000) /* 5MHz default */
|
||||
|
||||
#define FREQ_STEP (DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ)
|
||||
#define MAX_FREQ_COUNT 1000
|
||||
|
||||
#define DEFAULT_SAMPLE_COUNT 0x4000
|
||||
|
||||
#if defined _WIN32
|
||||
#define sleep(a) Sleep( (a*1000) )
|
||||
#endif
|
||||
|
||||
static float TimevalDiff(const struct timeval *a, const struct timeval *b) {
|
||||
return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec);
|
||||
}
|
||||
|
||||
int parse_u32(char* s, uint32_t* const value) {
|
||||
uint_fast8_t base = 10;
|
||||
char* s_end;
|
||||
uint64_t ulong_value;
|
||||
|
||||
if( strlen(s) > 2 ) {
|
||||
if( s[0] == '0' ) {
|
||||
if( (s[1] == 'x') || (s[1] == 'X') ) {
|
||||
base = 16;
|
||||
s += 2;
|
||||
} else if( (s[1] == 'b') || (s[1] == 'B') ) {
|
||||
base = 2;
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_end = s;
|
||||
ulong_value = strtoul(s, &s_end, base);
|
||||
if( (s != s_end) && (*s_end == 0) ) {
|
||||
*value = (uint32_t)ulong_value;
|
||||
return HACKRF_SUCCESS;
|
||||
} else {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_u32_range(char* s, uint32_t* const value_min, uint32_t* const value_max) {
|
||||
int result;
|
||||
|
||||
char *sep = strchr(s, ':');
|
||||
if (!sep)
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
|
||||
*sep = 0;
|
||||
|
||||
result = parse_u32(s, value_min);
|
||||
if (result != HACKRF_SUCCESS)
|
||||
return result;
|
||||
result = parse_u32(sep + 1, value_max);
|
||||
if (result != HACKRF_SUCCESS)
|
||||
return result;
|
||||
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
|
||||
volatile bool do_exit = false;
|
||||
|
||||
FILE* fd = NULL;
|
||||
volatile uint32_t byte_count = 0;
|
||||
|
||||
struct timeval time_start;
|
||||
struct timeval t_start;
|
||||
|
||||
bool amp = false;
|
||||
uint32_t amp_enable;
|
||||
|
||||
bool antenna = false;
|
||||
uint32_t antenna_enable;
|
||||
|
||||
uint32_t freq_min;
|
||||
uint32_t freq_max;
|
||||
|
||||
int fftSize;
|
||||
fftwf_complex *fftwIn = NULL;
|
||||
fftwf_complex *fftwOut = NULL;
|
||||
fftwf_plan fftwPlan = NULL;
|
||||
float* pwr;
|
||||
float* window;
|
||||
|
||||
float logPower(fftwf_complex in, float scale)
|
||||
{
|
||||
float re = in[0] * scale;
|
||||
float im = in[1] * scale;
|
||||
float magsq = re * re + im * im;
|
||||
return log2f(magsq) * 10.0f / log2(10.0f);
|
||||
}
|
||||
|
||||
int rx_callback(hackrf_transfer* transfer) {
|
||||
/* This is where we need to do interesting things with the samples
|
||||
* FFT
|
||||
* Throw away unused bins
|
||||
* write output to pipe
|
||||
*/
|
||||
ssize_t bytes_to_write;
|
||||
ssize_t bytes_written;
|
||||
int8_t* buf;
|
||||
float frequency;
|
||||
int i, j;
|
||||
|
||||
if( fd != NULL ) {
|
||||
byte_count += transfer->valid_length;
|
||||
bytes_to_write = transfer->valid_length;
|
||||
buf = (int8_t*) transfer->buffer;
|
||||
for(j=0; j<16; j++) {
|
||||
if(buf[0] == 0x7F && buf[1] == 0x7F) {
|
||||
frequency = *(uint16_t*)&buf[2];
|
||||
}
|
||||
/* copy to fftwIn as floats */
|
||||
buf += 16384 - (fftSize * 2);
|
||||
for(i=0; i < fftSize; i++) {
|
||||
fftwIn[i][0] = buf[i*2] * window[i] * 1.0f / 128.0f;
|
||||
fftwIn[i][1] = buf[i*2+1] * window[i] * 1.0f / 128.0f;
|
||||
}
|
||||
buf += fftSize * 2;
|
||||
fftwf_execute(fftwPlan);
|
||||
for (i=0; i < fftSize; i++) {
|
||||
// Start from the middle of the FFTW array and wrap
|
||||
// to rearrange the data
|
||||
int k = i ^ (fftSize >> 1);
|
||||
pwr[i] = logPower(fftwOut[k], 1.0f / fftSize);
|
||||
}
|
||||
fwrite(&frequency, sizeof(float), 1, stdout);
|
||||
fwrite(pwr, sizeof(float), fftSize, stdout);
|
||||
}
|
||||
|
||||
bytes_written = fwrite(transfer->buffer, 1, bytes_to_write, fd);
|
||||
if (bytes_written != bytes_to_write) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF.\n");
|
||||
fprintf(stderr, "\t[-a amp_enable] # RX/TX RF amplifier 1=Enable, 0=Disable.\n");
|
||||
fprintf(stderr, "\t[-f freq_min:freq_max # Specify minimum & maximum sweep frequencies (MHz).\n");
|
||||
fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable.\n");
|
||||
fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n");
|
||||
fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n");
|
||||
fprintf(stderr, "\t[-x gain_db] # TX VGA (IF) gain, 0-47dB, 1dB steps\n");
|
||||
fprintf(stderr, "\t[-n num_samples] # Number of samples per frequency, 0-4294967296\n");
|
||||
}
|
||||
|
||||
static hackrf_device* device = NULL;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
BOOL WINAPI
|
||||
sighandler(int signum) {
|
||||
if (CTRL_C_EVENT == signum) {
|
||||
fprintf(stderr, "Caught signal %d\n", signum);
|
||||
do_exit = true;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
void sigint_callback_handler(int signum) {
|
||||
fprintf(stderr, "Caught signal %d\n", signum);
|
||||
do_exit = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int opt, i, result, ifreq = 0;
|
||||
bool odd;
|
||||
const char* path = "/dev/null";
|
||||
const char* serial_number = NULL;
|
||||
int exit_code = EXIT_SUCCESS;
|
||||
struct timeval t_end;
|
||||
float time_diff;
|
||||
unsigned int lna_gain=16, vga_gain=20, txvga_gain=0;
|
||||
uint16_t frequencies[MAX_FREQ_COUNT];
|
||||
uint32_t num_samples = DEFAULT_SAMPLE_COUNT;
|
||||
|
||||
while( (opt = getopt(argc, argv, "a:f:p:l:g:x:d:n:")) != EOF ) {
|
||||
result = HACKRF_SUCCESS;
|
||||
switch( opt )
|
||||
{
|
||||
case 'd':
|
||||
serial_number = optarg;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
amp = true;
|
||||
result = parse_u32(optarg, &_enable);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
result = parse_u32_range(optarg, &freq_min, &freq_max);
|
||||
fprintf(stderr, "Scanning %uMHz to %uMHz\n", freq_min, freq_max);
|
||||
frequencies[ifreq++] = freq_min;
|
||||
odd = true;
|
||||
while(frequencies[ifreq-1] <= freq_max) {
|
||||
if (odd)
|
||||
frequencies[ifreq] = frequencies[ifreq-1] + FREQ_STEP / 4;
|
||||
else
|
||||
frequencies[ifreq] = frequencies[ifreq-1] + 3*(FREQ_STEP/4);
|
||||
ifreq++;
|
||||
odd = !odd;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
antenna = true;
|
||||
result = parse_u32(optarg, &antenna_enable);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
result = parse_u32(optarg, &lna_gain);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
result = parse_u32(optarg, &vga_gain);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
result = parse_u32(optarg, &txvga_gain);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
result = parse_u32(optarg, &num_samples);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "argument error: '-%c %s' %s (%d)\n", opt, optarg, hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (lna_gain % 8)
|
||||
fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n");
|
||||
|
||||
if (vga_gain % 2)
|
||||
fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n");
|
||||
|
||||
if (num_samples % 0x4000) {
|
||||
fprintf(stderr, "warning: num_samples (-n) must be a multiple of 16384\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( amp ) {
|
||||
if( amp_enable > 1 ) {
|
||||
fprintf(stderr, "argument error: amp_enable shall be 0 or 1.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (antenna) {
|
||||
if (antenna_enable > 1) {
|
||||
fprintf(stderr, "argument error: antenna_enable shall be 0 or 1.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifreq == 0) {
|
||||
fprintf(stderr, "argument error: must specify sweep frequency range (-f).\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fftSize = 64;
|
||||
fftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fftwPlan = fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE);
|
||||
pwr = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
||||
window = (float*)fftwf_malloc(sizeof(float) * fftSize);
|
||||
for (i = 0; i < fftSize; i++) {
|
||||
window[i] = 0.5f * (1.0f - cos(2 * M_PI * i / (fftSize - 1)));
|
||||
}
|
||||
|
||||
result = hackrf_init();
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
result = hackrf_open_by_serial(serial_number, &device);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fd = fopen(path, "wb");
|
||||
if( fd == NULL ) {
|
||||
fprintf(stderr, "Failed to open file: %s\n", path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
/* Change fd buffer to have bigger one to store or read data on/to HDD */
|
||||
result = setvbuf(fd , NULL , _IOFBF , FD_BUFFER_SIZE);
|
||||
if( result != 0 ) {
|
||||
fprintf(stderr, "setvbuf() failed: %d\n", result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
|
||||
#else
|
||||
signal(SIGINT, &sigint_callback_handler);
|
||||
signal(SIGILL, &sigint_callback_handler);
|
||||
signal(SIGFPE, &sigint_callback_handler);
|
||||
signal(SIGSEGV, &sigint_callback_handler);
|
||||
signal(SIGTERM, &sigint_callback_handler);
|
||||
signal(SIGABRT, &sigint_callback_handler);
|
||||
#endif
|
||||
fprintf(stderr, "call hackrf_sample_rate_set(%.03f MHz)\n",
|
||||
((float)DEFAULT_SAMPLE_RATE_HZ/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_sample_rate_manual(device, DEFAULT_SAMPLE_RATE_HZ, 1);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_sample_rate_set() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%.03f MHz)\n",
|
||||
((float)DEFAULT_BASEBAND_FILTER_BANDWIDTH/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_baseband_filter_bandwidth(device, DEFAULT_BASEBAND_FILTER_BANDWIDTH);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
result = hackrf_set_vga_gain(device, vga_gain);
|
||||
result |= hackrf_set_lna_gain(device, lna_gain);
|
||||
result |= hackrf_start_rx(device, rx_callback, NULL);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
result = hackrf_init_sweep(device, frequencies, ifreq, num_samples);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (amp) {
|
||||
fprintf(stderr, "call hackrf_set_amp_enable(%u)\n", amp_enable);
|
||||
result = hackrf_set_amp_enable(device, (uint8_t)amp_enable);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_set_amp_enable() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (antenna) {
|
||||
fprintf(stderr, "call hackrf_set_antenna_enable(%u)\n", antenna_enable);
|
||||
result = hackrf_set_antenna_enable(device, (uint8_t)antenna_enable);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_set_antenna_enable() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&t_start, NULL);
|
||||
gettimeofday(&time_start, NULL);
|
||||
|
||||
fprintf(stderr, "Stop with Ctrl-C\n");
|
||||
while((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) {
|
||||
uint32_t byte_count_now;
|
||||
struct timeval time_now;
|
||||
float time_difference, rate;
|
||||
sleep(1);
|
||||
|
||||
gettimeofday(&time_now, NULL);
|
||||
|
||||
byte_count_now = byte_count;
|
||||
byte_count = 0;
|
||||
|
||||
time_difference = TimevalDiff(&time_now, &time_start);
|
||||
rate = (float)byte_count_now / time_difference;
|
||||
fprintf(stderr, "%4.1f MiB / %5.3f sec = %4.1f MiB/second\n",
|
||||
(byte_count_now / 1e6f), time_difference, (rate / 1e6f) );
|
||||
|
||||
time_start = time_now;
|
||||
|
||||
if (byte_count_now == 0) {
|
||||
exit_code = EXIT_FAILURE;
|
||||
fprintf(stderr, "\nCouldn't transfer any bytes for one second.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = hackrf_is_streaming(device);
|
||||
if (do_exit) {
|
||||
fprintf(stderr, "\nUser cancel, exiting...\n");
|
||||
} else {
|
||||
fprintf(stderr, "\nExiting... hackrf_is_streaming() result: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
}
|
||||
|
||||
gettimeofday(&t_end, NULL);
|
||||
time_diff = TimevalDiff(&t_end, &t_start);
|
||||
fprintf(stderr, "Total time: %5.5f s\n", time_diff);
|
||||
|
||||
if(device != NULL) {
|
||||
result = hackrf_stop_rx(device);
|
||||
if(result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_stop_rx() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
} else {
|
||||
fprintf(stderr, "hackrf_stop_rx() done\n");
|
||||
}
|
||||
|
||||
result = hackrf_close(device);
|
||||
if(result != HACKRF_SUCCESS) {
|
||||
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
|
||||
hackrf_error_name(result), result);
|
||||
} else {
|
||||
fprintf(stderr, "hackrf_close() done\n");
|
||||
}
|
||||
|
||||
hackrf_exit();
|
||||
fprintf(stderr, "hackrf_exit() done\n");
|
||||
}
|
||||
|
||||
if(fd != NULL) {
|
||||
fclose(fd);
|
||||
fd = NULL;
|
||||
fprintf(stderr, "fclose(fd) done\n");
|
||||
}
|
||||
fprintf(stderr, "exit\n");
|
||||
return exit_code;
|
||||
}
|
@ -34,6 +34,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
@ -114,6 +116,11 @@ typedef enum {
|
||||
TRANSCEIVER_MODE_SS = 3,
|
||||
} transceiver_mode_t;
|
||||
|
||||
typedef enum {
|
||||
HW_SYNC_MODE_OFF = 0,
|
||||
HW_SYNC_MODE_ON = 1,
|
||||
} hw_sync_mode_t;
|
||||
|
||||
/* WAVE or RIFF WAVE file format containing IQ 2x8bits data for HackRF compatible with SDR# Wav IQ file */
|
||||
typedef struct
|
||||
{
|
||||
@ -303,6 +310,8 @@ volatile uint32_t byte_count = 0;
|
||||
bool signalsource = false;
|
||||
uint32_t amplitude = 0;
|
||||
|
||||
bool hw_sync = false;
|
||||
|
||||
bool receive = false;
|
||||
bool receive_wav = false;
|
||||
uint64_t stream_size = 0;
|
||||
@ -338,7 +347,7 @@ uint32_t sample_rate_hz;
|
||||
|
||||
bool limit_num_samples = false;
|
||||
uint64_t samples_to_xfer = 0;
|
||||
ssize_t bytes_to_xfer = 0;
|
||||
size_t bytes_to_xfer = 0;
|
||||
|
||||
bool baseband_filter_bw = false;
|
||||
uint32_t baseband_filter_bw_hz = 0;
|
||||
@ -349,9 +358,9 @@ bool crystal_correct = false;
|
||||
uint32_t crystal_correct_ppm ;
|
||||
|
||||
int rx_callback(hackrf_transfer* transfer) {
|
||||
ssize_t bytes_to_write;
|
||||
ssize_t bytes_written;
|
||||
int i;
|
||||
size_t bytes_to_write;
|
||||
size_t bytes_written;
|
||||
unsigned int i;
|
||||
|
||||
if( fd != NULL )
|
||||
{
|
||||
@ -370,25 +379,28 @@ int rx_callback(hackrf_transfer* transfer) {
|
||||
}
|
||||
}
|
||||
if (stream_size>0){
|
||||
if ((stream_size-1+stream_head-stream_tail)%stream_size <bytes_to_write){
|
||||
stream_drop++;
|
||||
}else{
|
||||
if(stream_tail+bytes_to_write <= stream_size){
|
||||
memcpy(stream_buf+stream_tail,transfer->buffer,bytes_to_write);
|
||||
}else{
|
||||
memcpy(stream_buf+stream_tail,transfer->buffer,(stream_size-stream_tail));
|
||||
memcpy(stream_buf,transfer->buffer+(stream_size-stream_tail),bytes_to_write-(stream_size-stream_tail));
|
||||
};
|
||||
__atomic_store_n(&stream_tail,(stream_tail+bytes_to_write)%stream_size,__ATOMIC_RELEASE);
|
||||
#ifndef _WIN32
|
||||
if ((stream_size-1+stream_head-stream_tail)%stream_size <bytes_to_write) {
|
||||
stream_drop++;
|
||||
} else {
|
||||
if(stream_tail+bytes_to_write <= stream_size) {
|
||||
memcpy(stream_buf+stream_tail,transfer->buffer,bytes_to_write);
|
||||
} else {
|
||||
memcpy(stream_buf+stream_tail,transfer->buffer,(stream_size-stream_tail));
|
||||
memcpy(stream_buf,transfer->buffer+(stream_size-stream_tail),bytes_to_write-(stream_size-stream_tail));
|
||||
};
|
||||
__atomic_store_n(&stream_tail,(stream_tail+bytes_to_write)%stream_size,__ATOMIC_RELEASE);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}else{
|
||||
bytes_written = fwrite(transfer->buffer, 1, bytes_to_write, fd);
|
||||
if ((bytes_written != bytes_to_write)
|
||||
|| (limit_num_samples && (bytes_to_xfer == 0))) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
bytes_written = fwrite(transfer->buffer, 1, bytes_to_write, fd);
|
||||
if ((bytes_written != bytes_to_write)
|
||||
|| (limit_num_samples && (bytes_to_xfer == 0))) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -397,9 +409,9 @@ int rx_callback(hackrf_transfer* transfer) {
|
||||
}
|
||||
|
||||
int tx_callback(hackrf_transfer* transfer) {
|
||||
ssize_t bytes_to_read;
|
||||
ssize_t bytes_read;
|
||||
int i;
|
||||
size_t bytes_to_read;
|
||||
size_t bytes_read;
|
||||
unsigned int i;
|
||||
|
||||
if( fd != NULL )
|
||||
{
|
||||
@ -416,15 +428,17 @@ int tx_callback(hackrf_transfer* transfer) {
|
||||
bytes_to_xfer -= bytes_to_read;
|
||||
}
|
||||
bytes_read = fread(transfer->buffer, 1, bytes_to_read, fd);
|
||||
if ((bytes_read != bytes_to_read)
|
||||
|| (limit_num_samples && (bytes_to_xfer == 0))) {
|
||||
if (limit_num_samples && (bytes_to_xfer == 0)) {
|
||||
return -1;
|
||||
}
|
||||
if (bytes_read != bytes_to_read) {
|
||||
if (repeat) {
|
||||
printf("Input file end reached. Rewind to beginning.\n");
|
||||
rewind(fd);
|
||||
fread(transfer->buffer + bytes_read, 1, bytes_to_read - bytes_read, fd);
|
||||
return 0;
|
||||
} else {
|
||||
return -1; // not loopback mode, EOF
|
||||
return -1; /* not repeat mode, end of file */
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -479,11 +493,15 @@ static void usage() {
|
||||
printf("\t[-s sample_rate_hz] # Sample rate in Hz (4/8/10/12.5/16/20MHz, default %sMHz).\n",
|
||||
u64toa((DEFAULT_SAMPLE_RATE_HZ/FREQ_ONE_MHZ),&ascii_u64_data1));
|
||||
printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n");
|
||||
#ifndef _WIN32
|
||||
/* The required atomic load/store functions aren't available when using C with MSVC */
|
||||
printf("\t[-S buf_size] # Enable receive streaming with buffer size buf_size.\n");
|
||||
#endif
|
||||
printf("\t[-c amplitude] # CW signal source mode, amplitude 0-127 (DC value to DAC).\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 < 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[-H] # Synchronise USB transfer using GPIO pins.\n");
|
||||
}
|
||||
|
||||
static hackrf_device* device = NULL;
|
||||
@ -527,11 +545,14 @@ int main(int argc, char** argv) {
|
||||
float time_diff;
|
||||
unsigned int lna_gain=8, vga_gain=20, txvga_gain=0;
|
||||
|
||||
while( (opt = getopt(argc, argv, "wr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:C:RS:")) != EOF )
|
||||
while( (opt = getopt(argc, argv, "Hwr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:C:RS:")) != EOF )
|
||||
{
|
||||
result = HACKRF_SUCCESS;
|
||||
switch( opt )
|
||||
{
|
||||
case 'H':
|
||||
hw_sync = true;
|
||||
break;
|
||||
case 'w':
|
||||
receive_wav = true;
|
||||
break;
|
||||
@ -653,6 +674,10 @@ int main(int argc, char** argv) {
|
||||
result = parse_u32(optarg, &crystal_correct_ppm);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
|
||||
usage();
|
||||
@ -778,24 +803,20 @@ int main(int argc, char** argv) {
|
||||
{
|
||||
/* Compute nearest freq for bw filter */
|
||||
baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw(baseband_filter_bw_hz);
|
||||
}else
|
||||
{
|
||||
/* Compute default value depending on sample rate */
|
||||
baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw_round_down_lt(sample_rate_hz);
|
||||
}
|
||||
|
||||
if (baseband_filter_bw_hz > BASEBAND_FILTER_BW_MAX) {
|
||||
fprintf(stderr, "argument error: baseband_filter_bw_hz must be less or equal to %u Hz/%.03f MHz\n",
|
||||
BASEBAND_FILTER_BW_MAX, (float)(BASEBAND_FILTER_BW_MAX/FREQ_ONE_MHZ));
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (baseband_filter_bw_hz > BASEBAND_FILTER_BW_MAX) {
|
||||
fprintf(stderr, "argument error: baseband_filter_bw_hz must be less or equal to %u Hz/%.03f MHz\n",
|
||||
BASEBAND_FILTER_BW_MAX, (float)(BASEBAND_FILTER_BW_MAX/FREQ_ONE_MHZ));
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (baseband_filter_bw_hz < BASEBAND_FILTER_BW_MIN) {
|
||||
fprintf(stderr, "argument error: baseband_filter_bw_hz must be greater or equal to %u Hz/%.03f MHz\n",
|
||||
BASEBAND_FILTER_BW_MIN, (float)(BASEBAND_FILTER_BW_MIN/FREQ_ONE_MHZ));
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
if (baseband_filter_bw_hz < BASEBAND_FILTER_BW_MIN) {
|
||||
fprintf(stderr, "argument error: baseband_filter_bw_hz must be greater or equal to %u Hz/%.03f MHz\n",
|
||||
BASEBAND_FILTER_BW_MIN, (float)(BASEBAND_FILTER_BW_MIN/FREQ_ONE_MHZ));
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( (transmit == false) && (receive == receive_wav) )
|
||||
@ -926,19 +947,30 @@ int main(int argc, char** argv) {
|
||||
signal(SIGTERM, &sigint_callback_handler);
|
||||
signal(SIGABRT, &sigint_callback_handler);
|
||||
#endif
|
||||
fprintf(stderr, "call hackrf_sample_rate_set(%u Hz/%.03f MHz)\n", sample_rate_hz,((float)sample_rate_hz/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_sample_rate_manual(device, sample_rate_hz, 1);
|
||||
fprintf(stderr, "call hackrf_set_sample_rate(%u Hz/%.03f MHz)\n", sample_rate_hz,((float)sample_rate_hz/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_sample_rate(device, sample_rate_hz);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_sample_rate_set() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
fprintf(stderr, "hackrf_set_sample_rate() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%d Hz/%.03f MHz)\n",
|
||||
baseband_filter_bw_hz, ((float)baseband_filter_bw_hz/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
|
||||
if( baseband_filter_bw ) {
|
||||
fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%d Hz/%.03f MHz)\n",
|
||||
baseband_filter_bw_hz, ((float)baseband_filter_bw_hz/(float)FREQ_ONE_MHZ));
|
||||
result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n",
|
||||
hw_sync);
|
||||
result = hackrf_set_hw_sync_mode(device, hw_sync ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF);
|
||||
if( result != HACKRF_SUCCESS ) {
|
||||
fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -1017,47 +1049,49 @@ int main(int argc, char** argv) {
|
||||
uint32_t byte_count_now;
|
||||
struct timeval time_now;
|
||||
float time_difference, rate;
|
||||
if (stream_size>0){
|
||||
if(stream_head==stream_tail){
|
||||
usleep(10000); // queue empty
|
||||
}else{
|
||||
ssize_t len;
|
||||
ssize_t bytes_written;
|
||||
uint32_t _st= __atomic_load_n(&stream_tail,__ATOMIC_ACQUIRE);
|
||||
if(stream_head<_st)
|
||||
len=_st-stream_head;
|
||||
else
|
||||
len=stream_size-stream_head;
|
||||
bytes_written = fwrite(stream_buf+stream_head, 1, len, fd);
|
||||
if (len != bytes_written){
|
||||
printf("write failed");
|
||||
do_exit=true;
|
||||
};
|
||||
stream_head=(stream_head+len)%stream_size;
|
||||
if (stream_size>0) {
|
||||
#ifndef _WIN32
|
||||
if(stream_head==stream_tail) {
|
||||
usleep(10000); // queue empty
|
||||
} else {
|
||||
ssize_t len;
|
||||
ssize_t bytes_written;
|
||||
uint32_t _st= __atomic_load_n(&stream_tail,__ATOMIC_ACQUIRE);
|
||||
if(stream_head<_st)
|
||||
len=_st-stream_head;
|
||||
else
|
||||
len=stream_size-stream_head;
|
||||
bytes_written = fwrite(stream_buf+stream_head, 1, len, fd);
|
||||
if (len != bytes_written) {
|
||||
printf("write failed");
|
||||
do_exit=true;
|
||||
};
|
||||
stream_head=(stream_head+len)%stream_size;
|
||||
}
|
||||
if(stream_drop>0){
|
||||
uint32_t drops= __atomic_exchange_n (&stream_drop,0,__ATOMIC_SEQ_CST);
|
||||
printf("dropped frames: [%d]\n",drops);
|
||||
if(stream_drop>0) {
|
||||
uint32_t drops= __atomic_exchange_n (&stream_drop,0,__ATOMIC_SEQ_CST);
|
||||
printf("dropped frames: [%d]\n",drops);
|
||||
}
|
||||
}else{
|
||||
sleep(1);
|
||||
#endif
|
||||
} else {
|
||||
sleep(1);
|
||||
gettimeofday(&time_now, NULL);
|
||||
|
||||
gettimeofday(&time_now, NULL);
|
||||
byte_count_now = byte_count;
|
||||
byte_count = 0;
|
||||
|
||||
byte_count_now = byte_count;
|
||||
byte_count = 0;
|
||||
time_difference = TimevalDiff(&time_now, &time_start);
|
||||
rate = (float)byte_count_now / time_difference;
|
||||
fprintf(stderr, "%4.1f MiB / %5.3f sec = %4.1f MiB/second\n",
|
||||
(byte_count_now / 1e6f), time_difference, (rate / 1e6f) );
|
||||
|
||||
time_difference = TimevalDiff(&time_now, &time_start);
|
||||
rate = (float)byte_count_now / time_difference;
|
||||
fprintf(stderr, "%4.1f MiB / %5.3f sec = %4.1f MiB/second\n",
|
||||
(byte_count_now / 1e6f), time_difference, (rate / 1e6f) );
|
||||
time_start = time_now;
|
||||
|
||||
time_start = time_now;
|
||||
|
||||
if (byte_count_now == 0) {
|
||||
exit_code = EXIT_FAILURE;
|
||||
fprintf(stderr, "\nCouldn't transfer any bytes for one second.\n");
|
||||
break;
|
||||
if (byte_count_now == 0) {
|
||||
exit_code = EXIT_FAILURE;
|
||||
fprintf(stderr, "\nCouldn't transfer any bytes for one second.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
This repository contains hardware designs and software for HackRF, a project to
|
||||
produce a low cost, open source software radio platform.
|
||||
|
||||

|
||||
|
||||
How to build host software on Windows:
|
||||
prerequisite for cygwin or mingw:
|
||||
* cmake-2.8.10.2 or more see http://www.cmake.org/cmake/resources/software.html
|
||||
* libusbx-1.0.14 or more see http://sourceforge.net/projects/libusbx/files/latest/download?source=files
|
||||
* Install Windows driver for HackRF hardware or use Zadig see http://sourceforge.net/projects/libwdi/files/zadig
|
||||
- If you want to use Zadig select HackRF USB device and just install/replace it with WinUSB driver.
|
||||
|
||||
For Cygwin:
|
||||
cmake -G "Unix Makefiles" -DCMAKE_LEGACY_CYGWIN_WIN32=1 -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
|
||||
For Mingw:
|
||||
#normal version
|
||||
cmake -G "MSYS Makefiles" -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
#debug version
|
||||
cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
|
||||
make
|
||||
make install
|
||||
|
||||
How to build host software on Linux:
|
||||
cmake ./
|
||||
make
|
||||
make install
|
||||
|
||||
principal author: Michael Ossmann <mike@ossmann.com>
|
||||
|
||||
http://greatscottgadgets.com/hackrf/
|
@ -26,6 +26,11 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Avoid redefinition of timespec from time.h (included by libusb.h) */
|
||||
#define HAVE_STRUCT_TIMESPEC 1
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef bool
|
||||
@ -67,6 +72,12 @@ typedef enum {
|
||||
HACKRF_VENDOR_REQUEST_SET_TXVGA_GAIN = 21,
|
||||
HACKRF_VENDOR_REQUEST_ANTENNA_ENABLE = 23,
|
||||
HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24,
|
||||
// USB_WCID_VENDOR_REQ = 25
|
||||
HACKRF_VENDOR_REQUEST_INIT_SWEEP = 26,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS = 27,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS = 28,
|
||||
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE = 29,
|
||||
HACKRF_VENDOR_REQUEST_RESET = 30,
|
||||
} hackrf_vendor_request;
|
||||
|
||||
typedef enum {
|
||||
@ -82,6 +93,11 @@ typedef enum {
|
||||
TRANSCEIVER_MODE_CPLD_UPDATE = 4,
|
||||
} hackrf_transceiver_mode;
|
||||
|
||||
typedef enum {
|
||||
HACKRF_HW_SYNC_MODE_OFF = 0,
|
||||
HACKRF_HW_SYNC_MODE_ON = 1,
|
||||
} hackrf_hw_sync_mode;
|
||||
|
||||
struct hackrf_device {
|
||||
libusb_device_handle* usb_device;
|
||||
struct libusb_transfer** transfers;
|
||||
@ -1094,6 +1110,11 @@ typedef struct {
|
||||
} set_fracrate_params_t;
|
||||
|
||||
|
||||
/*
|
||||
* You should probably use hackrf_set_sample_rate() below instead of this
|
||||
* function. They both result in automatic baseband filter selection as
|
||||
* described below.
|
||||
*/
|
||||
int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device,
|
||||
const uint32_t freq_hz, uint32_t divider)
|
||||
{
|
||||
@ -1120,10 +1141,17 @@ int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device,
|
||||
{
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
return hackrf_set_baseband_filter_bandwidth(device,
|
||||
hackrf_compute_baseband_filter_bw((uint32_t)(0.75*freq_hz/divider)));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For anti-aliasing, the baseband filter bandwidth is automatically set to the
|
||||
* widest available setting that is no more than 75% of the sample rate. This
|
||||
* happens every time the sample rate is set. If you want to override the
|
||||
* baseband filter selection, you must do so after setting the sample rate.
|
||||
*/
|
||||
int ADDCALL hackrf_set_sample_rate(hackrf_device* device, const double freq)
|
||||
{
|
||||
const int MAX_N = 32;
|
||||
@ -1417,6 +1445,7 @@ static int create_transfer_thread(hackrf_device* device,
|
||||
if( device->transfer_thread_started == false )
|
||||
{
|
||||
device->streaming = false;
|
||||
do_exit = false;
|
||||
|
||||
result = prepare_transfers(
|
||||
device, endpoint_address,
|
||||
@ -1548,6 +1577,26 @@ int ADDCALL hackrf_close(hackrf_device* device)
|
||||
return result1;
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value) {
|
||||
int result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE,
|
||||
value,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if( result != 0 )
|
||||
{
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ADDCALL hackrf_error_name(enum hackrf_error errcode)
|
||||
{
|
||||
switch(errcode)
|
||||
@ -1695,6 +1744,111 @@ uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz)
|
||||
return p->bandwidth_hz;
|
||||
}
|
||||
|
||||
/* Initialise sweep mode with alist of frequencies and dwell time in samples */
|
||||
int ADDCALL hackrf_init_sweep(hackrf_device* device, uint16_t* frequency_list, int length, uint32_t dwell_time)
|
||||
{
|
||||
int result, i;
|
||||
int size = length * sizeof(frequency_list[0]);
|
||||
|
||||
for(i=0; i<length; i++)
|
||||
frequency_list[i] = TO_LE(frequency_list[i]);
|
||||
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_INIT_SWEEP,
|
||||
dwell_time & 0xffff,
|
||||
(dwell_time >> 16) & 0xffff,
|
||||
(unsigned char*)frequency_list,
|
||||
size,
|
||||
0
|
||||
);
|
||||
|
||||
if (result < size) {
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Retrieve list of Operacake board addresses
|
||||
* boards must be *uint8_t[8]
|
||||
*/
|
||||
int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards)
|
||||
{
|
||||
int result;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_GET_BOARDS,
|
||||
0,
|
||||
0,
|
||||
boards,
|
||||
8,
|
||||
0
|
||||
);
|
||||
|
||||
if (result < 8)
|
||||
{
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Operacake ports */
|
||||
int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||
uint8_t address,
|
||||
uint8_t port_a,
|
||||
uint8_t port_b)
|
||||
{
|
||||
int result;
|
||||
/* Error checking */
|
||||
if((port_a > OPERACAKE_PB4) || (port_b > OPERACAKE_PB4)) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
/* Check which side PA and PB are on */
|
||||
if(((port_a <= OPERACAKE_PA4) && (port_b <= OPERACAKE_PA4))
|
||||
|| ((port_a > OPERACAKE_PA4) && (port_b > OPERACAKE_PA4))) {
|
||||
return HACKRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_PORTS,
|
||||
address,
|
||||
port_a | (port_b<<8),
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if (result != 0) {
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_reset(hackrf_device* device) {
|
||||
int result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_RESET,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if( result != 0 ) {
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
} else {
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // __cplusplus defined.
|
||||
#endif
|
||||
|
@ -83,6 +83,17 @@ enum rf_path_filter {
|
||||
RF_PATH_FILTER_HIGH_PASS = 2,
|
||||
};
|
||||
|
||||
enum operacake_ports {
|
||||
OPERACAKE_PA1 = 0,
|
||||
OPERACAKE_PA2 = 1,
|
||||
OPERACAKE_PA3 = 2,
|
||||
OPERACAKE_PA4 = 3,
|
||||
OPERACAKE_PB1 = 4,
|
||||
OPERACAKE_PB2 = 5,
|
||||
OPERACAKE_PB3 = 6,
|
||||
OPERACAKE_PB4 = 7,
|
||||
};
|
||||
|
||||
typedef struct hackrf_device hackrf_device;
|
||||
|
||||
typedef struct {
|
||||
@ -187,6 +198,9 @@ extern ADDAPI int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t
|
||||
/* antenna port power control */
|
||||
extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value);
|
||||
|
||||
/* set hardware sync mode */
|
||||
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
|
||||
|
||||
extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode);
|
||||
extern ADDAPI const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id);
|
||||
extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name(enum hackrf_usb_board_id usb_board_id);
|
||||
@ -196,6 +210,19 @@ extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_fil
|
||||
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz);
|
||||
/* Compute best default value depending on sample rate (auto filter) */
|
||||
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz);
|
||||
/* Start scan mode */
|
||||
extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
|
||||
uint16_t* frequency_list,
|
||||
int length, uint32_t dwell_time);
|
||||
|
||||
/* Operacake functions */
|
||||
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
|
||||
extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
||||
uint8_t address,
|
||||
uint8_t port_a,
|
||||
uint8_t port_b);
|
||||
|
||||
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // __cplusplus defined.
|
||||
|
@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2012 Jared Boone
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import usb
|
||||
import struct
|
||||
import sys
|
||||
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0x604b)
|
||||
if device:
|
||||
print 'Find: HackRF Jawbreaker'
|
||||
else:
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0x6089)
|
||||
if device:
|
||||
print 'Find: HackRF One'
|
||||
else:
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0xcc15)
|
||||
if device:
|
||||
print 'Find: rad1o'
|
||||
else:
|
||||
print 'Not find any HackRF device.'
|
||||
sys.exit()
|
||||
device.set_configuration()
|
||||
|
||||
def read_max2837_register(register_number):
|
||||
return struct.unpack('<H', device.ctrl_transfer(0xC0, 3, 0, register_number, 2))[0]
|
||||
|
||||
def write_max2837_register(register_number, value):
|
||||
device.ctrl_transfer(0x40, 2, value, register_number)
|
||||
|
||||
def dump_max2837():
|
||||
for i in range(32):
|
||||
print('%2d: %03x' % (i, read_max2837_register(i)))
|
||||
|
||||
dump_max2837()
|
@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2012 Jared Boone
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
import sys
|
||||
import usb
|
||||
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0x604b)
|
||||
if device:
|
||||
print 'Find: HackRF Jawbreaker'
|
||||
else:
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0x6089)
|
||||
if device:
|
||||
print 'Find: HackRF One'
|
||||
else:
|
||||
device = usb.core.find(idVendor=0x1d50, idProduct=0xcc15)
|
||||
if device:
|
||||
print 'Find: rad1o'
|
||||
else:
|
||||
print 'Not find any HackRF device.'
|
||||
sys.exit()
|
||||
device.set_configuration()
|
||||
|
||||
def set_rx():
|
||||
device.ctrl_transfer(0x40, 1, 1, 0)
|
||||
|
||||
def set_tx():
|
||||
device.ctrl_transfer(0x40, 1, 2, 0)
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'tx':
|
||||
set_tx()
|
||||
elif sys.argv[1] == 'rx':
|
||||
set_rx()
|
||||
else:
|
||||
print 'Usage: %s [rx|tx]' % sys.argv[0]
|
Reference in New Issue
Block a user