Initial experimental support for SoapySDR device input

This commit is contained in:
Charles J. Cliffe 2015-09-13 22:18:29 -04:00
parent 7a01c436d6
commit 1918707304
13 changed files with 913 additions and 76 deletions

View File

@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 2.8)
SET(CUBICSDR_VERSION_MAJOR "0")
SET(CUBICSDR_VERSION_MINOR "1")
SET(CUBICSDR_VERSION_PATCH "6")
SET(CUBICSDR_VERSION_REL "beta-issue140")
SET(CUBICSDR_VERSION_PATCH "7")
SET(CUBICSDR_VERSION_REL "beta-issue64")
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
SET(CPACK_PACKAGE_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}")
@ -15,9 +15,9 @@ ADD_DEFINITIONS(
-DCUBICSDR_VERSION="${CUBICSDR_VERSION}"
)
IF (NOT APPLE)
# IF (NOT APPLE)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
ENDIF(NOT APPLE)
# ENDIF(NOT APPLE)
macro(configure_files srcDir destDir globStr)
@ -80,11 +80,31 @@ SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/${EX_PLATFORM_NA
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/${EX_PLATFORM_NAME})
find_package(OpenGL REQUIRED)
IF (NOT WIN32)
find_package(FFTW REQUIRED)
find_package(Liquid REQUIRED)
include_directories(${LIQUID_INCLUDES} ${FFTW_INCLUDES})
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} ${LIQUID_LIBRARIES} ${FFTW_LIBRARIES})
ENDIF()
find_package(wxWidgets COMPONENTS gl core base REQUIRED)
set(wxWidgets_CONFIGURATION mswu)
include(${wxWidgets_USE_FILE})
SET(USE_SOAPY_SDR ON CACHE BOOL "Build with SoapySDR support instead of RTL-SDR.")
IF (USE_SOAPY_SDR)
find_package(SoapySDR NO_MODULE REQUIRED)
include_directories(${SOAPY_SDR_INCLUDE_DIR})
SET(OTHER_LIBRARIES ${SOAPY_SDR_LIBRARY} ${OTHER_LIBRARIES})
ADD_DEFINITIONS(
-DUSE_SOAPY_SDR=1
)
ELSE()
SET(USE_RTL_SDR ON CACHE BOOL "Build with RTL-SDR support only.")
ADD_DEFINITIONS(
-DUSE_RTL_SDR=1
)
ENDIF()
IF (WIN32)
set(wxWidgets_USE_STATIC ON)
@ -121,11 +141,16 @@ IF (WIN32)
#ENDIF(USE_AUDIO_ASIO)
# FFTW
include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release )
include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4 )
set(FFTW_LIB libfftw3f-3)
link_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/fftw-3.3.4/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
IF(USE_RTL_SDR)
include_directories( ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release )
ENDIF()
include_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/include )
set(LIQUID_LIB libliquid)
@ -135,15 +160,19 @@ IF (WIN32)
link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME}/ "*.dll")
# RTL-SDR
link_directories ( ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
IF(USE_RTL_SDR)
link_directories ( ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
ENDIF()
ELSE (MSVC) # GCC
# LIQUID
link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/gcc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/liquid-dsp/gcc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
# RTL-SDR
link_directories ( ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
IF(USE_RTL_SDR)
link_directories ( ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM} )
configure_files(${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
ENDIF()
ENDIF(MSVC)
# Copy DLL files to build dir
@ -154,18 +183,20 @@ ENDIF (WIN32)
IF (UNIX AND NOT APPLE)
set(BUILD_DEB OFF CACHE BOOL "Build DEB")
set(RTLSDR_INCLUDE "/usr/local/include" CACHE FILEPATH "RTL-SDR Include Path")
set(RTLSDR_LIB "/usr/local/lib" CACHE FILEPATH "RTL-SDR Lib Path")
set(USE_AUDIO_PULSE ON CACHE BOOL "Use Pulse Audio")
set(USE_AUDIO_JACK OFF CACHE BOOL "Use Jack Audio")
set(USE_AUDIO_ALSA OFF CACHE BOOL "Use ALSA Audio")
set(USE_AUDIO_OSS OFF CACHE BOOL "Use OSS Audio")
include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB})
IF(USE_RTL_SDR)
SET(RTLSDR_INCLUDE "/usr/local/include" CACHE FILEPATH "RTL-SDR Include Path")
SET(RTLSDR_LIB "/usr/local/lib" CACHE FILEPATH "RTL-SDR Lib Path")
include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB})
ENDIF()
SET(USE_AUDIO_PULSE ON CACHE BOOL "Use Pulse Audio")
SET(USE_AUDIO_JACK OFF CACHE BOOL "Use Jack Audio")
SET(USE_AUDIO_ALSA OFF CACHE BOOL "Use ALSA Audio")
SET(USE_AUDIO_OSS OFF CACHE BOOL "Use OSS Audio")
set(FFTW_LIB fftw3f)
set(LIQUID_LIB liquid)
set(OTHER_LIBRARIES dl)
SET(FFTW_LIB fftw3f)
SET(LIQUID_LIB liquid)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} dl)
IF(USE_AUDIO_PULSE)
SET (OTHER_LIBRARIES ${OTHER_LIBRARIES} pulse-simple pulse)
@ -203,21 +234,25 @@ ENDIF(USE_AUDIO_OSS)
ENDIF(UNIX AND NOT APPLE)
IF (APPLE)
set(RTLSDR_INCLUDE "/opt/local/include" CACHE FILEPATH "RTL-SDR Include Path")
set(RTLSDR_LIB "/opt/local/lib" CACHE FILEPATH "RTL-SDR Lib Path")
include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB})
set(LIB_DIRS "${LIB_DIRS} ${RTLSDR_LIB}")
IF (USE_RTL_SDR)
SET(RTLSDR_INCLUDE "/opt/local/include" CACHE FILEPATH "RTL-SDR Include Path")
SET(RTLSDR_LIB "/opt/local/lib" CACHE FILEPATH "RTL-SDR Lib Path")
include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB})
SET(LIB_DIRS ${LIB_DIRS} ${RTLSDR_LIB})
ENDIF()
set(FFTW_LIB fftw3f)
set(LIQUID_LIB liquid)
SET(FFTW_LIB fftw3f)
SET(LIQUID_LIB liquid)
link_directories(/usr/local/lib)
link_directories(/opt/local/lib)
ADD_DEFINITIONS(
-D__MACOSX_CORE__
)
FIND_LIBRARY(COREAUDIO_LIBRARY CoreAudio)
SET (OTHER_LIBRARIES ${COREAUDIO_LIBRARY})
SET (OTHER_LIBRARIES ${COREAUDIO_LIBRARY} ${OTHER_LIBRARIES})
set(BUNDLE_APP OFF CACHE BOOL "Bundle Application")
ENDIF (APPLE)
@ -230,7 +265,6 @@ SET (cubicsdr_sources
src/FrequencyDialog.cpp
src/IOThread.cpp
src/sdr/SDRDeviceInfo.cpp
src/sdr/SDRThread.cpp
src/sdr/SDRPostThread.cpp
src/demod/DemodulatorPreThread.cpp
src/demod/DemodulatorThread.cpp
@ -284,7 +318,6 @@ SET (cubicsdr_headers
src/FrequencyDialog.h
src/IOThread.h
src/sdr/SDRDeviceInfo.h
src/sdr/SDRThread.h
src/sdr/SDRPostThread.h
src/demod/DemodulatorPreThread.h
src/demod/DemodulatorThread.h
@ -347,6 +380,16 @@ SET (cubicsdr_headers
external/cubicvr2/math/vec4.h
)
IF (USE_SOAPY_SDR)
SET(cubicsdr_sources ${cubicsdr_sources} src/SDR/SoapySDRThread.cpp)
SET(cubicsdr_headers ${cubicsdr_headers} src/SDR/SoapySDRThread.h)
ELSE()
SET(cubicsdr_sources ${cubicsdr_sources} src/SDR/SDRThread.cpp)
SET(cubicsdr_headers ${cubicsdr_headers} src/SDR/SDRThread.h)
ENDIF()
set(REG_EXT "[^/]*([.]cpp|[.]c|[.]h|[.]hpp)$")
SOURCE_GROUP("Base" REGULAR_EXPRESSION src/${REG_EXT})
@ -410,7 +453,10 @@ IF (NOT BUNDLE_APP)
configure_files(${PROJECT_SOURCE_DIR}/font ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.png")
configure_files(${PROJECT_SOURCE_DIR}/icon ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} CubicSDR.ico)
add_executable(CubicSDR ${cubicsdr_sources} ${cubicsdr_headers} ${RES_FILES})
target_link_libraries(CubicSDR rtlsdr ${LIQUID_LIB} ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES})
IF (USE_RTL_SDR)
SET(OTHER_LIBRARIES rtlsdr ${OTHER_LIBRARIES})
ENDIF()
target_link_libraries(CubicSDR ${LIQUID_LIB} ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES})
ENDIF (NOT BUNDLE_APP)
IF (MSVC)
@ -479,7 +525,11 @@ IF (APPLE AND BUNDLE_APP)
MACOSX_PACKAGE_LOCATION Resources
)
target_link_libraries(CubicSDR rtlsdr ${LIQUID_LIB} ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES})
IF (USE_RTL_SDR)
SET(OTHER_LIBRARIES rtlsdr ${OTHER_LIBRARIES})
ENDIF()
target_link_libraries(CubicSDR ${LIQUID_LIB} ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES})
SET_TARGET_PROPERTIES(CubicSDR PROPERTIES MACOSX_BUNDLE TRUE)
SET_TARGET_PROPERTIES(CubicSDR PROPERTIES
@ -498,7 +548,7 @@ IF (APPLE AND BUNDLE_APP)
INSTALL(CODE "
SET(BU_COPY_FULL_FRAMEWORK_CONTENTS ON)
include(BundleUtilities)
fixup_bundle(\"${APPS}\" \"\" \"${RTLSDR_LIB}\")
fixup_bundle(\"${APPS}\" \"\" \"/usr/local/lib\")
VERIFY_APP(\"${APPS}\")
" COMPONENT Runtime)
@ -550,17 +600,23 @@ IF (WIN32 AND BUILD_INSTALLER)
${PROJECT_SOURCE_DIR}/external/fftw-3.3.4/${EX_PLATFORM}/libfftw3f-3.dll
DESTINATION .)
IF (MSVC)
install(FILES
${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM}/rtlsdr.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM}/libusb-1.0.dll
DESTINATION .)
IF (USE_RTL_SDR)
SET (OTHER_INSTALL_FILES ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM}/rtlsdr.dll)
ENDIF()
install(FILES
${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/msvc/${EX_PLATFORM}/libusb-1.0.dll
${OTHER_INSTALL_FILES}
DESTINATION .)
ELSE (MSVC)
install(FILES
${PROJECT_SOURCE_DIR}/external/liquid-dsp/gcc/${EX_PLATFORM}/libliquid.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM}/librtlsdr.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM}/libusb-1.0.dll
DESTINATION .)
IF (USE_RTL_SDR)
SET (OTHER_INSTALL_FILES ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM}/librtlsdr.dll)
ENDIF()
install(FILES
${PROJECT_SOURCE_DIR}/external/liquid-dsp/gcc/${EX_PLATFORM}/libliquid.dll
${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/gcc/${EX_PLATFORM}/libusb-1.0.dll
${OTHER_INSTALL_FILES}
DESTINATION .)
ENDIF(MSVC)
IF(MSVC AND EX_PLATFORM EQUAL 32)
@ -585,7 +641,10 @@ IF (UNIX AND BUILD_DEB)
set(CPACK_GENERATOR DEB)
set(CPACK_PACKAGE_NAME "CubicSDR")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS " librtlsdr0, libfftw3-single3, libwxgtk3.0-0, libpulse0")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS " libfftw3-single3, libwxgtk3.0-0, libpulse0")
IF (USE_RTL_SDR)
SET(CPACK_DEBIAN_PACKAGE_DEPENDS " librtlsdr0, ${CPACK_DEBIAN_PACKAGE_DEPENDS}")
ENDIF()
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Charles J. Cliffe <cj@cubicproductions.com>")
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "CubicSDR Software Defined Radio application v${CUBICSDR_VERSION}")
SET(CPACK_DEBIAN_PACKAGE_SECTION "comm")

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

