Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make HackRF bias tee configurable #794

Merged
merged 11 commits into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion data/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,12 @@ jobs:
displayName: "Install build dependencies"

- script: |
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8d748e26ccc9afc8ea0d0201ae234fda35de721e/Formula/boost.rb
echo "Reinstall icu4c"
brew reinstall https://raw.githubusercontent.com/Homebrew/homebrew-core/a806a621ed3722fb580a58000fb274a2f2d86a6d/Formula/icu4c.rb
echo "Link icu4c"
brew link icu4c --force
echo "Install boost"
brew install --force --ignore-dependencies https://raw.githubusercontent.com/Homebrew/homebrew-core/8d748e26ccc9afc8ea0d0201ae234fda35de721e/Formula/boost.rb
cd /tmp
wget https://github.com/libusb/libusb/releases/download/v1.0.22/libusb-1.0.22.tar.bz2
tar xf libusb-1.0.22.tar.bz2
Expand Down
554 changes: 287 additions & 267 deletions data/ui/send_recv_device_settings.ui

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion src/urh/controller/widgets/DeviceSettingsWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ def set_val(ui_widget, key: str, default):
checked = True if checked == "True" else False
self.ui.checkBoxDCCorrection.setChecked(checked)

checked = conf_dict.get("bias_tee_enabled", False)
if isinstance(checked, str):
checked = True if checked == "True" else False
self.ui.checkBoxBiasTee.setChecked(checked)

self.emit_editing_finished_signals()

@property
Expand Down Expand Up @@ -164,6 +169,7 @@ def create_connects(self):

self.ui.comboBoxDeviceIdentifier.editTextChanged.connect(self.on_combo_box_device_identifier_edit_text_changed)

self.ui.checkBoxBiasTee.clicked.connect(self.on_check_box_bias_tee_clicked)
self.ui.checkBoxDCCorrection.clicked.connect(self.on_check_box_dc_correction_clicked)

def set_gain_defaults(self):
Expand Down Expand Up @@ -307,6 +313,10 @@ def set_device_ui_items_visibility(self, device_name: str, overwrite_settings=Tr
self.ui.checkBoxDCCorrection.setVisible(show_dc_correction)
self.ui.labelDCCorrection.setVisible(show_dc_correction)

show_bias_tee = "bias_tee_enabled" in conf and self.device is not None and self.device.bias_tee_enabled is not None
self.ui.labelBiasTee.setVisible(show_bias_tee)
self.ui.checkBoxBiasTee.setVisible(show_bias_tee)

def get_devices_for_combobox(self, continuous_send_mode):
items = []
for device_name in self.backend_handler.DEVICE_NAMES:
Expand Down Expand Up @@ -357,7 +367,7 @@ def emit_editing_finished_signals(self):
def emit_device_parameters_changed(self):
settings = {"name": str(self.device.name)}
for attrib in ("frequency", "sample_rate", "bandwidth", "gain", "if_gain", "baseband_gain", "freq_correction",
"antenna_index", "num_sending_repeats", "apply_dc_correction", "subdevice"):
"antenna_index", "num_sending_repeats", "apply_dc_correction", "subdevice", "bias_tee_enabled"):
try:
value = getattr(self.device, attrib, None)
if value is not None:
Expand Down Expand Up @@ -510,6 +520,11 @@ def on_btn_refresh_device_identifier_clicked(self):
self.ui.comboBoxDeviceIdentifier.clear()
self.ui.comboBoxDeviceIdentifier.addItems(self.device.get_device_list())

@pyqtSlot(bool)
def on_check_box_bias_tee_clicked(self, checked: bool):
if self.device is not None:
self.device.bias_tee_enabled = bool(checked)

@pyqtSlot(bool)
def on_check_box_dc_correction_clicked(self, checked: bool):
self.device.apply_dc_correction = bool(checked)
Expand Down
16 changes: 16 additions & 0 deletions src/urh/dev/VirtualDevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ def __init__(self, backend_handler, name: str, mode: Mode, freq=None, sample_rat
if mode == Mode.spectrum:
self.__dev.is_in_spectrum_mode = True

@property
def backend_is_native(self) -> bool:
return self.backend == Backends.native

@property
def data_type(self):
if self.backend == Backends.native:
Expand Down Expand Up @@ -213,6 +217,18 @@ def apply_dc_correction(self, value: bool):
if self.backend == Backends.native:
self.__dev.apply_dc_correction = bool(value)

@property
def bias_tee_enabled(self):
if self.backend_is_native:
return self.__dev.bias_tee_enabled
else:
return None

@bias_tee_enabled.setter
def bias_tee_enabled(self, value: bool):
if self.backend_is_native:
self.__dev.bias_tee_enabled = value

@property
def bandwidth_is_adjustable(self):
if self.backend == Backends.grc:
Expand Down
3 changes: 2 additions & 1 deletion src/urh/dev/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"rx_rf_gain": [0, 14],
"rx_if_gain": [0, 8, 16, 24, 32, 40],
"tx_if_gain": list(range(0, 48)),
"rx_baseband_gain": list(range(0, 63, 2)) # only available in RX
"rx_baseband_gain": list(range(0, 63, 2)), # only available in RX
"bias_tee_enabled": [False, True]
}

