pax_global_header00006660000000000000000000000064131206072620014511gustar00rootroot0000000000000052 comment=3932325a3f8532f852cf335118684c18299657a8 SoapyRTLSDR-soapy-rtlsdr-0.2.4/000077500000000000000000000000001312060726200162035ustar00rootroot00000000000000SoapyRTLSDR-soapy-rtlsdr-0.2.4/.gitignore000066400000000000000000000000061312060726200201670ustar00rootroot00000000000000build SoapyRTLSDR-soapy-rtlsdr-0.2.4/.travis.yml000066400000000000000000000030501312060726200203120ustar00rootroot00000000000000######################################################################## ## Travis CI config for SoapyRTLSDR ## ## * installs rtl-sdr from PPA ## * installs SoapySDR from source ## * confirms build and install ## * checks that drivers load ######################################################################## sudo: required dist: trusty language: cpp compiler: gcc env: global: - INSTALL_PREFIX=/usr/local - SOAPY_SDR_BRANCH=master matrix: - BUILD_TYPE=Debug - BUILD_TYPE=Release before_install: # regular ubuntu packages - sudo add-apt-repository main - sudo add-apt-repository universe # driver development files from ppa - sudo add-apt-repository -y ppa:myriadrf/drivers # update after package changes - sudo apt-get update install: #sdr development files - sudo apt-get install --no-install-recommends -q -y librtlsdr-dev # install SoapySDR from source - git clone https://github.com/pothosware/SoapySDR.git - pushd SoapySDR - git checkout ${SOAPY_SDR_BRANCH} - mkdir build && cd build - cmake ../ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_PYTHON=OFF -DENABLE_PYTHON3=OFF - make && sudo make install - popd script: - mkdir build && cd build - cmake ../ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} - make && sudo make install # print info about the install - export LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${LD_LIBRARY_PATH} - export PATH=${INSTALL_PREFIX}/bin:${PATH} - SoapySDRUtil --info - SoapySDRUtil --check=rtlsdr SoapyRTLSDR-soapy-rtlsdr-0.2.4/CMakeLists.txt000066400000000000000000000033641312060726200207510ustar00rootroot00000000000000######################################################################## # Build Soapy SDR support module for RTL-SDR Devices ######################################################################## cmake_minimum_required(VERSION 2.8.7) project(SoapyRTLSDR CXX) find_package(SoapySDR "0.4.0" NO_MODULE REQUIRED) if (NOT SoapySDR_FOUND) message(FATAL_ERROR "Soapy SDR development files not found...") endif () list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) find_package(RTLSDR) if (NOT RTLSDR_FOUND) message(FATAL_ERROR "RTL-SDR development files not found...") endif () message(STATUS "RTLSDR_INCLUDE_DIRS - ${RTLSDR_INCLUDE_DIRS}") message(STATUS "RTLSDR_LIBRARIES - ${RTLSDR_LIBRARIES}") include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${RTLSDR_INCLUDE_DIRS}) #enable c++11 features if(CMAKE_COMPILER_IS_GNUCXX) #C++11 is a required language feature for this project include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_STD_CXX11) if(HAS_STD_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else(HAS_STD_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") endif() #Thread support enabled (not the same as -lpthread) list(APPEND RTLSDR_LIBRARIES -pthread) #disable warnings for unused parameters add_definitions(-Wno-unused-parameter) endif(CMAKE_COMPILER_IS_GNUCXX) if (APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wc++11-extensions") endif(APPLE) set(OTHER_LIBS "" CACHE STRING "Other libraries") SOAPY_SDR_MODULE_UTIL( TARGET rtlsdrSupport SOURCES SoapyRTLSDR.hpp Registation.cpp Settings.cpp Streaming.cpp LIBRARIES ${RTLSDR_LIBRARIES} ${OTHER_LIBS} ) SoapyRTLSDR-soapy-rtlsdr-0.2.4/Changelog.txt000066400000000000000000000017611312060726200206400ustar00rootroot00000000000000Release 0.2.4 (2017-06-15) ========================== - readStream - also drop remainder buffer on reset - Fixed configuration input for num async buffers Release 0.2.3 (2017-04-29) ========================== - Added support for frequency correction API - Separate buffer count for ring buffer and usb - Larger buffer size - same as rtl defaults - Use atomics for ring buffer implementation - Use Format string constants for stream types Release 0.2.2 (2016-09-01) ========================== - Update debian files for SoapySDR module ABI format - Fix build failure on all big endian architectures Release 0.2.1 (2016-04-25) ========================== - Fixes for E4000 and FC001x tuner types - Fixed debian control file Maintainer/Uploaders Release 0.2.0 (2015-12-10) ========================== - Added device info arguments and device settings - Added support for the direct access buffer API Release 0.1.0 (2015-10-10) ========================== - Initial release of Soapy RTL-SDR support module SoapyRTLSDR-soapy-rtlsdr-0.2.4/FindRTLSDR.cmake000066400000000000000000000043321312060726200210220ustar00rootroot00000000000000# # Copyright 2012-2013 The Iris Project Developers. See the # COPYRIGHT file at the top-level directory of this distribution # and at http://www.softwareradiosystems.com/iris/copyright.html. # # This file is part of the Iris Project. # # Iris is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of # the License, or (at your option) any later version. # # Iris is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # A copy of the GNU Lesser General Public License can be found in # the LICENSE file in the top-level directory of this distribution # and at http://www.gnu.org/licenses/. # # - Try to find rtlsdr - the hardware driver for the realtek chip in the dvb receivers # Once done this will define # RTLSDR_FOUND - System has rtlsdr # RTLSDR_LIBRARIES - The rtlsdr libraries # RTLSDR_INCLUDE_DIRS - The rtlsdr include directories # RTLSDR_LIB_DIRS - The rtlsdr library directories if(NOT RTLSDR_FOUND) find_package(PkgConfig) pkg_check_modules (RTLSDR_PKG librtlsdr) set(RTLSDR_DEFINITIONS ${PC_RTLSDR_CFLAGS_OTHER}) find_path(RTLSDR_INCLUDE_DIR NAMES rtl-sdr.h HINTS ${RTLSDR_PKG_INCLUDE_DIRS} $ENV{RTLSDR_DIR}/include PATHS /usr/local/include /usr/include /opt/include /opt/local/include) find_library(RTLSDR_LIBRARY NAMES rtlsdr HINTS ${RTLSDR_PKG_LIBRARY_DIRS} $ENV{RTLSDR_DIR}/include PATHS /usr/local/lib /usr/lib /opt/lib /opt/local/lib) set(RTLSDR_LIBRARIES ${RTLSDR_LIBRARY} ) set(RTLSDR_INCLUDE_DIRS ${RTLSDR_INCLUDE_DIR} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LibRTLSDR_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(rtlsdr DEFAULT_MSG RTLSDR_LIBRARY RTLSDR_INCLUDE_DIR) mark_as_advanced(RTLSDR_INCLUDE_DIR RTLSDR_LIBRARY) endif(NOT RTLSDR_FOUND) SoapyRTLSDR-soapy-rtlsdr-0.2.4/LICENSE.txt000066400000000000000000000020731312060726200200300ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Charles J. Cliffe 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 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.SoapyRTLSDR-soapy-rtlsdr-0.2.4/README.md000066400000000000000000000027401312060726200174650ustar00rootroot00000000000000# Soapy SDR module for RTL-SDR ## Build Status - Travis: [![Travis Build Status](https://travis-ci.org/pothosware/SoapyRTLSDR.svg?branch=master)](https://travis-ci.org/pothosware/SoapyRTLSDR) ## Dependencies * SoapySDR - https://github.com/pothosware/SoapySDR/wiki * librtl-sdr - http://sdr.osmocom.org/trac/wiki/rtl-sdr ## Documentation * https://github.com/pothosware/SoapyRTLSDR/wiki ## Licensing information The MIT License (MIT) Copyright (c) 2015 Charles J. Cliffe 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 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SoapyRTLSDR-soapy-rtlsdr-0.2.4/Registation.cpp000066400000000000000000000136621312060726200212070ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 Charles J. Cliffe * 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 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "SoapyRTLSDR.hpp" #include #include //malloc static std::vector findRTLSDR(const SoapySDR::Kwargs &args) { std::vector results; char manufact[256], product[256], serial[256]; int this_count = rtlsdr_get_device_count(); if (!SoapyRTLSDR::rtl_devices.size() || SoapyRTLSDR::rtl_count != this_count) { SoapyRTLSDR::rtl_count = this_count; if (SoapyRTLSDR::rtl_devices.size()) { SoapyRTLSDR::rtl_devices.erase(SoapyRTLSDR::rtl_devices.begin(), SoapyRTLSDR::rtl_devices.end()); } SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR Devices: %d", SoapyRTLSDR::rtl_count); for (int i = 0; i < SoapyRTLSDR::rtl_count; i++) { SoapySDR::Kwargs devInfo; std::string deviceName(rtlsdr_get_device_name(i)); std::string deviceManufacturer; std::string deviceProduct; std::string deviceTuner; std::string deviceSerial; bool deviceAvailable = false; SoapySDR_logf(SOAPY_SDR_DEBUG, "Device #%d: %s", i, deviceName.c_str()); if (rtlsdr_get_device_usb_strings(i, manufact, product, serial) == 0) { SoapySDR_logf(SOAPY_SDR_DEBUG, "\tManufacturer: %s, Product Name: %s, Serial: %s", manufact, product, serial); deviceSerial = serial; deviceProduct = product; deviceManufacturer = manufact; rtlsdr_dev_t *devTest; if (rtlsdr_open(&devTest, i) == 0) { deviceAvailable = true; if (!SoapyRTLSDR::gainMax) { int num_gains = rtlsdr_get_tuner_gains(devTest, NULL); int *gains = (int *) malloc(sizeof(int) * num_gains); num_gains = rtlsdr_get_tuner_gains(devTest, gains); int rangeMin = gains[0], rangeMax = gains[0]; for (int g = 0; g < num_gains; g++) { if (gains[g] < rangeMin) { rangeMin = gains[g]; } if (gains[g] > rangeMax) { rangeMax = gains[g]; } } free(gains); SoapyRTLSDR::gainMin = (double) rangeMin / 10.0; SoapyRTLSDR::gainMax = (double) rangeMax / 10.0; } deviceTuner = SoapyRTLSDR::rtlTunerToString(rtlsdr_get_tuner_type(devTest)); SoapySDR_logf(SOAPY_SDR_DEBUG, "\t Tuner type: %s", deviceTuner.c_str()); rtlsdr_close(devTest); } } if (!deviceAvailable) { SoapySDR_logf(SOAPY_SDR_DEBUG, "\tUnable to access device #%d (in use?)", i); } std::string deviceLabel = std::string(rtlsdr_get_device_name(i)) + " :: " + deviceSerial; devInfo["rtl"] = std::to_string(i); devInfo["label"] = deviceLabel; devInfo["available"] = deviceAvailable ? "Yes" : "No"; devInfo["product"] = deviceProduct; devInfo["serial"] = deviceSerial; devInfo["manufacturer"] = deviceManufacturer; devInfo["tuner"] = deviceTuner; SoapyRTLSDR::rtl_devices.push_back(devInfo); } } //filtering for (int i = 0; i < SoapyRTLSDR::rtl_count; i++) { SoapySDR::Kwargs devInfo = SoapyRTLSDR::rtl_devices[i]; if (args.count("rtl") != 0) { if (args.at("rtl") != devInfo.at("rtl")) { continue; } SoapySDR_logf(SOAPY_SDR_DEBUG, "Found device by index %s", devInfo.at("rtl").c_str()); } else if (args.count("serial") != 0) { if (devInfo.at("serial") != args.at("serial")) { continue; } SoapySDR_logf(SOAPY_SDR_DEBUG, "Found device by serial %s", args.at("serial").c_str()); } else if (args.count("label") != 0) { if (devInfo.at("label") != args.at("label")) { continue; } SoapySDR_logf(SOAPY_SDR_DEBUG, "Found device by label %s", args.at("label").c_str()); } results.push_back(SoapyRTLSDR::rtl_devices[i]); } return results; } static SoapySDR::Device *makeRTLSDR(const SoapySDR::Kwargs &args) { return new SoapyRTLSDR(args); } static SoapySDR::Registry registerRTLSDR("rtlsdr", &findRTLSDR, &makeRTLSDR, SOAPY_SDR_ABI_VERSION); SoapyRTLSDR-soapy-rtlsdr-0.2.4/Settings.cpp000066400000000000000000000467001312060726200205160ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 Charles J. Cliffe * 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 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "SoapyRTLSDR.hpp" int SoapyRTLSDR::rtl_count; std::vector SoapyRTLSDR::rtl_devices; double SoapyRTLSDR::gainMin; double SoapyRTLSDR::gainMax; SoapyRTLSDR::SoapyRTLSDR(const SoapySDR::Kwargs &args) { if (!SoapyRTLSDR::rtl_count) { throw std::runtime_error("RTL-SDR device not found."); } deviceId = -1; dev = NULL; rxFormat = RTL_RX_FORMAT_FLOAT32; tunerType = RTLSDR_TUNER_R820T; sampleRate = 2048000; centerFrequency = 100000000; ppm = 0; directSamplingMode = 0; numBuffers = DEFAULT_NUM_BUFFERS; bufferLength = DEFAULT_BUFFER_LENGTH; iqSwap = false; agcMode = false; offsetMode = false; bufferedElems = 0; resetBuffer = false; if (args.count("rtl") != 0) { try { deviceId = std::stoi(args.at("rtl")); } catch (const std::invalid_argument &) { } if (deviceId < 0 || deviceId >= SoapyRTLSDR::rtl_count) { throw std::runtime_error( "device index 'rtl' out of range [0 .. " + std::to_string(SoapyRTLSDR::rtl_count) + "]."); } SoapySDR_logf(SOAPY_SDR_DEBUG, "Found RTL-SDR Device using device index parameter 'rtl' = %d", deviceId); } else if (args.count("serial") != 0) { std::string deviceSerialFind = args.at("serial"); for (int i = 0; i < SoapyRTLSDR::rtl_count; i++) { SoapySDR::Kwargs devInfo = SoapyRTLSDR::rtl_devices[i]; if (devInfo.at("serial") == deviceSerialFind) { SoapySDR_logf(SOAPY_SDR_DEBUG, "Found RTL-SDR Device #%d by serial %s -- Manufacturer: %s, Product Name: %s, Serial: %s", i, deviceSerialFind.c_str(), devInfo.at("manufacturer").c_str(), devInfo.at("product").c_str(), devInfo.at("serial").c_str()); deviceId = i; break; } } } else if (args.count("label") != 0) { std::string labelFind = args.at("label"); for (int i = 0; i < SoapyRTLSDR::rtl_count; i++) { SoapySDR::Kwargs devInfo = SoapyRTLSDR::rtl_devices[i]; if (devInfo.at("label") == labelFind) { SoapySDR_logf(SOAPY_SDR_DEBUG, "Found RTL-SDR Device #%d by name: %s", devInfo.at("label").c_str()); deviceId = i; break; } } } if (deviceId == -1) { throw std::runtime_error("Unable to find requested RTL-SDR device."); } if (args.count("tuner") != 0) { tunerType = rtlStringToTuner(args.at("tuner")); } SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR Tuner type: %s", rtlTunerToString(tunerType).c_str()); SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR opening device %d", deviceId); rtlsdr_open(&dev, deviceId); } SoapyRTLSDR::~SoapyRTLSDR(void) { //cleanup device handles rtlsdr_close(dev); } /******************************************************************* * Identification API ******************************************************************/ std::string SoapyRTLSDR::getDriverKey(void) const { return "RTLSDR"; } std::string SoapyRTLSDR::getHardwareKey(void) const { return "RTLSDR"; } SoapySDR::Kwargs SoapyRTLSDR::getHardwareInfo(void) const { //key/value pairs for any useful information //this also gets printed in --probe SoapySDR::Kwargs args; args["origin"] = "https://github.com/pothosware/SoapyRTLSDR"; args["rtl"] = std::to_string(deviceId); return args; } /******************************************************************* * Channels API ******************************************************************/ size_t SoapyRTLSDR::getNumChannels(const int dir) const { return (dir == SOAPY_SDR_RX) ? 1 : 0; } /******************************************************************* * Antenna API ******************************************************************/ std::vector SoapyRTLSDR::listAntennas(const int direction, const size_t channel) const { std::vector antennas; antennas.push_back("RX"); return antennas; } void SoapyRTLSDR::setAntenna(const int direction, const size_t channel, const std::string &name) { if (direction != SOAPY_SDR_RX) { throw std::runtime_error("setAntena failed: RTL-SDR only supports RX"); } } std::string SoapyRTLSDR::getAntenna(const int direction, const size_t channel) const { return "RX"; } /******************************************************************* * Frontend corrections API ******************************************************************/ bool SoapyRTLSDR::hasDCOffsetMode(const int direction, const size_t channel) const { return false; } bool SoapyRTLSDR::hasFrequencyCorrection(const int direction, const size_t channel) const { return true; } void SoapyRTLSDR::setFrequencyCorrection(const int direction, const size_t channel, const double value) { ppm = int(value); rtlsdr_set_freq_correction(dev, ppm); } double SoapyRTLSDR::getFrequencyCorrection(const int direction, const size_t channel) const { return double(ppm); } /******************************************************************* * Gain API ******************************************************************/ std::vector SoapyRTLSDR::listGains(const int direction, const size_t channel) const { //list available gain elements, //the functions below have a "name" parameter std::vector results; if (tunerType == RTLSDR_TUNER_E4000) { results.push_back("IF1"); results.push_back("IF2"); results.push_back("IF3"); results.push_back("IF4"); results.push_back("IF5"); results.push_back("IF6"); } results.push_back("TUNER"); return results; } bool SoapyRTLSDR::hasGainMode(const int direction, const size_t channel) const { return true; } void SoapyRTLSDR::setGainMode(const int direction, const size_t channel, const bool automatic) { agcMode = automatic; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting RTL-SDR AGC: %s", automatic ? "Automatic" : "Manual"); rtlsdr_set_agc_mode(dev, agcMode ? 1 : 0); } bool SoapyRTLSDR::getGainMode(const int direction, const size_t channel) const { return SoapySDR::Device::getGainMode(direction, channel); } void SoapyRTLSDR::setGain(const int direction, const size_t channel, const double value) { //set the overall gain by distributing it across available gain elements //OR delete this function to use SoapySDR's default gain distribution algorithm... SoapySDR::Device::setGain(direction, channel, value); } void SoapyRTLSDR::setGain(const int direction, const size_t channel, const std::string &name, const double value) { if ((name.length() >= 2) && (name.substr(0, 2) == "IF")) { int stage = 1; if (name.length() > 2) { int stage_in = name.at(2) - '0'; if ((stage_in < 1) || (stage_in > 6)) { throw std::runtime_error("Invalid IF stage, 1 or 1-6 for E4000"); } } if (tunerType == RTLSDR_TUNER_E4000) { IFGain[stage - 1] = getE4000Gain(stage, (int)value); } else { IFGain[stage - 1] = value; } SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting RTL-SDR IF Gain for stage %d: %f", stage, IFGain[stage - 1]); rtlsdr_set_tuner_if_gain(dev, stage, (int) IFGain[stage - 1] * 10.0); } if (name == "TUNER") { tunerGain = value; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting RTL-SDR Tuner Gain: %f", tunerGain); rtlsdr_set_tuner_gain(dev, (int) tunerGain * 10.0); } } double SoapyRTLSDR::getGain(const int direction, const size_t channel, const std::string &name) const { if ((name.length() >= 2) && (name.substr(0, 2) == "IF")) { int stage = 1; if (name.length() > 2) { int stage_in = name.at(2) - '0'; if ((stage_in < 1) || (stage_in > 6)) { throw std::runtime_error("Invalid IF stage, 1 or 1-6 for E4000"); } else { stage = stage_in; } } if (tunerType == RTLSDR_TUNER_E4000) { return getE4000Gain(stage, IFGain[stage - 1]); } return IFGain[stage - 1]; } if (name == "TUNER") { return tunerGain; } return 0; } SoapySDR::Range SoapyRTLSDR::getGainRange(const int direction, const size_t channel, const std::string &name) const { if (tunerType == RTLSDR_TUNER_E4000 && name != "TUNER") { if (name == "IF1") { return SoapySDR::Range(-3, 6); } if (name == "IF2" || name == "IF3") { return SoapySDR::Range(0, 9); } if (name == "IF4") { return SoapySDR::Range(0, 2); } if (name == "IF5" || name == "IF6") { return SoapySDR::Range(3, 15); } return SoapySDR::Range(SoapyRTLSDR::gainMin, SoapyRTLSDR::gainMax); } else { return SoapySDR::Range(SoapyRTLSDR::gainMin, SoapyRTLSDR::gainMax); } } /******************************************************************* * Frequency API ******************************************************************/ void SoapyRTLSDR::setFrequency( const int direction, const size_t channel, const std::string &name, const double frequency, const SoapySDR::Kwargs &args) { if (name == "RF") { centerFrequency = (uint32_t) frequency; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting center freq: %d", centerFrequency); rtlsdr_set_center_freq(dev, centerFrequency); } if (name == "CORR") { ppm = (int) frequency; rtlsdr_set_freq_correction(dev, ppm); } } double SoapyRTLSDR::getFrequency(const int direction, const size_t channel, const std::string &name) const { if (name == "RF") { return (double) centerFrequency; } if (name == "CORR") { return (double) ppm; } return 0; } std::vector SoapyRTLSDR::listFrequencies(const int direction, const size_t channel) const { std::vector names; names.push_back("RF"); names.push_back("CORR"); return names; } SoapySDR::RangeList SoapyRTLSDR::getFrequencyRange( const int direction, const size_t channel, const std::string &name) const { SoapySDR::RangeList results; if (name == "RF") { if (tunerType == RTLSDR_TUNER_E4000) { results.push_back(SoapySDR::Range(52000000, 2200000000)); } else if (tunerType == RTLSDR_TUNER_FC0012) { results.push_back(SoapySDR::Range(22000000, 1100000000)); } else if (tunerType == RTLSDR_TUNER_FC0013) { results.push_back(SoapySDR::Range(22000000, 948600000)); } else { results.push_back(SoapySDR::Range(24000000, 1764000000)); } } if (name == "CORR") { results.push_back(SoapySDR::Range(-1000, 1000)); } return results; } SoapySDR::ArgInfoList SoapyRTLSDR::getFrequencyArgsInfo(const int direction, const size_t channel) const { SoapySDR::ArgInfoList freqArgs; // TODO: frequency arguments return freqArgs; } /******************************************************************* * Sample Rate API ******************************************************************/ void SoapyRTLSDR::setSampleRate(const int direction, const size_t channel, const double rate) { sampleRate = rate; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting sample rate: %d", sampleRate); rtlsdr_set_sample_rate(dev, sampleRate); } double SoapyRTLSDR::getSampleRate(const int direction, const size_t channel) const { return sampleRate; } std::vector SoapyRTLSDR::listSampleRates(const int direction, const size_t channel) const { std::vector results; results.push_back(250000); results.push_back(1024000); results.push_back(1536000); results.push_back(1792000); results.push_back(1920000); results.push_back(2048000); results.push_back(2160000); results.push_back(2560000); results.push_back(2880000); results.push_back(3200000); return results; } void SoapyRTLSDR::setBandwidth(const int direction, const size_t channel, const double bw) { SoapySDR::Device::setBandwidth(direction, channel, bw); } double SoapyRTLSDR::getBandwidth(const int direction, const size_t channel) const { return SoapySDR::Device::getBandwidth(direction, channel); } std::vector SoapyRTLSDR::listBandwidths(const int direction, const size_t channel) const { std::vector results; return results; } /******************************************************************* * Settings API ******************************************************************/ SoapySDR::ArgInfoList SoapyRTLSDR::getSettingInfo(void) const { SoapySDR::ArgInfoList setArgs; SoapySDR::ArgInfo directSampArg; directSampArg.key = "direct_samp"; directSampArg.value = "0"; directSampArg.name = "Direct Sampling"; directSampArg.description = "RTL-SDR Direct Sampling Mode"; directSampArg.type = SoapySDR::ArgInfo::STRING; directSampArg.options.push_back("0"); directSampArg.optionNames.push_back("Off"); directSampArg.options.push_back("1"); directSampArg.optionNames.push_back("I-ADC"); directSampArg.options.push_back("2"); directSampArg.optionNames.push_back("Q-ADC"); setArgs.push_back(directSampArg); SoapySDR::ArgInfo offsetTuneArg; offsetTuneArg.key = "offset_tune"; offsetTuneArg.value = "false"; offsetTuneArg.name = "Offset Tune"; offsetTuneArg.description = "RTL-SDR Offset Tuning Mode"; offsetTuneArg.type = SoapySDR::ArgInfo::BOOL; setArgs.push_back(offsetTuneArg); SoapySDR::ArgInfo iqSwapArg; iqSwapArg.key = "iq_swap"; iqSwapArg.value = "false"; iqSwapArg.name = "I/Q Swap"; iqSwapArg.description = "RTL-SDR I/Q Swap Mode"; iqSwapArg.type = SoapySDR::ArgInfo::BOOL; setArgs.push_back(iqSwapArg); SoapySDR_logf(SOAPY_SDR_DEBUG, "SETARGS?"); return setArgs; } void SoapyRTLSDR::writeSetting(const std::string &key, const std::string &value) { if (key == "direct_samp") { try { directSamplingMode = std::stoi(value); } catch (const std::invalid_argument &) { SoapySDR_logf(SOAPY_SDR_ERROR, "RTL-SDR invalid direct sampling mode '%s', [0:Off, 1:I-ADC, 2:Q-ADC]", value.c_str()); directSamplingMode = 0; } SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR direct sampling mode: %d", directSamplingMode); rtlsdr_set_direct_sampling(dev, directSamplingMode); } else if (key == "iq_swap") { iqSwap = ((value=="true") ? true : false); SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR I/Q swap: %s", iqSwap ? "true" : "false"); } else if (key == "offset_tune") { offsetMode = (value == "true") ? true : false; SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR offset_tune mode: %s", offsetMode ? "true" : "false"); rtlsdr_set_offset_tuning(dev, offsetMode ? 1 : 0); } } std::string SoapyRTLSDR::readSetting(const std::string &key) const { if (key == "direct_samp") { return std::to_string(directSamplingMode); } else if (key == "iq_swap") { return iqSwap?"true":"false"; } else if (key == "offset_tune") { return offsetMode?"true":"false"; } SoapySDR_logf(SOAPY_SDR_WARNING, "Unknown setting '%s'", key.c_str()); return ""; } std::string SoapyRTLSDR::rtlTunerToString(rtlsdr_tuner tunerType) { std::string deviceTuner; switch (tunerType) { case RTLSDR_TUNER_UNKNOWN: deviceTuner = "Unknown"; break; case RTLSDR_TUNER_E4000: deviceTuner = "Elonics E4000"; break; case RTLSDR_TUNER_FC0012: deviceTuner = "Fitipower FC0012"; break; case RTLSDR_TUNER_FC0013: deviceTuner = "Fitipower FC0013"; break; case RTLSDR_TUNER_FC2580: deviceTuner = "Fitipower FC2580"; break; case RTLSDR_TUNER_R820T: deviceTuner = "Rafael Micro R820T"; break; case RTLSDR_TUNER_R828D: deviceTuner = "Rafael Micro R828D"; break; default: deviceTuner = "Unknown"; } return deviceTuner; } int SoapyRTLSDR::getE4000Gain(int stage, int gain) { static const int8_t if_stage1_gain[] = { -3, 6 }; static const int8_t if_stage23_gain[] = { 0, 3, 6, 9 }; static const int8_t if_stage4_gain[] = { 0, 1, 2 //, 2 }; static const int8_t if_stage56_gain[] = { 3, 6, 9, 12, 15 // , 15, 15, 15 // wat? }; const int8_t *if_stage = nullptr; int n_gains = 0; if (stage == 1) { if_stage = if_stage1_gain; n_gains = 2; } else if (stage == 2 || stage == 3) { if_stage = if_stage23_gain; n_gains = 4; } else if (stage == 4) { if_stage = if_stage4_gain; n_gains = 3; } else if (stage == 5 || stage == 6) { if_stage = if_stage56_gain; n_gains = 5; } if (n_gains && if_stage) { int gainMin = if_stage[0]; int gainMax = if_stage[n_gains-1]; if (gain > gainMax) { gain = gainMax; } if (gain < gainMin) { gain = gainMin; } for (int i = 0; i < n_gains-1; i++) { if (gain >= if_stage[i] && gain <= if_stage[i+1]) { gain = ((gain-if_stage[i]) < (if_stage[i+1]-gain))?if_stage[i]:if_stage[i+1]; } } } return gain; } rtlsdr_tuner SoapyRTLSDR::rtlStringToTuner(std::string tunerType) { rtlsdr_tuner deviceTuner = RTLSDR_TUNER_UNKNOWN; deviceTuner = RTLSDR_TUNER_UNKNOWN; if (tunerType == "Elonics E4000") deviceTuner = RTLSDR_TUNER_E4000; if (tunerType == "Fitipower FC0012") deviceTuner = RTLSDR_TUNER_FC0012; if (tunerType == "Fitipower FC0013") deviceTuner = RTLSDR_TUNER_FC0013; if (tunerType == "Fitipower FC2580") deviceTuner = RTLSDR_TUNER_FC2580; if (tunerType == "Rafael Micro R820T") deviceTuner = RTLSDR_TUNER_R820T; if (tunerType == "Rafael Micro R828D") deviceTuner = RTLSDR_TUNER_R828D; return deviceTuner; } SoapyRTLSDR-soapy-rtlsdr-0.2.4/SoapyRTLSDR.hpp000066400000000000000000000222601312060726200207440ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 Charles J. Cliffe * 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 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #pragma once #include #include #include #include #include #include #include #include #include typedef enum rtlsdrRXFormat { RTL_RX_FORMAT_FLOAT32, RTL_RX_FORMAT_INT16, RTL_RX_FORMAT_INT8 } rtlsdrRXFormat; #define DEFAULT_BUFFER_LENGTH (16 * 32 * 512) #define DEFAULT_NUM_BUFFERS 15 #define BYTES_PER_SAMPLE 2 class SoapyRTLSDR: public SoapySDR::Device { public: SoapyRTLSDR(const SoapySDR::Kwargs &args); ~SoapyRTLSDR(void); /******************************************************************* * Identification API ******************************************************************/ std::string getDriverKey(void) const; std::string getHardwareKey(void) const; SoapySDR::Kwargs getHardwareInfo(void) const; /******************************************************************* * Channels API ******************************************************************/ size_t getNumChannels(const int) const; /******************************************************************* * Stream API ******************************************************************/ std::vector getStreamFormats(const int direction, const size_t channel) const; std::string getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const; SoapySDR::ArgInfoList getStreamArgsInfo(const int direction, const size_t channel) const; SoapySDR::Stream *setupStream(const int direction, const std::string &format, const std::vector &channels = std::vector(), const SoapySDR::Kwargs &args = SoapySDR::Kwargs()); void closeStream(SoapySDR::Stream *stream); size_t getStreamMTU(SoapySDR::Stream *stream) const; int activateStream( SoapySDR::Stream *stream, const int flags = 0, const long long timeNs = 0, const size_t numElems = 0); int deactivateStream(SoapySDR::Stream *stream, const int flags = 0, const long long timeNs = 0); int readStream( SoapySDR::Stream *stream, void * const *buffs, const size_t numElems, int &flags, long long &timeNs, const long timeoutUs = 100000); /******************************************************************* * Direct buffer access API ******************************************************************/ size_t getNumDirectAccessBuffers(SoapySDR::Stream *stream); int getDirectAccessBufferAddrs(SoapySDR::Stream *stream, const size_t handle, void **buffs); int acquireReadBuffer( SoapySDR::Stream *stream, size_t &handle, const void **buffs, int &flags, long long &timeNs, const long timeoutUs = 100000); void releaseReadBuffer( SoapySDR::Stream *stream, const size_t handle); /******************************************************************* * Antenna API ******************************************************************/ std::vector listAntennas(const int direction, const size_t channel) const; void setAntenna(const int direction, const size_t channel, const std::string &name); std::string getAntenna(const int direction, const size_t channel) const; /******************************************************************* * Frontend corrections API ******************************************************************/ bool hasDCOffsetMode(const int direction, const size_t channel) const; bool hasFrequencyCorrection(const int direction, const size_t channel) const; void setFrequencyCorrection(const int direction, const size_t channel, const double value); double getFrequencyCorrection(const int direction, const size_t channel) const; /******************************************************************* * Gain API ******************************************************************/ std::vector listGains(const int direction, const size_t channel) const; bool hasGainMode(const int direction, const size_t channel) const; void setGainMode(const int direction, const size_t channel, const bool automatic); bool getGainMode(const int direction, const size_t channel) const; void setGain(const int direction, const size_t channel, const double value); void setGain(const int direction, const size_t channel, const std::string &name, const double value); double getGain(const int direction, const size_t channel, const std::string &name) const; SoapySDR::Range getGainRange(const int direction, const size_t channel, const std::string &name) const; /******************************************************************* * Frequency API ******************************************************************/ void setFrequency( const int direction, const size_t channel, const std::string &name, const double frequency, const SoapySDR::Kwargs &args = SoapySDR::Kwargs()); double getFrequency(const int direction, const size_t channel, const std::string &name) const; std::vector listFrequencies(const int direction, const size_t channel) const; SoapySDR::RangeList getFrequencyRange(const int direction, const size_t channel, const std::string &name) const; SoapySDR::ArgInfoList getFrequencyArgsInfo(const int direction, const size_t channel) const; /******************************************************************* * Sample Rate API ******************************************************************/ void setSampleRate(const int direction, const size_t channel, const double rate); double getSampleRate(const int direction, const size_t channel) const; std::vector listSampleRates(const int direction, const size_t channel) const; void setBandwidth(const int direction, const size_t channel, const double bw); double getBandwidth(const int direction, const size_t channel) const; std::vector listBandwidths(const int direction, const size_t channel) const; /******************************************************************* * Utility ******************************************************************/ static std::string rtlTunerToString(rtlsdr_tuner tunerType); static rtlsdr_tuner rtlStringToTuner(std::string tunerType); static int getE4000Gain(int stage, int gain); /******************************************************************* * Settings API ******************************************************************/ SoapySDR::ArgInfoList getSettingInfo(void) const; void writeSetting(const std::string &key, const std::string &value); std::string readSetting(const std::string &key) const; private: //device handle int deviceId; rtlsdr_dev_t *dev; //cached settings rtlsdrRXFormat rxFormat; rtlsdr_tuner tunerType; uint32_t sampleRate, centerFrequency; int ppm, directSamplingMode; size_t numBuffers, bufferLength, asyncBuffs; bool iqSwap, agcMode, offsetMode; double IFGain[6], tunerGain; std::vector > _lut_32f; std::vector > _lut_swap_32f; std::vector > _lut_16i; std::vector > _lut_swap_16i; public: //async api usage std::thread _rx_async_thread; void rx_async_operation(void); void rx_callback(unsigned char *buf, uint32_t len); std::mutex _buf_mutex; std::condition_variable _buf_cond; std::vector > _buffs; size_t _buf_head; size_t _buf_tail; std::atomic _buf_count; signed char *_currentBuff; std::atomic _overflowEvent; size_t _currentHandle; size_t bufferedElems; std::atomic resetBuffer; static int rtl_count; static std::vector rtl_devices; static double gainMin, gainMax; }; SoapyRTLSDR-soapy-rtlsdr-0.2.4/Streaming.cpp000066400000000000000000000352501312060726200206450ustar00rootroot00000000000000/* * The MIT License (MIT) * * Copyright (c) 2015 Charles J. Cliffe * 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 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "SoapyRTLSDR.hpp" #include #include #include //min #include //SHRT_MAX #include // memcpy std::vector SoapyRTLSDR::getStreamFormats(const int direction, const size_t channel) const { std::vector formats; formats.push_back(SOAPY_SDR_CS8); formats.push_back(SOAPY_SDR_CS16); formats.push_back(SOAPY_SDR_CF32); return formats; } std::string SoapyRTLSDR::getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const { //check that direction is SOAPY_SDR_RX if (direction != SOAPY_SDR_RX) { throw std::runtime_error("RTL-SDR is RX only, use SOAPY_SDR_RX"); } fullScale = 128; return SOAPY_SDR_CS8; } SoapySDR::ArgInfoList SoapyRTLSDR::getStreamArgsInfo(const int direction, const size_t channel) const { //check that direction is SOAPY_SDR_RX if (direction != SOAPY_SDR_RX) { throw std::runtime_error("RTL-SDR is RX only, use SOAPY_SDR_RX"); } SoapySDR::ArgInfoList streamArgs; SoapySDR::ArgInfo bufflenArg; bufflenArg.key = "bufflen"; bufflenArg.value = std::to_string(DEFAULT_BUFFER_LENGTH); bufflenArg.name = "Buffer Size"; bufflenArg.description = "Number of bytes per buffer, multiples of 512 only."; bufflenArg.units = "bytes"; bufflenArg.type = SoapySDR::ArgInfo::INT; streamArgs.push_back(bufflenArg); SoapySDR::ArgInfo buffersArg; buffersArg.key = "buffers"; buffersArg.value = std::to_string(DEFAULT_NUM_BUFFERS); buffersArg.name = "Ring buffers"; buffersArg.description = "Number of buffers in the ring."; buffersArg.units = "buffers"; buffersArg.type = SoapySDR::ArgInfo::INT; streamArgs.push_back(buffersArg); SoapySDR::ArgInfo asyncbuffsArg; asyncbuffsArg.key = "asyncBuffs"; asyncbuffsArg.value = "0"; asyncbuffsArg.name = "Async buffers"; asyncbuffsArg.description = "Number of async usb buffers (advanced)."; asyncbuffsArg.units = "buffers"; asyncbuffsArg.type = SoapySDR::ArgInfo::INT; streamArgs.push_back(asyncbuffsArg); return streamArgs; } /******************************************************************* * Async thread work ******************************************************************/ static void _rx_callback(unsigned char *buf, uint32_t len, void *ctx) { //printf("_rx_callback\n"); SoapyRTLSDR *self = (SoapyRTLSDR *)ctx; self->rx_callback(buf, len); } void SoapyRTLSDR::rx_async_operation(void) { //printf("rx_async_operation\n"); rtlsdr_read_async(dev, &_rx_callback, this, asyncBuffs, bufferLength); //printf("rx_async_operation done!\n"); } void SoapyRTLSDR::rx_callback(unsigned char *buf, uint32_t len) { //printf("_rx_callback %d _buf_head=%d, numBuffers=%d\n", len, _buf_head, _buf_tail); //overflow condition: the caller is not reading fast enough if (_buf_count == numBuffers) { _overflowEvent = true; return; } //copy into the buffer queue auto &buff = _buffs[_buf_tail]; buff.resize(len); std::memcpy(buff.data(), buf, len); //increment the tail pointer _buf_tail = (_buf_tail + 1) % numBuffers; //increment buffers available under lock //to avoid race in acquireReadBuffer wait { std::lock_guard lock(_buf_mutex); _buf_count++; } //notify readStream() _buf_cond.notify_one(); } /******************************************************************* * Stream API ******************************************************************/ SoapySDR::Stream *SoapyRTLSDR::setupStream( const int direction, const std::string &format, const std::vector &channels, const SoapySDR::Kwargs &args) { if (direction != SOAPY_SDR_RX) { throw std::runtime_error("RTL-SDR is RX only, use SOAPY_SDR_RX"); } //check the channel configuration if (channels.size() > 1 or (channels.size() > 0 and channels.at(0) != 0)) { throw std::runtime_error("setupStream invalid channel selection"); } //check the format if (format == SOAPY_SDR_CF32) { SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32."); rxFormat = RTL_RX_FORMAT_FLOAT32; } else if (format == SOAPY_SDR_CS16) { SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16."); rxFormat = RTL_RX_FORMAT_INT16; } else if (format == SOAPY_SDR_CS8) { SoapySDR_log(SOAPY_SDR_INFO, "Using format CS8."); rxFormat = RTL_RX_FORMAT_INT8; } else { throw std::runtime_error( "setupStream invalid format '" + format + "' -- Only CS8, CS16 and CF32 are supported by SoapyRTLSDR module."); } if (rxFormat != RTL_RX_FORMAT_INT8 && !_lut_32f.size()) { SoapySDR_logf(SOAPY_SDR_DEBUG, "Generating RTL-SDR lookup tables"); // create lookup tables for (unsigned int i = 0; i <= 0xffff; i++) { # if (__BYTE_ORDER == __LITTLE_ENDIAN) float re = ((i & 0xff) - 127.4f) * (1.0f / 128.0f); float im = ((i >> 8) - 127.4f) * (1.0f / 128.0f); #else float re = ((i >> 8) - 127.4f) * (1.0f / 128.0f); float im = ((i & 0xff) - 127.4f) * (1.0f / 128.0f); #endif std::complex v32f, vs32f; v32f.real(re); v32f.imag(im); _lut_32f.push_back(v32f); vs32f.real(v32f.imag()); vs32f.imag(v32f.real()); _lut_swap_32f.push_back(vs32f); std::complex v16i, vs16i; v16i.real(int16_t((float(SHRT_MAX) * re))); v16i.imag(int16_t((float(SHRT_MAX) * im))); _lut_16i.push_back(v16i); vs16i.real(vs16i.imag()); vs16i.imag(vs16i.real()); _lut_swap_16i.push_back(vs16i); } } bufferLength = DEFAULT_BUFFER_LENGTH; if (args.count("bufflen") != 0) { try { int bufferLength_in = std::stoi(args.at("bufflen")); if (bufferLength_in > 0) { bufferLength = bufferLength_in; } } catch (const std::invalid_argument &){} } SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR Using buffer length %d", bufferLength); numBuffers = DEFAULT_NUM_BUFFERS; if (args.count("buffers") != 0) { try { int numBuffers_in = std::stoi(args.at("buffers")); if (numBuffers_in > 0) { numBuffers = numBuffers_in; } } catch (const std::invalid_argument &){} } SoapySDR_logf(SOAPY_SDR_DEBUG, "RTL-SDR Using %d buffers", numBuffers); asyncBuffs = 0; if (args.count("asyncBuffs") != 0) { try { int asyncBuffs_in = std::stoi(args.at("asyncBuffs")); if (asyncBuffs_in > 0) { asyncBuffs = asyncBuffs_in; } } catch (const std::invalid_argument &){} } if (tunerType == RTLSDR_TUNER_E4000) { IFGain[0] = 6; IFGain[1] = 9; IFGain[2] = 3; IFGain[3] = 2; IFGain[4] = 3; IFGain[5] = 3; } else { for (int i = 0; i < 6; i++) { IFGain[i] = 0; } } tunerGain = rtlsdr_get_tuner_gain(dev); //clear async fifo counts _buf_tail = 0; _buf_count = 0; _buf_head = 0; //allocate buffers _buffs.resize(numBuffers); for (auto &buff : _buffs) buff.reserve(bufferLength); for (auto &buff : _buffs) buff.resize(bufferLength); return (SoapySDR::Stream *) this; } void SoapyRTLSDR::closeStream(SoapySDR::Stream *stream) { _buffs.clear(); } size_t SoapyRTLSDR::getStreamMTU(SoapySDR::Stream *stream) const { return bufferLength / BYTES_PER_SAMPLE; } int SoapyRTLSDR::activateStream( SoapySDR::Stream *stream, const int flags, const long long timeNs, const size_t numElems) { if (flags != 0) return SOAPY_SDR_NOT_SUPPORTED; resetBuffer = true; bufferedElems = 0; //start the async thread if (not _rx_async_thread.joinable()) { rtlsdr_reset_buffer(dev); _rx_async_thread = std::thread(&SoapyRTLSDR::rx_async_operation, this); } return 0; } int SoapyRTLSDR::deactivateStream(SoapySDR::Stream *stream, const int flags, const long long timeNs) { if (flags != 0) return SOAPY_SDR_NOT_SUPPORTED; if (_rx_async_thread.joinable()) { rtlsdr_cancel_async(dev); _rx_async_thread.join(); } return 0; } int SoapyRTLSDR::readStream( SoapySDR::Stream *stream, void * const *buffs, const size_t numElems, int &flags, long long &timeNs, const long timeoutUs) { //drop remainder buffer on reset if (resetBuffer and bufferedElems != 0) { bufferedElems = 0; this->releaseReadBuffer(stream, _currentHandle); } //this is the user's buffer for channel 0 void *buff0 = buffs[0]; //are elements left in the buffer? if not, do a new read. if (bufferedElems == 0) { int ret = this->acquireReadBuffer(stream, _currentHandle, (const void **)&_currentBuff, flags, timeNs, timeoutUs); if (ret < 0) return ret; bufferedElems = ret; } size_t returnedElems = std::min(bufferedElems, numElems); //convert into user's buff0 if (rxFormat == RTL_RX_FORMAT_FLOAT32) { float *ftarget = (float *) buff0; std::complex tmp; if (iqSwap) { for (size_t i = 0; i < returnedElems; i++) { tmp = _lut_swap_32f[*((uint16_t*) &_currentBuff[2 * i])]; ftarget[i * 2] = tmp.real(); ftarget[i * 2 + 1] = tmp.imag(); } } else { for (size_t i = 0; i < returnedElems; i++) { tmp = _lut_32f[*((uint16_t*) &_currentBuff[2 * i])]; ftarget[i * 2] = tmp.real(); ftarget[i * 2 + 1] = tmp.imag(); } } } else if (rxFormat == RTL_RX_FORMAT_INT16) { int16_t *itarget = (int16_t *) buff0; std::complex tmp; if (iqSwap) { for (size_t i = 0; i < returnedElems; i++) { tmp = _lut_swap_16i[*((uint16_t*) &_currentBuff[2 * i])]; itarget[i * 2] = tmp.real(); itarget[i * 2 + 1] = tmp.imag(); } } else { for (size_t i = 0; i < returnedElems; i++) { tmp = _lut_16i[*((uint16_t*) &_currentBuff[2 * i])]; itarget[i * 2] = tmp.real(); itarget[i * 2 + 1] = tmp.imag(); } } } else if (rxFormat == RTL_RX_FORMAT_INT8) { int8_t *itarget = (int8_t *) buff0; if (iqSwap) { for (size_t i = 0; i < returnedElems; i++) { itarget[i * 2] = _currentBuff[i * 2 + 1]-127; itarget[i * 2 + 1] = _currentBuff[i * 2]-127; } } else { for (size_t i = 0; i < returnedElems; i++) { itarget[i * 2] = _currentBuff[i * 2]-127; itarget[i * 2 + 1] = _currentBuff[i * 2 + 1]-127; } } } //bump variables for next call into readStream bufferedElems -= returnedElems; _currentBuff += returnedElems*BYTES_PER_SAMPLE; //return number of elements written to buff0 if (bufferedElems != 0) flags |= SOAPY_SDR_MORE_FRAGMENTS; else this->releaseReadBuffer(stream, _currentHandle); return returnedElems; } /******************************************************************* * Direct buffer access API ******************************************************************/ size_t SoapyRTLSDR::getNumDirectAccessBuffers(SoapySDR::Stream *stream) { return _buffs.size(); } int SoapyRTLSDR::getDirectAccessBufferAddrs(SoapySDR::Stream *stream, const size_t handle, void **buffs) { buffs[0] = (void *)_buffs[handle].data(); return 0; } int SoapyRTLSDR::acquireReadBuffer( SoapySDR::Stream *stream, size_t &handle, const void **buffs, int &flags, long long &timeNs, const long timeoutUs) { //reset is issued by various settings //to drain old data out of the queue if (resetBuffer) { //drain all buffers from the fifo _buf_head = (_buf_head + _buf_count.exchange(0)) % numBuffers; resetBuffer = false; _overflowEvent = false; } //handle overflow from the rx callback thread if (_overflowEvent) { //drain the old buffers from the fifo _buf_head = (_buf_head + _buf_count.exchange(0)) % numBuffers; _overflowEvent = false; SoapySDR::log(SOAPY_SDR_SSI, "O"); return SOAPY_SDR_OVERFLOW; } //wait for a buffer to become available if (_buf_count == 0) { std::unique_lock lock(_buf_mutex); _buf_cond.wait_for(lock, std::chrono::microseconds(timeoutUs), [this]{return _buf_count != 0;}); if (_buf_count == 0) return SOAPY_SDR_TIMEOUT; } //extract handle and buffer handle = _buf_head; _buf_head = (_buf_head + 1) % numBuffers; buffs[0] = (void *)_buffs[handle].data(); flags = 0; //return number available return _buffs[handle].size() / BYTES_PER_SAMPLE; } void SoapyRTLSDR::releaseReadBuffer( SoapySDR::Stream *stream, const size_t handle) { //TODO this wont handle out of order releases _buf_count--; } SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/000077500000000000000000000000001312060726200174255ustar00rootroot00000000000000SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/changelog000066400000000000000000000015511312060726200213010ustar00rootroot00000000000000soapyrtlsdr (0.2.4-1) unstable; urgency=low * Release 0.2.4 (2017-06-15) -- Josh Blum Thu, 15 Jun 2017 17:48:13 -0000 soapyrtlsdr (0.2.3-1) unstable; urgency=low * Release 0.2.3 (2017-04-29) -- Josh Blum Sat, 29 Apr 2017 15:04:19 -0000 soapyrtlsdr (0.2.2) unstable; urgency=low * Release 0.2.2 (2016-09-01) -- Josh Blum Thu, 01 Sep 2016 21:23:34 -0700 soapyrtlsdr (0.2.1) unstable; urgency=low * Release 0.2.1 (2016-04-25) -- Josh Blum Mon, 25 Apr 2016 07:44:39 -0400 soapyrtlsdr (0.2.0) unstable; urgency=low * Release 0.2.0 (2015-12-10) -- Josh Blum Fri, 16 Oct 2015 18:40:55 -0700 soapyrtlsdr (0.1.0) unstable; urgency=low * Release 0.1.0 (2015-10-10) -- Josh Blum Sat, 10 Oct 2015 11:19:07 -0700 SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/compat000066400000000000000000000000021312060726200206230ustar00rootroot000000000000009 SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/control000066400000000000000000000025751312060726200210410ustar00rootroot00000000000000Source: soapyrtlsdr Section: hamradio Priority: optional Maintainer: Charles J. Cliffe Uploaders: Josh Blum Build-Depends: debhelper (>= 9.0.0), cmake, libsoapysdr-dev, librtlsdr-dev Standards-Version: 3.9.8 Homepage: https://github.com/pothosware/SoapyRTLSDR/wiki Vcs-Git: https://github.com/pothosware/SoapyRTLSDR.git Vcs-Browser: https://github.com/pothosware/SoapyRTLSDR Package: soapysdr0.6-module-rtlsdr Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends} Description: RTL-SDR device support for SoapySDR The Soapy RTL-SDR project provides a SoapySDR hardware support module. Using this, any program using SoapySDR to interface to software defined radio hardware can make use of low cost DVB-T/DAB+ USB dongles based on the Realtek RTL2832U chip as receivers. Package: soapysdr-module-rtlsdr Architecture: all Depends: soapysdr0.6-module-rtlsdr, ${misc:Depends} Description: RTL-SDR device support for SoapySDR (default version) The Soapy RTL-SDR project provides a SoapySDR hardware support module. Using this, any program using SoapySDR to interface to software defined radio hardware can make use of low cost DVB-T/DAB+ USB dongles based on the Realtek RTL2832U chip as receivers. . This is an empty dependency package that pulls in the RTL-SDR module for the default version of libsoapysdr. SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/copyright000066400000000000000000000023651312060726200213660ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: soapyrtlsdr Source: https://github.com/pothosware/SoapyRTLSDR/wiki Files: * Copyright: Copyright (c) 2015 Charles J. Cliffe 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 in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/docs000066400000000000000000000000121312060726200202710ustar00rootroot00000000000000README.md SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/rules000077500000000000000000000005641312060726200205120ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ --buildsystem=cmake --parallel override_dh_auto_configure: dh_auto_configure -- -DLIB_SUFFIX="/$(DEB_HOST_MULTIARCH)" override_dh_installchangelogs: dh_installchangelogs Changelog.txt SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/soapysdr0.6-module-rtlsdr.install000066400000000000000000000000121312060726200256710ustar00rootroot00000000000000usr/lib/* SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/source/000077500000000000000000000000001312060726200207255ustar00rootroot00000000000000SoapyRTLSDR-soapy-rtlsdr-0.2.4/debian/source/format000066400000000000000000000000141312060726200221330ustar00rootroot000000000000003.0 (quilt)