View File

@ -0,0 +1,22 @@
# - Find LIQUID
# Find the native LIQUID includes and library
#
# LIQUID_INCLUDES - where to find LIQUID3.h
# LIQUID_LIBRARIES - List of libraries when using LIQUID.
# LIQUID_FOUND - True if LIQUID found.
if (LIQUID_INCLUDES)
# Already in cache, be silent
set (LIQUID_FIND_QUIETLY TRUE)
endif (LIQUID_INCLUDES)
find_path (LIQUID_INCLUDES liquid/liquid.h)
find_library (LIQUID_LIBRARIES NAMES liquid)
# handle the QUIETLY and REQUIRED arguments and set LIQUID_FOUND to TRUE if
# all listed variables are TRUE
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (LIQUID DEFAULT_MSG LIQUID_LIBRARIES LIQUID_INCLUDES)
mark_as_advanced (LIQUID_LIBRARIES LIQUID_INCLUDES)

View File

@ -14,7 +14,6 @@
#endif
#include <vector>
#include "SDRThread.h"
#include "DemodulatorMgr.h"
#include "AudioThread.h"
#include "CubicSDR.h"
@ -284,6 +283,7 @@ AppFrame::AppFrame() :
sampleRateMenuItems[wxID_BANDWIDTH_2880M] = menu->AppendRadioItem(wxID_BANDWIDTH_2880M, "2.88M");
// sampleRateMenuItems[wxID_BANDWIDTH_3000M] = menu->AppendRadioItem(wxID_BANDWIDTH_3000M, "3.0M");
sampleRateMenuItems[wxID_BANDWIDTH_3200M] = menu->AppendRadioItem(wxID_BANDWIDTH_3200M, "3.2M");
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL] = menu->AppendRadioItem(wxID_BANDWIDTH_MANUAL, "Manual Entry");
sampleRateMenuItems[wxID_BANDWIDTH_2400M]->Check(true);
@ -584,6 +584,12 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
case wxID_BANDWIDTH_3200M:
wxGetApp().setSampleRate(3200000);
break;
case wxID_BANDWIDTH_MANUAL:
long bw = wxGetNumberFromUser("Set the bandwidth manually", "Sample Rate (Hz), i.e. 2560000 for 2.56M", "Manual Bandwidth Entry", wxGetApp().getSampleRate(), 250000, 16000000, this);
if (bw != -1) {
wxGetApp().setSampleRate(bw);
}
break;
}
std::vector<SDRDeviceInfo *> *devs = wxGetApp().getDevices();