# https://kb.ettus.com/About_USRP_Bandwidths_and_Sampling_Rates
Expand Down
19 changes: 19 additions & 0 deletions src/urh/dev/native/Device.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Command(Enum):
SET_FREQUENCY_CORRECTION = 8
SET_CHANNEL_INDEX = 9
SET_ANTENNA_INDEX = 10
SET_BIAS_TEE_ENABLED = 11

ASYNCHRONOUS = False

Expand Down Expand Up @@ -250,6 +251,7 @@ def __init__(self, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseban
self.__antenna_index = 0

self.__freq_correction = 0
self.__bias_tee_enabled = False
self.__direct_sampling_mode = 0
self.bandwidth_is_adjustable = True

Expand Down Expand Up @@ -523,6 +525,23 @@ def set_device_antenna_index(self, value):
except (BrokenPipeError, OSError):
pass

@property
def bias_tee_enabled(self):
return self.__bias_tee_enabled

@bias_tee_enabled.setter
def bias_tee_enabled(self, value: bool):
value = bool(value)
if value != self.__bias_tee_enabled:
self.__bias_tee_enabled = value
self.set_device_bias_tee_enabled(value)

def set_device_bias_tee_enabled(self, value):
try:
self.parent_ctrl_conn.send((self.Command.SET_BIAS_TEE_ENABLED.name, int(value)))
except (BrokenPipeError, OSError):
pass

@property
def freq_correction(self):
return self.__freq_correction
Expand Down
17 changes: 15 additions & 2 deletions src/urh/dev/native/HackRF.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import OrderedDict
from multiprocessing import Array
from multiprocessing.connection import Connection

Expand All @@ -13,7 +14,8 @@ class HackRF(Device):
DEVICE_METHODS = Device.DEVICE_METHODS.copy()
DEVICE_METHODS.update({
Device.Command.SET_FREQUENCY.name: "set_freq",
Device.Command.SET_BANDWIDTH.name: "set_baseband_filter_bandwidth"
Device.Command.SET_BANDWIDTH.name: "set_baseband_filter_bandwidth",
Device.Command.SET_BIAS_TEE_ENABLED.name: "set_bias_tee"
})

DATA_TYPE = np.int8
Expand All @@ -31,7 +33,7 @@ def setup_device(cls, ctrl_connection: Connection, device_identifier):
msg = "SETUP"
if device_identifier:
msg += " ({})".format(device_identifier)
msg += ": "+str(ret)
msg += ": " + str(ret)
ctrl_connection.send(msg)

return ret == 0
Expand Down Expand Up @@ -87,6 +89,17 @@ def __init__(self, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseban
-9999: "HACKRF_ERROR_OTHER"
}

@property
def device_parameters(self) -> OrderedDict:
return OrderedDict([(self.Command.SET_FREQUENCY.name, self.frequency),
(self.Command.SET_SAMPLE_RATE.name, self.sample_rate),
(self.Command.SET_BANDWIDTH.name, self.bandwidth),
(self.Command.SET_RF_GAIN.name, self.gain),
(self.Command.SET_IF_GAIN.name, self.if_gain),
(self.Command.SET_BB_GAIN.name, self.baseband_gain),
(self.Command.SET_BIAS_TEE_ENABLED.name, self.bias_tee_enabled),
("identifier", self.device_serial)])

@property
def has_multi_device_support(self):
return hackrf.has_multi_device_support()
Expand Down
19 changes: 9 additions & 10 deletions src/urh/dev/native/lib/chackrf.pxd
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t

cdef extern from "libhackrf/hackrf.h":
enum hackrf_error:
HACKRF_SUCCESS = 0
Expand Down Expand Up @@ -40,11 +42,6 @@ cdef extern from "libhackrf/hackrf.h":
ctypedef struct hackrf_device:
pass

ctypedef unsigned char uint8_t
ctypedef unsigned short uint16_t
ctypedef unsigned int uint32_t
ctypedef unsigned long long uint64_t

ctypedef struct hackrf_transfer:
hackrf_device* device
uint8_t* buffer
Expand Down Expand Up @@ -81,7 +78,7 @@ cdef extern from "libhackrf/hackrf.h":
int hackrf_open(hackrf_device** device);

IF HACKRF_MULTI_DEVICE_SUPPORT == 1:
int hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device)
int hackrf_open_by_serial(const char* desired_serial_number, hackrf_device** device)
hackrf_device_list_t* hackrf_device_list()


Expand All @@ -108,12 +105,11 @@ cdef extern from "libhackrf/hackrf.h":
int hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16_t value)

int hackrf_spiflash_erase(hackrf_device* device)
int hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data)
int hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, const unsigned char* data)
int hackrf_spiflash_read(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* data)

