[hamradio-commits] [soapyhackrf] 01/08: New upstream version 0.3.1
Andreas E. Bombe
aeb at moszumanska.debian.org
Sun Aug 6 22:54:25 UTC 2017
This is an automated email from the git hooks/post-receive script.
aeb pushed a commit to branch master
in repository soapyhackrf.
commit 8b225d312a96f2ead8df146139512a18eb2f2872
Author: Andreas Bombe <aeb at debian.org>
Date: Sun Aug 6 17:00:03 2017 -0400
New upstream version 0.3.1
---
Changelog.txt | 13 +
HackRF_Registation.cpp | 27 +-
HackRF_Settings.cpp | 273 +++++-------
HackRF_Streaming.cpp | 461 ++++++++++-----------
README.md | 6 +-
SoapyHackRF.hpp | 86 ++--
debian/changelog | 12 +
debian/control | 4 +-
debian/copyright | 3 +-
debian/rules | 0
...f.install => soapysdr0.6-module-hackrf.install} | 0
self_test.py | 4 +-
12 files changed, 428 insertions(+), 461 deletions(-)
diff --git a/Changelog.txt b/Changelog.txt
index 67d8516..31b4fc8 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,3 +1,16 @@
+Release 0.3.1 (2017-06-19)
+==========================
+
+- Cache discovered HackRF results for claimed devices
+
+Release 0.3.0 (2017-04-29)
+==========================
+
+- Major cleanup for thread safety and buffer management
+- Added label convention to hackrf discovery routine
+- Support filtering specific devices by serial number
+- Switch to format constants in streaming implementation
+
Release 0.2.2 (2016-10-19)
==========================
diff --git a/HackRF_Registation.cpp b/HackRF_Registation.cpp
index e69f02b..baee6bb 100644
--- a/HackRF_Registation.cpp
+++ b/HackRF_Registation.cpp
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2015 Wei Jiang
+ * Copyright (c) 2015-2017 Josh Blum
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -22,7 +23,7 @@
#include "SoapyHackRF.hpp"
#include <SoapySDR/Registry.hpp>
-
+static std::map<std::string, SoapySDR::Kwargs> _cachedResults;
static std::vector<SoapySDR::Kwargs> find_HackRF(const SoapySDR::Kwargs &args)
{
@@ -72,7 +73,21 @@ static std::vector<SoapySDR::Kwargs> find_HackRF(const SoapySDR::Kwargs &args)
read_partid_serialno.serial_no[3]);
options["serial"] = serial_str;
- results.push_back(options);
+ //generate a displayable label string with trimmed serial
+ size_t ofs = 0;
+ while (ofs < sizeof(serial_str) and serial_str[ofs] == '0') ofs++;
+ char label_str[100];
+ sprintf(label_str, "%s #%d %s", options["device"].c_str(), i, serial_str+ofs);
+ options["label"] = label_str;
+
+ //filter based on serial and idx
+ const bool serialMatch = args.count("serial") == 0 or args.at("serial") == options["serial"];
+ const bool idxMatch = args.count("hackrf") == 0 or std::stoi(args.at("hackrf")) == i;
+ if (serialMatch and idxMatch)
+ {
+ results.push_back(options);
+ _cachedResults[serial_str] = options;
+ }
hackrf_close(device);
}
@@ -83,6 +98,14 @@ static std::vector<SoapySDR::Kwargs> find_HackRF(const SoapySDR::Kwargs &args)
hackrf_device_list_free(list);
+ //fill in the cached results for claimed handles
+ for (const auto &serial : HackRF_getClaimedSerials())
+ {
+ if (_cachedResults.count(serial) == 0) continue;
+ if (args.count("serial") != 0 and args.at("serial") != serial) continue;
+ results.push_back(_cachedResults.at(serial));
+ }
+
return results;
}
diff --git a/HackRF_Settings.cpp b/HackRF_Settings.cpp
index ab62a05..4a8f1a6 100644
--- a/HackRF_Settings.cpp
+++ b/HackRF_Settings.cpp
@@ -2,6 +2,8 @@
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Wei Jiang
+ * Copyright (c) 2015-2017 Josh Blum
+ * Copyright (c) 2017 Kevin Mehall
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -21,55 +23,33 @@
#include "SoapyHackRF.hpp"
+std::set<std::string> &HackRF_getClaimedSerials(void)
+{
+ static std::set<std::string> serials;
+ return serials;
+}
SoapyHackRF::SoapyHackRF( const SoapySDR::Kwargs &args )
{
- std::string argsStr;
- for (const auto &pair : args)
- {
- if (not argsStr.empty()) argsStr += ", ";
- argsStr += pair.first + "=" + pair.second;
- }
- SoapySDR_logf( SOAPY_SDR_INFO, "Opening HackRF device instance {%s}...", argsStr.c_str());
-
- _rx_stream=new RXStream();
-
- _rx_stream->remainderSamps=0;
- _rx_stream->remainderOffset=0;
- _rx_stream->remainderBuff= nullptr;
- _rx_stream->remainderHandle=-1;
- _rx_stream->vga_gain=16;
- _rx_stream->lna_gain=16;
- _rx_stream->amp_gain=0;
- _rx_stream->frequecy=0;
- _rx_stream->samplerate=0;
- _rx_stream->bandwidth=0;
- _rx_stream->format=HACKRF_FORMAT_INT8;
- _rx_stream->buf_len=BUF_LEN;
- _rx_stream->buf_num=BUF_NUM;
- _rx_stream->buf_count=0;
- _rx_stream->buf_tail=0;
- _rx_stream->buf_head=0;
-
- _tx_stream=new TXStream();
-
- _tx_stream->remainderSamps=0;
- _tx_stream->remainderOffset=0;
- _tx_stream->remainderBuff= nullptr;
- _tx_stream->remainderHandle=-1;
- _tx_stream->vga_gain=0;
- _tx_stream->amp_gain=0;
- _tx_stream->frequecy=0;
- _tx_stream->samplerate=0;
- _tx_stream->bandwidth=0;
- _tx_stream->format=HACKRF_FORMAT_INT8;
- _tx_stream->buf_len=BUF_LEN;
- _tx_stream->buf_num=BUF_NUM;
- _tx_stream->buf_count=0;
- _tx_stream->buf_tail=0;
- _tx_stream->buf_head=0;
- _tx_stream->burst_samps=0;
- _tx_stream->burst_end=false;
+ if (args.count("label") != 0)
+ SoapySDR_logf( SOAPY_SDR_INFO, "Opening %s...", args.at("label").c_str());
+
+ _rx_stream.vga_gain=16;
+ _rx_stream.lna_gain=16;
+ _rx_stream.amp_gain=0;
+ _rx_stream.frequency=0;
+ _rx_stream.samplerate=0;
+ _rx_stream.bandwidth=0;
+ _rx_stream.overflow = false;
+
+ _tx_stream.vga_gain=0;
+ _tx_stream.amp_gain=0;
+ _tx_stream.frequency=0;
+ _tx_stream.samplerate=0;
+ _tx_stream.bandwidth=0;
+ _tx_stream.burst_samps=0;
+ _tx_stream.burst_end=false;
+ _tx_stream.underflow = false;
_current_mode=HACKRF_TRANSCEIVER_MODE_OFF;
@@ -77,7 +57,9 @@ SoapyHackRF::SoapyHackRF( const SoapySDR::Kwargs &args )
_dev = nullptr;
- _list= nullptr;
+ if (args.count("serial") == 0)
+ throw std::runtime_error("no hackrf device matches");
+ _serial = args.at("serial");
_current_amp = 0;
@@ -87,89 +69,26 @@ SoapyHackRF::SoapyHackRF( const SoapySDR::Kwargs &args )
_current_bandwidth=0;
- _id = -1;
-
-
- _list= hackrf_device_list();
-
- if ( args.count( "hackrf" ) != 0 )
- {
- _id = std::stoi( args.at( "hackrf" ) );
-
- if ( _id < 0 && _id > _list->devicecount )
- {
- throw std::runtime_error( "hackrf out of range [0 .. " + std::to_string( _list->devicecount ) + "]." );
- }
- int ret = hackrf_device_list_open(_list, _id, &_dev );
- if ( ret != HACKRF_SUCCESS )
- {
- hackrf_device_list_free(_list);
- SoapySDR_logf( SOAPY_SDR_INFO, "Could not Open HackRF Device by Index:%d", _id );
- throw std::runtime_error("hackrf open failed");
- }
- } else if ( _id == -1 )
+ int ret = hackrf_open_by_serial(_serial.c_str(), &_dev);
+ if ( ret != HACKRF_SUCCESS )
{
- int ret = hackrf_open( &_dev );
- if ( ret != HACKRF_SUCCESS )
- {
- SoapySDR_logf( SOAPY_SDR_INFO, "Could not Open HackRF Device" );
- throw std::runtime_error("hackrf open failed");
- }
+ SoapySDR_logf( SOAPY_SDR_INFO, "Could not Open HackRF Device" );
+ throw std::runtime_error("hackrf open failed");
}
-
-
+ HackRF_getClaimedSerials().insert(_serial);
}
SoapyHackRF::~SoapyHackRF( void )
{
+ HackRF_getClaimedSerials().erase(_serial);
+
if ( _dev )
{
- hackrf_device_list_free(_list);
hackrf_close( _dev );
}
-
- if (_rx_stream){
-
-
- if ( _rx_stream->buf )
- {
- for ( unsigned int i = 0; i < _rx_stream->buf_num; ++i )
- {
- if ( _rx_stream->buf[i] )
- {
- free( _rx_stream->buf[i] );
- }
- }
- free( _rx_stream->buf );
- _rx_stream->buf = NULL;
- }
-
- delete _rx_stream;
- }
-
-
- if (_tx_stream){
-
-
- if ( _tx_stream->buf )
- {
- for ( unsigned int i = 0; i < _tx_stream->buf_num; ++i )
- {
- if ( _tx_stream->buf[i] )
- {
- free( _tx_stream->buf[i] );
- }
- }
- free( _tx_stream->buf );
- _tx_stream->buf = NULL;
- }
-
- delete _tx_stream;
- }
-
/* cleanup device handles */
}
@@ -187,6 +106,7 @@ std::string SoapyHackRF::getDriverKey( void ) const
std::string SoapyHackRF::getHardwareKey( void ) const
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
uint8_t board_id=BOARD_ID_INVALID;
hackrf_board_id_read(_dev,&board_id);
@@ -197,6 +117,7 @@ std::string SoapyHackRF::getHardwareKey( void ) const
SoapySDR::Kwargs SoapyHackRF::getHardwareInfo( void ) const
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
SoapySDR::Kwargs info;
char version_str[100];
@@ -267,8 +188,9 @@ SoapySDR::ArgInfoList SoapyHackRF::getSettingInfo(void) const
void SoapyHackRF::writeSetting(const std::string &key, const std::string &value)
{
if(key=="bias_tx"){
- _tx_stream->bias=(value=="true") ? true : false;
- int ret=hackrf_set_antenna_enable(_dev,_tx_stream->bias);
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ _tx_stream.bias=(value=="true") ? true : false;
+ int ret=hackrf_set_antenna_enable(_dev,_tx_stream.bias);
if(ret!=HACKRF_SUCCESS){
SoapySDR_logf(SOAPY_SDR_INFO,"Failed to apply antenna bias voltage");
@@ -281,7 +203,7 @@ void SoapyHackRF::writeSetting(const std::string &key, const std::string &value)
std::string SoapyHackRF::readSetting(const std::string &key) const
{
if (key == "bias_tx") {
- return _tx_stream->bias?"true":"false";
+ return _tx_stream.bias?"true":"false";
}
return "";
}
@@ -357,57 +279,58 @@ bool SoapyHackRF::getGainMode( const int direction, const size_t channel ) const
void SoapyHackRF::setGain( const int direction, const size_t channel, const double value )
{
- int32_t ret, gain;
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ int32_t ret(0), gain(0);
gain = value;
if ( direction == SOAPY_SDR_RX )
{
if ( gain <= 0 )
{
- _rx_stream->lna_gain = 0;
- _rx_stream->vga_gain = 0;
+ _rx_stream.lna_gain = 0;
+ _rx_stream.vga_gain = 0;
_current_amp = 0;
}else if ( gain <= (HACKRF_RX_LNA_MAX_DB / 2) + (HACKRF_RX_VGA_MAX_DB / 2) )
{
- _rx_stream->vga_gain = (gain / 3) & ~0x1;
- _rx_stream->lna_gain = gain - _rx_stream->vga_gain;
+ _rx_stream.vga_gain = (gain / 3) & ~0x1;
+ _rx_stream.lna_gain = gain - _rx_stream.vga_gain;
_current_amp = 0;
}else if ( gain <= ( (HACKRF_RX_LNA_MAX_DB / 2) + (HACKRF_RX_VGA_MAX_DB / 2) + HACKRF_AMP_MAX_DB) )
{
_current_amp = HACKRF_AMP_MAX_DB;
- _rx_stream->vga_gain = ( (gain - _current_amp) / 3) & ~0x1;
- _rx_stream->lna_gain = gain -_current_amp - _rx_stream->vga_gain;
+ _rx_stream.vga_gain = ( (gain - _current_amp) / 3) & ~0x1;
+ _rx_stream.lna_gain = gain -_current_amp - _rx_stream.vga_gain;
}else if ( gain <= HACKRF_RX_LNA_MAX_DB + HACKRF_RX_VGA_MAX_DB + HACKRF_AMP_MAX_DB )
{
_current_amp = HACKRF_AMP_MAX_DB;
- _rx_stream->vga_gain = (gain - _current_amp) * double(HACKRF_RX_LNA_MAX_DB) / double(HACKRF_RX_VGA_MAX_DB);
- _rx_stream->lna_gain = gain - _current_amp - _rx_stream->vga_gain;
+ _rx_stream.vga_gain = (gain - _current_amp) * double(HACKRF_RX_LNA_MAX_DB) / double(HACKRF_RX_VGA_MAX_DB);
+ _rx_stream.lna_gain = gain - _current_amp - _rx_stream.vga_gain;
}
- _rx_stream->amp_gain=_current_amp;
+ _rx_stream.amp_gain=_current_amp;
- ret = hackrf_set_lna_gain( _dev, _rx_stream->lna_gain );
- ret |= hackrf_set_vga_gain( _dev, _rx_stream->vga_gain );
+ ret = hackrf_set_lna_gain( _dev, _rx_stream.lna_gain );
+ ret |= hackrf_set_vga_gain( _dev, _rx_stream.vga_gain );
ret |= hackrf_set_amp_enable( _dev, (_current_amp > 0) ? 1 : 0 );
}else if ( direction == SOAPY_SDR_TX )
{
if ( gain <= 0 )
{
_current_amp = 0;
- _tx_stream->vga_gain = 0;
+ _tx_stream.vga_gain = 0;
}else if ( gain <= (HACKRF_TX_VGA_MAX_DB / 2) )
{
_current_amp = 0;
- _tx_stream->vga_gain = gain;
+ _tx_stream.vga_gain = gain;
}else if ( gain <= HACKRF_TX_VGA_MAX_DB + HACKRF_AMP_MAX_DB )
{
_current_amp = HACKRF_AMP_MAX_DB;
- _tx_stream->vga_gain = gain - HACKRF_AMP_MAX_DB;
+ _tx_stream.vga_gain = gain - HACKRF_AMP_MAX_DB;
}
- _tx_stream->amp_gain=_current_amp;
+ _tx_stream.amp_gain=_current_amp;
- ret = hackrf_set_txvga_gain( _dev, _tx_stream->vga_gain );
+ ret = hackrf_set_txvga_gain( _dev, _tx_stream.vga_gain );
ret |= hackrf_set_amp_enable( _dev, (_current_amp > 0) ? 1 : 0 );
}
if ( ret != HACKRF_SUCCESS )
@@ -419,15 +342,16 @@ void SoapyHackRF::setGain( const int direction, const size_t channel, const doub
void SoapyHackRF::setGain( const int direction, const size_t channel, const std::string &name, const double value )
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
if ( name == "AMP" )
{
_current_amp = value;
_current_amp = (_current_amp > 0)?HACKRF_AMP_MAX_DB : 0; //clip to possible values
if(direction == SOAPY_SDR_RX){
- _rx_stream->amp_gain=_current_amp;
+ _rx_stream.amp_gain=_current_amp;
}else if (direction ==SOAPY_SDR_TX){
- _tx_stream->amp_gain=_current_amp;
+ _tx_stream.amp_gain=_current_amp;
}
if ( _dev != NULL )
@@ -440,35 +364,35 @@ void SoapyHackRF::setGain( const int direction, const size_t channel, const std:
}
}else if ( direction == SOAPY_SDR_RX and name == "LNA" )
{
- _rx_stream->lna_gain = value;
+ _rx_stream.lna_gain = value;
if ( _dev != NULL )
{
- int ret = hackrf_set_lna_gain( _dev, _rx_stream->lna_gain );
+ int ret = hackrf_set_lna_gain( _dev, _rx_stream.lna_gain );
if ( ret != HACKRF_SUCCESS )
{
- SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_lna_gain(%f) returned %s", _rx_stream->lna_gain, hackrf_error_name( (hackrf_error) ret ) );
+ SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_lna_gain(%f) returned %s", _rx_stream.lna_gain, hackrf_error_name( (hackrf_error) ret ) );
}
}
}else if ( direction == SOAPY_SDR_RX and name == "VGA" )
{
- _rx_stream->vga_gain = value;
+ _rx_stream.vga_gain = value;
if ( _dev != NULL )
{
- int ret = hackrf_set_vga_gain( _dev, _rx_stream->vga_gain );
+ int ret = hackrf_set_vga_gain( _dev, _rx_stream.vga_gain );
if ( ret != HACKRF_SUCCESS )
{
- SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_vga_gain(%f) returned %s", _rx_stream->vga_gain, hackrf_error_name( (hackrf_error) ret ) );
+ SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_vga_gain(%f) returned %s", _rx_stream.vga_gain, hackrf_error_name( (hackrf_error) ret ) );
}
}
}else if ( direction == SOAPY_SDR_TX and name == "VGA" )
{
- _tx_stream->vga_gain = value;
+ _tx_stream.vga_gain = value;
if ( _dev != NULL )
{
- int ret = hackrf_set_txvga_gain( _dev, _tx_stream->vga_gain );
+ int ret = hackrf_set_txvga_gain( _dev, _tx_stream.vga_gain );
if ( ret != HACKRF_SUCCESS )
{
- SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_txvga_gain(%f) returned %s", _tx_stream->vga_gain, hackrf_error_name( (hackrf_error) ret ) );
+ SoapySDR::logf( SOAPY_SDR_ERROR, "hackrf_set_txvga_gain(%f) returned %s", _tx_stream.vga_gain, hackrf_error_name( (hackrf_error) ret ) );
}
}
}
@@ -480,22 +404,23 @@ void SoapyHackRF::setGain( const int direction, const size_t channel, const std:
double SoapyHackRF::getGain( const int direction, const size_t channel, const std::string &name ) const
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
double gain = 0.0;
if ( direction == SOAPY_SDR_RX and name == "AMP" )
{
- gain = -_rx_stream->amp_gain;
+ gain = -_rx_stream.amp_gain;
}else if ( direction == SOAPY_SDR_TX and name == "AMP" )
{
- gain = _tx_stream->amp_gain;
+ gain = _tx_stream.amp_gain;
}else if ( direction == SOAPY_SDR_RX and name == "LNA" )
{
- gain = _rx_stream->lna_gain;
+ gain = _rx_stream.lna_gain;
}else if ( direction == SOAPY_SDR_RX and name == "VGA" )
{
- gain = _rx_stream->vga_gain;
+ gain = _rx_stream.vga_gain;
}else if ( direction == SOAPY_SDR_TX and name == "VGA" )
{
- gain = _tx_stream->vga_gain;
+ gain = _tx_stream.vga_gain;
}
return(gain);
@@ -527,16 +452,17 @@ void SoapyHackRF::setFrequency( const int direction, const size_t channel, const
if ( name != "RF" )
throw std::runtime_error( "setFrequency(" + name + ") unknown name" );
+ std::lock_guard<std::mutex> lock(_device_mutex);
_current_frequency = frequency;
if(direction==SOAPY_SDR_RX){
- _rx_stream->frequecy=_current_frequency;
+ _rx_stream.frequency=_current_frequency;
}
if(direction==SOAPY_SDR_TX){
- _tx_stream->frequecy=_current_frequency;
+ _tx_stream.frequency=_current_frequency;
}
if ( _dev != NULL )
@@ -558,15 +484,16 @@ double SoapyHackRF::getFrequency( const int direction, const size_t channel, con
if ( name != "RF" )
throw std::runtime_error( "getFrequency(" + name + ") unknown name" );
- double freq;
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ double freq(0.0);
if(direction==SOAPY_SDR_RX){
- freq = _rx_stream->frequecy;
+ freq = _rx_stream.frequency;
}
if(direction==SOAPY_SDR_TX){
- freq = _tx_stream->frequecy;
+ freq = _tx_stream.frequency;
}
return(freq);
}
@@ -602,15 +529,16 @@ SoapySDR::RangeList SoapyHackRF::getFrequencyRange( const int direction, const s
void SoapyHackRF::setSampleRate( const int direction, const size_t channel, const double rate )
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
_current_samplerate = rate;
if(direction==SOAPY_SDR_RX){
- _rx_stream->samplerate=_current_samplerate;
+ _rx_stream.samplerate=_current_samplerate;
}
if(direction==SOAPY_SDR_TX){
- _tx_stream->samplerate=_current_samplerate;
+ _tx_stream.samplerate=_current_samplerate;
}
if ( _dev != NULL )
@@ -624,11 +552,11 @@ void SoapyHackRF::setSampleRate( const int direction, const size_t channel, cons
if(direction==SOAPY_SDR_RX){
- _rx_stream->bandwidth=_current_bandwidth;
+ _rx_stream.bandwidth=_current_bandwidth;
}
if(direction==SOAPY_SDR_TX){
- _tx_stream->bandwidth=_current_bandwidth;
+ _tx_stream.bandwidth=_current_bandwidth;
}
ret|=hackrf_set_baseband_filter_bandwidth(_dev,_current_bandwidth);
@@ -645,14 +573,15 @@ void SoapyHackRF::setSampleRate( const int direction, const size_t channel, cons
double SoapyHackRF::getSampleRate( const int direction, const size_t channel ) const
{
- double samp;
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ double samp(0.0);
if(direction==SOAPY_SDR_RX){
- samp= _rx_stream->samplerate;
+ samp= _rx_stream.samplerate;
}
if(direction==SOAPY_SDR_TX){
- samp= _tx_stream->samplerate;
+ samp= _tx_stream.samplerate;
}
return(samp);
@@ -672,15 +601,16 @@ std::vector<double> SoapyHackRF::listSampleRates( const int direction, const siz
void SoapyHackRF::setBandwidth( const int direction, const size_t channel, const double bw )
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
_current_bandwidth = hackrf_compute_baseband_filter_bw(bw);
if(direction==SOAPY_SDR_RX){
- _rx_stream->bandwidth=_current_bandwidth;
+ _rx_stream.bandwidth=_current_bandwidth;
}
if(direction==SOAPY_SDR_TX){
- _tx_stream->bandwidth=_current_bandwidth;
+ _tx_stream.bandwidth=_current_bandwidth;
}
if(_current_bandwidth > 0){
@@ -705,14 +635,15 @@ void SoapyHackRF::setBandwidth( const int direction, const size_t channel, const
double SoapyHackRF::getBandwidth( const int direction, const size_t channel ) const
{
- double bw;
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ double bw(0.0);
if(direction==SOAPY_SDR_RX){
- bw = _rx_stream->bandwidth;
+ bw = _rx_stream.bandwidth;
}
if(direction==SOAPY_SDR_TX){
- bw = _tx_stream->bandwidth;
+ bw = _tx_stream.bandwidth;
}
return (bw);
@@ -740,5 +671,3 @@ std::vector<double> SoapyHackRF::listBandwidths( const int direction, const size
options.push_back( 28000000 );
return(options);
}
-
-
diff --git a/HackRF_Streaming.cpp b/HackRF_Streaming.cpp
index fd74223..a331e64 100644
--- a/HackRF_Streaming.cpp
+++ b/HackRF_Streaming.cpp
@@ -2,6 +2,8 @@
* The MIT License (MIT)
*
* Copyright (c) 2015-2016 Wei Jiang
+ * Copyright (c) 2015-2017 Josh Blum
+ * Copyright (c) 2017 Kevin Mehall
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -21,6 +23,7 @@
#include "SoapyHackRF.hpp"
#include <SoapySDR/Logger.hpp>
+#include <SoapySDR/Formats.hpp>
#include <chrono>
#include <thread>
#include <algorithm> //min
@@ -41,15 +44,15 @@ int _hackrf_tx_callback( hackrf_transfer *transfer )
int SoapyHackRF::hackrf_rx_callback( int8_t *buffer, int32_t length )
{
std::unique_lock<std::mutex> lock(_buf_mutex);
- _rx_stream->buf_tail = (_rx_stream->buf_head + _rx_stream->buf_count) % _rx_stream->buf_num;
- memcpy(_rx_stream->buf[_rx_stream->buf_tail], buffer, length );
+ _rx_stream.buf_tail = (_rx_stream.buf_head + _rx_stream.buf_count) % _rx_stream.buf_num;
+ memcpy(_rx_stream.buf[_rx_stream.buf_tail], buffer, length );
- if ( _rx_stream->buf_count == _rx_stream->buf_num )
+ if ( _rx_stream.buf_count == _rx_stream.buf_num )
{
- _rx_stream->overflow=true;
- _rx_stream->buf_head = (_rx_stream->buf_head + 1) % _rx_stream->buf_num;
+ _rx_stream.overflow=true;
+ _rx_stream.buf_head = (_rx_stream.buf_head + 1) % _rx_stream.buf_num;
}else {
- _rx_stream->buf_count++;
+ _rx_stream.buf_count++;
}
_buf_cond.notify_one();
@@ -60,22 +63,22 @@ int SoapyHackRF::hackrf_rx_callback( int8_t *buffer, int32_t length )
int SoapyHackRF::hackrf_tx_callback( int8_t *buffer, int32_t length )
{
std::unique_lock<std::mutex> lock(_buf_mutex);
- if ( _tx_stream->buf_count == 0 )
+ if ( _tx_stream.buf_count == 0 )
{
memset( buffer, 0, length );
- _tx_stream->underflow=true;
+ _tx_stream.underflow=true;
}else {
- memcpy( buffer, _tx_stream->buf[_tx_stream->buf_tail], length );
- _tx_stream->buf_tail = (_tx_stream->buf_tail + 1) % _tx_stream->buf_num;
+ memcpy( buffer, _tx_stream.buf[_tx_stream.buf_tail], length );
+ _tx_stream.buf_tail = (_tx_stream.buf_tail + 1) % _tx_stream.buf_num;
- _tx_stream->buf_count--;
+ _tx_stream.buf_count--;
- if(_tx_stream->burst_end)
+ if(_tx_stream.burst_end)
{
- _tx_stream->burst_samps -= (length/BYTES_PER_SAMPLE);
- if(_tx_stream->burst_samps < 0 ) {
- _tx_stream->burst_end = false;
- _tx_stream->burst_samps = 0;
+ _tx_stream.burst_samps -= (length/BYTES_PER_SAMPLE);
+ if(_tx_stream.burst_samps < 0 ) {
+ _tx_stream.burst_end = false;
+ _tx_stream.burst_samps = 0;
return -1;
}
}
@@ -89,10 +92,10 @@ std::vector<std::string> SoapyHackRF::getStreamFormats(const int direction, cons
{
std::vector<std::string> formats;
- formats.push_back("CS8");
- formats.push_back("CS16");
- formats.push_back("CF32");
- formats.push_back("CF64");
+ formats.push_back(SOAPY_SDR_CS8);
+ formats.push_back(SOAPY_SDR_CS16);
+ formats.push_back(SOAPY_SDR_CF32);
+ formats.push_back(SOAPY_SDR_CF64);
return formats;
}
@@ -100,7 +103,7 @@ std::vector<std::string> SoapyHackRF::getStreamFormats(const int direction, cons
std::string SoapyHackRF::getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const
{
fullScale = 128;
- return "CS8";
+ return SOAPY_SDR_CS8;
}
SoapySDR::ArgInfoList SoapyHackRF::getStreamArgsInfo(const int direction, const size_t channel) const
@@ -119,87 +122,113 @@ SoapySDR::ArgInfoList SoapyHackRF::getStreamArgsInfo(const int direction, const
return streamArgs;
}
+void SoapyHackRF::Stream::allocate_buffers() {
+ buf = (int8_t * *) malloc( buf_num * sizeof(int8_t *) );
+ if ( buf ) {
+ for ( unsigned int i = 0; i < buf_num; ++i ) {
+ buf[i] = (int8_t *) malloc( buf_len );
+ }
+ }
+}
+
+void SoapyHackRF::Stream::clear_buffers() {
+ if ( buf ) {
+ for ( unsigned int i = 0; i < buf_num; ++i ) {
+ if ( buf[i] ) {
+ free( buf[i] );
+ }
+ }
+ free( buf );
+ buf = NULL;
+ }
+
+ buf_count = 0;
+ buf_tail = 0;
+ buf_head = 0;
+ remainderSamps = 0;
+ remainderOffset = 0;
+ remainderBuff = nullptr;
+ remainderHandle = -1;
+}
+
SoapySDR::Stream *SoapyHackRF::setupStream(
const int direction,
const std::string &format,
const std::vector<size_t> &channels,
const SoapySDR::Kwargs &args )
{
+ std::lock_guard<std::mutex> lock(_device_mutex);
+
if ( channels.size() > 1 or( channels.size() > 0 and channels.at( 0 ) != 0 ) )
{
throw std::runtime_error( "setupStream invalid channel selection" );
}
- SoapyHackRFStream * data=new SoapyHackRFStream();
-
if(direction==SOAPY_SDR_RX){
+ if (_rx_stream.opened) {
+ throw std::runtime_error("RX stream already opened");
+ }
- if ( format == "CS8" )
+ if ( format == SOAPY_SDR_CS8 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CS8." );
- _rx_stream->format = HACKRF_FORMAT_INT8;
- }else if ( format == "CS16" )
+ _rx_stream.format = HACKRF_FORMAT_INT8;
+ }else if ( format == SOAPY_SDR_CS16 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CS16." );
- _rx_stream->format = HACKRF_FORMAT_INT16;
- }else if ( format == "CF32" )
+ _rx_stream.format = HACKRF_FORMAT_INT16;
+ }else if ( format == SOAPY_SDR_CF32 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CF32." );
- _rx_stream->format= HACKRF_FORMAT_FLOAT32;
- }else if(format=="CF64"){
+ _rx_stream.format= HACKRF_FORMAT_FLOAT32;
+ }else if(format==SOAPY_SDR_CF64){
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CF64." );
- _rx_stream->format= HACKRF_FORMAT_FLOAT64;
+ _rx_stream.format= HACKRF_FORMAT_FLOAT64;
}else throw std::runtime_error( "setupStream invalid format " + format );
+ _rx_stream.buf_num = BUF_NUM;
+
if ( args.count( "buffers" ) != 0 )
{
try
{
int numBuffers_in = std::stoi(args.at("buffers"));
if (numBuffers_in > 0) {
- if ( _rx_stream->buf ) {
- for ( unsigned int i = 0; i < _rx_stream->buf_num; ++i ) {
- if ( _rx_stream->buf[i] ) {
- free( _rx_stream->buf[i] );
- }
- }
- free( _rx_stream->buf );
- _rx_stream->buf = NULL;
- }
-
- _rx_stream->buf_num = numBuffers_in;
+ _rx_stream.buf_num = numBuffers_in;
}
}
catch (const std::invalid_argument &){}
}
- _rx_stream->buf = (int8_t * *) malloc( _rx_stream->buf_num * sizeof(int8_t *) );
- if ( _rx_stream->buf )
- {
- for ( unsigned int i = 0; i < _rx_stream->buf_num; ++i )
- _rx_stream->buf[i] = (int8_t *) malloc( _rx_stream->buf_len );
- }
- }
+ _rx_stream.allocate_buffers();
- if(direction==SOAPY_SDR_TX){
+ _rx_stream.opened = true;
- if ( format == "CS8" )
+ return RX_STREAM;
+ } else if(direction==SOAPY_SDR_TX){
+ if (_tx_stream.opened) {
+ throw std::runtime_error("TX stream already opened");
+ }
+
+ if ( format == SOAPY_SDR_CS8 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CS8." );
- _tx_stream->format = HACKRF_FORMAT_INT8;
- }else if ( format == "CS16" )
+ _tx_stream.format = HACKRF_FORMAT_INT8;
+ }else if ( format == SOAPY_SDR_CS16 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CS16." );
- _tx_stream->format = HACKRF_FORMAT_INT16;
- }else if ( format == "CF32" )
+ _tx_stream.format = HACKRF_FORMAT_INT16;
+ }else if ( format == SOAPY_SDR_CF32 )
{
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CF32." );
- _tx_stream->format= HACKRF_FORMAT_FLOAT32;
- }else if(format=="CF64"){
+ _tx_stream.format= HACKRF_FORMAT_FLOAT32;
+ }else if(format==SOAPY_SDR_CF64){
SoapySDR_log( SOAPY_SDR_DEBUG, "Using format CF64." );
- _tx_stream->format= HACKRF_FORMAT_FLOAT64;
+ _tx_stream.format= HACKRF_FORMAT_FLOAT64;
}else throw std::runtime_error( "setupStream invalid format " + format );
+ _tx_stream.buf_num = BUF_NUM;
+
if ( args.count( "buffers" ) != 0 )
{
try
@@ -207,63 +236,44 @@ SoapySDR::Stream *SoapyHackRF::setupStream(
int numBuffers_in = std::stoi(args.at("buffers"));
if (numBuffers_in > 0)
{
- if ( _tx_stream->buf )
- {
- for ( unsigned int i = 0; i < _tx_stream->buf_num; ++i )
- {
- if ( _tx_stream->buf[i] )
- {
- free( _tx_stream->buf[i] );
- }
- }
- free( _tx_stream->buf );
- _tx_stream->buf = NULL;
- }
-
- _tx_stream->buf_num = numBuffers_in;
+ _tx_stream.buf_num = numBuffers_in;
}
}
catch (const std::invalid_argument &){}
}
- _tx_stream->buf = (int8_t * *) malloc( _tx_stream->buf_num * sizeof(int8_t *) );
- if ( _tx_stream->buf )
- {
- for ( unsigned int i = 0; i < _tx_stream->buf_num; ++i )
- _tx_stream->buf[i] = (int8_t *) malloc( _tx_stream->buf_len );
- }
+ _tx_stream.allocate_buffers();
+ _tx_stream.opened = true;
+ return TX_STREAM;
+ } else {
+ throw std::runtime_error("Invalid direction");
}
-
- data->direction=direction;
-
-
- return ((SoapySDR::Stream *) data );
}
-
void SoapyHackRF::closeStream( SoapySDR::Stream *stream )
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
-
- delete data;;
+ std::lock_guard<std::mutex> lock(_device_mutex);
+ if (stream == RX_STREAM) {
+ _rx_stream.clear_buffers();
+ _rx_stream.opened = false;
+ } else if (stream == TX_STREAM) {
+ _tx_stream.clear_buffers();
+ _tx_stream.opened = false;
+ }
}
size_t SoapyHackRF::getStreamMTU( SoapySDR::Stream *stream ) const
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
- size_t mtu;
- if(data->direction==SOAPY_SDR_RX){
- mtu =_rx_stream->buf_len/BYTES_PER_SAMPLE;
-
- }
- if(data->direction==SOAPY_SDR_TX){
-
- mtu=_tx_stream->buf_len/BYTES_PER_SAMPLE;
+ if(stream == RX_STREAM){
+ return _rx_stream.buf_len/BYTES_PER_SAMPLE;
+ } else if(stream == TX_STREAM){
+ return _tx_stream.buf_len/BYTES_PER_SAMPLE;
+ } else {
+ throw std::runtime_error("Invalid stream");
}
- return mtu;
}
int SoapyHackRF::activateStream(
@@ -272,11 +282,10 @@ int SoapyHackRF::activateStream(
const long long timeNs,
const size_t numElems )
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
- if(data->direction==SOAPY_SDR_RX){
+ if(stream == RX_STREAM){
- std::lock_guard<std::mutex> lock(_activate_mutex);
+ std::lock_guard<std::mutex> lock(_device_mutex);
if(_current_mode==HACKRF_TRANSCEIVER_MODE_RX)
@@ -284,7 +293,7 @@ int SoapyHackRF::activateStream(
if(_current_mode==HACKRF_TRANSCEIVER_MODE_TX){
- if(_tx_stream->burst_end){
+ if(_tx_stream.burst_end){
while(hackrf_is_streaming(_dev)==HACKRF_TRUE)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -297,9 +306,9 @@ int SoapyHackRF::activateStream(
//reset buffer tracking before streaming
{
- _rx_stream->buf_count = 0;
- _rx_stream->buf_head = 0;
- _rx_stream->buf_tail = 0;
+ _rx_stream.buf_count = 0;
+ _rx_stream.buf_head = 0;
+ _rx_stream.buf_tail = 0;
}
int ret = hackrf_start_rx(_dev, _hackrf_rx_callback, (void *) this);
@@ -312,22 +321,17 @@ int SoapyHackRF::activateStream(
if (ret==HACKRF_ERROR_STREAMING_EXIT_CALLED){
hackrf_close(_dev);
-
- if (_id<0){
- hackrf_open(&_dev);
- }else {
- hackrf_device_list_open(_list,_id,&_dev);
- }
- _current_frequency=_rx_stream->frequecy;
+ hackrf_open_by_serial(_serial.c_str(), &_dev);
+ _current_frequency=_rx_stream.frequency;
hackrf_set_freq(_dev,_current_frequency);
- _current_samplerate=_rx_stream->samplerate;
+ _current_samplerate=_rx_stream.samplerate;
hackrf_set_sample_rate(_dev,_current_samplerate);
- _current_bandwidth=_rx_stream->bandwidth;
+ _current_bandwidth=_rx_stream.bandwidth;
hackrf_set_baseband_filter_bandwidth(_dev,_current_bandwidth);
- _current_amp=_rx_stream->amp_gain;
+ _current_amp=_rx_stream.amp_gain;
hackrf_set_amp_enable(_dev,_current_amp);
- hackrf_set_lna_gain(_dev,_rx_stream->lna_gain);
- hackrf_set_vga_gain(_dev,_rx_stream->vga_gain);
+ hackrf_set_lna_gain(_dev,_rx_stream.lna_gain);
+ hackrf_set_vga_gain(_dev,_rx_stream.vga_gain);
hackrf_start_rx(_dev,_hackrf_rx_callback,(void *) this);
ret=hackrf_is_streaming(_dev);
}
@@ -338,18 +342,16 @@ int SoapyHackRF::activateStream(
}
_current_mode = HACKRF_TRANSCEIVER_MODE_RX;
- }
-
- if(data->direction==SOAPY_SDR_TX ){
+ } else if (stream == TX_STREAM) {
- std::lock_guard<std::mutex> lock(_activate_mutex);
+ std::lock_guard<std::mutex> lock(_device_mutex);
if((flags & SOAPY_SDR_END_BURST)!=0 and numElems!=0) {
if(_current_mode==HACKRF_TRANSCEIVER_MODE_RX){
- _tx_stream->buf_head=0;
- _tx_stream->buf_tail=0;
- _tx_stream->burst_end = true;
- _tx_stream->burst_samps = numElems;
+ _tx_stream.buf_head=0;
+ _tx_stream.buf_tail=0;
+ _tx_stream.burst_end = true;
+ _tx_stream.burst_samps = numElems;
}
}
@@ -375,22 +377,17 @@ int SoapyHackRF::activateStream(
hackrf_close(_dev);
-
- if (_id<0){
- hackrf_open(&_dev);
- }else {
- hackrf_device_list_open(_list,_id,&_dev);
- }
- _current_frequency=_tx_stream->frequecy;
+ hackrf_open_by_serial(_serial.c_str(), &_dev);
+ _current_frequency=_tx_stream.frequency;
hackrf_set_freq(_dev,_current_frequency);
- _current_samplerate=_tx_stream->samplerate;
+ _current_samplerate=_tx_stream.samplerate;
hackrf_set_sample_rate(_dev,_current_samplerate);
- _current_bandwidth=_tx_stream->bandwidth;
+ _current_bandwidth=_tx_stream.bandwidth;
hackrf_set_baseband_filter_bandwidth(_dev,_current_bandwidth);
- _current_amp=_rx_stream->amp_gain;
+ _current_amp=_rx_stream.amp_gain;
hackrf_set_amp_enable(_dev,_current_amp);
- hackrf_set_txvga_gain(_dev,_tx_stream->vga_gain);
- hackrf_set_antenna_enable(_dev,_tx_stream->bias);
+ hackrf_set_txvga_gain(_dev,_tx_stream.vga_gain);
+ hackrf_set_antenna_enable(_dev,_tx_stream.bias);
hackrf_start_tx(_dev,_hackrf_tx_callback,(void *) this);
ret=hackrf_is_streaming(_dev);
}
@@ -412,11 +409,10 @@ int SoapyHackRF::deactivateStream(
const int flags,
const long long timeNs )
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
- if(data->direction==SOAPY_SDR_RX){
+ if(stream == RX_STREAM){
- std::lock_guard<std::mutex> lock(_activate_mutex);
+ std::lock_guard<std::mutex> lock(_device_mutex);
if(_current_mode==HACKRF_TRANSCEIVER_MODE_RX) {
@@ -426,11 +422,9 @@ int SoapyHackRF::deactivateStream(
}
_current_mode = HACKRF_TRANSCEIVER_MODE_OFF;
}
- }
-
- if(data->direction==SOAPY_SDR_TX){
+ } else if(stream == TX_STREAM) {
- std::lock_guard<std::mutex> lock(_activate_mutex);
+ std::lock_guard<std::mutex> lock(_device_mutex);
if(_current_mode==HACKRF_TRANSCEIVER_MODE_TX) {
int ret = hackrf_stop_tx(_dev);
@@ -520,30 +514,32 @@ int SoapyHackRF::readStream(
long long &timeNs,
const long timeoutUs )
{
+ if(stream != RX_STREAM){
+ return SOAPY_SDR_NOT_SUPPORTED;
+ }
/* this is the user's buffer for channel 0 */
-
size_t returnedElems = std::min(numElems,this->getStreamMTU(stream));
size_t samp_avail=0;
- if(_rx_stream->remainderHandle >= 0){
+ if(_rx_stream.remainderHandle >= 0){
- const size_t n =std::min(_rx_stream->remainderSamps,returnedElems);
+ const size_t n =std::min(_rx_stream.remainderSamps,returnedElems);
if(n<returnedElems){
samp_avail=n;
}
- readbuf(_rx_stream->remainderBuff+_rx_stream->remainderOffset*BYTES_PER_SAMPLE,buffs[0],n,_rx_stream->format,0);
+ readbuf(_rx_stream.remainderBuff+_rx_stream.remainderOffset*BYTES_PER_SAMPLE,buffs[0],n,_rx_stream.format,0);
- _rx_stream->remainderOffset+=n;
- _rx_stream->remainderSamps -=n;
+ _rx_stream.remainderOffset+=n;
+ _rx_stream.remainderSamps -=n;
- if(_rx_stream->remainderSamps==0){
+ if(_rx_stream.remainderSamps==0){
- this->releaseReadBuffer(stream,_rx_stream->remainderHandle);
- _rx_stream->remainderHandle=-1;
- _rx_stream->remainderOffset=0;
+ this->releaseReadBuffer(stream,_rx_stream.remainderHandle);
+ _rx_stream.remainderHandle=-1;
+ _rx_stream.remainderOffset=0;
}
if(n==returnedElems)
@@ -551,25 +547,25 @@ int SoapyHackRF::readStream(
}
size_t handle;
- int ret = this->acquireReadBuffer(stream, handle, (const void **)&_rx_stream->remainderBuff, flags, timeNs, timeoutUs);
+ int ret = this->acquireReadBuffer(stream, handle, (const void **)&_rx_stream.remainderBuff, flags, timeNs, timeoutUs);
if (ret < 0)
return ret;
- _rx_stream->remainderHandle=handle;
- _rx_stream->remainderSamps=ret;
+ _rx_stream.remainderHandle=handle;
+ _rx_stream.remainderSamps=ret;
- const size_t n =std::min((returnedElems-samp_avail),_rx_stream->remainderSamps);
+ const size_t n =std::min((returnedElems-samp_avail),_rx_stream.remainderSamps);
- readbuf(_rx_stream->remainderBuff,buffs[0],n,_rx_stream->format,samp_avail);
- _rx_stream->remainderSamps -=n;
- _rx_stream->remainderOffset +=n;
+ readbuf(_rx_stream.remainderBuff,buffs[0],n,_rx_stream.format,samp_avail);
+ _rx_stream.remainderSamps -=n;
+ _rx_stream.remainderOffset +=n;
- if(_rx_stream->remainderSamps==0){
- this->releaseReadBuffer(stream,_rx_stream->remainderHandle);
- _rx_stream->remainderHandle=-1;
- _rx_stream->remainderOffset=0;
+ if(_rx_stream.remainderSamps==0){
+ this->releaseReadBuffer(stream,_rx_stream.remainderHandle);
+ _rx_stream.remainderHandle=-1;
+ _rx_stream.remainderOffset=0;
}
return(returnedElems);
@@ -584,27 +580,30 @@ int SoapyHackRF::writeStream(
const long long timeNs,
const long timeoutUs )
{
+ if(stream != TX_STREAM){
+ return SOAPY_SDR_NOT_SUPPORTED;
+ }
size_t returnedElems = std::min(numElems,this->getStreamMTU(stream));
size_t samp_avail = 0;
- if(_tx_stream->remainderHandle>=0){
+ if(_tx_stream.remainderHandle>=0){
- const size_t n =std::min(_tx_stream->remainderSamps,returnedElems);
+ const size_t n =std::min(_tx_stream.remainderSamps,returnedElems);
if(n<returnedElems){
samp_avail=n;
}
- writebuf(buffs[0],_tx_stream->remainderBuff+_tx_stream->remainderOffset*BYTES_PER_SAMPLE,n,_tx_stream->format,0);
- _tx_stream->remainderSamps -=n;
- _tx_stream->remainderOffset +=n;
+ writebuf(buffs[0],_tx_stream.remainderBuff+_tx_stream.remainderOffset*BYTES_PER_SAMPLE,n,_tx_stream.format,0);
+ _tx_stream.remainderSamps -=n;
+ _tx_stream.remainderOffset +=n;
- if(_tx_stream->remainderSamps==0){
- this->releaseWriteBuffer(stream,_tx_stream->remainderHandle,_tx_stream->remainderOffset,flags,timeNs);
- _tx_stream->remainderHandle=-1;
- _tx_stream->remainderOffset=0;
+ if(_tx_stream.remainderSamps==0){
+ this->releaseWriteBuffer(stream,_tx_stream.remainderHandle,_tx_stream.remainderOffset,flags,timeNs);
+ _tx_stream.remainderHandle=-1;
+ _tx_stream.remainderOffset=0;
}
if(n==returnedElems)
@@ -614,22 +613,22 @@ int SoapyHackRF::writeStream(
size_t handle;
- int ret=this->acquireWriteBuffer(stream,handle,(void **)&_tx_stream->remainderBuff,timeoutUs);
+ int ret=this->acquireWriteBuffer(stream,handle,(void **)&_tx_stream.remainderBuff,timeoutUs);
if (ret<0)return ret;
- _tx_stream->remainderHandle=handle;
- _tx_stream->remainderSamps=ret;
+ _tx_stream.remainderHandle=handle;
+ _tx_stream.remainderSamps=ret;
- const size_t n =std::min((returnedElems-samp_avail),_tx_stream->remainderSamps);
+ const size_t n =std::min((returnedElems-samp_avail),_tx_stream.remainderSamps);
- writebuf(buffs[0],_tx_stream->remainderBuff,n,_tx_stream->format,samp_avail);
- _tx_stream->remainderSamps -=n;
- _tx_stream->remainderOffset +=n;
+ writebuf(buffs[0],_tx_stream.remainderBuff,n,_tx_stream.format,samp_avail);
+ _tx_stream.remainderSamps -=n;
+ _tx_stream.remainderOffset +=n;
- if(_tx_stream->remainderSamps==0){
- this->releaseWriteBuffer(stream,_tx_stream->remainderHandle,_tx_stream->remainderOffset,flags,timeNs);
- _tx_stream->remainderHandle=-1;
- _tx_stream->remainderOffset=0;
+ if(_tx_stream.remainderSamps==0){
+ this->releaseWriteBuffer(stream,_tx_stream.remainderHandle,_tx_stream.remainderOffset,flags,timeNs);
+ _tx_stream.remainderHandle=-1;
+ _tx_stream.remainderOffset=0;
}
return returnedElems;
@@ -644,10 +643,8 @@ int SoapyHackRF::readStreamStatus(
long long &timeNs,
const long timeoutUs
){
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
-
- if(data->direction!=SOAPY_SDR_TX){
+ if(stream != TX_STREAM){
return SOAPY_SDR_NOT_SUPPORTED;
}
@@ -658,8 +655,8 @@ int SoapyHackRF::readStreamStatus(
//poll for status events until the timeout expires
while (true)
{
- if(_tx_stream->underflow){
- _tx_stream->underflow=false;
+ if(_tx_stream.underflow){
+ _tx_stream.underflow=false;
SoapySDR::log(SOAPY_SDR_SSI, "U");
return SOAPY_SDR_UNDERFLOW;
}
@@ -683,9 +680,8 @@ int SoapyHackRF::acquireReadBuffer(
const long timeoutUs)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
- if(data->direction!=SOAPY_SDR_RX){
+ if(stream != RX_STREAM){
return SOAPY_SDR_NOT_SUPPORTED;
}
@@ -696,7 +692,7 @@ int SoapyHackRF::acquireReadBuffer(
while (true)
{
std::unique_lock <std::mutex> lock( _buf_mutex );
- if (_tx_stream->buf_count == 0) break;
+ if (_tx_stream.buf_count == 0) break;
if (std::chrono::high_resolution_clock::now() > exitTime) return SOAPY_SDR_TIMEOUT;
}
@@ -706,21 +702,21 @@ int SoapyHackRF::acquireReadBuffer(
std::unique_lock <std::mutex> lock( _buf_mutex );
- while (_rx_stream->buf_count == 0)
+ while (_rx_stream.buf_count == 0)
{
_buf_cond.wait_for(lock, std::chrono::microseconds(timeoutUs));
- if (_rx_stream->buf_count == 0) return SOAPY_SDR_TIMEOUT;
+ if (_rx_stream.buf_count == 0) return SOAPY_SDR_TIMEOUT;
}
- if(_rx_stream->overflow) {
+ if(_rx_stream.overflow) {
flags|=SOAPY_SDR_END_ABRUPT;
- _rx_stream->overflow=false;
+ _rx_stream.overflow=false;
SoapySDR::log(SOAPY_SDR_SSI,"O");
return SOAPY_SDR_OVERFLOW;
}
- handle=_rx_stream->buf_head;
- _rx_stream->buf_head = (_rx_stream->buf_head + 1) % _rx_stream->buf_num;
+ handle=_rx_stream.buf_head;
+ _rx_stream.buf_head = (_rx_stream.buf_head + 1) % _rx_stream.buf_num;
this->getDirectAccessBufferAddrs(stream,handle,(void **)buffs);
return this->getStreamMTU(stream);
@@ -730,13 +726,15 @@ void SoapyHackRF::releaseReadBuffer(
SoapySDR::Stream *stream,
const size_t handle)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
+ if(stream != RX_STREAM){
+ throw std::runtime_error("Invalid stream");
+ }
- if(!_tx_stream->burst_end){
+ if(!_tx_stream.burst_end){
std::unique_lock <std::mutex> lock( _buf_mutex );
- _rx_stream->buf_count--;
+ _rx_stream.buf_count--;
}
}
@@ -747,10 +745,8 @@ int SoapyHackRF::acquireWriteBuffer(
void **buffs,
const long timeoutUs)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
-
- if(data->direction!=SOAPY_SDR_TX){
+ if(stream != TX_STREAM){
return SOAPY_SDR_NOT_SUPPORTED;
}
@@ -761,21 +757,21 @@ int SoapyHackRF::acquireWriteBuffer(
std::unique_lock <std::mutex> lock( _buf_mutex );
- while ( _tx_stream->buf_count == _tx_stream->buf_num )
+ while ( _tx_stream.buf_count == _tx_stream.buf_num )
{
_buf_cond.wait_for(lock, std::chrono::microseconds(timeoutUs));
- if (_tx_stream->buf_count == _tx_stream->buf_num) return SOAPY_SDR_TIMEOUT;
+ if (_tx_stream.buf_count == _tx_stream.buf_num) return SOAPY_SDR_TIMEOUT;
}
- handle=_tx_stream->buf_head;
- _tx_stream->buf_head = (_tx_stream->buf_head + 1) % _tx_stream->buf_num;
+ handle=_tx_stream.buf_head;
+ _tx_stream.buf_head = (_tx_stream.buf_head + 1) % _tx_stream.buf_num;
this->getDirectAccessBufferAddrs(stream,handle,buffs);
- if(_tx_stream->burst_end){
- if((_tx_stream->burst_samps - int32_t(this->getStreamMTU(stream))) < 0){
+ if(_tx_stream.burst_end){
+ if((_tx_stream.burst_samps - int32_t(this->getStreamMTU(stream))) < 0){
memset(buffs[0],0,this->getStreamMTU(stream));
- return _tx_stream->burst_samps;
+ return _tx_stream.burst_samps;
}
}
return this->getStreamMTU(stream);
@@ -789,29 +785,24 @@ void SoapyHackRF::releaseWriteBuffer(
int &flags,
const long long timeNs)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
-
- std::unique_lock <std::mutex> lock( _buf_mutex );
-
- _tx_stream->buf_count++;
+ if (stream == TX_STREAM) {
+ std::unique_lock <std::mutex> lock( _buf_mutex );
+ _tx_stream.buf_count++;
+ } else {
+ throw std::runtime_error("Invalid stream");
+ }
}
size_t SoapyHackRF::getNumDirectAccessBuffers(
SoapySDR::Stream *stream)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
-
- size_t buffers;
- if(data->direction==SOAPY_SDR_RX){
- buffers =_rx_stream->buf_num;
-
- }
- if(data->direction==SOAPY_SDR_TX){
-
- buffers=_tx_stream->buf_num;
+ if (stream == RX_STREAM) {
+ return _rx_stream.buf_num;
+ } else if(stream == TX_STREAM){
+ return _tx_stream.buf_num;
+ } else {
+ throw std::runtime_error("Invalid stream");
}
-
- return buffers;
}
int SoapyHackRF::getDirectAccessBufferAddrs(
@@ -819,15 +810,13 @@ int SoapyHackRF::getDirectAccessBufferAddrs(
const size_t handle,
void **buffs)
{
- SoapyHackRFStream * data = (SoapyHackRFStream*)stream;
- if(data->direction==SOAPY_SDR_RX){
- buffs[0]=(void *)_rx_stream->buf[handle];
-
- }
- if(data->direction==SOAPY_SDR_TX){
-
- buffs[0]=(void *)_tx_stream->buf[handle];
+ if (stream == RX_STREAM) {
+ buffs[0]=(void *)_rx_stream.buf[handle];
+ } else if (stream == TX_STREAM) {
+ buffs[0]=(void *)_tx_stream.buf[handle];
+ } else {
+ throw std::runtime_error("Invalid stream");
}
return 0;
diff --git a/README.md b/README.md
index 84e0e23..49a1147 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
# Soapy SDR module for Hack RF
-##Build Status
+## Build Status
- Travis: [](https://travis-ci.org/pothosware/SoapyHackRF)
-##Dependencies
+## Dependencies
* SoapySDR - https://github.com/pothosware/SoapySDR/wiki
* libhackrf - https://github.com/mossmann/hackrf/wiki
-##Documentation
+## Documentation
* https://github.com/pothosware/SoapyHackRF/wiki
diff --git a/SoapyHackRF.hpp b/SoapyHackRF.hpp
index 53c5547..a6591bd 100644
--- a/SoapyHackRF.hpp
+++ b/SoapyHackRF.hpp
@@ -1,7 +1,9 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2015
+ * Copyright (c) 2015 Wei Jiang
+ * Copyright (c) 2015-2017 Josh Blum
+ * Copyright (c) 2017 Kevin Mehall
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -26,6 +28,7 @@
#include <condition_variable>
#include <SoapySDR/Device.hpp>
#include <SoapySDR/Logger.hpp>
+#include <set>
#define BUF_LEN 262144
#define BUF_NUM 15
@@ -48,6 +51,7 @@ typedef enum {
HACKRF_TRANSCEIVER_MODE_TX = 2,
} HackRF_transceiver_mode_t;
+std::set<std::string> &HackRF_getClaimedSerials(void);
/*!
* The session object manages hackrf_init/exit
@@ -293,20 +297,16 @@ public:
private:
- struct RXStream{
- uint32_t vga_gain;
- uint32_t lna_gain;
- uint8_t amp_gain;
- double samplerate;
- uint32_t bandwidth;
- uint64_t frequecy;
+ SoapySDR::Stream* const TX_STREAM = (SoapySDR::Stream*) 0x1;
+ SoapySDR::Stream* const RX_STREAM = (SoapySDR::Stream*) 0x2;
- int32_t remainderHandle;
- size_t remainderSamps;
- size_t remainderOffset;
- int8_t* remainderBuff;
- uint32_t format;
+ struct Stream {
+ Stream(): opened(false), buf_num(BUF_NUM), buf_len(BUF_LEN), buf(nullptr),
+ buf_head(0), buf_tail(0), buf_count(0),
+ remainderHandle(-1), remainderSamps(0), remainderOffset(0), remainderBuff(nullptr),
+ format(HACKRF_FORMAT_INT8) {}
+ bool opened;
uint32_t buf_num;
uint32_t buf_len;
int8_t **buf;
@@ -314,52 +314,49 @@ private:
uint32_t buf_tail;
uint32_t buf_count;
- bool overflow;
- } ;
+ int32_t remainderHandle;
+ size_t remainderSamps;
+ size_t remainderOffset;
+ int8_t* remainderBuff;
+ uint32_t format;
+ ~Stream() { clear_buffers(); }
+ void clear_buffers();
+ void allocate_buffers();
+ };
- struct TXStream{
+ struct RXStream: Stream {
uint32_t vga_gain;
+ uint32_t lna_gain;
uint8_t amp_gain;
double samplerate;
uint32_t bandwidth;
- uint64_t frequecy;
- bool bias;
+ uint64_t frequency;
- int32_t remainderHandle;
- size_t remainderSamps;
- size_t remainderOffset;
- int8_t* remainderBuff;
- uint32_t format;
+ bool overflow;
+ };
+
+ struct TXStream: Stream {
+ uint32_t vga_gain;
+ uint8_t amp_gain;
+ double samplerate;
+ uint32_t bandwidth;
+ uint64_t frequency;
+ bool bias;
- uint32_t buf_num;
- uint32_t buf_len;
- int8_t **buf;
- uint32_t buf_head;
- uint32_t buf_tail;
- uint32_t buf_count;
bool underflow;
bool burst_end;
int32_t burst_samps;
} ;
- struct SoapyHackRFStream
- {
- RXStream * rxStream;
- TXStream * txStream;
- int32_t direction;
- };
-
-
- RXStream * _rx_stream;
- TXStream * _tx_stream;
+ RXStream _rx_stream;
+ TXStream _tx_stream;
bool _auto_bandwidth;
hackrf_device * _dev;
-
- hackrf_device_list_t * _list;
+ std::string _serial;
uint64_t _current_frequency;
@@ -369,8 +366,11 @@ private:
uint8_t _current_amp;
- int32_t _id;
- std::mutex _activate_mutex;
+ /// Mutex protecting all use of the hackrf device _dev and other instance variables.
+ /// Most of the hackrf API is thread-safe because it only calls libusb, however
+ /// the activateStream() method in this library can close and re-open the device,
+ /// so all use of _dev must be protected
+ mutable std::mutex _device_mutex;
std::mutex _buf_mutex;
std::condition_variable _buf_cond;
diff --git a/debian/changelog b/debian/changelog
index 7ef1c22..4381ccb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+soapyhackrf (0.3.1-1) unstable; urgency=low
+
+ * Release 0.3.1 (2017-06-19)
+
+ -- Josh Blum <josh at pothosware.com> Mon, 19 Jun 2017 20:18:21 -0000
+
+soapyhackrf (0.3.0-1) unstable; urgency=low
+
+ * Release 0.3.0 (2017-04-29)
+
+ -- Josh Blum <josh at pothosware.com> Sat, 29 Apr 2017 15:04:55 -0000
+
soapyhackrf (0.2.2) unstable; urgency=low
* Release 0.2.2 (2016-10-19)
diff --git a/debian/control b/debian/control
index e006d7b..270397a 100644
--- a/debian/control
+++ b/debian/control
@@ -13,7 +13,7 @@ Homepage: https://github.com/pothosware/SoapyHackRF/wiki
Vcs-Git: https://github.com/pothosware/SoapyHackRF.git
Vcs-Browser: https://github.com/pothosware/SoapyHackRF
-Package: soapysdr0.5-2-module-hackrf
+Package: soapysdr0.6-module-hackrf
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}
@@ -22,7 +22,7 @@ Description: Soapy HackRF - HackRF device support for Soapy SDR.
Package: soapysdr-module-hackrf
Architecture: all
-Depends: soapysdr0.5-2-module-hackrf, ${misc:Depends}
+Depends: soapysdr0.6-module-hackrf, ${misc:Depends}
Description: Soapy HackRF - HackRF device support for Soapy SDR.
A Soapy module that supports HackRF devices within the Soapy API.
.
diff --git a/debian/copyright b/debian/copyright
index 1d5caa2..a98a3bf 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -5,7 +5,8 @@ Source: https://github.com/pothosware/SoapyHackRF/wiki
Files: *
Copyright:
Copyright (c) 2015-2016 Wei Jiang
- Copyright (c) 2015 Josh Blum
+ Copyright (c) 2015-2017 Josh Blum
+ Copyright (c) 2017 Kevin Mehall
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/debian/rules b/debian/rules
old mode 100644
new mode 100755
diff --git a/debian/soapysdr0.5-2-module-hackrf.install b/debian/soapysdr0.6-module-hackrf.install
similarity index 100%
rename from debian/soapysdr0.5-2-module-hackrf.install
rename to debian/soapysdr0.6-module-hackrf.install
diff --git a/self_test.py b/self_test.py
index 11ebc95..49129f5 100644
--- a/self_test.py
+++ b/self_test.py
@@ -52,7 +52,7 @@ if __name__ == "__main__":
rxStream = hackrf.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0])
txStream = hackrf.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CF32, [0])
- hackrf.activateStream(txStream)
+ hackrf.activateStream(rxStream)
hackrf.activateStream(txStream)
numSampsTotal = 10000
@@ -74,7 +74,7 @@ if __name__ == "__main__":
assert(sr.ret > 0)
numSampsTotal -= sr.ret
- hackrf.deactivateStream(txStream)
+ hackrf.deactivateStream(rxStream)
hackrf.deactivateStream(txStream)
hackrf.closeStream(rxStream)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/soapyhackrf.git
More information about the pkg-hamradio-commits
mailing list