View File

@ -45,6 +45,7 @@
#define wxID_BANDWIDTH_2880M 2161
//#define wxID_BANDWIDTH_3000M 2162
#define wxID_BANDWIDTH_3200M 2163
#define wxID_BANDWIDTH_MANUAL 2164
#define wxID_DEVICE_ID 3500

View File

@ -97,19 +97,20 @@ bool CubicSDR::OnInit() {
std::vector<SDRDeviceInfo *>::iterator devs_i;
SDRThread::enumerate_rtl(&devs);
// SDRThread::enumerate_rtl(&devs);
devs = SDRThread::enumerate_devices();
SDRDeviceInfo *dev = NULL;
if (devs.size() > 1) {
if (devs->size() > 1) {
wxArrayString choices;
for (devs_i = devs.begin(); devs_i != devs.end(); devs_i++) {
for (devs_i = devs->begin(); devs_i != devs->end(); devs_i++) {
std::string devName = (*devs_i)->getName();
if ((*devs_i)->isAvailable()) {
devName.append(": ");
devName.append((*devs_i)->getProduct());
devName.append(" [");
devName.append((*devs_i)->getSerial());
devName.append("]");
// devName.append(": ");
// devName.append((*devs_i)->getProduct());
// devName.append(" [");
// devName.append((*devs_i)->getSerial());
// devName.append("]");
} else {
devName.append(" (In Use?)");
}
@ -121,11 +122,11 @@ bool CubicSDR::OnInit() {
return false;
}
dev = devs[devId];
dev = (*devs)[devId];
sdrThread->setDeviceId(devId);
} else if (devs.size() == 1) {
dev = devs[0];
} else if (devs->size() == 1) {
dev = (*devs)[0];
}
if (!dev) {
@ -347,7 +348,7 @@ void CubicSDR::removeDemodulator(DemodulatorInstance *demod) {
}
std::vector<SDRDeviceInfo*>* CubicSDR::getDevices() {
return &devs;
return devs;
}
void CubicSDR::setDevice(int deviceId) {

View File

@ -10,7 +10,11 @@
#include "PrimaryGLContext.h"
#include "ThreadQueue.h"
#include "SDRThread.h"
#ifdef USE_RTL_SDR
#include "SDRThread.h"
#else
#include "SoapySDRThread.h"
#endif
#include "SDRPostThread.h"
#include "AudioThread.h"
#include "DemodulatorMgr.h"
@ -86,7 +90,7 @@ private:
AppFrame *appframe;
AppConfig config;
PrimaryGLContext *m_glContext;
std::vector<SDRDeviceInfo *> devs;
std::vector<SDRDeviceInfo *> *devs;
DemodulatorMgr demodMgr;

View File

@ -1,6 +1,64 @@
#include "SDRDeviceInfo.h"
int SDRDeviceChannel::getChannel() const {
return channel;
}
void SDRDeviceChannel::setChannel(const int channel) {
this->channel = channel;
}
bool SDRDeviceChannel::isFullDuplex() {
return fullDuplex;
}
void SDRDeviceChannel::setFullDuplex(bool fullDuplex) {
this->fullDuplex = fullDuplex;
}
bool SDRDeviceChannel::isTx() {
return tx;
}
void SDRDeviceChannel::setTx(bool tx) {
this->tx = tx;
}
bool SDRDeviceChannel::isRx() {
return rx;
}
void SDRDeviceChannel::setRx(bool rx) {
this->rx = rx;
}
const SDRDeviceRange &SDRDeviceChannel::getGain() const {
return rangeGain;
}
const SDRDeviceRange &SDRDeviceChannel::getLNAGain() const {
return rangeLNA;
}
const SDRDeviceRange &SDRDeviceChannel::getFreqRange() const {
return rangeFull;
}
const SDRDeviceRange &SDRDeviceChannel::getRFRange() const {
return rangeRF;
}
const std::vector<long long> &SDRDeviceChannel::getSampleRates() const {
return sampleRates;
}
const std::vector<long long> &SDRDeviceChannel::getFilterBandwidths() const {
return filterBandwidths;
}
SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false) {
}
@ -9,12 +67,20 @@ std::string SDRDeviceInfo::getDeviceId() {
std::string deviceId;
deviceId.append(getName());
deviceId.append(" :: ");
deviceId.append(getSerial());
// deviceId.append(" :: ");
// deviceId.append(getSerial());
return deviceId;
}
const int SDRDeviceInfo::getIndex() const {
return index;
}
void SDRDeviceInfo::setIndex(const int index) {
this->index = index;
}
bool SDRDeviceInfo::isAvailable() const {
return available;
}
@ -63,3 +129,31 @@ void SDRDeviceInfo::setProduct(const std::string& product) {
this->product = product;
}
const std::string& SDRDeviceInfo::getDriver() const {
return driver;
}
void SDRDeviceInfo::setDriver(const std::string& driver) {
this->driver = driver;
}
const std::string& SDRDeviceInfo::getHardware() const {
return hardware;
}
void SDRDeviceInfo::setHardware(const std::string& hardware) {
this->hardware = hardware;
}
bool SDRDeviceInfo::hasTimestamps() const {
return timestamps;
}
void SDRDeviceInfo::setTimestamps(bool timestamps) {
this->timestamps = timestamps;
}
std::string SDRDeviceInfo::getDeviceArgs() {
return "driver=" + driver;
//+ "," + getDriver() + "=" + std::to_string(getIndex());
}

View File

@ -1,6 +1,77 @@
#pragma once
#include <string>
#include <vector>
/*
----------------------------------------------------
-- Device identification
----------------------------------------------------
driver=rtl
hardware=rtl
----------------------------------------------------
-- Peripheral summary
----------------------------------------------------
Channels: 1 Rx, 0 Tx
Timestamps: NO
----------------------------------------------------
-- RX Channel 0
----------------------------------------------------
Full-duplex: YES
Antennas: RX
Full gain range: [0, 49.6] dB
LNA gain range: [0, 49.6] dB
Full freq range: [24, 1766] MHz
RF freq range: [24, 1766] MHz
CORR freq range: MHz
Sample rates: [0.25, 2.56] MHz
Filter bandwidths: [] MHz
*/
class SDRDeviceRange {
public:
SDRDeviceRange(float low, float high);
float getLow() const;
void setLow(const float low);
float getHigh() const;
void setHigh(const float high);
private:
float low, high;
};
class SDRDeviceChannel {
int getChannel() const;
void setChannel(const int channel);
bool isFullDuplex();
void setFullDuplex(bool fullDuplex);
bool isTx();
void setTx(bool tx);
bool isRx();
void setRx(bool rx);
const SDRDeviceRange &getGain() const;
const SDRDeviceRange &getLNAGain() const;
const SDRDeviceRange &getFreqRange() const;
const SDRDeviceRange &getRFRange() const;
const std::vector<long long> &getSampleRates() const;
const std::vector<long long> &getFilterBandwidths() const;
private:
int channel;
bool fullDuplex, tx, rx;
SDRDeviceRange rangeGain, rangeLNA, rangeFull, rangeRF;
std::vector<long long> sampleRates;
std::vector<long long> filterBandwidths;
};
class SDRDeviceInfo {
public:
@ -8,6 +79,9 @@ public:
std::string getDeviceId();
const int getIndex() const;
void setIndex(const int index);
bool isAvailable() const;
void setAvailable(bool available);
@ -25,12 +99,24 @@ public:
const std::string& getProduct() const;
void setProduct(const std::string& product);
const std::string& getDriver() const;
void setDriver(const std::string& driver);
const std::string& getHardware() const;
void setHardware(const std::string& hardware);
bool hasTimestamps() const;
void setTimestamps(bool timestamps);
const std::vector<SDRDeviceChannel>& getChannels() const;
std::string getDeviceArgs();
private:
std::string name;
std::string serial;
std::string product;
std::string manufacturer;
std::string tuner;
bool available;
int index;
std::string name, serial, product, manufacturer, tuner;
std::string driver, hardware;
bool timestamps, available;
std::vector<SDRDeviceChannel> channels;
};

View File

@ -96,16 +96,22 @@ void SDRPostThread::run() {
fpData.resize(dataSize);
dataOut.resize(dataSize);
}
if (swapIQ) {
for (int i = 0; i < dataSize; i++) {
fpData[i] = _lut_swap[*((uint16_t*)&data_in->data[2*i])];
}
} else {
for (int i = 0; i < dataSize; i++) {
fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])];
}
for (int i = 0; i < dataSize; i++) {
fpData[i].real = data_in->data[i*2];
fpData[i].imag = data_in->data[i*2+1];
}
// if (swapIQ) {
// for (int i = 0; i < dataSize; i++) {
// fpData[i] = _lut_swap[*((uint16_t*)&data_in->data[2*i])];
// }
// } else {
// for (int i = 0; i < dataSize; i++) {
// fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])];
// }
// }
iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]);

View File

@ -1,6 +1,10 @@
#pragma once
#if USE_RTL_SDR
#include "SDRThread.h"
#else
#include "SoapySDRThread.h"
#endif
#include <algorithm>
class SDRPostThread : public IOThread {

459
src/sdr/SoapySDRThread.cpp Normal file
View File

@ -0,0 +1,459 @@
#include "SoapySDRThread.h"
#include "CubicSDRDefs.h"
#include <vector>
#include "CubicSDR.h"
#include <string>
#include <SoapySDR/Version.hpp>
#include <SoapySDR/Modules.hpp>
#include <SoapySDR/Registry.hpp>
#include <SoapySDR/Device.hpp>
std::vector<std::string> SDRThread::factories;
std::vector<std::string> SDRThread::modules;
std::vector<SDRDeviceInfo *> SDRThread::devs;
SDRThread::SDRThread() : IOThread() {
offset.store(0);
deviceId.store(-1);
// dev = NULL;
sampleRate.store(DEFAULT_SAMPLE_RATE);
}
SDRThread::~SDRThread() {
// rtlsdr_close(dev);
}
std::vector<SDRDeviceInfo *> *SDRThread::enumerate_devices() {
if (SDRThread::devs.size()) {
return &SDRThread::devs;
}
std::cout << "SoapySDR init.." << std::endl;
std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl;
std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl;
std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl;
modules = SoapySDR::listModules();
for (size_t i = 0; i < modules.size(); i++) {
std::cout << "\tModule found: " << modules[i] << std::endl;
}
if (modules.empty()) {
std::cout << "No modules found!" << std::endl;
}
std::cout << "\tLoading modules... " << std::flush;
SoapySDR::loadModules();
std::cout << "done" << std::endl;
if (SDRThread::factories.size()) {
SDRThread::factories.erase(SDRThread::factories.begin(), SDRThread::factories.end());
}
std::cout << "\tAvailable factories...";
SoapySDR::FindFunctions factories = SoapySDR::Registry::listFindFunctions();
for (SoapySDR::FindFunctions::const_iterator it = factories.begin(); it != factories.end(); ++it) {
if (it != factories.begin()) {
std::cout << ", ";
}
std::cout << it->first;
SDRThread::factories.push_back(it->first);
}
if (factories.empty()) {
std::cout << "No factories found!" << std::endl;
}
std::cout << std::endl;
std::vector<SoapySDR::Kwargs> results = SoapySDR::Device::enumerate();
std::map<std::string, int> deviceIndexes;
for (size_t i = 0; i < results.size(); i++) {
std::cout << "Found device " << i << std::endl;
SDRDeviceInfo *dev = new SDRDeviceInfo();
for (SoapySDR::Kwargs::const_iterator it = results[i].begin(); it != results[i].end(); ++it) {
std::cout << " " << it->first << " = " << it->second << std::endl;
if (it->first == "driver") {
dev->setDriver(it->second);
} else if (it->first == "label") {
dev->setName(it->second);
}
// else if (it->first == dev->getDriver()) {
// dev->setIndex(std::stoi(it->second.c_str()));
// }
}
dev->setIndex(deviceIndexes[dev->getDriver()]);
deviceIndexes[dev->getDriver()]++;
std::cout << "Make device " << dev->getDeviceArgs() << std::endl;
try {
SoapySDR::Device *device = SoapySDR::Device::make(dev->getDeviceArgs());
SoapySDR::Kwargs info = device->getHardwareInfo();
for (SoapySDR::Kwargs::const_iterator it = info.begin(); it != info.end(); ++it) {
std::cout << " " << it->first << "=" << it->second << std::endl;
if (it->first == "hardware") {
dev->setHardware(it->second);
}
}
SoapySDR::Device::unmake(device);
dev->setAvailable(true);
} catch (const std::exception &ex) {
std::cerr << "Error making device: " << ex.what() << std::endl;
dev->setAvailable(false);
}
std::cout << std::endl;
SDRThread::devs.push_back(dev);
}
if (results.empty()) {
std::cout << "No devices found!" << std::endl;
}
std::cout << std::endl;
return &SDRThread::devs;
}
void SDRThread::run() {
//#ifdef __APPLE__
// pthread_t tID = pthread_self(); // ID of this thread
// int priority = sched_get_priority_max( SCHED_FIFO) - 1;
// sched_param prio = { priority }; // scheduling priority of thread
// pthread_setschedparam(tID, SCHED_FIFO, &prio);
//#endif
std::cout << "SDR thread initializing.." << std::endl;
if (deviceId == -1 && devs.size() == 0) {
std::cout << "No devices found.. SDR Thread exiting.." << std::endl;
return;
} else {
if (deviceId == -1) {
deviceId = 0;
}
std::cout << "Using device #" << deviceId << std::endl;
}
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devs[deviceId]->getDeviceId());
long long frequency = wxGetApp().getConfig()->getCenterFreq();
int ppm = devConfig->getPPM();
int direct_sampling_mode = devConfig->getDirectSampling();;
// int buf_size = BUF_SIZE;
offset.store(devConfig->getOffset());
wxGetApp().setSwapIQ(devConfig->getIQSwap());
SDRDeviceInfo *dev = devs[deviceId];
std::vector<SoapySDR::Kwargs> dev_results = SoapySDR::Device::enumerate(dev->getDeviceArgs());
SoapySDR::Device *device = SoapySDR::Device::make(dev_results[dev->getIndex()]);
device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load());
device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load());
device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm);
device->setGainMode(SOAPY_SDR_RX,0, true);
SoapySDR::Stream *stream = device->setupStream(SOAPY_SDR_RX,"CF32");
device->activateStream(stream);
void *buffs[1];
buffs[0] = malloc(BUF_SIZE * sizeof(float));
int flags;
long long timeNs;
ReBuffer<SDRThreadIQData> buffers;
SDRThreadIQDataQueue* iqDataOutQueue = (SDRThreadIQDataQueue*) getOutputQueue("IQDataOutput");
SDRThreadCommandQueue* cmdQueue = (SDRThreadCommandQueue*) getInputQueue("SDRCommandQueue");
while (!terminated) {
if (!cmdQueue->empty()) {
bool freq_changed = false;
bool offset_changed = false;
bool rate_changed = false;
bool device_changed = false;
bool ppm_changed = false;
bool direct_sampling_changed = false;
long long new_freq = frequency;
long long new_offset = offset.load();
long long new_rate = sampleRate.load();
int new_device = deviceId;
int new_ppm = ppm;
while (!cmdQueue->empty()) {
SDRThreadCommand command;
cmdQueue->pop(command);
switch (command.cmd) {
case SDRThreadCommand::SDR_THREAD_CMD_TUNE:
freq_changed = true;
new_freq = command.llong_value;
if (new_freq < sampleRate.load() / 2) {
new_freq = sampleRate.load() / 2;
}
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_OFFSET:
offset_changed = true;
new_offset = command.llong_value;
std::cout << "Set offset: " << new_offset << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_SAMPLERATE:
rate_changed = true;
new_rate = command.llong_value;
std::cout << "Set sample rate: " << new_rate << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE:
device_changed = true;
new_device = (int) command.llong_value;
std::cout << "Set device: " << new_device << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_PPM:
ppm_changed = true;
new_ppm = (int) command.llong_value;
//std::cout << "Set PPM: " << new_ppm << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_DIRECT_SAMPLING:
direct_sampling_mode = (int)command.llong_value;
direct_sampling_changed = true;
break;
default:
break;
}
}
if (device_changed) {
device->deactivateStream(stream);
device->closeStream(stream);
SoapySDR::Device::unmake(device);
SDRDeviceInfo *dev = devs[new_device];
std::vector<SoapySDR::Kwargs> dev_results = SoapySDR::Device::enumerate(dev->getDeviceArgs());
device = SoapySDR::Device::make(dev_results[dev->getIndex()]);
device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load());
device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load());
device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm);
device->setGainMode(SOAPY_SDR_RX,0, true);
SoapySDR::Stream *stream = device->setupStream(SOAPY_SDR_RX,"CF32");
device->activateStream(stream);
}
if (offset_changed) {
if (!freq_changed) {
new_freq = frequency;
freq_changed = true;
}
offset.store(new_offset);
}
if (rate_changed) {
device->setSampleRate(SOAPY_SDR_RX,0,new_rate);
sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0));
}
if (freq_changed) {
frequency = new_freq;
device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency - offset.load());
}
if (ppm_changed) {
ppm = new_ppm;
device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm);
}
if (direct_sampling_changed) {
// rtlsdr_set_direct_sampling(dev, direct_sampling_mode);
}
}
int n_read = device->readStream(stream, buffs, BUF_SIZE/2, flags, timeNs, 99999999);
// std::cout << n_read << ", " << timeNs << std::endl;
SDRThreadIQData *dataOut = buffers.getBuffer();
dataOut->setRefCount(1);
dataOut->frequency = frequency;
dataOut->sampleRate = sampleRate.load();
dataOut->data.resize(n_read * 2);
memcpy(&dataOut->data[0],buffs[0],n_read * sizeof(float) * 2);
if (iqDataOutQueue != NULL) {
iqDataOutQueue->push(dataOut);
} else {
dataOut->setRefCount(0);
}
}
device->deactivateStream(stream);
device->closeStream(stream);
SoapySDR::Device::unmake(device);
/*
rtlsdr_open(&dev, deviceId);
rtlsdr_set_sample_rate(dev, sampleRate.load());
rtlsdr_set_center_freq(dev, frequency - offset.load());
rtlsdr_set_freq_correction(dev, ppm);
rtlsdr_set_agc_mode(dev, 1);
rtlsdr_set_offset_tuning(dev, 0);
rtlsdr_reset_buffer(dev);
// sampleRate = rtlsdr_get_sample_rate(dev);
std::cout << "Sample Rate is: " << sampleRate.load() << std::endl;
int n_read;
double seconds = 0.0;
std::cout << "SDR thread started.." << std::endl;
ReBuffer<SDRThreadIQData> buffers;
SDRThreadIQDataQueue* iqDataOutQueue = (SDRThreadIQDataQueue*) getOutputQueue("IQDataOutput");
SDRThreadCommandQueue* cmdQueue = (SDRThreadCommandQueue*) getInputQueue("SDRCommandQueue");
while (!terminated) {
if (!cmdQueue->empty()) {
bool freq_changed = false;
bool offset_changed = false;
bool rate_changed = false;
bool device_changed = false;
bool ppm_changed = false;
bool direct_sampling_changed = false;
long long new_freq = frequency;
long long new_offset = offset.load();
long long new_rate = sampleRate.load();
int new_device = deviceId;
int new_ppm = ppm;
while (!cmdQueue->empty()) {
SDRThreadCommand command;
cmdQueue->pop(command);
switch (command.cmd) {
case SDRThreadCommand::SDR_THREAD_CMD_TUNE:
freq_changed = true;
new_freq = command.llong_value;
if (new_freq < sampleRate.load() / 2) {
new_freq = sampleRate.load() / 2;
}
// std::cout << "Set frequency: " << new_freq << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_OFFSET:
offset_changed = true;
new_offset = command.llong_value;
std::cout << "Set offset: " << new_offset << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_SAMPLERATE:
rate_changed = true;
new_rate = command.llong_value;
if (new_rate <= 250000) {
buf_size = BUF_SIZE/4;
} else if (new_rate < 1500000) {
buf_size = BUF_SIZE/2;
} else {
buf_size = BUF_SIZE;
}
std::cout << "Set sample rate: " << new_rate << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_DEVICE:
device_changed = true;
new_device = (int) command.llong_value;
std::cout << "Set device: " << new_device << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_PPM:
ppm_changed = true;
new_ppm = (int) command.llong_value;
//std::cout << "Set PPM: " << new_ppm << std::endl;
break;
case SDRThreadCommand::SDR_THREAD_CMD_SET_DIRECT_SAMPLING:
direct_sampling_mode = (int)command.llong_value;
direct_sampling_changed = true;
break;
default:
break;
}
}
if (device_changed) {
rtlsdr_close(dev);
rtlsdr_open(&dev, new_device);
rtlsdr_set_sample_rate(dev, sampleRate.load());
rtlsdr_set_center_freq(dev, frequency - offset.load());
rtlsdr_set_freq_correction(dev, ppm);
rtlsdr_set_agc_mode(dev, 1);
rtlsdr_set_offset_tuning(dev, 0);
rtlsdr_set_direct_sampling(dev, direct_sampling_mode);
rtlsdr_reset_buffer(dev);
}
if (offset_changed) {
if (!freq_changed) {
new_freq = frequency;
freq_changed = true;
}
offset.store(new_offset);
}
if (rate_changed) {
rtlsdr_set_sample_rate(dev, new_rate);
rtlsdr_reset_buffer(dev);
sampleRate.store(rtlsdr_get_sample_rate(dev));
}
if (freq_changed) {
frequency = new_freq;
rtlsdr_set_center_freq(dev, frequency - offset.load());
}
if (ppm_changed) {
ppm = new_ppm;
rtlsdr_set_freq_correction(dev, ppm);
}
if (direct_sampling_changed) {
rtlsdr_set_direct_sampling(dev, direct_sampling_mode);
}
}
rtlsdr_read_sync(dev, buf, buf_size, &n_read);
SDRThreadIQData *dataOut = buffers.getBuffer();
// std::lock_guard < std::mutex > lock(dataOut->m_mutex);
dataOut->setRefCount(1);
dataOut->frequency = frequency;
dataOut->sampleRate = sampleRate.load();
if (dataOut->data.capacity() < n_read) {
dataOut->data.reserve(n_read);
}
if (dataOut->data.size() != n_read) {
dataOut->data.resize(n_read);
}
memcpy(&dataOut->data[0], buf, n_read);
double time_slice = (double) n_read / (double) sampleRate.load();
seconds += time_slice;
if (iqDataOutQueue != NULL) {
iqDataOutQueue->push(dataOut);
}
}
// buffers.purge();
*/
std::cout << "SDR thread done." << std::endl;
}
int SDRThread::getDeviceId() const {
return deviceId.load();
}
void SDRThread::setDeviceId(int deviceId) {
this->deviceId.store(deviceId);
}