# device will need to be reset after hackrf_cpld_write
int hackrf_cpld_write(hackrf_device* device,
unsigned char* const data, const unsigned int total_length)
int hackrf_cpld_write(hackrf_device* device, const unsigned char* data, const unsigned int total_length)

int hackrf_board_id_read(hackrf_device* device, uint8_t* value)
int hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length)
Expand All @@ -130,7 +126,10 @@ cdef extern from "libhackrf/hackrf.h":

# external amp, bool on/off
int hackrf_set_amp_enable(hackrf_device* device, const uint8_t value)


# Bias Tee, bool on/off
int hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value)

int hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno)

# range 0-40 step 8d, IF gain in osmosdr
Expand Down
58 changes: 23 additions & 35 deletions src/urh/dev/native/lib/hackrf.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cimport urh.dev.native.lib.chackrf as chackrf
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
from libc.stdlib cimport malloc
import time

Expand Down Expand Up @@ -70,21 +71,21 @@ ELSE:
cpdef get_device_list():
return None

cpdef setup(str serial):
cpdef int setup(str serial):
"""
Convenience method for init + open. This one is used by HackRF class.
:return:
"""
init()
return open(serial)

cpdef init():
cpdef int init():
return chackrf.hackrf_init()

cpdef exit():
cpdef int exit():
return chackrf.hackrf_exit()

cpdef close():
cpdef int close():
return chackrf.hackrf_close(_c_device)

cpdef int start_rx_mode(callback):
Expand All @@ -93,42 +94,25 @@ cpdef int start_rx_mode(callback):
f = callback
return chackrf.hackrf_start_rx(_c_device, _c_callback_recv, NULL)

cpdef stop_rx_mode():
cpdef int stop_rx_mode():
global RUNNING
RUNNING = -1
time.sleep(TIMEOUT)
return chackrf.hackrf_stop_rx(_c_device)

cpdef start_tx_mode(callback):
cpdef int start_tx_mode(callback):
global f, RUNNING
RUNNING = 0
f = callback
return chackrf.hackrf_start_tx(_c_device, _c_callback_send, NULL)

cpdef stop_tx_mode():
cpdef int stop_tx_mode():
global RUNNING
RUNNING = -1
time.sleep(TIMEOUT)
return chackrf.hackrf_stop_tx(_c_device)

cpdef board_id_read():
cdef unsigned char value
ret = chackrf.hackrf_board_id_read(_c_device, &value)
if ret == hackrf_success:
return value
else:
return ""

cpdef version_string_read():
cdef char*version = <char *> malloc(20 * sizeof(char))
cdef unsigned char length = 20
ret = chackrf.hackrf_version_string_read(_c_device, version, length)
if ret == hackrf_success:
return version.decode('UTF-8')
else:
return ""

cpdef set_freq(freq_hz):
cpdef int set_freq(freq_hz):
time.sleep(TIMEOUT)
return chackrf.hackrf_set_freq(_c_device, freq_hz)

Expand All @@ -140,35 +124,39 @@ cpdef is_streaming():
else:
return False

cpdef set_rf_gain(value):
""" Enable or disable RF amplifier """
cpdef int set_amp_enable(value):
time.sleep(TIMEOUT)
cdef uint8_t val = 1 if value else 0
return chackrf.hackrf_set_amp_enable(_c_device, val)

cpdef int set_rf_gain(value):
""" Enable or disable RF amplifier """
return set_amp_enable(value)

cpdef set_if_rx_gain(value):
cpdef int set_if_rx_gain(value):
""" Sets the LNA gain, in 8Db steps, maximum value of 40 """
time.sleep(TIMEOUT)
return chackrf.hackrf_set_lna_gain(_c_device, value)

cpdef set_if_tx_gain(value):
cpdef int set_if_tx_gain(value):
""" Sets the txvga gain, in 1db steps, maximum value of 47 """
time.sleep(TIMEOUT)
return chackrf.hackrf_set_txvga_gain(_c_device, value)

cpdef set_baseband_gain(value):
cpdef int set_baseband_gain(value):
""" Sets the vga gain, in 2db steps, maximum value of 62 """
time.sleep(TIMEOUT)
return chackrf.hackrf_set_vga_gain(_c_device, value)

cpdef set_sample_rate(sample_rate):
cpdef int set_sample_rate(sample_rate):
time.sleep(TIMEOUT)
return chackrf.hackrf_set_sample_rate(_c_device, sample_rate)

cpdef set_amp_enable(value):
cpdef int set_bias_tee(on_or_off):
time.sleep(TIMEOUT)
cdef bint val = 1 if value else 0
return chackrf.hackrf_set_amp_enable(_c_device, val)
cdef uint8_t bias_tee = 1 if on_or_off else 0
return chackrf.hackrf_set_antenna_enable(_c_device, bias_tee)

cpdef set_baseband_filter_bandwidth(bandwidth_hz):
cpdef int set_baseband_filter_bandwidth(bandwidth_hz):
time.sleep(TIMEOUT)
return chackrf.hackrf_set_baseband_filter_bandwidth(_c_device, bandwidth_hz)
Loading