73
src/sdr/SoapySDRThread.h Normal file
View File

@ -0,0 +1,73 @@
#pragma once
#include <atomic>
#include "ThreadQueue.h"
#include "DemodulatorMgr.h"
#include "SDRDeviceInfo.h"
class SDRThreadCommand {
public:
enum SDRThreadCommandEnum {
SDR_THREAD_CMD_NULL, SDR_THREAD_CMD_TUNE, SDR_THREAD_CMD_SET_OFFSET, SDR_THREAD_CMD_SET_SAMPLERATE, SDR_THREAD_CMD_SET_PPM, SDR_THREAD_CMD_SET_DEVICE, SDR_THREAD_CMD_SET_DIRECT_SAMPLING
};
SDRThreadCommand() :
cmd(SDR_THREAD_CMD_NULL), llong_value(0) {
}
SDRThreadCommand(SDRThreadCommandEnum cmd) :
cmd(cmd), llong_value(0) {
}
SDRThreadCommandEnum cmd;
long long llong_value;
};
class SDRThreadIQData: public ReferenceCounter {
public:
long long frequency;
long long sampleRate;
// std::vector<unsigned char> data;
std::vector<float> data;
SDRThreadIQData() :
frequency(0), sampleRate(DEFAULT_SAMPLE_RATE) {
}
SDRThreadIQData(long long bandwidth, long long frequency, std::vector<signed char> *data) :
frequency(frequency), sampleRate(bandwidth) {
}
~SDRThreadIQData() {
}
};
typedef ThreadQueue<SDRThreadCommand> SDRThreadCommandQueue;
typedef ThreadQueue<SDRThreadIQData *> SDRThreadIQDataQueue;
class SDRThread : public IOThread {
public:
SDRThread();
~SDRThread();
static std::vector<SDRDeviceInfo *> *enumerate_devices();
void run();
int getDeviceId() const;
void setDeviceId(int deviceId);
protected:
static std::vector<std::string> factories;
static std::vector<std::string> modules;
static std::vector<SDRDeviceInfo *> devs;
std::atomic<uint32_t> sampleRate;
std::atomic_llong offset;
std::atomic_int deviceId;
};