forked from sdr/gr-osmosdr
Compare commits
71 Commits
master
...
standalone
Author | SHA1 | Date |
---|---|---|
Jon Szymaniak | fe99478a0c | |
Jon Szymaniak | b7360fc879 | |
Dimitri Stolnikov | 99c9e5ead9 | |
Dimitri Stolnikov | 9d85dcf6d1 | |
Dimitri Stolnikov | 0e99eb95f7 | |
Brian Padalino | 98a6e7604f | |
Jon Szymaniak | 9964a5e6a9 | |
Jon Szymaniak | 9a8710757f | |
Jon Szymaniak | 0ee06038ae | |
Jon Szymaniak | 1905cdc64c | |
Dimitri Stolnikov | a734c1ae85 | |
Dimitri Stolnikov | d7557d9432 | |
Dimitri Stolnikov | 9701906aaf | |
Dimitri Stolnikov | 27a5e07ba3 | |
Dimitri Stolnikov | 22705c89cf | |
Dimitri Stolnikov | f78d79398f | |
Dimitri Stolnikov | 6b61662b37 | |
Dimitri Stolnikov | 2a54ac2aed | |
Sylvain Munaut | 81c53bf547 | |
Dimitri Stolnikov | 9b76d230e9 | |
Dimitri Stolnikov | c7a77e88d9 | |
Dimitri Stolnikov | 411a2b683b | |
Dimitri Stolnikov | 8984357be5 | |
Dimitri Stolnikov | e48f8cf2c9 | |
Steve Markgraf | 19556d00da | |
Dimitri Stolnikov | 505c19f82e | |
Dimitri Stolnikov | 8522c4edf2 | |
Dimitri Stolnikov | 2bd29cbe99 | |
Steve Markgraf | eb3865010d | |
Dimitri Stolnikov | 8c5e74c213 | |
Jon Szymaniak | dd35921292 | |
Jon Szymaniak | e735418224 | |
Jon Szymaniak | 3ef7394f61 | |
Daniel Gröber | 0d75ab353d | |
Sylvain Munaut | 49a3772491 | |
Sylvain Munaut | 2cbc1e14e0 | |
Dimitri Stolnikov | 0ee591f163 | |
Dimitri Stolnikov | 8f86bd2dca | |
Dimitri Stolnikov | f7640dc11c | |
Dimitri Stolnikov | 26acce3d35 | |
Dimitri Stolnikov | dd7d584137 | |
Dimitri Stolnikov | 68481ac40d | |
Dimitri Stolnikov | 860962e501 | |
Dimitri Stolnikov | 8300354c05 | |
Dimitri Stolnikov | 2934d8512b | |
Sylvain Munaut | 5534662c0c | |
Dimitri Stolnikov | f61734e58b | |
Dimitri Stolnikov | d81936d907 | |
Dimitri Stolnikov | 7b199a8b95 | |
Dimitri Stolnikov | 1f44c44054 | |
Dimitri Stolnikov | 56281a6a30 | |
Dimitri Stolnikov | 882cac8465 | |
Dimitri Stolnikov | 217872a785 | |
Dimitri Stolnikov | b97cac30c6 | |
Dimitri Stolnikov | d8534d8721 | |
Dimitri Stolnikov | 851e94b82f | |
Dimitri Stolnikov | a279fb1455 | |
Jon Szymaniak | cbf791469c | |
Dimitri Stolnikov | 0690c077d2 | |
Dimitri Stolnikov | 154100a11f | |
Sylvain Munaut | 970658c071 | |
Frederik M.J. Vestre | cdeb105495 | |
Dimitri Stolnikov | 6fe392546a | |
Dimitri Stolnikov | e65dd08785 | |
Dimitri Stolnikov | 80f72d52ea | |
Dimitri Stolnikov | bdc8f22132 | |
Dimitri Stolnikov | 6e29bf179f | |
Dimitri Stolnikov | bd800ed89e | |
Dimitri Stolnikov | f4fd3a176a | |
Dimitri Stolnikov | 3df0e00276 | |
Dimitri Stolnikov | be1314af10 |
|
@ -56,10 +56,14 @@ ENDIF()
|
||||||
message(FATAL_ERROR "Option ${USE_SIMD} not supported, valid entries are ${USE_SIMD_VALUES}")
|
message(FATAL_ERROR "Option ${USE_SIMD} not supported, valid entries are ${USE_SIMD_VALUES}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
IF(CMAKE_CXX_COMPILER MATCHES ".*clang")
|
||||||
|
SET(CMAKE_COMPILER_IS_CLANGXX 1)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
|
||||||
ADD_DEFINITIONS(-Wall)
|
ADD_DEFINITIONS(-Wall)
|
||||||
ADD_DEFINITIONS(-Wextra)
|
ADD_DEFINITIONS(-Wextra)
|
||||||
ADD_DEFINITIONS(-Wno-unused)
|
ADD_DEFINITIONS(-Wno-unused-parameter)
|
||||||
ADD_DEFINITIONS(-Wsign-compare)
|
ADD_DEFINITIONS(-Wsign-compare)
|
||||||
#ADD_DEFINITIONS(-Wconversion)
|
#ADD_DEFINITIONS(-Wconversion)
|
||||||
#ADD_DEFINITIONS(-pedantic)
|
#ADD_DEFINITIONS(-pedantic)
|
||||||
|
@ -86,7 +90,7 @@ ELSEIF(MSVC)
|
||||||
ADD_DEFINITIONS(/arch:AVX)
|
ADD_DEFINITIONS(/arch:AVX)
|
||||||
ADD_DEFINITIONS(-DUSE_AVX)
|
ADD_DEFINITIONS(-DUSE_AVX)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
ENDIF()
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Setup boost
|
# Setup boost
|
||||||
|
@ -97,6 +101,7 @@ MESSAGE(STATUS "Configuring Boost C++ Libraries...")
|
||||||
SET(BOOST_REQUIRED_COMPONENTS
|
SET(BOOST_REQUIRED_COMPONENTS
|
||||||
thread
|
thread
|
||||||
system
|
system
|
||||||
|
filesystem
|
||||||
)
|
)
|
||||||
|
|
||||||
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
|
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
|
||||||
|
@ -140,6 +145,26 @@ set(GR_LIBEXEC_DIR libexec)
|
||||||
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
|
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
|
||||||
set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
|
set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
|
||||||
|
|
||||||
|
# Special exception if prefix is /usr so we don't make a /usr/etc.
|
||||||
|
string(COMPARE EQUAL ${CMAKE_INSTALL_PREFIX} "/usr" isusr)
|
||||||
|
if(isusr)
|
||||||
|
set(SYSCONFDIR "/${GR_CONF_DIR}" CACHE PATH "System configuration directory")
|
||||||
|
else(isusr)
|
||||||
|
set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" CACHE PATH "System configuration directory" FORCE)
|
||||||
|
endif(isusr)
|
||||||
|
|
||||||
|
set(GR_PREFSDIR ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}/conf.d)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Variables replaced when configuring the package config files
|
||||||
|
########################################################################
|
||||||
|
file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}" prefix)
|
||||||
|
file(TO_NATIVE_PATH "\${prefix}" exec_prefix)
|
||||||
|
file(TO_NATIVE_PATH "\${exec_prefix}/${GR_LIBRARY_DIR}" libdir)
|
||||||
|
file(TO_NATIVE_PATH "\${prefix}/${GR_INCLUDE_DIR}" includedir)
|
||||||
|
file(TO_NATIVE_PATH "${SYSCONFDIR}" SYSCONFDIR)
|
||||||
|
file(TO_NATIVE_PATH "${GR_PREFSDIR}" GR_PREFSDIR)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Find build dependencies
|
# Find build dependencies
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -154,12 +179,48 @@ find_package(LibOsmoSDR)
|
||||||
find_package(LibRTLSDR)
|
find_package(LibRTLSDR)
|
||||||
find_package(LibMiriSDR)
|
find_package(LibMiriSDR)
|
||||||
find_package(LibHackRF)
|
find_package(LibHackRF)
|
||||||
|
find_package(LibAIRSPY)
|
||||||
find_package(LibbladeRF)
|
find_package(LibbladeRF)
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
set(PYTHON_RUNTIME_CHECK TRUE)
|
||||||
|
|
||||||
if(NOT GNURADIO_RUNTIME_FOUND)
|
if(NOT GNURADIO_RUNTIME_FOUND)
|
||||||
message(FATAL_ERROR "GnuRadio Runtime required to build " ${CMAKE_PROJECT_NAME})
|
message(STATUS "Enabling built-in GNU Radio runtime...")
|
||||||
endif()
|
set(RUNTIME_MODE TRUE CACHE INTERNAL "Built-in GNU Radio runtime")
|
||||||
|
|
||||||
|
add_subdirectory(include/osmosdr/runtime)
|
||||||
|
|
||||||
|
set(GNURADIO_RUNTIME_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include/osmosdr/runtime)
|
||||||
|
set(GNURADIO_RUNTIME_LIBRARY_DIRS "")
|
||||||
|
set(GNURADIO_RUNTIME_LIBRARIES "")
|
||||||
|
|
||||||
|
set(GNURADIO_PMT_INCLUDE_DIRS "")
|
||||||
|
set(GNURADIO_PMT_LIBRARY_DIRS "")
|
||||||
|
set(GNURADIO_PMT_LIBRARIES "")
|
||||||
|
|
||||||
|
set(GNURADIO_BLOCKS_INCLUDE_DIRS "")
|
||||||
|
set(GNURADIO_BLOCKS_LIBRARY_DIRS "")
|
||||||
|
set(GNURADIO_BLOCKS_LIBRARIES "")
|
||||||
|
|
||||||
|
set(GNURADIO_UHD_INCLUDE_DIRS "")
|
||||||
|
set(GNURADIO_UHD_LIBRARIES "")
|
||||||
|
|
||||||
|
LIST(APPEND GR_OSMOSDR_PC_CFLAGS "-I\${includedir}/osmosdr/runtime")
|
||||||
|
|
||||||
|
# disable python bindings as long as we don't have any swig files for the runtime
|
||||||
|
set(PYTHON_RUNTIME_CHECK FALSE)
|
||||||
|
endif(NOT GNURADIO_RUNTIME_FOUND)
|
||||||
|
|
||||||
|
if(GNURADIO_RUNTIME_FOUND)
|
||||||
|
LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-runtime")
|
||||||
|
endif(GNURADIO_RUNTIME_FOUND)
|
||||||
|
if(GNURADIO_PMT_FOUND)
|
||||||
|
# LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-pmt")
|
||||||
|
endif(GNURADIO_PMT_FOUND)
|
||||||
|
if(GNURADIO_BLOCKS_FOUND)
|
||||||
|
LIST(APPEND GR_OSMOSDR_PC_REQUIRES "gnuradio-blocks")
|
||||||
|
endif(GNURADIO_BLOCKS_FOUND)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Setup the include and linker paths
|
# Setup the include and linker paths
|
||||||
|
@ -211,10 +272,11 @@ if(SWIG_FOUND)
|
||||||
endif(SWIG_FOUND)
|
endif(SWIG_FOUND)
|
||||||
|
|
||||||
include(GrComponent)
|
include(GrComponent)
|
||||||
GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON
|
GR_REGISTER_COMPONENT("Python bindings" ENABLE_PYTHON
|
||||||
PYTHONLIBS_FOUND
|
PYTHONLIBS_FOUND
|
||||||
SWIG_FOUND
|
SWIG_FOUND
|
||||||
SWIG_VERSION_CHECK
|
SWIG_VERSION_CHECK
|
||||||
|
PYTHON_RUNTIME_CHECK
|
||||||
)
|
)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
13
README
13
README
|
@ -4,13 +4,16 @@ as well supports:
|
||||||
* FUNcube Dongle through libgnuradio-fcd
|
* FUNcube Dongle through libgnuradio-fcd
|
||||||
* FUNcube Dongle Pro+ through gr-fcdproplus
|
* FUNcube Dongle Pro+ through gr-fcdproplus
|
||||||
* sysmocom OsmoSDR Devices through libosmosdr
|
* sysmocom OsmoSDR Devices through libosmosdr
|
||||||
* Nuand LLC bladeRF through libbladeRF library
|
|
||||||
* Great Scott Gadgets HackRF through libhackrf
|
|
||||||
* Ettus USRP Devices through Ettus UHD library
|
|
||||||
* RTL2832U based DVB-T dongles through librtlsdr
|
* RTL2832U based DVB-T dongles through librtlsdr
|
||||||
* RTL-TCP spectrum server (see librtlsdr project)
|
* RTL-TCP spectrum server (see librtlsdr project)
|
||||||
* MSi2500 based DVB-T dongles through libmirisdr
|
* MSi2500 based DVB-T dongles through libmirisdr
|
||||||
* gnuradio .cfile input through libgnuradio-blocks
|
* gnuradio .cfile input through libgnuradio-blocks
|
||||||
|
* RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option)
|
||||||
|
* AirSpy Wideband Receiver through libairspy
|
||||||
|
* Great Scott Gadgets HackRF through libhackrf
|
||||||
|
* Nuand LLC bladeRF through libbladeRF library
|
||||||
|
* Ettus USRP Devices through Ettus UHD library
|
||||||
|
* Fairwaves UmTRX through Fairwaves' fork of UHD
|
||||||
|
|
||||||
By using the OsmoSDR block you can take advantage of a common software api in
|
By using the OsmoSDR block you can take advantage of a common software api in
|
||||||
your application(s) independent of the underlying radio hardware.
|
your application(s) independent of the underlying radio hardware.
|
||||||
|
@ -18,11 +21,11 @@ your application(s) independent of the underlying radio hardware.
|
||||||
For installation and usage guidelines please read the documentation available
|
For installation and usage guidelines please read the documentation available
|
||||||
at http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
at http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
||||||
|
|
||||||
For the impatient :) a short excerpt:
|
A short excerpt from the wiki:
|
||||||
|
|
||||||
The Gnu Radio block requires a recent gnuradio (>= v3.7) to be installed.
|
The Gnu Radio block requires a recent gnuradio (>= v3.7) to be installed.
|
||||||
|
|
||||||
Before building the block you have to make sure that all the dependencies
|
Before building the block you have to make sure that all dependencies
|
||||||
(see list of supported devices above) you are intend to work with are
|
(see list of supported devices above) you are intend to work with are
|
||||||
properly installed. The build system of gr-osmosdr will recognize them and
|
properly installed. The build system of gr-osmosdr will recognize them and
|
||||||
enable specific source/sink components thereafter.
|
enable specific source/sink components thereafter.
|
||||||
|
|
367
apps/osmocom_fft
367
apps/osmocom_fft
|
@ -66,17 +66,23 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
help="Set sample rate (bandwidth), minimum by default")
|
help="Set sample rate (bandwidth), minimum by default")
|
||||||
parser.add_option("-f", "--center-freq", type="eng_float", default=None,
|
parser.add_option("-f", "--center-freq", type="eng_float", default=None,
|
||||||
help="Set frequency to FREQ", metavar="FREQ")
|
help="Set frequency to FREQ", metavar="FREQ")
|
||||||
parser.add_option("-c", "--freq-corr", type="eng_float", default=0,
|
parser.add_option("-c", "--freq-corr", type="eng_float", default=None,
|
||||||
help="Set frequency correction (ppm)")
|
help="Set frequency correction (ppm)")
|
||||||
parser.add_option("-g", "--gain", type="eng_float", default=None,
|
parser.add_option("-g", "--gain", type="eng_float", default=None,
|
||||||
help="Set gain in dB (default is midpoint)")
|
help="Set gain in dB (default is midpoint)")
|
||||||
|
parser.add_option("", "--dc-offset-mode", type="int", default=None,
|
||||||
|
help="Set the RX frontend DC offset correction mode")
|
||||||
|
parser.add_option("", "--iq-balance-mode", type="int", default=None,
|
||||||
|
help="Set the RX frontend IQ imbalance correction mode")
|
||||||
parser.add_option("-W", "--waterfall", action="store_true", default=False,
|
parser.add_option("-W", "--waterfall", action="store_true", default=False,
|
||||||
help="Enable waterfall display")
|
help="Enable waterfall display")
|
||||||
|
parser.add_option("-F", "--fosphor", action="store_true", default=False,
|
||||||
|
help="Enable fosphor display")
|
||||||
parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
|
parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
|
||||||
help="Enable oscilloscope display")
|
help="Enable oscilloscope display")
|
||||||
parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
|
parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
|
||||||
help="Set fftsink averaging factor, default=[%default]")
|
help="Set fftsink averaging factor, default=[%default]")
|
||||||
parser.add_option ("", "--averaging", action="store_true", default=False,
|
parser.add_option("", "--averaging", action="store_true", default=False,
|
||||||
help="Enable fftsink averaging, default=[%default]")
|
help="Enable fftsink averaging, default=[%default]")
|
||||||
parser.add_option("", "--ref-scale", type="eng_float", default=1.0,
|
parser.add_option("", "--ref-scale", type="eng_float", default=1.0,
|
||||||
help="Set dBFS=0dB input value, default=[%default]")
|
help="Set dBFS=0dB input value, default=[%default]")
|
||||||
|
@ -111,16 +117,29 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
options.samp_rate = self.src.get_sample_rates().start()
|
options.samp_rate = self.src.get_sample_rates().start()
|
||||||
|
|
||||||
if options.gain is None:
|
if options.gain is None:
|
||||||
# if no gain was specified, use the mid-point in dB
|
gain = self.src.get_gain()
|
||||||
r = self.src.get_gain_range()
|
if gain is None:
|
||||||
options.gain = float(r.start()+r.stop())/2
|
# if no gain was specified, use the mid-point in dB
|
||||||
|
r = self.src.get_gain_range()
|
||||||
|
try: # empty gain range returned in file= mode
|
||||||
|
options.gain = float(r.start()+r.stop())/2
|
||||||
|
except RuntimeError:
|
||||||
|
options.gain = 0
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
options.gain = gain
|
||||||
|
|
||||||
if options.center_freq is None:
|
if options.center_freq is None:
|
||||||
# if no freq was specified, use the mid-point in Hz
|
freq = self.src.get_center_freq()
|
||||||
r = self.src.get_freq_range()
|
if freq != 0:
|
||||||
options.center_freq = float(r.start()+r.stop())/2
|
options.center_freq = freq
|
||||||
|
else:
|
||||||
|
# if no freq was specified, use the mid-point in Hz
|
||||||
|
r = self.src.get_freq_range()
|
||||||
|
options.center_freq = float(r.start()+r.stop())/2
|
||||||
|
|
||||||
input_rate = self.src.set_sample_rate(options.samp_rate)
|
input_rate = self.src.set_sample_rate(options.samp_rate)
|
||||||
|
self.src.set_bandwidth(input_rate)
|
||||||
|
|
||||||
self.src.set_gain(options.gain)
|
self.src.set_gain(options.gain)
|
||||||
|
|
||||||
|
@ -143,6 +162,15 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
self[CENTER_FREQ_KEY] = options.center_freq
|
self[CENTER_FREQ_KEY] = options.center_freq
|
||||||
self[FREQ_CORR_KEY] = options.freq_corr
|
self[FREQ_CORR_KEY] = options.freq_corr
|
||||||
|
|
||||||
|
self.dc_offset_mode = options.dc_offset_mode
|
||||||
|
self.iq_balance_mode = options.iq_balance_mode
|
||||||
|
|
||||||
|
# initialize reasonable defaults for DC / IQ correction
|
||||||
|
self['dc_offset_real'] = 0
|
||||||
|
self['dc_offset_imag'] = 0
|
||||||
|
self['iq_balance_mag'] = 0
|
||||||
|
self['iq_balance_pha'] = 0
|
||||||
|
|
||||||
#subscribe set methods
|
#subscribe set methods
|
||||||
self.subscribe(SAMP_RATE_KEY, self.set_sample_rate)
|
self.subscribe(SAMP_RATE_KEY, self.set_sample_rate)
|
||||||
|
|
||||||
|
@ -153,12 +181,22 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
self.subscribe(CENTER_FREQ_KEY, self.set_freq)
|
self.subscribe(CENTER_FREQ_KEY, self.set_freq)
|
||||||
self.subscribe(FREQ_CORR_KEY, self.set_freq_corr)
|
self.subscribe(FREQ_CORR_KEY, self.set_freq_corr)
|
||||||
|
|
||||||
|
self.subscribe('dc_offset_real', self.set_dc_offset)
|
||||||
|
self.subscribe('dc_offset_imag', self.set_dc_offset)
|
||||||
|
self.subscribe('iq_balance_mag', self.set_iq_balance)
|
||||||
|
self.subscribe('iq_balance_pha', self.set_iq_balance)
|
||||||
|
|
||||||
#force update on pubsub keys
|
#force update on pubsub keys
|
||||||
#for key in (SAMP_RATE_KEY, BWIDTH_KEY, CENTER_FREQ_KEY, FREQ_CORR_KEY):
|
#for key in (SAMP_RATE_KEY, BWIDTH_KEY, CENTER_FREQ_KEY, FREQ_CORR_KEY):
|
||||||
#print key, "=", self[key]
|
#print key, "=", self[key]
|
||||||
#self[key] = self[key]
|
#self[key] = self[key]
|
||||||
|
|
||||||
if options.waterfall:
|
if options.fosphor:
|
||||||
|
from gnuradio import fosphor
|
||||||
|
self.scope = fosphor.wx_sink_c(panel, size=(800,300))
|
||||||
|
self.scope.set_sample_rate(input_rate)
|
||||||
|
self.frame.SetMinSize((800,600))
|
||||||
|
elif options.waterfall:
|
||||||
self.scope = waterfallsink2.waterfall_sink_c (panel,
|
self.scope = waterfallsink2.waterfall_sink_c (panel,
|
||||||
fft_size=options.fft_size,
|
fft_size=options.fft_size,
|
||||||
sample_rate=input_rate,
|
sample_rate=input_rate,
|
||||||
|
@ -189,6 +227,12 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
|
|
||||||
self._build_gui(vbox)
|
self._build_gui(vbox)
|
||||||
|
|
||||||
|
if self.dc_offset_mode != None:
|
||||||
|
self.set_dc_offset_mode(self.dc_offset_mode)
|
||||||
|
|
||||||
|
if self.iq_balance_mode != None:
|
||||||
|
self.set_iq_balance_mode(self.iq_balance_mode)
|
||||||
|
|
||||||
# set initial values
|
# set initial values
|
||||||
if not(self.set_freq(options.center_freq)):
|
if not(self.set_freq(options.center_freq)):
|
||||||
self._set_status_msg("Failed to set initial frequency")
|
self._set_status_msg("Failed to set initial frequency")
|
||||||
|
@ -201,8 +245,9 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
|
|
||||||
def _build_gui(self, vbox):
|
def _build_gui(self, vbox):
|
||||||
|
|
||||||
vbox.Add(self.scope.win, 0, wx.EXPAND)
|
if hasattr(self.scope, 'win'):
|
||||||
vbox.AddSpacer(3)
|
vbox.Add(self.scope.win, 1, wx.EXPAND)
|
||||||
|
vbox.AddSpacer(3)
|
||||||
|
|
||||||
# add control area at the bottom
|
# add control area at the bottom
|
||||||
self.myform = myform = form.form()
|
self.myform = myform = form.form()
|
||||||
|
@ -227,7 +272,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
# Add frequency controls to top window sizer
|
# Add frequency controls to top window sizer
|
||||||
vbox.Add(fc_vbox, 0, wx.EXPAND)
|
vbox.Add(fc_vbox, 0, wx.EXPAND)
|
||||||
vbox.AddSpacer(5)
|
vbox.AddSpacer(5)
|
||||||
vbox.AddStretchSpacer()
|
|
||||||
|
|
||||||
freq_hbox.AddSpacer(3)
|
freq_hbox.AddSpacer(3)
|
||||||
forms.text_box(
|
forms.text_box(
|
||||||
|
@ -240,39 +284,46 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
)
|
)
|
||||||
freq_hbox.AddSpacer(5)
|
freq_hbox.AddSpacer(5)
|
||||||
|
|
||||||
forms.slider(
|
try: # range.start() == range.stop() in file= mode
|
||||||
parent=self.panel, sizer=freq_hbox,
|
|
||||||
proportion=3,
|
|
||||||
ps=self,
|
|
||||||
key=CENTER_FREQ_KEY,
|
|
||||||
minimum=self[FREQ_RANGE_KEY].start(),
|
|
||||||
maximum=self[FREQ_RANGE_KEY].stop(),
|
|
||||||
num_steps=101,
|
|
||||||
)
|
|
||||||
freq_hbox.AddSpacer(3)
|
|
||||||
|
|
||||||
corr_hbox.AddSpacer(3)
|
forms.slider(
|
||||||
forms.text_box(
|
parent=self.panel, sizer=freq_hbox,
|
||||||
parent=self.panel, sizer=corr_hbox,
|
proportion=3,
|
||||||
label='Freq. Correction (ppm)',
|
ps=self,
|
||||||
proportion=1,
|
key=CENTER_FREQ_KEY,
|
||||||
converter=forms.float_converter(),
|
minimum=self[FREQ_RANGE_KEY].start(),
|
||||||
ps=self,
|
maximum=self[FREQ_RANGE_KEY].stop(),
|
||||||
key=FREQ_CORR_KEY,
|
num_steps=1000,
|
||||||
)
|
)
|
||||||
corr_hbox.AddSpacer(5)
|
freq_hbox.AddSpacer(3)
|
||||||
|
|
||||||
forms.slider(
|
except AssertionError:
|
||||||
parent=self.panel, sizer=corr_hbox,
|
pass
|
||||||
proportion=3,
|
|
||||||
ps=self,
|
if self[FREQ_CORR_KEY] != None: # show frequency correction scrollbar
|
||||||
key=FREQ_CORR_KEY,
|
|
||||||
minimum=-100,
|
corr_hbox.AddSpacer(3)
|
||||||
maximum=+100,
|
forms.text_box(
|
||||||
num_steps=2010,
|
parent=self.panel, sizer=corr_hbox,
|
||||||
step_size=0.1,
|
label='Freq. Correction (ppm)',
|
||||||
)
|
proportion=1,
|
||||||
corr_hbox.AddSpacer(3)
|
converter=forms.float_converter(),
|
||||||
|
ps=self,
|
||||||
|
key=FREQ_CORR_KEY,
|
||||||
|
)
|
||||||
|
corr_hbox.AddSpacer(5)
|
||||||
|
|
||||||
|
forms.slider(
|
||||||
|
parent=self.panel, sizer=corr_hbox,
|
||||||
|
proportion=3,
|
||||||
|
ps=self,
|
||||||
|
key=FREQ_CORR_KEY,
|
||||||
|
minimum=-100,
|
||||||
|
maximum=+100,
|
||||||
|
num_steps=2010,
|
||||||
|
step_size=0.1,
|
||||||
|
)
|
||||||
|
corr_hbox.AddSpacer(3)
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# Gain controls
|
# Gain controls
|
||||||
|
@ -286,7 +337,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
# Add gain controls to top window sizer
|
# Add gain controls to top window sizer
|
||||||
vbox.Add(gc_vbox, 0, wx.EXPAND)
|
vbox.Add(gc_vbox, 0, wx.EXPAND)
|
||||||
vbox.AddSpacer(5)
|
vbox.AddSpacer(5)
|
||||||
vbox.AddStretchSpacer()
|
|
||||||
|
|
||||||
for gain_name in self.get_gain_names():
|
for gain_name in self.get_gain_names():
|
||||||
range = self[GAIN_RANGE_KEY(gain_name)]
|
range = self[GAIN_RANGE_KEY(gain_name)]
|
||||||
|
@ -315,7 +365,7 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
key=GAIN_KEY(gain_name),
|
key=GAIN_KEY(gain_name),
|
||||||
minimum=range.start(),
|
minimum=range.start(),
|
||||||
maximum=range.stop(),
|
maximum=range.stop(),
|
||||||
step_size=range.step(),
|
step_size=range.step() or (range.stop() - range.start())/10,
|
||||||
)
|
)
|
||||||
gain_hbox.AddSpacer(3)
|
gain_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
@ -338,7 +388,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
|
|
||||||
vbox.Add(bwidth_vbox, 0, wx.EXPAND)
|
vbox.Add(bwidth_vbox, 0, wx.EXPAND)
|
||||||
vbox.AddSpacer(5)
|
vbox.AddSpacer(5)
|
||||||
vbox.AddStretchSpacer()
|
|
||||||
|
|
||||||
bwidth_hbox.AddSpacer(3)
|
bwidth_hbox.AddSpacer(3)
|
||||||
forms.text_box(
|
forms.text_box(
|
||||||
|
@ -357,7 +406,7 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
key=BWIDTH_KEY,
|
key=BWIDTH_KEY,
|
||||||
minimum=bw_range.start(),
|
minimum=bw_range.start(),
|
||||||
maximum=bw_range.stop(),
|
maximum=bw_range.stop(),
|
||||||
step_size=bw_range.step(),
|
step_size=bw_range.step() or (bw_range.stop() - bw_range.start())/100,
|
||||||
)
|
)
|
||||||
bwidth_hbox.AddSpacer(3)
|
bwidth_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
@ -381,7 +430,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
# Add frequency controls to top window sizer
|
# Add frequency controls to top window sizer
|
||||||
vbox.Add(sr_vbox, 0, wx.EXPAND)
|
vbox.Add(sr_vbox, 0, wx.EXPAND)
|
||||||
vbox.AddSpacer(5)
|
vbox.AddSpacer(5)
|
||||||
vbox.AddStretchSpacer()
|
|
||||||
|
|
||||||
sr_hbox.AddSpacer(3)
|
sr_hbox.AddSpacer(3)
|
||||||
forms.text_box(
|
forms.text_box(
|
||||||
|
@ -405,11 +453,228 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
#)
|
#)
|
||||||
#sr_hbox.AddSpacer(3)
|
#sr_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# DC Offset controls
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
if self.dc_offset_mode != None:
|
||||||
|
|
||||||
|
dc_offset_vbox = forms.static_box_sizer(parent=self.panel,
|
||||||
|
label="DC Offset Correction",
|
||||||
|
orient=wx.VERTICAL,
|
||||||
|
bold=True)
|
||||||
|
dc_offset_vbox.AddSpacer(3)
|
||||||
|
# First row of sample rate controls
|
||||||
|
dc_offset_hbox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
dc_offset_vbox.Add(dc_offset_hbox, 0, wx.EXPAND)
|
||||||
|
dc_offset_vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
# Add frequency controls to top window sizer
|
||||||
|
vbox.Add(dc_offset_vbox, 0, wx.EXPAND)
|
||||||
|
vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.dc_offset_mode_chooser = forms.radio_buttons(
|
||||||
|
parent=self.panel,
|
||||||
|
value=self.dc_offset_mode,
|
||||||
|
callback=self.set_dc_offset_mode,
|
||||||
|
label='',
|
||||||
|
choices=[0, 1, 2],
|
||||||
|
labels=["Off", "Manual", "Auto"],
|
||||||
|
style=wx.RA_HORIZONTAL,
|
||||||
|
)
|
||||||
|
dc_offset_hbox.Add(self.dc_offset_mode_chooser)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
self.dc_offset_real_text = forms.text_box(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
label='Real',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self,
|
||||||
|
key='dc_offset_real',
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.dc_offset_real_slider = forms.slider(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self,
|
||||||
|
key='dc_offset_real',
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
self.dc_offset_imag_text = forms.text_box(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
label='Imag',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self,
|
||||||
|
key='dc_offset_imag',
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.dc_offset_imag_slider = forms.slider(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self,
|
||||||
|
key='dc_offset_imag',
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# IQ Imbalance controls
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
if self.iq_balance_mode != None:
|
||||||
|
|
||||||
|
iq_balance_vbox = forms.static_box_sizer(parent=self.panel,
|
||||||
|
label="IQ Imbalance Correction",
|
||||||
|
orient=wx.VERTICAL,
|
||||||
|
bold=True)
|
||||||
|
iq_balance_vbox.AddSpacer(3)
|
||||||
|
# First row of sample rate controls
|
||||||
|
iq_balance_hbox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
iq_balance_vbox.Add(iq_balance_hbox, 0, wx.EXPAND)
|
||||||
|
iq_balance_vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
# Add frequency controls to top window sizer
|
||||||
|
vbox.Add(iq_balance_vbox, 0, wx.EXPAND)
|
||||||
|
vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.iq_balance_mode_chooser = forms.radio_buttons(
|
||||||
|
parent=self.panel,
|
||||||
|
value=self.iq_balance_mode,
|
||||||
|
callback=self.set_iq_balance_mode,
|
||||||
|
label='',
|
||||||
|
choices=[0, 1, 2],
|
||||||
|
labels=["Off", "Manual", "Auto"],
|
||||||
|
style=wx.RA_HORIZONTAL,
|
||||||
|
)
|
||||||
|
iq_balance_hbox.Add(self.iq_balance_mode_chooser)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
self.iq_balance_mag_text = forms.text_box(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
label='Mag',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self,
|
||||||
|
key='iq_balance_mag',
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.iq_balance_mag_slider = forms.slider(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self,
|
||||||
|
key='iq_balance_mag',
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
self.iq_balance_pha_text = forms.text_box(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
label='Phase',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self,
|
||||||
|
key='iq_balance_pha',
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
self.iq_balance_pha_slider = forms.slider(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self,
|
||||||
|
key='iq_balance_pha',
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
def set_dc_offset_mode(self, dc_offset_mode):
|
||||||
|
if dc_offset_mode == 1:
|
||||||
|
self.dc_offset_real_text.Enable()
|
||||||
|
self.dc_offset_real_slider.Enable()
|
||||||
|
self.dc_offset_imag_text.Enable()
|
||||||
|
self.dc_offset_imag_slider.Enable()
|
||||||
|
|
||||||
|
self.set_dc_offset(0)
|
||||||
|
else:
|
||||||
|
self.dc_offset_real_text.Disable()
|
||||||
|
self.dc_offset_real_slider.Disable()
|
||||||
|
self.dc_offset_imag_text.Disable()
|
||||||
|
self.dc_offset_imag_slider.Disable()
|
||||||
|
|
||||||
|
self.dc_offset_mode = dc_offset_mode
|
||||||
|
self.src.set_dc_offset_mode(dc_offset_mode)
|
||||||
|
self.dc_offset_mode_chooser.set_value(self.dc_offset_mode)
|
||||||
|
|
||||||
|
def set_dc_offset(self, value):
|
||||||
|
correction = complex( self['dc_offset_real'], self['dc_offset_imag'] )
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.src.set_dc_offset( correction )
|
||||||
|
|
||||||
|
if self._verbose:
|
||||||
|
print "Set DC offset to", correction
|
||||||
|
except RuntimeError as ex:
|
||||||
|
print ex
|
||||||
|
|
||||||
|
def set_iq_balance_mode(self, iq_balance_mode):
|
||||||
|
if iq_balance_mode == 1:
|
||||||
|
self.iq_balance_mag_text.Enable()
|
||||||
|
self.iq_balance_mag_slider.Enable()
|
||||||
|
self.iq_balance_pha_text.Enable()
|
||||||
|
self.iq_balance_pha_slider.Enable()
|
||||||
|
|
||||||
|
self.set_iq_balance(0)
|
||||||
|
else:
|
||||||
|
self.iq_balance_mag_text.Disable()
|
||||||
|
self.iq_balance_mag_slider.Disable()
|
||||||
|
self.iq_balance_pha_text.Disable()
|
||||||
|
self.iq_balance_pha_slider.Disable()
|
||||||
|
|
||||||
|
self.iq_balance_mode = iq_balance_mode
|
||||||
|
self.src.set_iq_balance_mode(iq_balance_mode)
|
||||||
|
self.iq_balance_mode_chooser.set_value(self.iq_balance_mode)
|
||||||
|
|
||||||
|
def set_iq_balance(self, value):
|
||||||
|
correction = complex( self['iq_balance_mag'], self['iq_balance_pha'] )
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.src.set_iq_balance( correction )
|
||||||
|
|
||||||
|
if self._verbose:
|
||||||
|
print "Set IQ balance to", correction
|
||||||
|
except RuntimeError as ex:
|
||||||
|
print ex
|
||||||
|
|
||||||
def set_sample_rate(self, samp_rate):
|
def set_sample_rate(self, samp_rate):
|
||||||
samp_rate = self.src.set_sample_rate(samp_rate)
|
samp_rate = self.src.set_sample_rate(samp_rate)
|
||||||
self.scope.set_sample_rate(samp_rate)
|
if hasattr(self.scope, 'set_sample_rate'):
|
||||||
|
self.scope.set_sample_rate(samp_rate)
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
print "Set sample rate to:", samp_rate
|
print "Set sample rate to:", samp_rate
|
||||||
|
|
||||||
|
try:
|
||||||
|
self[BWIDTH_KEY] = self.set_bandwidth(samp_rate)
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
return samp_rate
|
return samp_rate
|
||||||
|
|
||||||
def get_gain_names(self):
|
def get_gain_names(self):
|
||||||
|
@ -436,6 +701,8 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
print "Set bandwidth to:", bw
|
print "Set bandwidth to:", bw
|
||||||
|
|
||||||
|
return bw
|
||||||
|
|
||||||
def set_freq_from_callback(self, freq):
|
def set_freq_from_callback(self, freq):
|
||||||
freq = self.src.set_center_freq(freq)
|
freq = self.src.set_center_freq(freq)
|
||||||
self[CENTER_FREQ_KEY] = freq;
|
self[CENTER_FREQ_KEY] = freq;
|
||||||
|
@ -451,7 +718,7 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
||||||
|
|
||||||
freq = self.src.set_center_freq(freq)
|
freq = self.src.set_center_freq(freq)
|
||||||
|
|
||||||
if not self.options.oscilloscope:
|
if hasattr(self.scope, 'set_baseband_freq'):
|
||||||
self.scope.set_baseband_freq(freq)
|
self.scope.set_baseband_freq(freq)
|
||||||
|
|
||||||
if freq is not None:
|
if freq is not None:
|
||||||
|
|
|
@ -314,6 +314,130 @@ class app_gui(pubsub):
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# DC Offset controls
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
dc_offset_vbox = forms.static_box_sizer(parent=self.panel,
|
||||||
|
label="DC Offset Correction",
|
||||||
|
orient=wx.VERTICAL,
|
||||||
|
bold=True)
|
||||||
|
dc_offset_vbox.AddSpacer(3)
|
||||||
|
# First row of sample rate controls
|
||||||
|
dc_offset_hbox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
dc_offset_vbox.Add(dc_offset_hbox, 0, wx.EXPAND)
|
||||||
|
dc_offset_vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
# Add frequency controls to top window sizer
|
||||||
|
self.vbox.Add(dc_offset_vbox, 0, wx.EXPAND)
|
||||||
|
self.vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
forms.text_box(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
label='Real',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.DC_OFFSET_REAL
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
forms.slider(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.DC_OFFSET_REAL
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
forms.text_box(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
label='Imag',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.DC_OFFSET_IMAG
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
forms.slider(
|
||||||
|
parent=self.panel, sizer=dc_offset_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.DC_OFFSET_IMAG
|
||||||
|
)
|
||||||
|
dc_offset_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# IQ Imbalance controls
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
iq_balance_vbox = forms.static_box_sizer(parent=self.panel,
|
||||||
|
label="IQ Imbalance Correction",
|
||||||
|
orient=wx.VERTICAL,
|
||||||
|
bold=True)
|
||||||
|
iq_balance_vbox.AddSpacer(3)
|
||||||
|
# First row of sample rate controls
|
||||||
|
iq_balance_hbox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
iq_balance_vbox.Add(iq_balance_hbox, 0, wx.EXPAND)
|
||||||
|
iq_balance_vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
# Add frequency controls to top window sizer
|
||||||
|
self.vbox.Add(iq_balance_vbox, 0, wx.EXPAND)
|
||||||
|
self.vbox.AddSpacer(3)
|
||||||
|
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
forms.text_box(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
label='Mag',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.IQ_BALANCE_MAG
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
forms.slider(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.IQ_BALANCE_MAG
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
forms.text_box(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
label='Phase',
|
||||||
|
proportion=1,
|
||||||
|
converter=forms.float_converter(),
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.IQ_BALANCE_PHA
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
|
forms.slider(
|
||||||
|
parent=self.panel, sizer=iq_balance_hbox,
|
||||||
|
proportion=3,
|
||||||
|
minimum=-1,
|
||||||
|
maximum=+1,
|
||||||
|
step_size=0.001,
|
||||||
|
ps=self.tb,
|
||||||
|
key=osmocom_siggen.IQ_BALANCE_PHA
|
||||||
|
)
|
||||||
|
iq_balance_hbox.AddSpacer(3)
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# Sample Rate controls
|
# Sample Rate controls
|
||||||
##################################################
|
##################################################
|
||||||
|
|
|
@ -33,6 +33,10 @@ WAVEFORM2_FREQ_KEY = 'waveform2_freq'
|
||||||
FREQ_RANGE_KEY = 'freq_range'
|
FREQ_RANGE_KEY = 'freq_range'
|
||||||
GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
|
GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
|
||||||
BWIDTH_RANGE_KEY = 'bwidth_range'
|
BWIDTH_RANGE_KEY = 'bwidth_range'
|
||||||
|
DC_OFFSET_REAL = 'dc_offset_real'
|
||||||
|
DC_OFFSET_IMAG = 'dc_offset_imag'
|
||||||
|
IQ_BALANCE_MAG = 'iq_balance_mag'
|
||||||
|
IQ_BALANCE_PHA = 'iq_balance_pha'
|
||||||
TYPE_KEY = 'type'
|
TYPE_KEY = 'type'
|
||||||
|
|
||||||
def setter(ps, key, val): ps[key] = val
|
def setter(ps, key, val): ps[key] = val
|
||||||
|
@ -67,22 +71,28 @@ class gsm_source_c(gr.hier_block2):
|
||||||
gr.io_signature(0, 0, 0), # Input signature
|
gr.io_signature(0, 0, 0), # Input signature
|
||||||
gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
|
gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
|
||||||
|
|
||||||
self._bits = blocks.vector_source_b(self.gen_gsm_seq(), True)
|
self._symb_rate = 13e6 / 48;
|
||||||
|
|
||||||
self._symb_rate = 270833
|
|
||||||
self._samples_per_symbol = 2
|
self._samples_per_symbol = 2
|
||||||
|
|
||||||
bits_per_symbol = 1
|
self._data = blocks.vector_source_b(self.gen_gsm_seq(), True, 2)
|
||||||
self._pack = blocks.unpacked_to_packed_bb(bits_per_symbol, gr.GR_MSB_FIRST)
|
self._split = blocks.vector_to_streams(gr.sizeof_char*1, 2)
|
||||||
|
|
||||||
self._mod = digital.gmsk_mod( self._samples_per_symbol, bt=0.35 )
|
self._pack = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)
|
||||||
|
self._mod = digital.gmsk_mod(self._samples_per_symbol, bt=0.35)
|
||||||
|
|
||||||
|
self._pwr_f = blocks.char_to_float(1, 1)
|
||||||
|
self._pwr_c = blocks.float_to_complex(1)
|
||||||
|
self._pwr_w = blocks.repeat(gr.sizeof_gr_complex*1, self._samples_per_symbol)
|
||||||
|
|
||||||
|
self._mul = blocks.multiply_vcc(1)
|
||||||
self._interpolate = filter.fractional_resampler_cc( 0,
|
self._interpolate = filter.fractional_resampler_cc( 0,
|
||||||
(self._symb_rate * self._samples_per_symbol) / sample_rate )
|
(self._symb_rate * self._samples_per_symbol) / sample_rate )
|
||||||
|
|
||||||
self._scale = blocks.multiply_const_cc(amplitude)
|
self._scale = blocks.multiply_const_cc(amplitude)
|
||||||
|
|
||||||
self.connect(self._bits, self._pack, self._mod, self._interpolate, self._scale, self)
|
self.connect(self._data, self._split)
|
||||||
|
self.connect((self._split, 0), self._pack, self._mod, (self._mul, 0))
|
||||||
|
self.connect((self._split, 1), self._pwr_f, self._pwr_c, self._pwr_w, (self._mul, 1))
|
||||||
|
self.connect(self._mul, self._interpolate, self._scale, self)
|
||||||
|
|
||||||
def set_amplitude(self, amplitude):
|
def set_amplitude(self, amplitude):
|
||||||
self._scale.set_k(amplitude)
|
self._scale.set_k(amplitude)
|
||||||
|
@ -97,9 +107,11 @@ class gsm_source_c(gr.hier_block2):
|
||||||
[0,0,1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,1],
|
[0,0,1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,1],
|
||||||
list(numpy.random.randint(0, 2, 58)),
|
list(numpy.random.randint(0, 2, 58)),
|
||||||
[0,0,0],
|
[0,0,0],
|
||||||
[1] * (l-148)
|
|
||||||
]
|
]
|
||||||
return map(int, sum(chunks,[]))
|
burst = sum(chunks,[])
|
||||||
|
burst = sum(map(list, zip(burst, (1,) * len(burst))), [])
|
||||||
|
burst += [1,0] * (l-148)
|
||||||
|
return map(int, burst)
|
||||||
|
|
||||||
def gen_gsm_frame(self):
|
def gen_gsm_frame(self):
|
||||||
return \
|
return \
|
||||||
|
@ -135,6 +147,12 @@ class top_block(gr.top_block, pubsub):
|
||||||
self[WAVEFORM_OFFSET_KEY] = options.offset
|
self[WAVEFORM_OFFSET_KEY] = options.offset
|
||||||
self[WAVEFORM2_FREQ_KEY] = options.waveform2_freq
|
self[WAVEFORM2_FREQ_KEY] = options.waveform2_freq
|
||||||
|
|
||||||
|
# initialize reasonable defaults for DC / IQ correction
|
||||||
|
self[DC_OFFSET_REAL] = 0
|
||||||
|
self[DC_OFFSET_IMAG] = 0
|
||||||
|
self[IQ_BALANCE_MAG] = 0
|
||||||
|
self[IQ_BALANCE_PHA] = 0
|
||||||
|
|
||||||
#subscribe set methods
|
#subscribe set methods
|
||||||
self.subscribe(SAMP_RATE_KEY, self.set_samp_rate)
|
self.subscribe(SAMP_RATE_KEY, self.set_samp_rate)
|
||||||
|
|
||||||
|
@ -149,6 +167,11 @@ class top_block(gr.top_block, pubsub):
|
||||||
self.subscribe(WAVEFORM2_FREQ_KEY, self.set_waveform2_freq)
|
self.subscribe(WAVEFORM2_FREQ_KEY, self.set_waveform2_freq)
|
||||||
self.subscribe(TYPE_KEY, self.set_waveform)
|
self.subscribe(TYPE_KEY, self.set_waveform)
|
||||||
|
|
||||||
|
self.subscribe(DC_OFFSET_REAL, self.set_dc_offset)
|
||||||
|
self.subscribe(DC_OFFSET_IMAG, self.set_dc_offset)
|
||||||
|
self.subscribe(IQ_BALANCE_MAG, self.set_iq_balance)
|
||||||
|
self.subscribe(IQ_BALANCE_PHA, self.set_iq_balance)
|
||||||
|
|
||||||
#force update on pubsub keys
|
#force update on pubsub keys
|
||||||
for key in (SAMP_RATE_KEY, GAIN_KEY, BWIDTH_KEY,
|
for key in (SAMP_RATE_KEY, GAIN_KEY, BWIDTH_KEY,
|
||||||
TX_FREQ_KEY, FREQ_CORR_KEY, AMPLITUDE_KEY,
|
TX_FREQ_KEY, FREQ_CORR_KEY, AMPLITUDE_KEY,
|
||||||
|
@ -240,6 +263,28 @@ class top_block(gr.top_block, pubsub):
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
print "Set bandwidth to:", bw
|
print "Set bandwidth to:", bw
|
||||||
|
|
||||||
|
def set_dc_offset(self, value):
|
||||||
|
correction = complex( self[DC_OFFSET_REAL], self[DC_OFFSET_IMAG] )
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._sink.set_dc_offset( correction )
|
||||||
|
|
||||||
|
if self._verbose:
|
||||||
|
print "Set DC offset to", correction
|
||||||
|
except RuntimeError as ex:
|
||||||
|
print ex
|
||||||
|
|
||||||
|
def set_iq_balance(self, value):
|
||||||
|
correction = complex( self[IQ_BALANCE_MAG], self[IQ_BALANCE_PHA] )
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._sink.set_iq_balance( correction )
|
||||||
|
|
||||||
|
if self._verbose:
|
||||||
|
print "Set IQ balance to", correction
|
||||||
|
except RuntimeError as ex:
|
||||||
|
print ex
|
||||||
|
|
||||||
def set_freq(self, freq):
|
def set_freq(self, freq):
|
||||||
if freq is None:
|
if freq is None:
|
||||||
f = self[FREQ_RANGE_KEY]
|
f = self[FREQ_RANGE_KEY]
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
INCLUDE(FindPkgConfig)
|
||||||
|
PKG_CHECK_MODULES(PC_LIBAIRSPY libairspy)
|
||||||
|
|
||||||
|
FIND_PATH(
|
||||||
|
LIBAIRSPY_INCLUDE_DIRS
|
||||||
|
NAMES libairspy/airspy.h
|
||||||
|
HINTS $ENV{LIBAIRSPY_DIR}/include
|
||||||
|
${PC_LIBAIRSPY_INCLUDEDIR}
|
||||||
|
PATHS /usr/local/include
|
||||||
|
/usr/include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(
|
||||||
|
LIBAIRSPY_LIBRARIES
|
||||||
|
NAMES airspy
|
||||||
|
HINTS $ENV{LIBAIRSPY_DIR}/lib
|
||||||
|
${PC_LIBAIRSPY_LIBDIR}
|
||||||
|
PATHS /usr/local/lib
|
||||||
|
/usr/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBAIRSPY DEFAULT_MSG LIBAIRSPY_LIBRARIES LIBAIRSPY_INCLUDE_DIRS)
|
||||||
|
MARK_AS_ADVANCED(LIBAIRSPY_LIBRARIES LIBAIRSPY_INCLUDE_DIRS)
|
|
@ -1,6 +1,6 @@
|
||||||
if(NOT LIBMIRISDR_FOUND)
|
if(NOT LIBMIRISDR_FOUND)
|
||||||
pkg_check_modules (LIBMIRISDR_PKG libmirisdr)
|
pkg_check_modules (LIBMIRISDR_PKG libmirisdr)
|
||||||
find_path(LIBMIRISDR_INCLUDE_DIR NAMES mirisdr.h
|
find_path(LIBMIRISDR_INCLUDE_DIRS NAMES mirisdr.h
|
||||||
PATHS
|
PATHS
|
||||||
${LIBMIRISDR_PKG_INCLUDE_DIRS}
|
${LIBMIRISDR_PKG_INCLUDE_DIRS}
|
||||||
/usr/include
|
/usr/include
|
||||||
|
@ -14,14 +14,14 @@ if(NOT LIBMIRISDR_FOUND)
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES)
|
if(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
|
||||||
set(LIBMIRISDR_FOUND TRUE CACHE INTERNAL "libmirisdr found")
|
set(LIBMIRISDR_FOUND TRUE CACHE INTERNAL "libmirisdr found")
|
||||||
message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIR}, ${LIBMIRISDR_LIBRARIES}")
|
message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIRS}, ${LIBMIRISDR_LIBRARIES}")
|
||||||
else(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES)
|
else(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
|
||||||
set(LIBMIRISDR_FOUND FALSE CACHE INTERNAL "libmirisdr found")
|
set(LIBMIRISDR_FOUND FALSE CACHE INTERNAL "libmirisdr found")
|
||||||
message(STATUS "libmirisdr not found.")
|
message(STATUS "libmirisdr not found.")
|
||||||
endif(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES)
|
endif(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
|
||||||
|
|
||||||
mark_as_advanced(LIBMIRISDR_INCLUDE_DIR LIBMIRISDR_LIBRARIES)
|
mark_as_advanced(LIBMIRISDR_LIBRARIES LIBMIRISDR_INCLUDE_DIRS)
|
||||||
|
|
||||||
endif(NOT LIBMIRISDR_FOUND)
|
endif(NOT LIBMIRISDR_FOUND)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
if(NOT LIBOSMOSDR_FOUND)
|
if(NOT LIBOSMOSDR_FOUND)
|
||||||
pkg_check_modules (LIBOSMOSDR_PKG libosmosdr)
|
pkg_check_modules (LIBOSMOSDR_PKG libosmosdr)
|
||||||
find_path(LIBOSMOSDR_INCLUDE_DIR NAMES osmosdr.h
|
find_path(LIBOSMOSDR_INCLUDE_DIRS NAMES osmosdr.h
|
||||||
PATHS
|
PATHS
|
||||||
${LIBOSMOSDR_PKG_INCLUDE_DIRS}
|
${LIBOSMOSDR_PKG_INCLUDE_DIRS}
|
||||||
/usr/include
|
/usr/include
|
||||||
|
@ -14,14 +14,14 @@ if(NOT LIBOSMOSDR_FOUND)
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES)
|
if(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
|
||||||
set(LIBOSMOSDR_FOUND TRUE CACHE INTERNAL "libosmosdr found")
|
set(LIBOSMOSDR_FOUND TRUE CACHE INTERNAL "libosmosdr found")
|
||||||
message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIR}, ${LIBOSMOSDR_LIBRARIES}")
|
message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIRS}, ${LIBOSMOSDR_LIBRARIES}")
|
||||||
else(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES)
|
else(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
|
||||||
set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr found")
|
set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr found")
|
||||||
message(STATUS "libosmosdr not found.")
|
message(STATUS "libosmosdr not found.")
|
||||||
endif(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES)
|
endif(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
|
||||||
|
|
||||||
mark_as_advanced(LIBOSMOSDR_INCLUDE_DIR LIBOSMOSDR_LIBRARIES)
|
mark_as_advanced(LIBOSMOSDR_LIBRARIES LIBOSMOSDR_INCLUDE_DIRS)
|
||||||
|
|
||||||
endif(NOT LIBOSMOSDR_FOUND)
|
endif(NOT LIBOSMOSDR_FOUND)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
if(NOT LIBRTLSDR_FOUND)
|
if(NOT LIBRTLSDR_FOUND)
|
||||||
pkg_check_modules (LIBRTLSDR_PKG librtlsdr)
|
pkg_check_modules (LIBRTLSDR_PKG librtlsdr)
|
||||||
find_path(LIBRTLSDR_INCLUDE_DIR NAMES rtl-sdr.h
|
find_path(LIBRTLSDR_INCLUDE_DIRS NAMES rtl-sdr.h
|
||||||
PATHS
|
PATHS
|
||||||
${LIBRTLSDR_PKG_INCLUDE_DIRS}
|
${LIBRTLSDR_PKG_INCLUDE_DIRS}
|
||||||
/usr/include
|
/usr/include
|
||||||
|
@ -14,14 +14,14 @@ if(NOT LIBRTLSDR_FOUND)
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES)
|
if(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES)
|
||||||
set(LIBRTLSDR_FOUND TRUE CACHE INTERNAL "librtlsdr found")
|
set(LIBRTLSDR_FOUND TRUE CACHE INTERNAL "librtlsdr found")
|
||||||
message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIR}, ${LIBRTLSDR_LIBRARIES}")
|
message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIRS}, ${LIBRTLSDR_LIBRARIES}")
|
||||||
else(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES)
|
else(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES)
|
||||||
set(LIBRTLSDR_FOUND FALSE CACHE INTERNAL "librtlsdr found")
|
set(LIBRTLSDR_FOUND FALSE CACHE INTERNAL "librtlsdr found")
|
||||||
message(STATUS "librtlsdr not found.")
|
message(STATUS "librtlsdr not found.")
|
||||||
endif(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES)
|
endif(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES)
|
||||||
|
|
||||||
mark_as_advanced(LIBRTLSDR_INCLUDE_DIR LIBRTLSDR_LIBRARIES)
|
mark_as_advanced(LIBRTLSDR_LIBRARIES LIBRTLSDR_INCLUDE_DIRS)
|
||||||
|
|
||||||
endif(NOT LIBRTLSDR_FOUND)
|
endif(NOT LIBRTLSDR_FOUND)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
if(NOT LIBBLADERF_FOUND)
|
if(NOT LIBBLADERF_FOUND)
|
||||||
pkg_check_modules (LIBBLADERF_PKG libbladeRF)
|
pkg_check_modules (LIBBLADERF_PKG libbladeRF)
|
||||||
find_path(LIBBLADERF_INCLUDE_DIR NAMES libbladeRF.h
|
find_path(LIBBLADERF_INCLUDE_DIRS NAMES libbladeRF.h
|
||||||
PATHS
|
PATHS
|
||||||
${LIBBLADERF_PKG_INCLUDE_DIRS}
|
${LIBBLADERF_PKG_INCLUDE_DIRS}
|
||||||
/usr/include
|
/usr/include
|
||||||
|
@ -14,14 +14,14 @@ if(NOT LIBBLADERF_FOUND)
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES)
|
if(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES)
|
||||||
set(LIBBLADERF_FOUND TRUE CACHE INTERNAL "libbladeRF found")
|
set(LIBBLADERF_FOUND TRUE CACHE INTERNAL "libbladeRF found")
|
||||||
message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIR}, ${LIBBLADERF_LIBRARIES}")
|
message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIRS}, ${LIBBLADERF_LIBRARIES}")
|
||||||
else(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES)
|
else(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES)
|
||||||
set(LIBBLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF found")
|
set(LIBBLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF found")
|
||||||
message(STATUS "libbladeRF not found.")
|
message(STATUS "libbladeRF not found.")
|
||||||
endif(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES)
|
endif(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES)
|
||||||
|
|
||||||
mark_as_advanced(LIBBLADERF_INCLUDE_DIR LIBBLADERF_LIBRARIES)
|
mark_as_advanced(LIBBLADERF_LIBRARIES LIBBLADERF_INCLUDE_DIRS)
|
||||||
|
|
||||||
endif(NOT LIBBLADERF_FOUND)
|
endif(NOT LIBBLADERF_FOUND)
|
||||||
|
|
|
@ -48,8 +48,15 @@ else(PYTHON_EXECUTABLE)
|
||||||
|
|
||||||
endif(PYTHON_EXECUTABLE)
|
endif(PYTHON_EXECUTABLE)
|
||||||
|
|
||||||
|
if (CMAKE_CROSSCOMPILING)
|
||||||
|
set(QA_PYTHON_EXECUTABLE "/usr/bin/python")
|
||||||
|
else (CMAKE_CROSSCOMPILING)
|
||||||
|
set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||||
|
endif(CMAKE_CROSSCOMPILING)
|
||||||
|
|
||||||
#make the path to the executable appear in the cmake gui
|
#make the path to the executable appear in the cmake gui
|
||||||
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
|
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
|
||||||
|
set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests")
|
||||||
|
|
||||||
#make sure we can use -B with python (introduced in 2.6)
|
#make sure we can use -B with python (introduced in 2.6)
|
||||||
if(PYTHON_EXECUTABLE)
|
if(PYTHON_EXECUTABLE)
|
||||||
|
|
|
@ -30,6 +30,7 @@ set(__INCLUDED_GR_TEST_CMAKE TRUE)
|
||||||
# GR_TEST_TARGET_DEPS - built targets for the library path
|
# GR_TEST_TARGET_DEPS - built targets for the library path
|
||||||
# GR_TEST_LIBRARY_DIRS - directories for the library path
|
# GR_TEST_LIBRARY_DIRS - directories for the library path
|
||||||
# GR_TEST_PYTHON_DIRS - directories for the python path
|
# GR_TEST_PYTHON_DIRS - directories for the python path
|
||||||
|
# GR_TEST_ENVIRONS - other environment key/value pairs
|
||||||
########################################################################
|
########################################################################
|
||||||
function(GR_ADD_TEST test_name)
|
function(GR_ADD_TEST test_name)
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ function(GR_ADD_TEST test_name)
|
||||||
file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
|
file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
|
||||||
|
|
||||||
set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
|
set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
|
||||||
|
list(APPEND environs ${GR_TEST_ENVIRONS})
|
||||||
|
|
||||||
#http://www.cmake.org/pipermail/cmake/2009-May/029464.html
|
#http://www.cmake.org/pipermail/cmake/2009-May/029464.html
|
||||||
#Replaced this add test + set environs code with the shell script generation.
|
#Replaced this add test + set environs code with the shell script generation.
|
||||||
|
@ -89,7 +91,11 @@ function(GR_ADD_TEST test_name)
|
||||||
list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
|
list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
|
||||||
|
|
||||||
#generate a bat file that sets the environment and runs the test
|
#generate a bat file that sets the environment and runs the test
|
||||||
find_program(SHELL sh)
|
if (CMAKE_CROSSCOMPILING)
|
||||||
|
set(SHELL "/bin/sh")
|
||||||
|
else(CMAKE_CROSSCOMPILING)
|
||||||
|
find_program(SHELL sh)
|
||||||
|
endif(CMAKE_CROSSCOMPILING)
|
||||||
set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
|
set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
|
||||||
file(WRITE ${sh_file} "#!${SHELL}\n")
|
file(WRITE ${sh_file} "#!${SHELL}\n")
|
||||||
#each line sets an environment variable
|
#each line sets an environment variable
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_CONFIG_H_ // [
|
||||||
|
#define _MSC_CONFIG_H_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// enable inline functions for C code
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# define inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// signed size_t
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <stddef.h>
|
||||||
|
typedef ptrdiff_t ssize_t;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// rint functions
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <math.h>
|
||||||
|
static inline long lrint(double x){return (long)(x > 0.0 ? x + 0.5 : x - 0.5);}
|
||||||
|
static inline long lrintf(float x){return (long)(x > 0.0f ? x + 0.5f : x - 0.5f);}
|
||||||
|
static inline long long llrint(double x){return (long long)(x > 0.0 ? x + 0.5 : x - 0.5);}
|
||||||
|
static inline long long llrintf(float x){return (long long)(x > 0.0f ? x + 0.5f : x - 0.5f);}
|
||||||
|
static inline double rint(double x){return (x > 0.0)? floor(x + 0.5) : ceil(x - 0.5);}
|
||||||
|
static inline float rintf(float x){return (x > 0.0f)? floorf(x + 0.5f) : ceilf(x - 0.5f);}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// math constants
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#define INFINITY HUGE_VAL
|
||||||
|
|
||||||
|
# define M_E 2.7182818284590452354 /* e */
|
||||||
|
# define M_LOG2E 1.4426950408889634074 /* log_2 e */
|
||||||
|
# define M_LOG10E 0.43429448190325182765 /* log_10 e */
|
||||||
|
# define M_LN2 0.69314718055994530942 /* log_e 2 */
|
||||||
|
# define M_LN10 2.30258509299404568402 /* log_e 10 */
|
||||||
|
# define M_PI 3.14159265358979323846 /* pi */
|
||||||
|
# define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||||
|
# define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||||
|
# define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||||
|
# define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||||
|
# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||||
|
# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||||
|
# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// random and srandom
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <stdlib.h>
|
||||||
|
static inline long int random (void) { return rand(); }
|
||||||
|
static inline void srandom (unsigned int seed) { srand(seed); }
|
||||||
|
|
||||||
|
#endif // _MSC_CONFIG_H_ ]
|
|
@ -0,0 +1,301 @@
|
||||||
|
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
|
||||||
|
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006 Alexander Chemeris
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. The name of the author may be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_INTTYPES_H_ // [
|
||||||
|
#define _MSC_INTTYPES_H_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 7.8 Format conversion of integer types
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
intmax_t quot;
|
||||||
|
intmax_t rem;
|
||||||
|
} imaxdiv_t;
|
||||||
|
|
||||||
|
// 7.8.1 Macros for format specifiers
|
||||||
|
|
||||||
|
// The fprintf macros for signed integers are:
|
||||||
|
#define PRId8 "d"
|
||||||
|
#define PRIi8 "i"
|
||||||
|
#define PRIdLEAST8 "d"
|
||||||
|
#define PRIiLEAST8 "i"
|
||||||
|
#define PRIdFAST8 "d"
|
||||||
|
#define PRIiFAST8 "i"
|
||||||
|
|
||||||
|
#define PRId16 "hd"
|
||||||
|
#define PRIi16 "hi"
|
||||||
|
#define PRIdLEAST16 "hd"
|
||||||
|
#define PRIiLEAST16 "hi"
|
||||||
|
#define PRIdFAST16 "hd"
|
||||||
|
#define PRIiFAST16 "hi"
|
||||||
|
|
||||||
|
#define PRId32 "I32d"
|
||||||
|
#define PRIi32 "I32i"
|
||||||
|
#define PRIdLEAST32 "I32d"
|
||||||
|
#define PRIiLEAST32 "I32i"
|
||||||
|
#define PRIdFAST32 "I32d"
|
||||||
|
#define PRIiFAST32 "I32i"
|
||||||
|
|
||||||
|
#define PRId64 "I64d"
|
||||||
|
#define PRIi64 "I64i"
|
||||||
|
#define PRIdLEAST64 "I64d"
|
||||||
|
#define PRIiLEAST64 "I64i"
|
||||||
|
#define PRIdFAST64 "I64d"
|
||||||
|
#define PRIiFAST64 "I64i"
|
||||||
|
|
||||||
|
#define PRIdMAX "I64d"
|
||||||
|
#define PRIiMAX "I64i"
|
||||||
|
|
||||||
|
#define PRIdPTR "Id"
|
||||||
|
#define PRIiPTR "Ii"
|
||||||
|
|
||||||
|
// The fprintf macros for unsigned integers are:
|
||||||
|
#define PRIo8 "o"
|
||||||
|
#define PRIu8 "u"
|
||||||
|
#define PRIx8 "x"
|
||||||
|
#define PRIX8 "X"
|
||||||
|
#define PRIoLEAST8 "o"
|
||||||
|
#define PRIuLEAST8 "u"
|
||||||
|
#define PRIxLEAST8 "x"
|
||||||
|
#define PRIXLEAST8 "X"
|
||||||
|
#define PRIoFAST8 "o"
|
||||||
|
#define PRIuFAST8 "u"
|
||||||
|
#define PRIxFAST8 "x"
|
||||||
|
#define PRIXFAST8 "X"
|
||||||
|
|
||||||
|
#define PRIo16 "ho"
|
||||||
|
#define PRIu16 "hu"
|
||||||
|
#define PRIx16 "hx"
|
||||||
|
#define PRIX16 "hX"
|
||||||
|
#define PRIoLEAST16 "ho"
|
||||||
|
#define PRIuLEAST16 "hu"
|
||||||
|
#define PRIxLEAST16 "hx"
|
||||||
|
#define PRIXLEAST16 "hX"
|
||||||
|
#define PRIoFAST16 "ho"
|
||||||
|
#define PRIuFAST16 "hu"
|
||||||
|
#define PRIxFAST16 "hx"
|
||||||
|
#define PRIXFAST16 "hX"
|
||||||
|
|
||||||
|
#define PRIo32 "I32o"
|
||||||
|
#define PRIu32 "I32u"
|
||||||
|
#define PRIx32 "I32x"
|
||||||
|
#define PRIX32 "I32X"
|
||||||
|
#define PRIoLEAST32 "I32o"
|
||||||
|
#define PRIuLEAST32 "I32u"
|
||||||
|
#define PRIxLEAST32 "I32x"
|
||||||
|
#define PRIXLEAST32 "I32X"
|
||||||
|
#define PRIoFAST32 "I32o"
|
||||||
|
#define PRIuFAST32 "I32u"
|
||||||
|
#define PRIxFAST32 "I32x"
|
||||||
|
#define PRIXFAST32 "I32X"
|
||||||
|
|
||||||
|
#define PRIo64 "I64o"
|
||||||
|
#define PRIu64 "I64u"
|
||||||
|
#define PRIx64 "I64x"
|
||||||
|
#define PRIX64 "I64X"
|
||||||
|
#define PRIoLEAST64 "I64o"
|
||||||
|
#define PRIuLEAST64 "I64u"
|
||||||
|
#define PRIxLEAST64 "I64x"
|
||||||
|
#define PRIXLEAST64 "I64X"
|
||||||
|
#define PRIoFAST64 "I64o"
|
||||||
|
#define PRIuFAST64 "I64u"
|
||||||
|
#define PRIxFAST64 "I64x"
|
||||||
|
#define PRIXFAST64 "I64X"
|
||||||
|
|
||||||
|
#define PRIoMAX "I64o"
|
||||||
|
#define PRIuMAX "I64u"
|
||||||
|
#define PRIxMAX "I64x"
|
||||||
|
#define PRIXMAX "I64X"
|
||||||
|
|
||||||
|
#define PRIoPTR "Io"
|
||||||
|
#define PRIuPTR "Iu"
|
||||||
|
#define PRIxPTR "Ix"
|
||||||
|
#define PRIXPTR "IX"
|
||||||
|
|
||||||
|
// The fscanf macros for signed integers are:
|
||||||
|
#define SCNd8 "d"
|
||||||
|
#define SCNi8 "i"
|
||||||
|
#define SCNdLEAST8 "d"
|
||||||
|
#define SCNiLEAST8 "i"
|
||||||
|
#define SCNdFAST8 "d"
|
||||||
|
#define SCNiFAST8 "i"
|
||||||
|
|
||||||
|
#define SCNd16 "hd"
|
||||||
|
#define SCNi16 "hi"
|
||||||
|
#define SCNdLEAST16 "hd"
|
||||||
|
#define SCNiLEAST16 "hi"
|
||||||
|
#define SCNdFAST16 "hd"
|
||||||
|
#define SCNiFAST16 "hi"
|
||||||
|
|
||||||
|
#define SCNd32 "ld"
|
||||||
|
#define SCNi32 "li"
|
||||||
|
#define SCNdLEAST32 "ld"
|
||||||
|
#define SCNiLEAST32 "li"
|
||||||
|
#define SCNdFAST32 "ld"
|
||||||
|
#define SCNiFAST32 "li"
|
||||||
|
|
||||||
|
#define SCNd64 "I64d"
|
||||||
|
#define SCNi64 "I64i"
|
||||||
|
#define SCNdLEAST64 "I64d"
|
||||||
|
#define SCNiLEAST64 "I64i"
|
||||||
|
#define SCNdFAST64 "I64d"
|
||||||
|
#define SCNiFAST64 "I64i"
|
||||||
|
|
||||||
|
#define SCNdMAX "I64d"
|
||||||
|
#define SCNiMAX "I64i"
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define SCNdPTR "I64d"
|
||||||
|
# define SCNiPTR "I64i"
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define SCNdPTR "ld"
|
||||||
|
# define SCNiPTR "li"
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// The fscanf macros for unsigned integers are:
|
||||||
|
#define SCNo8 "o"
|
||||||
|
#define SCNu8 "u"
|
||||||
|
#define SCNx8 "x"
|
||||||
|
#define SCNX8 "X"
|
||||||
|
#define SCNoLEAST8 "o"
|
||||||
|
#define SCNuLEAST8 "u"
|
||||||
|
#define SCNxLEAST8 "x"
|
||||||
|
#define SCNXLEAST8 "X"
|
||||||
|
#define SCNoFAST8 "o"
|
||||||
|
#define SCNuFAST8 "u"
|
||||||
|
#define SCNxFAST8 "x"
|
||||||
|
#define SCNXFAST8 "X"
|
||||||
|
|
||||||
|
#define SCNo16 "ho"
|
||||||
|
#define SCNu16 "hu"
|
||||||
|
#define SCNx16 "hx"
|
||||||
|
#define SCNX16 "hX"
|
||||||
|
#define SCNoLEAST16 "ho"
|
||||||
|
#define SCNuLEAST16 "hu"
|
||||||
|
#define SCNxLEAST16 "hx"
|
||||||
|
#define SCNXLEAST16 "hX"
|
||||||
|
#define SCNoFAST16 "ho"
|
||||||
|
#define SCNuFAST16 "hu"
|
||||||
|
#define SCNxFAST16 "hx"
|
||||||
|
#define SCNXFAST16 "hX"
|
||||||
|
|
||||||
|
#define SCNo32 "lo"
|
||||||
|
#define SCNu32 "lu"
|
||||||
|
#define SCNx32 "lx"
|
||||||
|
#define SCNX32 "lX"
|
||||||
|
#define SCNoLEAST32 "lo"
|
||||||
|
#define SCNuLEAST32 "lu"
|
||||||
|
#define SCNxLEAST32 "lx"
|
||||||
|
#define SCNXLEAST32 "lX"
|
||||||
|
#define SCNoFAST32 "lo"
|
||||||
|
#define SCNuFAST32 "lu"
|
||||||
|
#define SCNxFAST32 "lx"
|
||||||
|
#define SCNXFAST32 "lX"
|
||||||
|
|
||||||
|
#define SCNo64 "I64o"
|
||||||
|
#define SCNu64 "I64u"
|
||||||
|
#define SCNx64 "I64x"
|
||||||
|
#define SCNX64 "I64X"
|
||||||
|
#define SCNoLEAST64 "I64o"
|
||||||
|
#define SCNuLEAST64 "I64u"
|
||||||
|
#define SCNxLEAST64 "I64x"
|
||||||
|
#define SCNXLEAST64 "I64X"
|
||||||
|
#define SCNoFAST64 "I64o"
|
||||||
|
#define SCNuFAST64 "I64u"
|
||||||
|
#define SCNxFAST64 "I64x"
|
||||||
|
#define SCNXFAST64 "I64X"
|
||||||
|
|
||||||
|
#define SCNoMAX "I64o"
|
||||||
|
#define SCNuMAX "I64u"
|
||||||
|
#define SCNxMAX "I64x"
|
||||||
|
#define SCNXMAX "I64X"
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define SCNoPTR "I64o"
|
||||||
|
# define SCNuPTR "I64u"
|
||||||
|
# define SCNxPTR "I64x"
|
||||||
|
# define SCNXPTR "I64X"
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define SCNoPTR "lo"
|
||||||
|
# define SCNuPTR "lu"
|
||||||
|
# define SCNxPTR "lx"
|
||||||
|
# define SCNXPTR "lX"
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// 7.8.2 Functions for greatest-width integer types
|
||||||
|
|
||||||
|
// 7.8.2.1 The imaxabs function
|
||||||
|
#define imaxabs _abs64
|
||||||
|
|
||||||
|
// 7.8.2.2 The imaxdiv function
|
||||||
|
|
||||||
|
// This is modified version of div() function from Microsoft's div.c found
|
||||||
|
// in %MSVC.NET%\crt\src\div.c
|
||||||
|
#ifdef STATIC_IMAXDIV // [
|
||||||
|
static
|
||||||
|
#else // STATIC_IMAXDIV ][
|
||||||
|
_inline
|
||||||
|
#endif // STATIC_IMAXDIV ]
|
||||||
|
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||||
|
{
|
||||||
|
imaxdiv_t result;
|
||||||
|
|
||||||
|
result.quot = numer / denom;
|
||||||
|
result.rem = numer % denom;
|
||||||
|
|
||||||
|
if (numer < 0 && result.rem > 0) {
|
||||||
|
// did division wrong; must fix up
|
||||||
|
++result.quot;
|
||||||
|
result.rem -= denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||||
|
#define strtoimax _strtoi64
|
||||||
|
#define strtoumax _strtoui64
|
||||||
|
|
||||||
|
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||||
|
#define wcstoimax _wcstoi64
|
||||||
|
#define wcstoumax _wcstoui64
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _MSC_INTTYPES_H_ ]
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005, 2006 Apple Computer, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public License
|
||||||
|
* along with this library; see the file COPYING.LIB. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STDBOOL_WIN32_H
|
||||||
|
#define STDBOOL_WIN32_H
|
||||||
|
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
typedef unsigned char bool;
|
||||||
|
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
|
#ifndef CASSERT
|
||||||
|
#define CASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CASSERT(sizeof(bool) == 1, bool_is_one_byte)
|
||||||
|
CASSERT(true, true_is_true)
|
||||||
|
CASSERT(!false, false_is_false)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,251 @@
|
||||||
|
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||||
|
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||||
|
//
|
||||||
|
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. The name of the author may be used to endorse or promote products
|
||||||
|
// derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||||
|
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_STDINT_H_ // [
|
||||||
|
#define _MSC_STDINT_H_
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||||
|
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||||
|
// or compiler give many errors like this:
|
||||||
|
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
# include <wchar.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||||
|
#ifndef _W64
|
||||||
|
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||||
|
# define _W64 __w64
|
||||||
|
# else
|
||||||
|
# define _W64
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.1 Integer types
|
||||||
|
|
||||||
|
// 7.18.1.1 Exact-width integer types
|
||||||
|
|
||||||
|
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||||
|
// realize that, e.g. char has the same size as __int8
|
||||||
|
// so we give up on __intX for them.
|
||||||
|
#if (_MSC_VER < 1300)
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
#else
|
||||||
|
typedef signed __int8 int8_t;
|
||||||
|
typedef signed __int16 int16_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
#endif
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.1.2 Minimum-width integer types
|
||||||
|
typedef int8_t int_least8_t;
|
||||||
|
typedef int16_t int_least16_t;
|
||||||
|
typedef int32_t int_least32_t;
|
||||||
|
typedef int64_t int_least64_t;
|
||||||
|
typedef uint8_t uint_least8_t;
|
||||||
|
typedef uint16_t uint_least16_t;
|
||||||
|
typedef uint32_t uint_least32_t;
|
||||||
|
typedef uint64_t uint_least64_t;
|
||||||
|
|
||||||
|
// 7.18.1.3 Fastest minimum-width integer types
|
||||||
|
typedef int8_t int_fast8_t;
|
||||||
|
typedef int16_t int_fast16_t;
|
||||||
|
typedef int32_t int_fast32_t;
|
||||||
|
typedef int64_t int_fast64_t;
|
||||||
|
typedef uint8_t uint_fast8_t;
|
||||||
|
typedef uint16_t uint_fast16_t;
|
||||||
|
typedef uint32_t uint_fast32_t;
|
||||||
|
typedef uint64_t uint_fast64_t;
|
||||||
|
|
||||||
|
// 7.18.1.4 Integer types capable of holding object pointers
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
typedef signed __int64 intptr_t;
|
||||||
|
typedef unsigned __int64 uintptr_t;
|
||||||
|
#else // _WIN64 ][
|
||||||
|
typedef _W64 signed int intptr_t;
|
||||||
|
typedef _W64 unsigned int uintptr_t;
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// 7.18.1.5 Greatest-width integer types
|
||||||
|
typedef int64_t intmax_t;
|
||||||
|
typedef uint64_t uintmax_t;
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.2 Limits of specified-width integer types
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||||
|
|
||||||
|
// 7.18.2.1 Limits of exact-width integer types
|
||||||
|
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||||
|
#define INT8_MAX _I8_MAX
|
||||||
|
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||||
|
#define INT16_MAX _I16_MAX
|
||||||
|
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||||
|
#define INT32_MAX _I32_MAX
|
||||||
|
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||||
|
#define INT64_MAX _I64_MAX
|
||||||
|
#define UINT8_MAX _UI8_MAX
|
||||||
|
#define UINT16_MAX _UI16_MAX
|
||||||
|
#define UINT32_MAX _UI32_MAX
|
||||||
|
#define UINT64_MAX _UI64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.2 Limits of minimum-width integer types
|
||||||
|
#define INT_LEAST8_MIN INT8_MIN
|
||||||
|
#define INT_LEAST8_MAX INT8_MAX
|
||||||
|
#define INT_LEAST16_MIN INT16_MIN
|
||||||
|
#define INT_LEAST16_MAX INT16_MAX
|
||||||
|
#define INT_LEAST32_MIN INT32_MIN
|
||||||
|
#define INT_LEAST32_MAX INT32_MAX
|
||||||
|
#define INT_LEAST64_MIN INT64_MIN
|
||||||
|
#define INT_LEAST64_MAX INT64_MAX
|
||||||
|
#define UINT_LEAST8_MAX UINT8_MAX
|
||||||
|
#define UINT_LEAST16_MAX UINT16_MAX
|
||||||
|
#define UINT_LEAST32_MAX UINT32_MAX
|
||||||
|
#define UINT_LEAST64_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||||
|
#define INT_FAST8_MIN INT8_MIN
|
||||||
|
#define INT_FAST8_MAX INT8_MAX
|
||||||
|
#define INT_FAST16_MIN INT16_MIN
|
||||||
|
#define INT_FAST16_MAX INT16_MAX
|
||||||
|
#define INT_FAST32_MIN INT32_MIN
|
||||||
|
#define INT_FAST32_MAX INT32_MAX
|
||||||
|
#define INT_FAST64_MIN INT64_MIN
|
||||||
|
#define INT_FAST64_MAX INT64_MAX
|
||||||
|
#define UINT_FAST8_MAX UINT8_MAX
|
||||||
|
#define UINT_FAST16_MAX UINT16_MAX
|
||||||
|
#define UINT_FAST32_MAX UINT32_MAX
|
||||||
|
#define UINT_FAST64_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define INTPTR_MIN INT64_MIN
|
||||||
|
# define INTPTR_MAX INT64_MAX
|
||||||
|
# define UINTPTR_MAX UINT64_MAX
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define INTPTR_MIN INT32_MIN
|
||||||
|
# define INTPTR_MAX INT32_MAX
|
||||||
|
# define UINTPTR_MAX UINT32_MAX
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
// 7.18.2.5 Limits of greatest-width integer types
|
||||||
|
#define INTMAX_MIN INT64_MIN
|
||||||
|
#define INTMAX_MAX INT64_MAX
|
||||||
|
#define UINTMAX_MAX UINT64_MAX
|
||||||
|
|
||||||
|
// 7.18.3 Limits of other integer types
|
||||||
|
|
||||||
|
#ifdef _WIN64 // [
|
||||||
|
# define PTRDIFF_MIN _I64_MIN
|
||||||
|
# define PTRDIFF_MAX _I64_MAX
|
||||||
|
#else // _WIN64 ][
|
||||||
|
# define PTRDIFF_MIN _I32_MIN
|
||||||
|
# define PTRDIFF_MAX _I32_MAX
|
||||||
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
|
#define SIG_ATOMIC_MIN INT_MIN
|
||||||
|
#define SIG_ATOMIC_MAX INT_MAX
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX // [
|
||||||
|
# ifdef _WIN64 // [
|
||||||
|
# define SIZE_MAX _UI64_MAX
|
||||||
|
# else // _WIN64 ][
|
||||||
|
# define SIZE_MAX _UI32_MAX
|
||||||
|
# endif // _WIN64 ]
|
||||||
|
#endif // SIZE_MAX ]
|
||||||
|
|
||||||
|
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||||
|
#ifndef WCHAR_MIN // [
|
||||||
|
# define WCHAR_MIN 0
|
||||||
|
#endif // WCHAR_MIN ]
|
||||||
|
#ifndef WCHAR_MAX // [
|
||||||
|
# define WCHAR_MAX _UI16_MAX
|
||||||
|
#endif // WCHAR_MAX ]
|
||||||
|
|
||||||
|
#define WINT_MIN 0
|
||||||
|
#define WINT_MAX _UI16_MAX
|
||||||
|
|
||||||
|
#endif // __STDC_LIMIT_MACROS ]
|
||||||
|
|
||||||
|
|
||||||
|
// 7.18.4 Limits of other integer types
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||||
|
|
||||||
|
// 7.18.4.1 Macros for minimum-width integer constants
|
||||||
|
|
||||||
|
#define INT8_C(val) val##i8
|
||||||
|
#define INT16_C(val) val##i16
|
||||||
|
#define INT32_C(val) val##i32
|
||||||
|
#define INT64_C(val) val##i64
|
||||||
|
|
||||||
|
#define UINT8_C(val) val##ui8
|
||||||
|
#define UINT16_C(val) val##ui16
|
||||||
|
#define UINT32_C(val) val##ui32
|
||||||
|
#define UINT64_C(val) val##ui64
|
||||||
|
|
||||||
|
// 7.18.4.2 Macros for greatest-width integer constants
|
||||||
|
#ifndef INTMAX_C
|
||||||
|
#define INTMAX_C INT64_C
|
||||||
|
#endif
|
||||||
|
#ifndef UINTMAX_C
|
||||||
|
#define UINTMAX_C UINT64_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __STDC_CONSTANT_MACROS ]
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _MSC_STDINT_H_ ]
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_SYS_TIME_H_
|
||||||
|
#define _MSC_SYS_TIME_H_
|
||||||
|
|
||||||
|
//http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/430449b3-f6dd-4e18-84de-eebd26a8d668
|
||||||
|
#include < time.h >
|
||||||
|
#include <windows.h> //I've ommited this line.
|
||||||
|
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
|
||||||
|
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
|
||||||
|
#else
|
||||||
|
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct timespec {
|
||||||
|
|
||||||
|
time_t tv_sec; /* Seconds since 00:00:00 GMT, */
|
||||||
|
|
||||||
|
/* 1 January 1970 */
|
||||||
|
|
||||||
|
long tv_nsec; /* Additional nanoseconds since */
|
||||||
|
|
||||||
|
/* tv_sec */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timezone
|
||||||
|
{
|
||||||
|
int tz_minuteswest; /* minutes W of Greenwich */
|
||||||
|
int tz_dsttime; /* type of dst correction */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
unsigned __int64 tmpres = 0;
|
||||||
|
static int tzflag;
|
||||||
|
|
||||||
|
if (NULL != tv)
|
||||||
|
{
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
|
||||||
|
tmpres |= ft.dwHighDateTime;
|
||||||
|
tmpres <<= 32;
|
||||||
|
tmpres |= ft.dwLowDateTime;
|
||||||
|
|
||||||
|
/*converting file time to unix epoch*/
|
||||||
|
tmpres -= DELTA_EPOCH_IN_MICROSECS;
|
||||||
|
tv->tv_sec = (long)(tmpres / 1000000UL);
|
||||||
|
tv->tv_usec = (long)(tmpres % 1000000UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != tz)
|
||||||
|
{
|
||||||
|
if (!tzflag)
|
||||||
|
{
|
||||||
|
_tzset();
|
||||||
|
tzflag++;
|
||||||
|
}
|
||||||
|
tz->tz_minuteswest = _timezone / 60;
|
||||||
|
tz->tz_dsttime = _daylight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_MSC_SYS_TIME_H_
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef _MSC_VER // [
|
||||||
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
|
#endif // _MSC_VER ]
|
||||||
|
|
||||||
|
#ifndef _MSC_UNISTD_H_ // [
|
||||||
|
#define _MSC_UNISTD_H_
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
#endif // _MSC_UNISTD_H_ ]
|
|
@ -1,14 +1,14 @@
|
||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
prefix=@prefix@
|
||||||
exec_prefix=${prefix}
|
exec_prefix=@exec_prefix@
|
||||||
libdir=${exec_prefix}/@GR_LIBRARY_DIR@
|
libdir=@libdir@
|
||||||
includedir=${prefix}/@GR_INCLUDE_DIR@
|
includedir=@includedir@
|
||||||
|
|
||||||
Name: @CPACK_PACKAGE_NAME@
|
Name: @CPACK_PACKAGE_NAME@
|
||||||
Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@
|
Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@
|
||||||
URL: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
URL: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
||||||
Version: @CPACK_PACKAGE_VERSION@
|
Version: @CPACK_PACKAGE_VERSION@
|
||||||
Requires: gnuradio-runtime gnuradio-blocks
|
Requires: @GR_OSMOSDR_PC_REQUIRES@
|
||||||
Requires.private: @GR_OSMOSDR_PC_REQUIRES@
|
Requires.private:
|
||||||
Conflicts:
|
Conflicts:
|
||||||
Cflags: -I${includedir} @GR_OSMOSDR_PC_CFLAGS@
|
Cflags: -I${includedir} @GR_OSMOSDR_PC_CFLAGS@
|
||||||
Libs: -L${libdir} -lgnuradio-osmosdr
|
Libs: -L${libdir} -lgnuradio-osmosdr
|
||||||
|
|
|
@ -26,7 +26,7 @@ MAIN_TMPL = """\
|
||||||
<category>$($sourk.title())s</category>
|
<category>$($sourk.title())s</category>
|
||||||
<throttle>1</throttle>
|
<throttle>1</throttle>
|
||||||
<import>import osmosdr</import>
|
<import>import osmosdr</import>
|
||||||
<make>osmosdr.$(sourk)( args="nchan=" + str(\$nchan) + " " + \$args )
|
<make>osmosdr.$(sourk)( args="numchan=" + str(\$nchan) + " " + \$args )
|
||||||
self.\$(id).set_sample_rate(\$sample_rate)
|
self.\$(id).set_sample_rate(\$sample_rate)
|
||||||
#for $n in range($max_nchan)
|
#for $n in range($max_nchan)
|
||||||
\#if \$nchan() > $n
|
\#if \$nchan() > $n
|
||||||
|
@ -118,16 +118,17 @@ While primarily being developed for the OsmoSDR hardware, this block as well sup
|
||||||
* FUNcube Dongle through libgnuradio-fcd
|
* FUNcube Dongle through libgnuradio-fcd
|
||||||
* FUNcube Dongle Pro+ through gr-fcdproplus
|
* FUNcube Dongle Pro+ through gr-fcdproplus
|
||||||
* sysmocom OsmoSDR Devices through libosmosdr
|
* sysmocom OsmoSDR Devices through libosmosdr
|
||||||
#end if
|
|
||||||
* Nuand LLC bladeRF through libbladeRF library
|
|
||||||
* Great Scott Gadgets HackRF through libhackrf
|
|
||||||
* Ettus USRP Devices through Ettus UHD library
|
|
||||||
#if $sourk == 'source':
|
|
||||||
* RTL2832U based DVB-T dongles through librtlsdr
|
* RTL2832U based DVB-T dongles through librtlsdr
|
||||||
* RTL-TCP spectrum server (see librtlsdr project)
|
* RTL-TCP spectrum server (see librtlsdr project)
|
||||||
* MSi2500 based DVB-T dongles through libmirisdr
|
* MSi2500 based DVB-T dongles through libmirisdr
|
||||||
* gnuradio .cfile input through libgnuradio-blocks
|
* gnuradio .cfile input through libgnuradio-blocks
|
||||||
|
* RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option)
|
||||||
|
* AirSpy Wideband Receiver through libairspy
|
||||||
#end if
|
#end if
|
||||||
|
* Great Scott Gadgets HackRF through libhackrf
|
||||||
|
* Nuand LLC bladeRF through libbladeRF library
|
||||||
|
* Ettus USRP Devices through Ettus UHD library
|
||||||
|
* Fairwaves UmTRX through Fairwaves' fork of UHD
|
||||||
|
|
||||||
By using the osmocom $sourk block you can take advantage of a common software api in your application(s) independent of the underlying radio hardware.
|
By using the osmocom $sourk block you can take advantage of a common software api in your application(s) independent of the underlying radio hardware.
|
||||||
|
|
||||||
|
@ -145,22 +146,22 @@ Lines ending with ... mean it's possible to bind devices together by specifying
|
||||||
|
|
||||||
#if $sourk == 'source':
|
#if $sourk == 'source':
|
||||||
fcd=0[,device=hw:2][,type=2]
|
fcd=0[,device=hw:2][,type=2]
|
||||||
hackrf=0[,buffers=32]
|
|
||||||
miri=0[,buffers=32] ...
|
miri=0[,buffers=32] ...
|
||||||
rtl=serial_number ...
|
rtl=serial_number ...
|
||||||
rtl=0[,rtl_xtal=28.8e6][,tuner_xtal=28.8e6] ...
|
rtl=0[,rtl_xtal=28.8e6][,tuner_xtal=28.8e6] ...
|
||||||
rtl=1[,buffers=32][,buflen=N*512] ...
|
rtl=1[,buffers=32][,buflen=N*512] ...
|
||||||
rtl=2[,direct_samp=0|1|2][,offset_tune=0|1] ...
|
rtl=2[,direct_samp=0|1|2][,offset_tune=0|1] ...
|
||||||
rtl_tcp=127.0.0.1:1234[,psize=16384][,direct_samp=0|1|2][,offset_tune=0|1] ...
|
rtl_tcp=127.0.0.1:1234[,psize=16384][,direct_samp=0|1|2][,offset_tune=0|1] ...
|
||||||
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
|
|
||||||
bladerf=0[,fpga='/path/to/the/bitstream.rbf'][,fw='/path/to/the/firmware.img']
|
|
||||||
osmosdr=0[,buffers=32][,buflen=N*512] ...
|
osmosdr=0[,buffers=32][,buflen=N*512] ...
|
||||||
file='/path/to/your file',rate=1e6[,freq=100e6][,repeat=true][,throttle=true] ...
|
file='/path/to/your file',rate=1e6[,freq=100e6][,repeat=true][,throttle=true] ...
|
||||||
|
netsdr=127.0.0.1[:50000][,nchan=2]
|
||||||
|
sdr-ip=127.0.0.1[:50000]
|
||||||
|
sdr-iq=/dev/ttyUSB0
|
||||||
|
airspy=0
|
||||||
#end if
|
#end if
|
||||||
#if $sourk == 'sink':
|
|
||||||
hackrf=0[,buffers=32]
|
hackrf=0[,buffers=32]
|
||||||
|
bladerf=0[,fpga='/path/to/the/bitstream.rbf']
|
||||||
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
|
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
|
||||||
#end if
|
|
||||||
|
|
||||||
Num Channels:
|
Num Channels:
|
||||||
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
|
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
|
||||||
|
|
|
@ -101,6 +101,9 @@ namespace osmosdr {
|
||||||
* The device hint should be used to narrow down the search
|
* The device hint should be used to narrow down the search
|
||||||
* to particular transport types and/or transport arguments.
|
* to particular transport types and/or transport arguments.
|
||||||
*
|
*
|
||||||
|
* The device hint "nofake" switches off dummy devices created
|
||||||
|
* by "file" (and other) implementations.
|
||||||
|
*
|
||||||
* \param hint a partially (or fully) filled in logical device
|
* \param hint a partially (or fully) filled in logical device
|
||||||
* \return a vector of logical devices for all radios on the system
|
* \return a vector of logical devices for all radios on the system
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
# Copyright 2011 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This file is part of GNU Radio
|
||||||
|
#
|
||||||
|
# GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Install public header files
|
||||||
|
########################################################################
|
||||||
|
install(FILES
|
||||||
|
gnuradio/blocks/api.h
|
||||||
|
gnuradio/blocks/null_sink.h
|
||||||
|
gnuradio/blocks/null_source.h
|
||||||
|
gnuradio/blocks/throttle.h
|
||||||
|
DESTINATION include/osmosdr/runtime/gnuradio/blocks
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES
|
||||||
|
gnuradio/thread/thread.h
|
||||||
|
gnuradio/thread/thread_body_wrapper.h
|
||||||
|
gnuradio/thread/thread_group.h
|
||||||
|
DESTINATION include/osmosdr/runtime/gnuradio/thread
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES
|
||||||
|
gnuradio/uhd/api.h
|
||||||
|
gnuradio/uhd/usrp_sink.h
|
||||||
|
gnuradio/uhd/usrp_source.h
|
||||||
|
DESTINATION include/osmosdr/runtime/gnuradio/uhd
|
||||||
|
)
|
||||||
|
install(FILES
|
||||||
|
gnuradio/api.h
|
||||||
|
gnuradio/attributes.h
|
||||||
|
gnuradio/basic_block.h
|
||||||
|
gnuradio/block.h
|
||||||
|
gnuradio/block_detail.h
|
||||||
|
gnuradio/block_gateway.h
|
||||||
|
gnuradio/block_registry.h
|
||||||
|
gnuradio/buffer.h
|
||||||
|
gnuradio/constants.h
|
||||||
|
gnuradio/endianness.h
|
||||||
|
gnuradio/expj.h
|
||||||
|
gnuradio/feval.h
|
||||||
|
gnuradio/flowgraph.h
|
||||||
|
gnuradio/fxpt.h
|
||||||
|
gnuradio/fxpt_nco.h
|
||||||
|
gnuradio/fxpt_vco.h
|
||||||
|
gnuradio/gr_complex.h
|
||||||
|
gnuradio/hier_block2.h
|
||||||
|
gnuradio/high_res_timer.h
|
||||||
|
gnuradio/io_signature.h
|
||||||
|
gnuradio/logger.h
|
||||||
|
gnuradio/math.h
|
||||||
|
gnuradio/misc.h
|
||||||
|
gnuradio/prefs.h
|
||||||
|
gnuradio/random.h
|
||||||
|
gnuradio/realtime.h
|
||||||
|
gnuradio/realtime_impl.h
|
||||||
|
gnuradio/runtime_types.h
|
||||||
|
gnuradio/sincos.h
|
||||||
|
gnuradio/sptr_magic.h
|
||||||
|
gnuradio/sync_block.h
|
||||||
|
gnuradio/sync_decimator.h
|
||||||
|
gnuradio/sync_interpolator.h
|
||||||
|
gnuradio/sys_paths.h
|
||||||
|
gnuradio/top_block.h
|
||||||
|
gnuradio/tpb_detail.h
|
||||||
|
gnuradio/types.h
|
||||||
|
DESTINATION include/osmosdr/runtime/gnuradio
|
||||||
|
)
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2011 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_RUNTIME_API_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_RUNTIME_API_H
|
||||||
|
|
||||||
|
#include <gnuradio/attributes.h>
|
||||||
|
|
||||||
|
#ifdef gnuradio_runtime_EXPORTS
|
||||||
|
# define GR_RUNTIME_API __GR_ATTR_EXPORT
|
||||||
|
#else
|
||||||
|
# define GR_RUNTIME_API __GR_ATTR_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_RUNTIME_API_H */
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GNURADIO_ATTRIBUTES_H
|
||||||
|
#define INCLUDED_GNURADIO_ATTRIBUTES_H
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cross-platform attribute macros
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#if defined __GNUC__
|
||||||
|
# define __GR_ATTR_ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
# define __GR_ATTR_UNUSED __attribute__((unused))
|
||||||
|
# define __GR_ATTR_INLINE __attribute__((always_inline))
|
||||||
|
# define __GR_ATTR_DEPRECATED __attribute__((deprecated))
|
||||||
|
# if __GNUC__ >= 4
|
||||||
|
# define __GR_ATTR_EXPORT __attribute__((visibility("default")))
|
||||||
|
# define __GR_ATTR_IMPORT __attribute__((visibility("default")))
|
||||||
|
# else
|
||||||
|
# define __GR_ATTR_EXPORT
|
||||||
|
# define __GR_ATTR_IMPORT
|
||||||
|
# endif
|
||||||
|
#elif _MSC_VER
|
||||||
|
# define __GR_ATTR_ALIGNED(x) __declspec(align(x))
|
||||||
|
# define __GR_ATTR_UNUSED
|
||||||
|
# define __GR_ATTR_INLINE __forceinline
|
||||||
|
# define __GR_ATTR_DEPRECATED __declspec(deprecated)
|
||||||
|
# define __GR_ATTR_EXPORT __declspec(dllexport)
|
||||||
|
# define __GR_ATTR_IMPORT __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
# define __GR_ATTR_ALIGNED(x)
|
||||||
|
# define __GR_ATTR_UNUSED
|
||||||
|
# define __GR_ATTR_INLINE
|
||||||
|
# define __GR_ATTR_DEPRECATED
|
||||||
|
# define __GR_ATTR_EXPORT
|
||||||
|
# define __GR_ATTR_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// define inline when building C
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline)
|
||||||
|
# define inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// suppress warnings
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
|
||||||
|
# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
|
||||||
|
# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data
|
||||||
|
# pragma warning(disable: 4305) // 'initializing' : truncation from 'double' to 'float'
|
||||||
|
# pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GNURADIO_ATTRIBUTES_H */
|
|
@ -0,0 +1,209 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2008,2009,2011,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_BASIC_BLOCK_H
|
||||||
|
#define INCLUDED_GR_BASIC_BLOCK_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/sptr_magic.h>
|
||||||
|
#include <gnuradio/runtime_types.h>
|
||||||
|
#include <gnuradio/io_signature.h>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <boost/any.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#ifdef GR_CTRLPORT
|
||||||
|
#include <gnuradio/rpcregisterhelpers.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The abstract base class for all signal processing blocks.
|
||||||
|
* \ingroup internal
|
||||||
|
*
|
||||||
|
* Basic blocks are the bare abstraction of an entity that has a
|
||||||
|
* name, a set of inputs and outputs, and a message queue. These
|
||||||
|
* are never instantiated directly; rather, this is the abstract
|
||||||
|
* parent class of both gr_hier_block, which is a recursive
|
||||||
|
* container, and block, which implements actual signal
|
||||||
|
* processing functions.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API basic_block : public boost::enable_shared_from_this<basic_block>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
gr::thread::mutex mutex; //< protects all vars
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class flowgraph;
|
||||||
|
friend class flat_flowgraph; // TODO: will be redundant
|
||||||
|
friend class tpb_thread_body;
|
||||||
|
|
||||||
|
enum vcolor { WHITE, GREY, BLACK };
|
||||||
|
|
||||||
|
std::string d_name;
|
||||||
|
gr::io_signature::sptr d_input_signature;
|
||||||
|
gr::io_signature::sptr d_output_signature;
|
||||||
|
long d_unique_id;
|
||||||
|
long d_symbolic_id;
|
||||||
|
std::string d_symbol_name;
|
||||||
|
std::string d_symbol_alias;
|
||||||
|
vcolor d_color;
|
||||||
|
bool d_rpc_set;
|
||||||
|
|
||||||
|
std::vector<boost::any> d_rpc_vars; // container for all RPC variables
|
||||||
|
|
||||||
|
basic_block(void) {} // allows pure virtual interface sub-classes
|
||||||
|
|
||||||
|
//! Protected constructor prevents instantiation by non-derived classes
|
||||||
|
basic_block(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
//! may only be called during constructor
|
||||||
|
void set_input_signature(gr::io_signature::sptr iosig) {
|
||||||
|
d_input_signature = iosig;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! may only be called during constructor
|
||||||
|
void set_output_signature(gr::io_signature::sptr iosig) {
|
||||||
|
d_output_signature = iosig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Allow the flowgraph to set for sorting and partitioning
|
||||||
|
*/
|
||||||
|
void set_color(vcolor color) { d_color = color; }
|
||||||
|
vcolor color() const { return d_color; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~basic_block();
|
||||||
|
long unique_id() const { return d_unique_id; }
|
||||||
|
long symbolic_id() const { return d_symbolic_id; }
|
||||||
|
std::string name() const { return d_name; }
|
||||||
|
std::string symbol_name() const { return d_symbol_name; }
|
||||||
|
gr::io_signature::sptr input_signature() const { return d_input_signature; }
|
||||||
|
gr::io_signature::sptr output_signature() const { return d_output_signature; }
|
||||||
|
basic_block_sptr to_basic_block(); // Needed for Python type coercion
|
||||||
|
bool alias_set() { return !d_symbol_alias.empty(); }
|
||||||
|
std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
|
||||||
|
void set_block_alias(std::string name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GR_CTRLPORT
|
||||||
|
/*!
|
||||||
|
* \brief Add an RPC variable (get or set).
|
||||||
|
*
|
||||||
|
* Using controlport, we create new getters/setters and need to
|
||||||
|
* store them. Each block has a vector to do this, and these never
|
||||||
|
* need to be accessed again once they are registered with the RPC
|
||||||
|
* backend. This function takes a
|
||||||
|
* boost::shared_sptr<rpcbasic_base> so that when the block is
|
||||||
|
* deleted, all RPC registered variables are cleaned up.
|
||||||
|
*
|
||||||
|
* \param s an rpcbasic_sptr of the new RPC variable register to store.
|
||||||
|
*/
|
||||||
|
void add_rpc_variable(rpcbasic_sptr s)
|
||||||
|
{
|
||||||
|
d_rpc_vars.push_back(s);
|
||||||
|
}
|
||||||
|
#endif /* GR_CTRLPORT */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set up the RPC registered variables.
|
||||||
|
*
|
||||||
|
* This must be overloaded by a block that wants to use
|
||||||
|
* controlport. This is where rpcbasic_register_{get,set} pointers
|
||||||
|
* are created, which then get wrapped as shared pointers
|
||||||
|
* (rpcbasic_sptr(...)) and stored using add_rpc_variable.
|
||||||
|
*/
|
||||||
|
virtual void setup_rpc() {};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Ask if this block has been registered to the RPC.
|
||||||
|
*
|
||||||
|
* We can only register a block once, so we use this to protect us
|
||||||
|
* from calling it multiple times.
|
||||||
|
*/
|
||||||
|
bool is_rpc_set() { return d_rpc_set; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief When the block is registered with the RPC, set this.
|
||||||
|
*/
|
||||||
|
void rpc_set() { d_rpc_set = true; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Confirm that ninputs and noutputs is an acceptable combination.
|
||||||
|
*
|
||||||
|
* \param ninputs number of input streams connected
|
||||||
|
* \param noutputs number of output streams connected
|
||||||
|
*
|
||||||
|
* \returns true if this is a valid configuration for this block.
|
||||||
|
*
|
||||||
|
* This function is called by the runtime system whenever the
|
||||||
|
* topology changes. Most classes do not need to override this.
|
||||||
|
* This check is in addition to the constraints specified by the
|
||||||
|
* input and output gr::io_signatures.
|
||||||
|
*/
|
||||||
|
virtual bool check_topology(int ninputs, int noutputs) {
|
||||||
|
(void)ninputs;
|
||||||
|
(void)noutputs;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set_processor_affinity(const std::vector<int> &mask)
|
||||||
|
{ throw std::runtime_error("set_processor_affinity not overloaded in child class."); }
|
||||||
|
|
||||||
|
virtual void unset_processor_affinity()
|
||||||
|
{ throw std::runtime_error("unset_processor_affinity not overloaded in child class."); }
|
||||||
|
|
||||||
|
virtual std::vector<int> processor_affinity()
|
||||||
|
{ throw std::runtime_error("processor_affinity not overloaded in child class."); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator<(basic_block_sptr lhs, basic_block_sptr rhs)
|
||||||
|
{
|
||||||
|
return lhs->unique_id() < rhs->unique_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::vector<basic_block_sptr> basic_block_vector_t;
|
||||||
|
typedef std::vector<basic_block_sptr>::iterator basic_block_viter_t;
|
||||||
|
|
||||||
|
GR_RUNTIME_API long basic_block_ncurrently_allocated();
|
||||||
|
|
||||||
|
inline std::ostream &operator << (std::ostream &os, basic_block_sptr basic_block)
|
||||||
|
{
|
||||||
|
os << basic_block->name() << "(" << basic_block->unique_id() << ")";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_BASIC_BLOCK_H */
|
|
@ -0,0 +1,573 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2007,2009,2010,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_BLOCK_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_BLOCK_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/basic_block.h>
|
||||||
|
#include <gnuradio/logger.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The abstract base class for all 'terminal' processing blocks.
|
||||||
|
* \ingroup base_blk
|
||||||
|
*
|
||||||
|
* A signal processing flow is constructed by creating a tree of
|
||||||
|
* hierarchical blocks, which at any level may also contain terminal
|
||||||
|
* nodes that actually implement signal processing functions. This
|
||||||
|
* is the base class for all such leaf nodes.
|
||||||
|
*
|
||||||
|
* Blocks have a set of input streams and output streams. The
|
||||||
|
* input_signature and output_signature define the number of input
|
||||||
|
* streams and output streams respectively, and the type of the data
|
||||||
|
* items in each stream.
|
||||||
|
*
|
||||||
|
* Although blocks may consume data on each input stream at a
|
||||||
|
* different rate, all outputs streams must produce data at the same
|
||||||
|
* rate. That rate may be different from any of the input rates.
|
||||||
|
*
|
||||||
|
* User derived blocks override two methods, forecast and
|
||||||
|
* general_work, to implement their signal processing
|
||||||
|
* behavior. forecast is called by the system scheduler to determine
|
||||||
|
* how many items are required on each input stream in order to
|
||||||
|
* produce a given number of output items.
|
||||||
|
*
|
||||||
|
* general_work is called to perform the signal processing in the
|
||||||
|
* block. It reads the input items and writes the output items.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API block : public basic_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Magic return values from general_work
|
||||||
|
enum {
|
||||||
|
WORK_CALLED_PRODUCE = -2,
|
||||||
|
WORK_DONE = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum tag_propagation_policy_t {
|
||||||
|
TPP_DONT = 0,
|
||||||
|
TPP_ALL_TO_ALL = 1,
|
||||||
|
TPP_ONE_TO_ONE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~block();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...)
|
||||||
|
* History is the number of x_i's that are examined to produce one y_i.
|
||||||
|
* This comes in handy for FIR filters, where we use history to
|
||||||
|
* ensure that our input contains the appropriate "history" for the
|
||||||
|
* filter. History should be equal to the number of filter taps.
|
||||||
|
*/
|
||||||
|
unsigned history() const { return d_history; }
|
||||||
|
void set_history(unsigned history) { d_history = history; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return true if this block has a fixed input to output rate.
|
||||||
|
*
|
||||||
|
* If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
|
||||||
|
*/
|
||||||
|
bool fixed_rate() const { return d_fixed_rate; }
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// override these to define your behavior
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Estimate input requirements given output request
|
||||||
|
*
|
||||||
|
* \param noutput_items number of output items to produce
|
||||||
|
* \param ninput_items_required number of input items required on each input stream
|
||||||
|
*
|
||||||
|
* Given a request to product \p noutput_items, estimate the
|
||||||
|
* number of data items required on each input stream. The
|
||||||
|
* estimate doesn't have to be exact, but should be close.
|
||||||
|
*/
|
||||||
|
virtual void forecast(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items_required);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief compute output items from input items
|
||||||
|
*
|
||||||
|
* \param noutput_items number of output items to write on each output stream
|
||||||
|
* \param ninput_items number of input items available on each input stream
|
||||||
|
* \param input_items vector of pointers to the input items, one entry per input stream
|
||||||
|
* \param output_items vector of pointers to the output items, one entry per output stream
|
||||||
|
*
|
||||||
|
* \returns number of items actually written to each output stream, or -1 on EOF.
|
||||||
|
* It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items
|
||||||
|
*
|
||||||
|
* general_work must call consume or consume_each to indicate how
|
||||||
|
* many items were consumed on each input stream.
|
||||||
|
*/
|
||||||
|
virtual int general_work(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Called to enable drivers, etc for i/o devices.
|
||||||
|
*
|
||||||
|
* This allows a block to enable an associated driver to begin
|
||||||
|
* transfering data just before we start to execute the scheduler.
|
||||||
|
* The end result is that this reduces latency in the pipeline
|
||||||
|
* when dealing with audio devices, usrps, etc.
|
||||||
|
*/
|
||||||
|
virtual bool start();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Called to disable drivers, etc for i/o devices.
|
||||||
|
*/
|
||||||
|
virtual bool stop();
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constrain the noutput_items argument passed to forecast and general_work
|
||||||
|
*
|
||||||
|
* set_output_multiple causes the scheduler to ensure that the
|
||||||
|
* noutput_items argument passed to forecast and general_work will
|
||||||
|
* be an integer multiple of \param multiple The default value of
|
||||||
|
* output multiple is 1.
|
||||||
|
*/
|
||||||
|
void set_output_multiple(int multiple);
|
||||||
|
int output_multiple() const { return d_output_multiple; }
|
||||||
|
bool output_multiple_set() const { return d_output_multiple_set; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constrains buffers to work on a set item alignment (for SIMD)
|
||||||
|
*
|
||||||
|
* set_alignment_multiple causes the scheduler to ensure that the
|
||||||
|
* noutput_items argument passed to forecast and general_work will
|
||||||
|
* be an integer multiple of \param multiple The default value is
|
||||||
|
* 1.
|
||||||
|
*
|
||||||
|
* This control is similar to the output_multiple setting, except
|
||||||
|
* that if the number of items passed to the block is less than
|
||||||
|
* the output_multiple, this value is ignored and the block can
|
||||||
|
* produce like normal. The d_unaligned value is set to the number
|
||||||
|
* of items the block is off by. In the next call to general_work,
|
||||||
|
* the noutput_items is set to d_unaligned or less until
|
||||||
|
* d_unaligned==0. The buffers are now aligned again and the
|
||||||
|
* aligned calls can be performed again.
|
||||||
|
*/
|
||||||
|
void set_alignment(int multiple);
|
||||||
|
int alignment() const { return d_output_multiple; }
|
||||||
|
|
||||||
|
void set_unaligned(int na);
|
||||||
|
int unaligned() const { return d_unaligned; }
|
||||||
|
void set_is_unaligned(bool u);
|
||||||
|
bool is_unaligned() const { return d_is_unaligned; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items of input stream \p
|
||||||
|
* which_input were consumed.
|
||||||
|
*/
|
||||||
|
void consume(int which_input, int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items were consumed on
|
||||||
|
* each input stream.
|
||||||
|
*/
|
||||||
|
void consume_each(int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items were produced on
|
||||||
|
* output stream \p which_output.
|
||||||
|
*
|
||||||
|
* If the block's general_work method calls produce, \p
|
||||||
|
* general_work must return WORK_CALLED_PRODUCE.
|
||||||
|
*/
|
||||||
|
void produce(int which_output, int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the approximate output rate / input rate
|
||||||
|
*
|
||||||
|
* Provide a hint to the buffer allocator and scheduler.
|
||||||
|
* The default relative_rate is 1.0
|
||||||
|
*
|
||||||
|
* decimators have relative_rates < 1.0
|
||||||
|
* interpolators have relative_rates > 1.0
|
||||||
|
*/
|
||||||
|
void set_relative_rate(double relative_rate);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return the approximate output rate / input rate
|
||||||
|
*/
|
||||||
|
double relative_rate() const { return d_relative_rate; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following two methods provide special case info to the
|
||||||
|
* scheduler in the event that a block has a fixed input to output
|
||||||
|
* ratio. sync_block, sync_decimator and
|
||||||
|
* sync_interpolator override these. If you're fixed rate,
|
||||||
|
* subclass one of those.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
* \brief Given ninput samples, return number of output samples that will be produced.
|
||||||
|
* N.B. this is only defined if fixed_rate returns true.
|
||||||
|
* Generally speaking, you don't need to override this.
|
||||||
|
*/
|
||||||
|
virtual int fixed_rate_ninput_to_noutput(int ninput);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Given noutput samples, return number of input samples required to produce noutput.
|
||||||
|
* N.B. this is only defined if fixed_rate returns true.
|
||||||
|
* Generally speaking, you don't need to override this.
|
||||||
|
*/
|
||||||
|
virtual int fixed_rate_noutput_to_ninput(int noutput);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the number of items read on input stream which_input
|
||||||
|
*/
|
||||||
|
uint64_t nitems_read(unsigned int which_input);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the number of items written on output stream which_output
|
||||||
|
*/
|
||||||
|
uint64_t nitems_written(unsigned int which_output);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the minimum number of output items this block can
|
||||||
|
* produce during a call to work.
|
||||||
|
*
|
||||||
|
* Should be 0 for most blocks. Useful if we're dealing with
|
||||||
|
* packets and the block produces one packet per call to work.
|
||||||
|
*/
|
||||||
|
int min_noutput_items() const { return d_min_noutput_items; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the minimum number of output items this block can
|
||||||
|
* produce during a call to work.
|
||||||
|
*
|
||||||
|
* \param m the minimum noutput_items this block can produce.
|
||||||
|
*/
|
||||||
|
void set_min_noutput_items(int m) { d_min_noutput_items = m; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the maximum number of output items this block will
|
||||||
|
* handle during a call to work.
|
||||||
|
*/
|
||||||
|
int max_noutput_items();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the maximum number of output items this block will
|
||||||
|
* handle during a call to work.
|
||||||
|
*
|
||||||
|
* \param m the maximum noutput_items this block will handle.
|
||||||
|
*/
|
||||||
|
void set_max_noutput_items(int m);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Clear the switch for using the max_noutput_items value of this block.
|
||||||
|
*
|
||||||
|
* When is_set_max_noutput_items() returns 'true', the scheduler
|
||||||
|
* will use the value returned by max_noutput_items() to limit the
|
||||||
|
* size of the number of items possible for this block's work
|
||||||
|
* function. If is_set_max_notput_items() returns 'false', then
|
||||||
|
* the scheduler ignores the internal value and uses the value set
|
||||||
|
* globally in the top_block.
|
||||||
|
*
|
||||||
|
* Use this value to clear the 'is_set' flag so the scheduler will
|
||||||
|
* ignore this. Use the set_max_noutput_items(m) call to both set
|
||||||
|
* a new value for max_noutput_items and to reenable its use in
|
||||||
|
* the scheduler.
|
||||||
|
*/
|
||||||
|
void unset_max_noutput_items();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Ask the block if the flag is or is not set to use the
|
||||||
|
* internal value of max_noutput_items during a call to work.
|
||||||
|
*/
|
||||||
|
bool is_set_max_noutput_items();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to expand the vectors that hold the min/max buffer sizes.
|
||||||
|
*
|
||||||
|
* Specifically, when -1 is used, the vectors are just initialized
|
||||||
|
* with 1 value; this is used by the flat_flowgraph to expand when
|
||||||
|
* required to add a new value for new ports on these blocks.
|
||||||
|
*/
|
||||||
|
void expand_minmax_buffer(int port);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns max buffer size on output port \p i.
|
||||||
|
*/
|
||||||
|
long max_output_buffer(size_t i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets max buffer size on all output ports.
|
||||||
|
*/
|
||||||
|
void set_max_output_buffer(long max_output_buffer);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets max buffer size on output port \p port.
|
||||||
|
*/
|
||||||
|
void set_max_output_buffer(int port, long max_output_buffer);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns min buffer size on output port \p i.
|
||||||
|
*/
|
||||||
|
long min_output_buffer(size_t i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets min buffer size on all output ports.
|
||||||
|
*/
|
||||||
|
void set_min_output_buffer(long min_output_buffer);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets min buffer size on output port \p port.
|
||||||
|
*/
|
||||||
|
void set_min_output_buffer(int port, long min_output_buffer);
|
||||||
|
|
||||||
|
// --------------- Performance counter functions -------------
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous noutput_items performance counter.
|
||||||
|
*/
|
||||||
|
float pc_noutput_items();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average noutput_items performance counter.
|
||||||
|
*/
|
||||||
|
float pc_noutput_items_avg();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of noutput_items performance counter.
|
||||||
|
*/
|
||||||
|
float pc_noutput_items_var();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous num items produced performance counter.
|
||||||
|
*/
|
||||||
|
float pc_nproduced();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average num items produced performance counter.
|
||||||
|
*/
|
||||||
|
float pc_nproduced_avg();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of num items produced performance counter.
|
||||||
|
*/
|
||||||
|
float pc_nproduced_var();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_input_buffers_full(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_input_buffers_full_avg(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_input_buffers_full_var(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous fullness of all input buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_input_buffers_full();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average fullness of all input buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_input_buffers_full_avg();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of fullness of all input buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_input_buffers_full_var();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_output_buffers_full(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_output_buffers_full_avg(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of fullness of \p which input buffer.
|
||||||
|
*/
|
||||||
|
float pc_output_buffers_full_var(int which);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous fullness of all output buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_output_buffers_full();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average fullness of all output buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_output_buffers_full_avg();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets variance of fullness of all output buffers.
|
||||||
|
*/
|
||||||
|
std::vector<float> pc_output_buffers_full_var();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets instantaneous clock cycles spent in work.
|
||||||
|
*/
|
||||||
|
float pc_work_time();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average clock cycles spent in work.
|
||||||
|
*/
|
||||||
|
float pc_work_time_avg();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets average clock cycles spent in work.
|
||||||
|
*/
|
||||||
|
float pc_work_time_var();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Resets the performance counters
|
||||||
|
*/
|
||||||
|
void reset_perf_counters();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets up export of perf. counters to ControlPort. Only
|
||||||
|
* called by the scheduler.
|
||||||
|
*/
|
||||||
|
void setup_pc_rpc();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if this block is already exporting perf. counters
|
||||||
|
* to ControlPort.
|
||||||
|
*/
|
||||||
|
bool is_pc_rpc_set() { return d_pc_rpc_set; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If the block calls this in its constructor, it's
|
||||||
|
* perf. counters will not be exported.
|
||||||
|
*/
|
||||||
|
void no_pc_rpc() { d_pc_rpc_set = true; }
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Functions to handle thread affinity
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the thread's affinity to processor core \p n.
|
||||||
|
*
|
||||||
|
* \param mask a vector of ints of the core numbers available to this block.
|
||||||
|
*/
|
||||||
|
void set_processor_affinity(const std::vector<int> &mask);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Remove processor affinity to a specific core.
|
||||||
|
*/
|
||||||
|
void unset_processor_affinity();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current processor affinity.
|
||||||
|
*/
|
||||||
|
std::vector<int> processor_affinity() { return d_affinity; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current thread priority in use
|
||||||
|
*/
|
||||||
|
int active_thread_priority();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current thread priority stored
|
||||||
|
*/
|
||||||
|
int thread_priority();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the current thread priority
|
||||||
|
*/
|
||||||
|
int set_thread_priority(int priority);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private:
|
||||||
|
int d_output_multiple;
|
||||||
|
bool d_output_multiple_set;
|
||||||
|
int d_unaligned;
|
||||||
|
bool d_is_unaligned;
|
||||||
|
double d_relative_rate; // approx output_rate / input_rate
|
||||||
|
block_detail_sptr d_detail; // implementation details
|
||||||
|
unsigned d_history;
|
||||||
|
bool d_fixed_rate;
|
||||||
|
bool d_max_noutput_items_set; // if d_max_noutput_items is valid
|
||||||
|
int d_max_noutput_items; // value of max_noutput_items for this block
|
||||||
|
int d_min_noutput_items;
|
||||||
|
std::vector<int> d_affinity; // thread affinity proc. mask
|
||||||
|
int d_priority; // thread priority level
|
||||||
|
bool d_pc_rpc_set;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
block(void) {} // allows pure virtual interface sub-classes
|
||||||
|
block(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
void set_fixed_rate(bool fixed_rate) { d_fixed_rate = fixed_rate; }
|
||||||
|
|
||||||
|
std::vector<long> d_max_output_buffer;
|
||||||
|
std::vector<long> d_min_output_buffer;
|
||||||
|
|
||||||
|
/*! Used by block's setters and work functions to make
|
||||||
|
* setting/resetting of parameters thread-safe.
|
||||||
|
*
|
||||||
|
* Used by calling gr::thread::scoped_lock l(d_setlock);
|
||||||
|
*/
|
||||||
|
gr::thread::mutex d_setlock;
|
||||||
|
|
||||||
|
/*! Used by blocks to access the logger system.
|
||||||
|
*/
|
||||||
|
gr::logger_ptr d_logger;
|
||||||
|
gr::logger_ptr d_debug_logger;
|
||||||
|
|
||||||
|
// These are really only for internal use, but leaving them public avoids
|
||||||
|
// having to work up an ever-varying list of friend GR_RUNTIME_APIs
|
||||||
|
|
||||||
|
public:
|
||||||
|
block_detail_sptr detail() const { return d_detail; }
|
||||||
|
void set_detail(block_detail_sptr detail) { d_detail = detail; }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<block_sptr> block_vector_t;
|
||||||
|
typedef std::vector<block_sptr>::iterator block_viter_t;
|
||||||
|
|
||||||
|
inline block_sptr cast_to_block_sptr(basic_block_sptr p)
|
||||||
|
{
|
||||||
|
return boost::dynamic_pointer_cast<block, basic_block>(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator << (std::ostream& os, const block *m);
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_BLOCK_H */
|
|
@ -0,0 +1,207 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2009,2010,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more detail.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/runtime_types.h>
|
||||||
|
#include <gnuradio/tpb_detail.h>
|
||||||
|
#include <gnuradio/high_res_timer.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Implementation details to support the signal processing abstraction
|
||||||
|
* \ingroup internal
|
||||||
|
*
|
||||||
|
* This class contains implementation detail that should be "out of
|
||||||
|
* sight" of almost all users of GNU Radio. This decoupling also
|
||||||
|
* means that we can make changes to the guts without having to
|
||||||
|
* recompile everything.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API block_detail
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~block_detail();
|
||||||
|
|
||||||
|
int ninputs() const { return d_ninputs; }
|
||||||
|
int noutputs() const { return d_noutputs; }
|
||||||
|
bool sink_p() const { return d_noutputs == 0; }
|
||||||
|
bool source_p() const { return d_ninputs == 0; }
|
||||||
|
|
||||||
|
void set_done(bool done);
|
||||||
|
bool done() const { return d_done; }
|
||||||
|
|
||||||
|
void set_input(unsigned int which, buffer_reader_sptr reader);
|
||||||
|
buffer_reader_sptr input(unsigned int which)
|
||||||
|
{
|
||||||
|
if(which >= d_ninputs)
|
||||||
|
throw std::invalid_argument("block_detail::input");
|
||||||
|
return d_input[which];
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_output(unsigned int which, buffer_sptr buffer);
|
||||||
|
buffer_sptr output(unsigned int which)
|
||||||
|
{
|
||||||
|
if(which >= d_noutputs)
|
||||||
|
throw std::invalid_argument("block_detail::output");
|
||||||
|
return d_output[which];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items of input stream \p
|
||||||
|
* which_input were consumed.
|
||||||
|
*/
|
||||||
|
void consume(int which_input, int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items were consumed on
|
||||||
|
* each input stream.
|
||||||
|
*/
|
||||||
|
void consume_each(int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items were produced on
|
||||||
|
* output stream \p which_output.
|
||||||
|
*/
|
||||||
|
void produce(int which_output, int how_many_items);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tell the scheduler \p how_many_items were produced on
|
||||||
|
* each output stream.
|
||||||
|
*/
|
||||||
|
void produce_each(int how_many_items);
|
||||||
|
|
||||||
|
// Return the number of items read on input stream which_input
|
||||||
|
uint64_t nitems_read(unsigned int which_input);
|
||||||
|
|
||||||
|
// Return the number of items written on output stream which_output
|
||||||
|
uint64_t nitems_written(unsigned int which_output);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set core affinity of block to the cores in the vector
|
||||||
|
* mask.
|
||||||
|
*
|
||||||
|
* \param mask a vector of ints of the core numbers available to
|
||||||
|
* this block.
|
||||||
|
*/
|
||||||
|
void set_processor_affinity(const std::vector<int> &mask);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Unset core affinity.
|
||||||
|
*/
|
||||||
|
void unset_processor_affinity();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current thread priority
|
||||||
|
*/
|
||||||
|
int thread_priority();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the current thread priority
|
||||||
|
*
|
||||||
|
* \param priority the new thread priority to set
|
||||||
|
*/
|
||||||
|
int set_thread_priority(int priority);
|
||||||
|
|
||||||
|
bool threaded; // set if thread is currently running.
|
||||||
|
gr::thread::gr_thread_t thread; // portable thread handle
|
||||||
|
|
||||||
|
void start_perf_counters();
|
||||||
|
void stop_perf_counters(int noutput_items, int nproduced);
|
||||||
|
void reset_perf_counters();
|
||||||
|
|
||||||
|
// Calls to get performance counter items
|
||||||
|
float pc_noutput_items();
|
||||||
|
float pc_nproduced();
|
||||||
|
float pc_input_buffers_full(size_t which);
|
||||||
|
std::vector<float> pc_input_buffers_full();
|
||||||
|
float pc_output_buffers_full(size_t which);
|
||||||
|
std::vector<float> pc_output_buffers_full();
|
||||||
|
float pc_work_time();
|
||||||
|
|
||||||
|
float pc_noutput_items_avg();
|
||||||
|
float pc_nproduced_avg();
|
||||||
|
float pc_input_buffers_full_avg(size_t which);
|
||||||
|
std::vector<float> pc_input_buffers_full_avg();
|
||||||
|
float pc_output_buffers_full_avg(size_t which);
|
||||||
|
std::vector<float> pc_output_buffers_full_avg();
|
||||||
|
float pc_work_time_avg();
|
||||||
|
|
||||||
|
float pc_noutput_items_var();
|
||||||
|
float pc_nproduced_var();
|
||||||
|
float pc_input_buffers_full_var(size_t which);
|
||||||
|
std::vector<float> pc_input_buffers_full_var();
|
||||||
|
float pc_output_buffers_full_var(size_t which);
|
||||||
|
std::vector<float> pc_output_buffers_full_var();
|
||||||
|
float pc_work_time_var();
|
||||||
|
|
||||||
|
tpb_detail d_tpb; // used by thread-per-block scheduler
|
||||||
|
int d_produce_or;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int d_ninputs;
|
||||||
|
unsigned int d_noutputs;
|
||||||
|
std::vector<buffer_reader_sptr> d_input;
|
||||||
|
std::vector<buffer_sptr> d_output;
|
||||||
|
bool d_done;
|
||||||
|
|
||||||
|
// Performance counters
|
||||||
|
float d_ins_noutput_items;
|
||||||
|
float d_avg_noutput_items;
|
||||||
|
float d_var_noutput_items;
|
||||||
|
float d_ins_nproduced;
|
||||||
|
float d_avg_nproduced;
|
||||||
|
float d_var_nproduced;
|
||||||
|
std::vector<float> d_ins_input_buffers_full;
|
||||||
|
std::vector<float> d_avg_input_buffers_full;
|
||||||
|
std::vector<float> d_var_input_buffers_full;
|
||||||
|
std::vector<float> d_ins_output_buffers_full;
|
||||||
|
std::vector<float> d_avg_output_buffers_full;
|
||||||
|
std::vector<float> d_var_output_buffers_full;
|
||||||
|
gr::high_res_timer_type d_start_of_work, d_end_of_work;
|
||||||
|
float d_ins_work_time;
|
||||||
|
float d_avg_work_time;
|
||||||
|
float d_var_work_time;
|
||||||
|
float d_pc_counter;
|
||||||
|
|
||||||
|
block_detail(unsigned int ninputs, unsigned int noutputs);
|
||||||
|
|
||||||
|
friend struct tpb_detail;
|
||||||
|
|
||||||
|
friend GR_RUNTIME_API block_detail_sptr
|
||||||
|
make_block_detail(unsigned int ninputs, unsigned int noutputs);
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_RUNTIME_API block_detail_sptr
|
||||||
|
make_block_detail(unsigned int ninputs, unsigned int noutputs);
|
||||||
|
|
||||||
|
GR_RUNTIME_API long
|
||||||
|
block_detail_ncurrently_allocated();
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H */
|
|
@ -0,0 +1,178 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2011-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_H
|
||||||
|
#define INCLUDED_RUNTIME_BLOCK_GATEWAY_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/block.h>
|
||||||
|
#include <gnuradio/feval.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The work type enum tells the gateway what kind of block to
|
||||||
|
* implement. The choices are familiar gnuradio block overloads
|
||||||
|
* (sync, decim, interp).
|
||||||
|
*/
|
||||||
|
enum block_gw_work_type {
|
||||||
|
GR_BLOCK_GW_WORK_GENERAL,
|
||||||
|
GR_BLOCK_GW_WORK_SYNC,
|
||||||
|
GR_BLOCK_GW_WORK_DECIM,
|
||||||
|
GR_BLOCK_GW_WORK_INTERP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Shared message structure between python and gateway.
|
||||||
|
* Each action type represents a scheduler-called function.
|
||||||
|
*/
|
||||||
|
struct block_gw_message_type {
|
||||||
|
enum action_type {
|
||||||
|
ACTION_GENERAL_WORK, //dispatch work
|
||||||
|
ACTION_WORK, //dispatch work
|
||||||
|
ACTION_FORECAST, //dispatch forecast
|
||||||
|
ACTION_START, //dispatch start
|
||||||
|
ACTION_STOP, //dispatch stop
|
||||||
|
};
|
||||||
|
|
||||||
|
action_type action;
|
||||||
|
|
||||||
|
int general_work_args_noutput_items;
|
||||||
|
std::vector<int> general_work_args_ninput_items;
|
||||||
|
std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
|
||||||
|
std::vector<void *> general_work_args_output_items;
|
||||||
|
int general_work_args_return_value;
|
||||||
|
|
||||||
|
int work_args_ninput_items;
|
||||||
|
int work_args_noutput_items;
|
||||||
|
std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
|
||||||
|
std::vector<void *> work_args_output_items;
|
||||||
|
int work_args_return_value;
|
||||||
|
|
||||||
|
int forecast_args_noutput_items;
|
||||||
|
std::vector<int> forecast_args_ninput_items_required;
|
||||||
|
|
||||||
|
bool start_args_return_value;
|
||||||
|
|
||||||
|
bool stop_args_return_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The gateway block which performs all the magic.
|
||||||
|
*
|
||||||
|
* The gateway provides access to all the gr::block routines.
|
||||||
|
* The methods prefixed with gr::block__ are renamed
|
||||||
|
* to class methods without the prefix in python.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API block_gateway : virtual public gr::block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// gr::block_gateway::sptr
|
||||||
|
typedef boost::shared_ptr<block_gateway> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Make a new gateway block.
|
||||||
|
* \param handler the swig director object with callback
|
||||||
|
* \param name the name of the block (Ex: "Shirley")
|
||||||
|
* \param in_sig the input signature for this block
|
||||||
|
* \param out_sig the output signature for this block
|
||||||
|
* \param work_type the type of block overload to implement
|
||||||
|
* \param factor the decimation or interpolation factor
|
||||||
|
* \return a new gateway block
|
||||||
|
*/
|
||||||
|
static sptr make(gr::feval_ll *handler,
|
||||||
|
const std::string &name,
|
||||||
|
gr::io_signature::sptr in_sig,
|
||||||
|
gr::io_signature::sptr out_sig,
|
||||||
|
const block_gw_work_type work_type,
|
||||||
|
const unsigned factor);
|
||||||
|
|
||||||
|
//! Provide access to the shared message object
|
||||||
|
virtual block_gw_message_type &block_message(void) = 0;
|
||||||
|
|
||||||
|
long block__unique_id(void) const {
|
||||||
|
return gr::block::unique_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string block__name(void) const {
|
||||||
|
return gr::block::name();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned block__history(void) const {
|
||||||
|
return gr::block::history();
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__set_history(unsigned history) {
|
||||||
|
return gr::block::set_history(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__set_fixed_rate(bool fixed_rate) {
|
||||||
|
return gr::block::set_fixed_rate(fixed_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool block__fixed_rate(void) const {
|
||||||
|
return gr::block::fixed_rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__set_output_multiple(int multiple) {
|
||||||
|
return gr::block::set_output_multiple(multiple);
|
||||||
|
}
|
||||||
|
|
||||||
|
int block__output_multiple(void) const {
|
||||||
|
return gr::block::output_multiple();
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__consume(int which_input, int how_many_items) {
|
||||||
|
return gr::block::consume(which_input, how_many_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__consume_each(int how_many_items) {
|
||||||
|
return gr::block::consume_each(how_many_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__produce(int which_output, int how_many_items) {
|
||||||
|
return gr::block::produce(which_output, how_many_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void block__set_relative_rate(double relative_rate) {
|
||||||
|
return gr::block::set_relative_rate(relative_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
double block__relative_rate(void) const {
|
||||||
|
return gr::block::relative_rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t block__nitems_read(unsigned int which_input) {
|
||||||
|
return gr::block::nitems_read(which_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t block__nitems_written(unsigned int which_output) {
|
||||||
|
return gr::block::nitems_written(which_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GR_RUNTIME_BLOCK_REGISTRY_H
|
||||||
|
#define GR_RUNTIME_BLOCK_REGISTRY_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/basic_block.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
#ifndef GR_BASIC_BLOCK_H
|
||||||
|
class basic_block;
|
||||||
|
class block;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class GR_RUNTIME_API block_registry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
block_registry();
|
||||||
|
|
||||||
|
long block_register(basic_block* block);
|
||||||
|
void block_unregister(basic_block* block);
|
||||||
|
|
||||||
|
std::string register_symbolic_name(basic_block* block);
|
||||||
|
void register_symbolic_name(basic_block* block, std::string name);
|
||||||
|
|
||||||
|
void register_primitive(std::string blk, gr::block* ref);
|
||||||
|
void unregister_primitive(std::string blk);
|
||||||
|
void notify_blk(std::string blk);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//typedef std::map< long, basic_block_sptr > blocksubmap_t;
|
||||||
|
typedef std::map< long, basic_block* > blocksubmap_t;
|
||||||
|
typedef std::map< std::string, blocksubmap_t > blockmap_t;
|
||||||
|
|
||||||
|
blockmap_t d_map;
|
||||||
|
std::map< std::string, block*> primitive_map;
|
||||||
|
gr::thread::mutex d_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
GR_RUNTIME_API extern gr::block_registry global_block_registry;
|
||||||
|
|
||||||
|
#endif /* GR_RUNTIME_BLOCK_REGISTRY_H */
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_BLOCKS_API_H
|
||||||
|
#define INCLUDED_BLOCKS_API_H
|
||||||
|
|
||||||
|
#include <gnuradio/attributes.h>
|
||||||
|
|
||||||
|
#ifdef gnuradio_blocks_EXPORTS
|
||||||
|
# define BLOCKS_API __GR_ATTR_EXPORT
|
||||||
|
#else
|
||||||
|
# define BLOCKS_API __GR_ATTR_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INCLUDED_BLOCKS_API_H */
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_BLOCKS_FILE_SOURCE_H
|
||||||
|
#define INCLUDED_BLOCKS_FILE_SOURCE_H
|
||||||
|
|
||||||
|
#include <gnuradio/blocks/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace blocks {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Read stream from file
|
||||||
|
* \ingroup file_operators_blk
|
||||||
|
*/
|
||||||
|
class BLOCKS_API file_source : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// gr::blocks::file_source::sptr
|
||||||
|
typedef boost::shared_ptr<file_source> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create a file source.
|
||||||
|
*
|
||||||
|
* Opens \p filename as a source of items into a flowgraph. The
|
||||||
|
* data is expected to be in binary format, item after item. The
|
||||||
|
* \p itemsize of the block determines the conversion from bits
|
||||||
|
* to items.
|
||||||
|
*
|
||||||
|
* If \p repeat is turned on, the file will repeat the file after
|
||||||
|
* it's reached the end.
|
||||||
|
*
|
||||||
|
* \param itemsize the size of each item in the file, in bytes
|
||||||
|
* \param filename name of the file to source from
|
||||||
|
* \param repeat repeat file from start
|
||||||
|
*/
|
||||||
|
static sptr make(size_t itemsize, const char *filename, bool repeat = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief seek file to \p seek_point relative to \p whence
|
||||||
|
*
|
||||||
|
* \param seek_point sample offset in file
|
||||||
|
* \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek)
|
||||||
|
*/
|
||||||
|
virtual bool seek(long seek_point, int whence) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Opens a new file.
|
||||||
|
*
|
||||||
|
* \param filename name of the file to source from
|
||||||
|
* \param repeat repeat file from start
|
||||||
|
*/
|
||||||
|
virtual void open(const char *filename, bool repeat) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Close the file handle.
|
||||||
|
*/
|
||||||
|
virtual void close() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace blocks */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_BLOCKS_FILE_SOURCE_H */
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_NULL_SINK_H
|
||||||
|
#define INCLUDED_GR_NULL_SINK_H
|
||||||
|
|
||||||
|
#include <gnuradio/blocks/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace blocks {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Bit bucket. Use as a termination point when a sink is
|
||||||
|
* required and we don't want to do anything real.
|
||||||
|
* \ingroup misc_blk
|
||||||
|
*/
|
||||||
|
class BLOCKS_API null_sink : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// gr::blocks::null_sink::sptr
|
||||||
|
typedef boost::shared_ptr<null_sink> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Build a null sink block.
|
||||||
|
*
|
||||||
|
* \param sizeof_stream_item size of the stream items in bytes.
|
||||||
|
*/
|
||||||
|
static sptr make(size_t sizeof_stream_item);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace blocks */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_NULL_SINK_H */
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2010,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_NULL_SOURCE_H
|
||||||
|
#define INCLUDED_GR_NULL_SOURCE_H
|
||||||
|
|
||||||
|
#include <gnuradio/blocks/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace blocks {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief A source of zeros used mainly for testing.
|
||||||
|
* \ingroup misc_blk
|
||||||
|
*/
|
||||||
|
class BLOCKS_API null_source : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// gr::blocks::null_source::sptr
|
||||||
|
typedef boost::shared_ptr<null_source> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Build a null source block.
|
||||||
|
*
|
||||||
|
* \param sizeof_stream_item size of the stream items in bytes.
|
||||||
|
*/
|
||||||
|
static sptr make(size_t sizeof_stream_item);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace blocks */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_NULL_SOURCE_H */
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2011,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_THROTTLE_H
|
||||||
|
#define INCLUDED_GR_THROTTLE_H
|
||||||
|
|
||||||
|
#include <gnuradio/blocks/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace blocks {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief throttle flow of samples such that the average rate does
|
||||||
|
* not exceed samples_per_sec.
|
||||||
|
* \ingroup misc_blk
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* input: one stream of itemsize; output: one stream of itemsize
|
||||||
|
*
|
||||||
|
* N.B. this should only be used in GUI apps where there is no
|
||||||
|
* other rate limiting block. It is not intended nor effective at
|
||||||
|
* precisely controlling the rate of samples. That should be
|
||||||
|
* controlled by a source or sink tied to sample clock. E.g., a
|
||||||
|
* USRP or audio card.
|
||||||
|
*/
|
||||||
|
class BLOCKS_API throttle : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<throttle> sptr;
|
||||||
|
|
||||||
|
static sptr make(size_t itemsize, double samples_per_sec);
|
||||||
|
|
||||||
|
//! Sets the sample rate in samples per second.
|
||||||
|
virtual void set_sample_rate(double rate) = 0;
|
||||||
|
|
||||||
|
//! Get the sample rate in samples per second.
|
||||||
|
virtual double sample_rate() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace blocks */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_THROTTLE_H */
|
|
@ -0,0 +1,258 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2009-2011,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_BUFFER_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_BUFFER_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/runtime_types.h>
|
||||||
|
#include <boost/weak_ptr.hpp>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
class vmcircbuf;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
|
||||||
|
*
|
||||||
|
* The total size of the buffer will be rounded up to a system
|
||||||
|
* dependent boundary. This is typically the system page size, but
|
||||||
|
* under MS windows is 64KB.
|
||||||
|
*
|
||||||
|
* \param nitems is the minimum number of items the buffer will hold.
|
||||||
|
* \param sizeof_item is the size of an item in bytes.
|
||||||
|
* \param link is the block that writes to this buffer.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item,
|
||||||
|
block_sptr link=block_sptr());
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Single writer, multiple reader fifo.
|
||||||
|
* \ingroup internal
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~buffer();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return number of items worth of space available for writing
|
||||||
|
*/
|
||||||
|
int space_available();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return size of this buffer in items
|
||||||
|
*/
|
||||||
|
int bufsize() const { return d_bufsize; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return pointer to write buffer.
|
||||||
|
*
|
||||||
|
* The return value points at space that can hold at least
|
||||||
|
* space_available() items.
|
||||||
|
*/
|
||||||
|
void *write_pointer();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief tell buffer that we wrote \p nitems into it
|
||||||
|
*/
|
||||||
|
void update_write_pointer(int nitems);
|
||||||
|
|
||||||
|
void set_done(bool done);
|
||||||
|
bool done() const { return d_done; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the block that writes to this buffer.
|
||||||
|
*/
|
||||||
|
block_sptr link() { return block_sptr(d_link); }
|
||||||
|
|
||||||
|
size_t nreaders() const { return d_readers.size(); }
|
||||||
|
buffer_reader* reader(size_t index) { return d_readers[index]; }
|
||||||
|
|
||||||
|
gr::thread::mutex *mutex() { return &d_mutex; }
|
||||||
|
|
||||||
|
uint64_t nitems_written() { return d_abs_write_offset; }
|
||||||
|
|
||||||
|
size_t get_sizeof_item() { return d_sizeof_item; }
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class buffer_reader;
|
||||||
|
friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link);
|
||||||
|
friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char *d_base; // base address of buffer
|
||||||
|
unsigned int d_bufsize; // in items
|
||||||
|
private:
|
||||||
|
gr::vmcircbuf *d_vmcircbuf;
|
||||||
|
size_t d_sizeof_item; // in bytes
|
||||||
|
std::vector<buffer_reader *> d_readers;
|
||||||
|
boost::weak_ptr<block> d_link; // block that writes to this buffer
|
||||||
|
|
||||||
|
//
|
||||||
|
// The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
|
||||||
|
// and the d_read_index's and d_abs_read_offset's in the buffer readers.
|
||||||
|
//
|
||||||
|
gr::thread::mutex d_mutex;
|
||||||
|
unsigned int d_write_index; // in items [0,d_bufsize)
|
||||||
|
uint64_t d_abs_write_offset; // num items written since the start
|
||||||
|
bool d_done;
|
||||||
|
uint64_t d_last_min_items_read;
|
||||||
|
|
||||||
|
unsigned index_add(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned s = a + b;
|
||||||
|
|
||||||
|
if(s >= d_bufsize)
|
||||||
|
s -= d_bufsize;
|
||||||
|
|
||||||
|
assert(s < d_bufsize);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned index_sub(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
int s = a - b;
|
||||||
|
|
||||||
|
if(s < 0)
|
||||||
|
s += d_bufsize;
|
||||||
|
|
||||||
|
assert((unsigned) s < d_bufsize);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool allocate_buffer(int nitems, size_t sizeof_item);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief constructor is private. Use gr_make_buffer to create instances.
|
||||||
|
*
|
||||||
|
* Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
|
||||||
|
*
|
||||||
|
* \param nitems is the minimum number of items the buffer will hold.
|
||||||
|
* \param sizeof_item is the size of an item in bytes.
|
||||||
|
* \param link is the block that writes to this buffer.
|
||||||
|
*
|
||||||
|
* The total size of the buffer will be rounded up to a system
|
||||||
|
* dependent boundary. This is typically the system page size, but
|
||||||
|
* under MS windows is 64KB.
|
||||||
|
*/
|
||||||
|
buffer(int nitems, size_t sizeof_item, block_sptr link);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief disassociate \p reader from this buffer
|
||||||
|
*/
|
||||||
|
void drop_reader(buffer_reader *reader);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create a new gr::buffer_reader and attach it to buffer \p buf
|
||||||
|
* \param buf is the buffer the \p gr::buffer_reader reads from.
|
||||||
|
* \param nzero_preload -- number of zero items to "preload" into buffer.
|
||||||
|
* \param link is the block that reads from the buffer using this gr::buffer_reader.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API buffer_reader_sptr
|
||||||
|
buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link=block_sptr());
|
||||||
|
|
||||||
|
//! returns # of buffers currently allocated
|
||||||
|
GR_RUNTIME_API long buffer_ncurrently_allocated();
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief How we keep track of the readers of a gr::buffer.
|
||||||
|
* \ingroup internal
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API buffer_reader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~buffer_reader();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return number of items available for reading.
|
||||||
|
*/
|
||||||
|
int items_available() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return buffer this reader reads from.
|
||||||
|
*/
|
||||||
|
buffer_sptr buffer() const { return d_buffer; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return maximum number of items that could ever be available for reading.
|
||||||
|
* This is used as a sanity check in the scheduler to avoid looping forever.
|
||||||
|
*/
|
||||||
|
int max_possible_items_available() const { return d_buffer->d_bufsize - 1; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return pointer to read buffer.
|
||||||
|
*
|
||||||
|
* The return value points to items_available() number of items
|
||||||
|
*/
|
||||||
|
const void *read_pointer();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief tell buffer we read \p items from it
|
||||||
|
*/
|
||||||
|
void update_read_pointer(int nitems);
|
||||||
|
|
||||||
|
void set_done(bool done) { d_buffer->set_done(done); }
|
||||||
|
bool done() const { return d_buffer->done(); }
|
||||||
|
|
||||||
|
gr::thread::mutex *mutex() { return d_buffer->mutex(); }
|
||||||
|
|
||||||
|
uint64_t nitems_read() { return d_abs_read_offset; }
|
||||||
|
|
||||||
|
size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the block that reads via this reader.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
block_sptr link() { return block_sptr(d_link); }
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class buffer;
|
||||||
|
friend GR_RUNTIME_API buffer_reader_sptr
|
||||||
|
buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link);
|
||||||
|
|
||||||
|
buffer_sptr d_buffer;
|
||||||
|
unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
|
||||||
|
uint64_t d_abs_read_offset; // num items seen since the start
|
||||||
|
boost::weak_ptr<block> d_link; // block that reads via this buffer reader
|
||||||
|
|
||||||
|
//! constructor is private. Use gr::buffer::add_reader to create instances
|
||||||
|
buffer_reader(buffer_sptr buffer, unsigned int read_index, block_sptr link);
|
||||||
|
};
|
||||||
|
|
||||||
|
//! returns # of buffer_readers currently allocated
|
||||||
|
GR_RUNTIME_API long buffer_reader_ncurrently_allocated ();
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_BUFFER_H */
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2009,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_CONSTANTS_H
|
||||||
|
#define INCLUDED_GR_CONSTANTS_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return SYSCONFDIR. Typically ${CMAKE_INSTALL_PREFIX}/etc or /etc
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API const std::string prefix();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return SYSCONFDIR. Typically ${CMAKE_INSTALL_PREFIX}/etc or /etc
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API const std::string sysconfdir();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return preferences file directory. Typically ${SYSCONFDIR}/etc/conf.d
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API const std::string prefsdir();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return date/time of build, as set when 'cmake' is run
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API const std::string build_date();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief return version string defined by cmake (GrVersion.cmake)
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API const std::string version();
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_CONSTANTS_H */
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_ENDIANNESS_H
|
||||||
|
#define INCLUDED_GR_ENDIANNESS_H
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} endianness_t;
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_ENDIANNESS_H */
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDED_GR_EXPJ_H
|
||||||
|
#define INCLUDED_GR_EXPJ_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/sincos.h>
|
||||||
|
#include <gnuradio/types.h>
|
||||||
|
|
||||||
|
static inline gr_complex
|
||||||
|
gr_expj(float phase)
|
||||||
|
{
|
||||||
|
float t_imag, t_real;
|
||||||
|
gr::sincosf(phase, &t_imag, &t_real);
|
||||||
|
return gr_complex(t_real, t_imag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_EXPJ_H */
|
|
@ -0,0 +1,186 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_FEVAL_H
|
||||||
|
#define INCLUDED_GR_FEVAL_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief base class for evaluating a function: double -> double
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* This class is designed to be subclassed in Python or C++ and is
|
||||||
|
* callable from both places. It uses SWIG's "director" feature to
|
||||||
|
* implement the magic.
|
||||||
|
*
|
||||||
|
* It's slow. Don't use it in a performance critical path.
|
||||||
|
*
|
||||||
|
* Override eval to define the behavior.
|
||||||
|
* Use calleval to invoke eval (this kludge is required to allow a
|
||||||
|
* python specific "shim" to be inserted.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API feval_dd
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief override this to define the function
|
||||||
|
*/
|
||||||
|
virtual double eval(double x);
|
||||||
|
|
||||||
|
public:
|
||||||
|
feval_dd() {}
|
||||||
|
virtual ~feval_dd();
|
||||||
|
|
||||||
|
virtual double calleval(double x); // invoke "eval"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief base class for evaluating a function: complex -> complex
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* This class is designed to be subclassed in Python or C++ and is
|
||||||
|
* callable from both places. It uses SWIG's "director" feature to
|
||||||
|
* implement the magic.
|
||||||
|
*
|
||||||
|
* It's slow. Don't use it in a performance critical path.
|
||||||
|
*
|
||||||
|
* Override eval to define the behavior.
|
||||||
|
* Use calleval to invoke eval (this kludge is required to allow a
|
||||||
|
* python specific "shim" to be inserted.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API feval_cc
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief override this to define the function
|
||||||
|
*/
|
||||||
|
virtual gr_complex eval(gr_complex x);
|
||||||
|
|
||||||
|
public:
|
||||||
|
feval_cc() {}
|
||||||
|
virtual ~feval_cc();
|
||||||
|
|
||||||
|
virtual gr_complex calleval(gr_complex x); // invoke "eval"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief base class for evaluating a function: long -> long
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* This class is designed to be subclassed in Python or C++ and is
|
||||||
|
* callable from both places. It uses SWIG's "director" feature to
|
||||||
|
* implement the magic.
|
||||||
|
*
|
||||||
|
* It's slow. Don't use it in a performance critical path.
|
||||||
|
*
|
||||||
|
* Override eval to define the behavior.
|
||||||
|
* Use calleval to invoke eval (this kludge is required to allow a
|
||||||
|
* python specific "shim" to be inserted.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API feval_ll
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief override this to define the function
|
||||||
|
*/
|
||||||
|
virtual long eval(long x);
|
||||||
|
|
||||||
|
public:
|
||||||
|
feval_ll() {}
|
||||||
|
virtual ~feval_ll();
|
||||||
|
|
||||||
|
virtual long calleval(long x); // invoke "eval"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief base class for evaluating a function: void -> void
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* This class is designed to be subclassed in Python or C++ and is
|
||||||
|
* callable from both places. It uses SWIG's "director" feature to
|
||||||
|
* implement the magic.
|
||||||
|
*
|
||||||
|
* It's slow. Don't use it in a performance critical path.
|
||||||
|
*
|
||||||
|
* Override eval to define the behavior.
|
||||||
|
* Use calleval to invoke eval (this kludge is required to allow a
|
||||||
|
* python specific "shim" to be inserted.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API feval
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief override this to define the function
|
||||||
|
*/
|
||||||
|
virtual void eval();
|
||||||
|
|
||||||
|
public:
|
||||||
|
feval() {}
|
||||||
|
virtual ~feval();
|
||||||
|
|
||||||
|
virtual void calleval(); // invoke "eval"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief base class for evaluating a function: pmt -> void
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* This class is designed to be subclassed in Python or C++ and is
|
||||||
|
* callable from both places. It uses SWIG's "director" feature to
|
||||||
|
* implement the magic.
|
||||||
|
*
|
||||||
|
* It's slow. Don't use it in a performance critical path.
|
||||||
|
*
|
||||||
|
* Override eval to define the behavior.
|
||||||
|
* Use calleval to invoke eval (this kludge is required to allow a
|
||||||
|
* python specific "shim" to be inserted.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API feval_p
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief override this to define the function
|
||||||
|
*/
|
||||||
|
virtual void eval(double);
|
||||||
|
|
||||||
|
public:
|
||||||
|
feval_p() {}
|
||||||
|
virtual ~feval_p();
|
||||||
|
|
||||||
|
virtual void calleval(double); // invoke "eval"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief trivial examples / test cases showing C++ calling Python code
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API double feval_dd_example(feval_dd *f, double x);
|
||||||
|
GR_RUNTIME_API gr_complex feval_cc_example(feval_cc *f, gr_complex x);
|
||||||
|
GR_RUNTIME_API long feval_ll_example(feval_ll *f, long x);
|
||||||
|
GR_RUNTIME_API void feval_example(feval *f);
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_FEVAL_H */
|
|
@ -0,0 +1,194 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2007,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_FLOWGRAPH_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_FLOWGRAPH_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/basic_block.h>
|
||||||
|
#include <gnuradio/io_signature.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Class representing a specific input or output graph endpoint
|
||||||
|
* \ingroup internal
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API endpoint
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
basic_block_sptr d_basic_block;
|
||||||
|
int d_port;
|
||||||
|
|
||||||
|
public:
|
||||||
|
endpoint() : d_basic_block(), d_port(0) { }
|
||||||
|
endpoint(basic_block_sptr block, int port) { d_basic_block = block; d_port = port; }
|
||||||
|
basic_block_sptr block() const { return d_basic_block; }
|
||||||
|
int port() const { return d_port; }
|
||||||
|
|
||||||
|
bool operator==(const endpoint &other) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool endpoint::operator==(const endpoint &other) const
|
||||||
|
{
|
||||||
|
return (d_basic_block == other.d_basic_block &&
|
||||||
|
d_port == other.d_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hold vectors of gr::endpoint objects
|
||||||
|
typedef std::vector<endpoint> endpoint_vector_t;
|
||||||
|
typedef std::vector<endpoint>::iterator endpoint_viter_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*\brief Class representing a connection between to graph endpoints
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API edge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
edge() : d_src(), d_dst() { };
|
||||||
|
edge(const endpoint &src, const endpoint &dst)
|
||||||
|
: d_src(src), d_dst(dst) { }
|
||||||
|
~edge();
|
||||||
|
|
||||||
|
const endpoint &src() const { return d_src; }
|
||||||
|
const endpoint &dst() const { return d_dst; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
endpoint d_src;
|
||||||
|
endpoint d_dst;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hold vectors of gr::edge objects
|
||||||
|
typedef std::vector<edge> edge_vector_t;
|
||||||
|
typedef std::vector<edge>::iterator edge_viter_t;
|
||||||
|
|
||||||
|
// Create a shared pointer to a heap allocated flowgraph
|
||||||
|
// (types defined in runtime_types.h)
|
||||||
|
GR_RUNTIME_API flowgraph_sptr make_flowgraph();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Class representing a directed, acyclic graph of basic blocks
|
||||||
|
* \ingroup internal
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API flowgraph
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend GR_RUNTIME_API flowgraph_sptr make_flowgraph();
|
||||||
|
|
||||||
|
// Destruct an arbitrary flowgraph
|
||||||
|
~flowgraph();
|
||||||
|
|
||||||
|
// Connect two endpoints
|
||||||
|
void connect(const endpoint &src, const endpoint &dst);
|
||||||
|
|
||||||
|
// Disconnect two endpoints
|
||||||
|
void disconnect(const endpoint &src, const endpoint &dst);
|
||||||
|
|
||||||
|
// Connect an output port to an input port (convenience)
|
||||||
|
void connect(basic_block_sptr src_block, int src_port,
|
||||||
|
basic_block_sptr dst_block, int dst_port);
|
||||||
|
|
||||||
|
// Disconnect an input port from an output port (convenience)
|
||||||
|
void disconnect(basic_block_sptr src_block, int src_port,
|
||||||
|
basic_block_sptr dst_block, int dst_port);
|
||||||
|
|
||||||
|
// Validate connectivity, raise exception if invalid
|
||||||
|
void validate();
|
||||||
|
|
||||||
|
// Clear existing flowgraph
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Return vector of edges
|
||||||
|
const edge_vector_t &edges() const { return d_edges; }
|
||||||
|
|
||||||
|
// Return vector of connected blocks
|
||||||
|
basic_block_vector_t calc_used_blocks();
|
||||||
|
|
||||||
|
// Return toplogically sorted vector of blocks. All the sources come first.
|
||||||
|
basic_block_vector_t topological_sort(basic_block_vector_t &blocks);
|
||||||
|
|
||||||
|
// Return vector of vectors of disjointly connected blocks,
|
||||||
|
// topologically sorted.
|
||||||
|
std::vector<basic_block_vector_t> partition();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
basic_block_vector_t d_blocks;
|
||||||
|
edge_vector_t d_edges;
|
||||||
|
|
||||||
|
flowgraph();
|
||||||
|
std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs);
|
||||||
|
basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port);
|
||||||
|
edge_vector_t calc_upstream_edges(basic_block_sptr block);
|
||||||
|
bool has_block_p(basic_block_sptr block);
|
||||||
|
edge calc_upstream_edge(basic_block_sptr block, int port);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void check_valid_port(gr::io_signature::sptr sig, int port);
|
||||||
|
void check_dst_not_used(const endpoint &dst);
|
||||||
|
void check_type_match(const endpoint &src, const endpoint &dst);
|
||||||
|
edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs
|
||||||
|
void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs);
|
||||||
|
|
||||||
|
basic_block_vector_t calc_downstream_blocks(basic_block_sptr block);
|
||||||
|
basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
|
||||||
|
void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks);
|
||||||
|
basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks);
|
||||||
|
basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks);
|
||||||
|
bool source_p(basic_block_sptr block);
|
||||||
|
void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience functions
|
||||||
|
inline
|
||||||
|
void flowgraph::connect(basic_block_sptr src_block, int src_port,
|
||||||
|
basic_block_sptr dst_block, int dst_port)
|
||||||
|
{
|
||||||
|
connect(endpoint(src_block, src_port),
|
||||||
|
endpoint(dst_block, dst_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void flowgraph::disconnect(basic_block_sptr src_block, int src_port,
|
||||||
|
basic_block_sptr dst_block, int dst_port)
|
||||||
|
{
|
||||||
|
disconnect(endpoint(src_block, src_port),
|
||||||
|
endpoint(dst_block, dst_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream&
|
||||||
|
operator <<(std::ostream &os, const endpoint endp)
|
||||||
|
{
|
||||||
|
os << endp.block()->alias() << ":" << endp.port();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream&
|
||||||
|
operator <<(std::ostream &os, const edge edge)
|
||||||
|
{
|
||||||
|
os << edge.src() << "->" << edge.dst();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_FXPT_H
|
||||||
|
#define INCLUDED_GR_FXPT_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/types.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief fixed point sine and cosine and friends.
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* fixed pt radians
|
||||||
|
* --------- --------
|
||||||
|
* -2**31 -pi
|
||||||
|
* 0 0
|
||||||
|
* 2**31-1 pi - epsilon
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API fxpt
|
||||||
|
{
|
||||||
|
static const int WORDBITS = 32;
|
||||||
|
static const int NBITS = 10;
|
||||||
|
static const float s_sine_table[1 << NBITS][2];
|
||||||
|
static const float PI;
|
||||||
|
static const float TWO_TO_THE_31;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static gr_int32
|
||||||
|
float_to_fixed(float x)
|
||||||
|
{
|
||||||
|
// Fold x into -PI to PI.
|
||||||
|
int d = (int)floor(x/2/PI+0.5);
|
||||||
|
x -= d*2*PI;
|
||||||
|
// And convert to an integer.
|
||||||
|
return (gr_int32) ((float) x * TWO_TO_THE_31 / PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
fixed_to_float (gr_int32 x)
|
||||||
|
{
|
||||||
|
return x * (PI / TWO_TO_THE_31);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Given a fixed point angle x, return float sine (x)
|
||||||
|
*/
|
||||||
|
static float
|
||||||
|
sin(gr_int32 x)
|
||||||
|
{
|
||||||
|
gr_uint32 ux = x;
|
||||||
|
int index = ux >> (WORDBITS - NBITS);
|
||||||
|
return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Given a fixed point angle x, return float cosine (x)
|
||||||
|
*/
|
||||||
|
static float
|
||||||
|
cos (gr_int32 x)
|
||||||
|
{
|
||||||
|
gr_uint32 ux = x + 0x40000000;
|
||||||
|
int index = ux >> (WORDBITS - NBITS);
|
||||||
|
return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief Given a fixedpoint angle x, return float cos(x) and sin (x)
|
||||||
|
*/
|
||||||
|
static void sincos(gr_int32 x, float *s, float *c)
|
||||||
|
{
|
||||||
|
gr_uint32 ux = x;
|
||||||
|
int sin_index = ux >> (WORDBITS - NBITS);
|
||||||
|
*s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1];
|
||||||
|
|
||||||
|
ux = x + 0x40000000;
|
||||||
|
int cos_index = ux >> (WORDBITS - NBITS);
|
||||||
|
*c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1];
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_FXPT_H */
|
|
@ -0,0 +1,160 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2002,2004,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_FXPT_NCO_H
|
||||||
|
#define INCLUDED_GR_FXPT_NCO_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/fxpt.h>
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Numerically Controlled Oscillator (NCO)
|
||||||
|
* \ingroup misc
|
||||||
|
*/
|
||||||
|
class /*GR_RUNTIME_API*/ fxpt_nco
|
||||||
|
{
|
||||||
|
uint32_t d_phase;
|
||||||
|
int32_t d_phase_inc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fxpt_nco() : d_phase(0), d_phase_inc(0) {}
|
||||||
|
|
||||||
|
~fxpt_nco() {}
|
||||||
|
|
||||||
|
// radians
|
||||||
|
void set_phase(float angle) {
|
||||||
|
d_phase = gr::fxpt::float_to_fixed(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjust_phase(float delta_phase) {
|
||||||
|
d_phase += gr::fxpt::float_to_fixed(delta_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// angle_rate is in radians / step
|
||||||
|
void set_freq(float angle_rate){
|
||||||
|
d_phase_inc = gr::fxpt::float_to_fixed(angle_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// angle_rate is a delta in radians / step
|
||||||
|
void adjust_freq(float delta_angle_rate)
|
||||||
|
{
|
||||||
|
d_phase_inc += gr::fxpt::float_to_fixed(delta_angle_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment current phase angle
|
||||||
|
|
||||||
|
void step()
|
||||||
|
{
|
||||||
|
d_phase += d_phase_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(int n)
|
||||||
|
{
|
||||||
|
d_phase += d_phase_inc * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// units are radians / step
|
||||||
|
float get_phase() const { return gr::fxpt::fixed_to_float(d_phase); }
|
||||||
|
float get_freq() const { return gr::fxpt::fixed_to_float(d_phase_inc); }
|
||||||
|
|
||||||
|
// compute sin and cos for current phase angle
|
||||||
|
void sincos(float *sinx, float *cosx) const
|
||||||
|
{
|
||||||
|
*sinx = gr::fxpt::sin(d_phase);
|
||||||
|
*cosx = gr::fxpt::cos(d_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos and sin for a block of phase angles
|
||||||
|
void sincos(gr_complex *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = gr_complex(gr::fxpt::cos(d_phase) * ampl, gr::fxpt::sin(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sin for a block of phase angles
|
||||||
|
void sin(float *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (float)(gr::fxpt::sin(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos for a block of phase angles
|
||||||
|
void cos(float *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (float)(gr::fxpt::cos(d_phase) * ampl);
|
||||||
|
step ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sin for a block of phase angles
|
||||||
|
void sin(short *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (short)(gr::fxpt::sin(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos for a block of phase angles
|
||||||
|
void cos(short *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (short)(gr::fxpt::cos(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sin for a block of phase angles
|
||||||
|
void sin(int *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (int)(gr::fxpt::sin(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos for a block of phase angles
|
||||||
|
void cos(int *output, int noutput_items, double ampl=1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (int)(gr::fxpt::cos(d_phase) * ampl);
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos or sin for current phase angle
|
||||||
|
float cos() const { return gr::fxpt::cos(d_phase); }
|
||||||
|
float sin() const { return gr::fxpt::sin(d_phase); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_FXPT_NCO_H */
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2002,2004,2005,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_FXPT_VCO_H
|
||||||
|
#define INCLUDED_GR_FXPT_VCO_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/fxpt.h>
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Voltage Controlled Oscillator (VCO)
|
||||||
|
* \ingroup misc
|
||||||
|
*/
|
||||||
|
class /*GR_RUNTIME_API*/ fxpt_vco {
|
||||||
|
gr_int32 d_phase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fxpt_vco () : d_phase(0) {}
|
||||||
|
|
||||||
|
~fxpt_vco() {}
|
||||||
|
|
||||||
|
// radians
|
||||||
|
void set_phase(float angle) {
|
||||||
|
d_phase = fxpt::float_to_fixed(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjust_phase(float delta_phase) {
|
||||||
|
d_phase += fxpt::float_to_fixed(delta_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_phase() const {
|
||||||
|
return fxpt::fixed_to_float(d_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sin and cos for current phase angle
|
||||||
|
void sincos(float *sinx, float *cosx) const
|
||||||
|
{
|
||||||
|
*sinx = fxpt::sin(d_phase);
|
||||||
|
*cosx = fxpt::cos(d_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute a block at a time
|
||||||
|
void cos(float *output, const float *input, int noutput_items, float k, float ampl = 1.0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < noutput_items; i++) {
|
||||||
|
output[i] = (float)(fxpt::cos(d_phase) * ampl);
|
||||||
|
adjust_phase(input[i] * k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute cos or sin for current phase angle
|
||||||
|
float cos() const { return fxpt::cos(d_phase); }
|
||||||
|
float sin() const { return fxpt::sin(d_phase); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_FXPT_VCO_H */
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_COMPLEX_H
|
||||||
|
#define INCLUDED_GR_COMPLEX_H
|
||||||
|
|
||||||
|
#include <complex>
|
||||||
|
typedef std::complex<float> gr_complex;
|
||||||
|
typedef std::complex<double> gr_complexd;
|
||||||
|
|
||||||
|
inline bool is_complex (gr_complex x) { (void) x; return true;}
|
||||||
|
inline bool is_complex (gr_complexd x) { (void) x; return true;}
|
||||||
|
inline bool is_complex (float x) { (void) x; return false;}
|
||||||
|
inline bool is_complex (double x) { (void) x; return false;}
|
||||||
|
inline bool is_complex (int x) { (void) x; return false;}
|
||||||
|
inline bool is_complex (char x) { (void) x; return false;}
|
||||||
|
inline bool is_complex (short x) { (void) x; return false;}
|
||||||
|
|
||||||
|
// this doesn't really belong here, but there are worse places for it...
|
||||||
|
|
||||||
|
#define CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected,actual,delta) \
|
||||||
|
CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.real(), actual.real(), delta); \
|
||||||
|
CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.imag(), actual.imag(), delta);
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_COMPLEX_H */
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006-2009,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_HIER_BLOCK2_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_HIER_BLOCK2_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/basic_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief public constructor for hier_block2
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API hier_block2_sptr
|
||||||
|
make_hier_block2(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
class hier_block2_detail;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Hierarchical container class for gr::block's and gr::hier_block2's
|
||||||
|
* \ingroup container_blk
|
||||||
|
* \ingroup base_blk
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API hier_block2 : public basic_block
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend class hier_block2_detail;
|
||||||
|
friend GR_RUNTIME_API hier_block2_sptr
|
||||||
|
make_hier_block2(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Private implementation details of gr::hier_block2
|
||||||
|
*/
|
||||||
|
hier_block2_detail *d_detail;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
hier_block2(void) {} // allows pure virtual interface sub-classes
|
||||||
|
hier_block2(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~hier_block2();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief typedef for object returned from self().
|
||||||
|
*
|
||||||
|
* This type is only guaranteed to be passable to connect and
|
||||||
|
* disconnect. No other assumptions should be made about it.
|
||||||
|
*/
|
||||||
|
typedef basic_block_sptr opaque_self;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return an object, representing the current block, which
|
||||||
|
* can be passed to connect.
|
||||||
|
*
|
||||||
|
* The returned object may only be used as an argument to connect
|
||||||
|
* or disconnect. Any other use of self() results in unspecified
|
||||||
|
* (erroneous) behavior.
|
||||||
|
*/
|
||||||
|
opaque_self self();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add a stand-alone (possibly hierarchical) block to
|
||||||
|
* internal graph
|
||||||
|
*
|
||||||
|
* This adds a gr-block or hierarchical block to the internal
|
||||||
|
* graph without wiring it to anything else.
|
||||||
|
*/
|
||||||
|
void connect(basic_block_sptr block);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add gr-blocks or hierarchical blocks to internal graph
|
||||||
|
* and wire together
|
||||||
|
*
|
||||||
|
* This adds (if not done earlier by another connect) a pair of
|
||||||
|
* gr-blocks or hierarchical blocks to the internal flowgraph, and
|
||||||
|
* wires the specified output port to the specified input port.
|
||||||
|
*/
|
||||||
|
void connect(basic_block_sptr src, int src_port,
|
||||||
|
basic_block_sptr dst, int dst_port);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Remove a gr-block or hierarchical block from the
|
||||||
|
* internal flowgraph.
|
||||||
|
*
|
||||||
|
* This removes a gr-block or hierarchical block from the internal
|
||||||
|
* flowgraph, disconnecting it from other blocks as needed.
|
||||||
|
*/
|
||||||
|
void disconnect(basic_block_sptr block);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Disconnect a pair of gr-blocks or hierarchical blocks in
|
||||||
|
* internal flowgraph.
|
||||||
|
*
|
||||||
|
* This disconnects the specified input port from the specified
|
||||||
|
* output port of a pair of gr-blocks or hierarchical blocks.
|
||||||
|
*/
|
||||||
|
void disconnect(basic_block_sptr src, int src_port,
|
||||||
|
basic_block_sptr dst, int dst_port);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Disconnect all connections in the internal flowgraph.
|
||||||
|
*
|
||||||
|
* This call removes all output port to input port connections in
|
||||||
|
* the internal flowgraph.
|
||||||
|
*/
|
||||||
|
void disconnect_all();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Lock a flowgraph in preparation for reconfiguration. When an
|
||||||
|
* equal number of calls to lock() and unlock() have occurred, the
|
||||||
|
* flowgraph will be reconfigured.
|
||||||
|
*
|
||||||
|
* N.B. lock() and unlock() may not be called from a flowgraph
|
||||||
|
* thread (E.g., gr::block::work method) or deadlock will occur
|
||||||
|
* when reconfiguration happens.
|
||||||
|
*/
|
||||||
|
virtual void lock();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Unlock a flowgraph in preparation for reconfiguration. When an
|
||||||
|
* equal number of calls to lock() and unlock() have occurred, the
|
||||||
|
* flowgraph will be reconfigured.
|
||||||
|
*
|
||||||
|
* N.B. lock() and unlock() may not be called from a flowgraph
|
||||||
|
* thread (E.g., gr::block::work method) or deadlock will occur
|
||||||
|
* when reconfiguration happens.
|
||||||
|
*/
|
||||||
|
virtual void unlock();
|
||||||
|
|
||||||
|
// This is a public method for ease of code organization, but should be
|
||||||
|
// ignored by the user.
|
||||||
|
flat_flowgraph_sptr flatten() const;
|
||||||
|
|
||||||
|
hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the affinity of all blocks in hier_block2 to processor core \p n.
|
||||||
|
*
|
||||||
|
* \param mask a vector of ints of the core numbers available to this block.
|
||||||
|
*/
|
||||||
|
void set_processor_affinity(const std::vector<int> &mask);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Remove processor affinity for all blocks in hier_block2.
|
||||||
|
*/
|
||||||
|
void unset_processor_affinity();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current processor affinity.
|
||||||
|
*
|
||||||
|
* \details This returns the processor affinity value for the first
|
||||||
|
* block in the hier_block2's list of blocks with the assumption
|
||||||
|
* that they have always only been set through the hier_block2's
|
||||||
|
* interface. If any block has been individually set, then this
|
||||||
|
* call could be misleading.
|
||||||
|
*/
|
||||||
|
std::vector<int> processor_affinity();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline hier_block2_sptr cast_to_hier_block2_sptr(basic_block_sptr block) {
|
||||||
|
return boost::dynamic_pointer_cast<hier_block2, basic_block>(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_HIER_BLOCK2_H */
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2011,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GNURADIO_HIGH_RES_TIMER_H
|
||||||
|
#define INCLUDED_GNURADIO_HIGH_RES_TIMER_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Use architecture defines to determine the implementation
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#if defined(linux) || defined(__linux) || defined(__linux__)
|
||||||
|
#define GNURADIO_HRT_USE_CLOCK_GETTIME
|
||||||
|
#include <ctime>
|
||||||
|
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
#define GNURADIO_HRT_USE_QUERY_PERFORMANCE_COUNTER
|
||||||
|
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||||
|
#define GNURADIO_HRT_USE_MACH_ABSOLUTE_TIME
|
||||||
|
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
#define GNURADIO_HRT_USE_CLOCK_GETTIME
|
||||||
|
#include <ctime>
|
||||||
|
#else
|
||||||
|
#define GNURADIO_HRT_USE_MICROSEC_CLOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
//! Typedef for the timer tick count
|
||||||
|
typedef signed long long high_res_timer_type;
|
||||||
|
|
||||||
|
//! Get the current time in ticks
|
||||||
|
high_res_timer_type high_res_timer_now(void);
|
||||||
|
|
||||||
|
//! Get the current time in ticks - for performance monitoring
|
||||||
|
high_res_timer_type high_res_timer_now_perfmon(void);
|
||||||
|
|
||||||
|
//! Get the number of ticks per second
|
||||||
|
high_res_timer_type high_res_timer_tps(void);
|
||||||
|
|
||||||
|
//! Get the tick count at the epoch
|
||||||
|
high_res_timer_type high_res_timer_epoch(void);
|
||||||
|
|
||||||
|
#ifdef GNURADIO_HRT_USE_CLOCK_GETTIME
|
||||||
|
//! storage for high res timer type
|
||||||
|
GR_RUNTIME_API extern clockid_t high_res_timer_source;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef GNURADIO_HRT_USE_CLOCK_GETTIME
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now(void){
|
||||||
|
timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
|
||||||
|
timespec ts;
|
||||||
|
clock_gettime(high_res_timer_source, &ts);
|
||||||
|
return ts.tv_sec*high_res_timer_tps() + ts.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
|
||||||
|
return 1000000000UL;
|
||||||
|
}
|
||||||
|
#endif /* GNURADIO_HRT_USE_CLOCK_GETTIME */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef GNURADIO_HRT_USE_MACH_ABSOLUTE_TIME
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now(void){
|
||||||
|
return mach_absolute_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
|
||||||
|
return gr::high_res_timer_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
|
||||||
|
mach_timebase_info_data_t info;
|
||||||
|
mach_timebase_info(&info);
|
||||||
|
return gr::high_res_timer_type(info.numer*1000000000UL)/info.denom;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef GNURADIO_HRT_USE_QUERY_PERFORMANCE_COUNTER
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now(void){
|
||||||
|
LARGE_INTEGER counts;
|
||||||
|
QueryPerformanceCounter(&counts);
|
||||||
|
return counts.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
|
||||||
|
return gr::high_res_timer_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
QueryPerformanceFrequency(&freq);
|
||||||
|
return freq.QuadPart;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef GNURADIO_HRT_USE_MICROSEC_CLOCK
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now(void){
|
||||||
|
static const boost::posix_time::ptime epoch(boost::posix_time::from_time_t(0));
|
||||||
|
return (boost::posix_time::microsec_clock::universal_time() - epoch).ticks();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_now_perfmon(void){
|
||||||
|
return gr::high_res_timer_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_tps(void){
|
||||||
|
return boost::posix_time::time_duration::ticks_per_second();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
inline gr::high_res_timer_type gr::high_res_timer_epoch(void){
|
||||||
|
static const double hrt_ticks_per_utc_ticks = gr::high_res_timer_tps()/double(boost::posix_time::time_duration::ticks_per_second());
|
||||||
|
boost::posix_time::time_duration utc = boost::posix_time::microsec_clock::universal_time() - boost::posix_time::from_time_t(0);
|
||||||
|
return gr::high_res_timer_now() - utc.ticks()*hrt_ticks_per_utc_ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GNURADIO_HIGH_RES_TIMER_H */
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_IO_SIGNATURE_H
|
||||||
|
#define INCLUDED_IO_SIGNATURE_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/runtime_types.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief i/o signature for input and output ports.
|
||||||
|
* \brief misc
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API io_signature
|
||||||
|
{
|
||||||
|
int d_min_streams;
|
||||||
|
int d_max_streams;
|
||||||
|
std::vector<int> d_sizeof_stream_item;
|
||||||
|
|
||||||
|
io_signature(int min_streams, int max_streams,
|
||||||
|
const std::vector<int> &sizeof_stream_items);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<io_signature> sptr;
|
||||||
|
|
||||||
|
static const int IO_INFINITE = -1;
|
||||||
|
|
||||||
|
~io_signature();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create an i/o signature
|
||||||
|
*
|
||||||
|
* \ingroup internal
|
||||||
|
* \param min_streams specify minimum number of streams (>= 0)
|
||||||
|
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
|
||||||
|
* \param sizeof_stream_item specify the size of the items in each stream
|
||||||
|
*/
|
||||||
|
static sptr make(int min_streams, int max_streams,
|
||||||
|
int sizeof_stream_item);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create an i/o signature
|
||||||
|
*
|
||||||
|
* \param min_streams specify minimum number of streams (>= 0)
|
||||||
|
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
|
||||||
|
* \param sizeof_stream_item1 specify the size of the items in the first stream
|
||||||
|
* \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams
|
||||||
|
*/
|
||||||
|
static sptr make2(int min_streams, int max_streams,
|
||||||
|
int sizeof_stream_item1,
|
||||||
|
int sizeof_stream_item2);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create an i/o signature
|
||||||
|
*
|
||||||
|
* \param min_streams specify minimum number of streams (>= 0)
|
||||||
|
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
|
||||||
|
* \param sizeof_stream_item1 specify the size of the items in the first stream
|
||||||
|
* \param sizeof_stream_item2 specify the size of the items in the second stream
|
||||||
|
* \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams
|
||||||
|
*/
|
||||||
|
static sptr make3(int min_streams, int max_streams,
|
||||||
|
int sizeof_stream_item1,
|
||||||
|
int sizeof_stream_item2,
|
||||||
|
int sizeof_stream_item3);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create an i/o signature
|
||||||
|
*
|
||||||
|
* \param min_streams specify minimum number of streams (>= 0)
|
||||||
|
* \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
|
||||||
|
* \param sizeof_stream_items specify the size of the items in the streams
|
||||||
|
*
|
||||||
|
* If there are more streams than there are entries in
|
||||||
|
* sizeof_stream_items, the value of the last entry in
|
||||||
|
* sizeof_stream_items is used for the missing values.
|
||||||
|
* sizeof_stream_items must contain at least 1 entry.
|
||||||
|
*/
|
||||||
|
static sptr makev(int min_streams, int max_streams,
|
||||||
|
const std::vector<int> &sizeof_stream_items);
|
||||||
|
|
||||||
|
int min_streams() const { return d_min_streams; }
|
||||||
|
int max_streams() const { return d_max_streams; }
|
||||||
|
int sizeof_stream_item(int index) const;
|
||||||
|
std::vector<int> sizeof_stream_items() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_IO_SIGNATURE_H */
|
|
@ -0,0 +1,733 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Author: Mark Plett
|
||||||
|
* Description:
|
||||||
|
* The gr::logger module wraps the log4cpp library for logging in gnuradio
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_LOGGER_H
|
||||||
|
#define INCLUDED_GR_LOGGER_H
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup logging
|
||||||
|
* \brief GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ENABLE_GR_LOG
|
||||||
|
//#cmakedefine ENABLE_GR_LOG
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_LOG4CPP
|
||||||
|
//#cmakedefine HAVE_LOG4CPP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned short mode_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <time.h>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
#ifdef ENABLE_GR_LOG
|
||||||
|
|
||||||
|
// We have three configurations... first logging to stdout/stderr
|
||||||
|
#ifndef HAVE_LOG4CPP
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
//#warning GR logging Enabled and using std::cout
|
||||||
|
typedef std::string logger_ptr;
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger)
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
|
||||||
|
#define GR_CONFIG_LOGGER(config)
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name)
|
||||||
|
#define GR_SET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level)
|
||||||
|
#define GR_GET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level)
|
||||||
|
#define GR_ADD_APPENDER(name,appender)
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger,appender)
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_GET_LOGGER_NAMES(names)
|
||||||
|
#define GR_RESET_CONFIGURATION()
|
||||||
|
#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl
|
||||||
|
#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl
|
||||||
|
#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl
|
||||||
|
#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl
|
||||||
|
#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl
|
||||||
|
#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl
|
||||||
|
#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
|
||||||
|
#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);}
|
||||||
|
#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ERRORIF(logger, cond, msg) { \
|
||||||
|
if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg) { \
|
||||||
|
if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* HAVE_LOG4CPP */
|
||||||
|
|
||||||
|
// Second configuration...logging to log4cpp
|
||||||
|
#include <log4cpp/Category.hh>
|
||||||
|
#include <log4cpp/PropertyConfigurator.hh>
|
||||||
|
#include <log4cpp/FileAppender.hh>
|
||||||
|
#include <log4cpp/RollingFileAppender.hh>
|
||||||
|
#include <log4cpp/OstreamAppender.hh>
|
||||||
|
#include <log4cpp/PatternLayout.hh>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief GR_LOG macros
|
||||||
|
* \ingroup logging
|
||||||
|
*
|
||||||
|
* These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros
|
||||||
|
* are:
|
||||||
|
* LOG_DEBUG
|
||||||
|
* LOG_INFO
|
||||||
|
* LOG_WARN
|
||||||
|
* LOG_TRACE
|
||||||
|
* LOG_ERROR
|
||||||
|
* LOG_ALERT
|
||||||
|
* LOG_CRIT
|
||||||
|
* LOG_FATAL
|
||||||
|
* LOG_EMERG
|
||||||
|
*/
|
||||||
|
typedef log4cpp::Category* logger_ptr;
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros for Programmatic Configuration */
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger) \
|
||||||
|
gr::logger_ptr logger;
|
||||||
|
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name) \
|
||||||
|
logger = gr::logger_get_logger(name);
|
||||||
|
|
||||||
|
#define GR_CONFIG_LOGGER(config) \
|
||||||
|
gr::logger_config::load_config(config)
|
||||||
|
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \
|
||||||
|
gr::logger_config::load_config(config,period)
|
||||||
|
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name) \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name);
|
||||||
|
|
||||||
|
#define GR_SET_LEVEL(name, level) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_set_level(logger,level);}
|
||||||
|
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level) \
|
||||||
|
gr::logger_set_level(logger, level);
|
||||||
|
|
||||||
|
#define GR_GET_LEVEL(name, level) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_get_level(logger,level);}
|
||||||
|
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level) \
|
||||||
|
gr::logger_get_level(logger,level);
|
||||||
|
|
||||||
|
#define GR_ADD_APPENDER(name, appender) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_appender(logger,appender);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger, appender) { \
|
||||||
|
gr::logger_add_appender(logger, appender);}
|
||||||
|
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(name, target, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_console_appender(logger,target,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger, target, pattern) { \
|
||||||
|
gr::logger_add_console_appender(logger,target,pattern);}
|
||||||
|
|
||||||
|
#define GR_ADD_FILE_APPENDER(name, filename, append, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_file_appender(logger,filename,append,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger, filename, append, pattern) { \
|
||||||
|
gr::logger_add_file_appender(logger,filename,append,pattern);}
|
||||||
|
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name, filename, filesize, bkup_index, append, mode, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger, filename, filesize, bkup_index, append, mode, pattern) { \
|
||||||
|
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
|
||||||
|
|
||||||
|
#define GR_GET_LOGGER_NAMES(names) { \
|
||||||
|
names = gr::logger_get_logger_names();}
|
||||||
|
|
||||||
|
#define GR_RESET_CONFIGURATION() \
|
||||||
|
gr::logger_config::reset_config();
|
||||||
|
|
||||||
|
/* Logger name referenced macros */
|
||||||
|
#define GR_DEBUG(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_INFO(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_NOTICE(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger << log4cpp::Priority::NOTICE << msg;}
|
||||||
|
|
||||||
|
#define GR_WARN(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ERROR(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_CRIT(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ALERT(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_FATAL(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_EMERG(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ERRORIF(name, cond, msg) { \
|
||||||
|
if((cond)) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GR_ASSERT(name, cond, msg) { \
|
||||||
|
if(!(cond)) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} \
|
||||||
|
assert(0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LoggerPtr Referenced Macros */
|
||||||
|
#define GR_LOG_DEBUG(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_INFO(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::INFO << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_NOTICE(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_WARN(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::WARN << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ERROR(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_CRIT(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ALERT(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_FATAL(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_EMERG(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ERRORIF(logger,cond, msg) { \
|
||||||
|
if((cond)) { \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg) { \
|
||||||
|
if(!(cond)) { \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol; \
|
||||||
|
assert(0);} \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Class to control configuration of logger.
|
||||||
|
* This is a singleton that cna launch a thread to wathc a config file for changes
|
||||||
|
* \ingroup logging
|
||||||
|
*/
|
||||||
|
class logger_config
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*! \brief filename of logger config file */
|
||||||
|
std::string filename;
|
||||||
|
/*! \brief Period (seconds) over which watcher thread checks config file for changes */
|
||||||
|
unsigned int watch_period;
|
||||||
|
/*! \brief Pointer to watch thread for config file changes */
|
||||||
|
boost::thread *watch_thread;
|
||||||
|
|
||||||
|
/*! \brief Watcher thread method
|
||||||
|
* /param filename Name of configuration file
|
||||||
|
* /param watch_period Seconds between checks for changes in config file
|
||||||
|
*/
|
||||||
|
static void watch_file(std::string filename,unsigned int watch_period);
|
||||||
|
|
||||||
|
static bool logger_configured;
|
||||||
|
|
||||||
|
logger_config()
|
||||||
|
{
|
||||||
|
} //!< Constructor
|
||||||
|
|
||||||
|
/*
|
||||||
|
rpcbasic_register_get<logger_config,std::string> rpc_get_filename;
|
||||||
|
rpcbasic_register_get<logger_config,int> rpc_get_watchperiod;
|
||||||
|
rpcbasic_register_get<logger_config,std::string> rpc_get_config;
|
||||||
|
rpcbasic_register_set<logger_config,std::string> rpc_set_config;
|
||||||
|
*/
|
||||||
|
|
||||||
|
logger_config(logger_config const&); //!<Copy constructor
|
||||||
|
void operator=(logger_config const&); //!<Assignment Operator
|
||||||
|
|
||||||
|
std::string get_filename4rpc() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
int get_watchperiod4rpc(){return watch_period;};
|
||||||
|
|
||||||
|
std::string get_config4rpc() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_config4rpc(std::string set) {
|
||||||
|
printf("Set string was:%s\n", set.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief destrcutor stops watch thread before exits */
|
||||||
|
~logger_config() {
|
||||||
|
stop_watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Instance getter for singleton. Only used by class. */
|
||||||
|
static logger_config& get_instance(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Getter for config filename */
|
||||||
|
static std::string get_filename();
|
||||||
|
/*! \brief Getter for watch period */
|
||||||
|
static unsigned int get_watch_period();
|
||||||
|
/*! \brief Method to load configuration
|
||||||
|
* /param filename Name of configuration file
|
||||||
|
* /param watch_period Seconds between checks for changes in config file
|
||||||
|
*/
|
||||||
|
static void load_config(std::string filename,unsigned int watch_period=0);
|
||||||
|
/*! \brief Method to stop watcher thread */
|
||||||
|
static void stop_watch();
|
||||||
|
/*! \brief method to reset logger configuration */
|
||||||
|
static void reset_config(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve a pointer to a logger by name
|
||||||
|
*
|
||||||
|
* Retrives a logger pointer
|
||||||
|
* \p name.
|
||||||
|
*
|
||||||
|
* \param name Name of the logger for which a pointer is requested
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API logger_ptr logger_get_logger(std::string name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Load logger's configuration file.
|
||||||
|
*
|
||||||
|
* Initialize the GNU Radio logger by loading the configuration file
|
||||||
|
* \p config_filename.
|
||||||
|
*
|
||||||
|
* \param config_filename The configuration file. Set to "" for the
|
||||||
|
* basic logger that outputs to the console.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API bool logger_load_config(const std::string &config_filename="");
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Reset logger's configuration file.
|
||||||
|
*
|
||||||
|
* Remove all appenders from loggers
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_reset_config(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the logger's output level.
|
||||||
|
*
|
||||||
|
* Sets the level of the logger. This takes a string that is
|
||||||
|
* translated to the standard levels and can be (case insensitive):
|
||||||
|
*
|
||||||
|
* \li off , notset
|
||||||
|
* \li debug
|
||||||
|
* \li info
|
||||||
|
* \li notice
|
||||||
|
* \li warn
|
||||||
|
* \li error
|
||||||
|
* \li crit
|
||||||
|
* \li alert
|
||||||
|
* \li fatal
|
||||||
|
* \li emerg
|
||||||
|
*
|
||||||
|
* \param logger the logger to set the level of.
|
||||||
|
* \param level string to set the level to.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
|
||||||
|
const std::string &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the logger's output level.
|
||||||
|
*
|
||||||
|
* Sets the level of the logger. This takes the actual Log4cpp::Priority
|
||||||
|
* data type, which can be:
|
||||||
|
*
|
||||||
|
* \li log4cpp::Priority::NOTSET
|
||||||
|
* \li log4cpp::Priority::DEBUG
|
||||||
|
* \li log4cpp::Priority::INFO
|
||||||
|
* \li log4cpp::Priority::NOTICE
|
||||||
|
* \li log4cpp::Priority::WARN
|
||||||
|
* \li log4cpp::Priority::ERROR
|
||||||
|
* \li log4cpp::Priority::CRIT
|
||||||
|
* \li log4cpp::Priority::ALERT
|
||||||
|
* \li log4cpp::Priority::FATAL
|
||||||
|
* \li log4cpp::Priority::EMERG
|
||||||
|
*
|
||||||
|
* \param logger the logger to set the level of.
|
||||||
|
* \param level new logger level of type Log4cpp::Priority
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
|
||||||
|
log4cpp::Priority::Value level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the logger's output level.
|
||||||
|
*
|
||||||
|
* Gets the level of the logger. This returns a string that
|
||||||
|
* corresponds to the standard levels and can be (case insensitive):
|
||||||
|
*
|
||||||
|
* \li notset
|
||||||
|
* \li debug
|
||||||
|
* \li info
|
||||||
|
* \li notice
|
||||||
|
* \li warn
|
||||||
|
* \li error
|
||||||
|
* \li crit
|
||||||
|
* \li alert
|
||||||
|
* \li fatal
|
||||||
|
* \li emerg
|
||||||
|
*
|
||||||
|
* \param logger the logger to get the level of.
|
||||||
|
* \param level string to get the level into.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_get_level(logger_ptr logger, std::string &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the logger's output level.
|
||||||
|
*
|
||||||
|
* Gets the level of the logger. This returns the actual Log4cpp::Level
|
||||||
|
* data type, which can be:
|
||||||
|
*
|
||||||
|
* \li log4cpp::Priority::NOTSET
|
||||||
|
* \li log4cpp::Priority::DEBUG
|
||||||
|
* \li log4cpp::Priority::INFO
|
||||||
|
* \li log4cpp::Priority::NOTICE
|
||||||
|
* \li log4cpp::Priority::WARN
|
||||||
|
* \li log4cpp::Priority::ERROR
|
||||||
|
* \li log4cpp::Priority::CRIT
|
||||||
|
* \li log4cpp::Priority::ALERT
|
||||||
|
* \li log4cpp::Priority::FATAL
|
||||||
|
* \li log4cpp::Priority::EMERG
|
||||||
|
*
|
||||||
|
* \param logger the logger to get the level of.
|
||||||
|
* \param level of the logger.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_get_level(logger_ptr logger,
|
||||||
|
log4cpp::Priority::Value &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param appender Name of appender to add to logger
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_appender(logger_ptr logger,
|
||||||
|
std::string appender);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param target Std target to write 'cout' or 'cerr' (default is cout)
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_console_appender(logger_ptr logger,
|
||||||
|
std::string target,
|
||||||
|
std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add file appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param filename File to which log will be written
|
||||||
|
* \param append Overwrite or append to log file
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_file_appender(logger_ptr logger,
|
||||||
|
std::string filename,
|
||||||
|
bool append, std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param filename File to which log will be written
|
||||||
|
* \param filesize Sizez of files to write
|
||||||
|
* \param bkup_index Number of files to write
|
||||||
|
* \param append Overwrite or append to log file
|
||||||
|
* \param mode Permissions to set on log file
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_rollingfile_appender(logger_ptr logger, std::string filename,
|
||||||
|
size_t filesize, int bkup_index, bool append,
|
||||||
|
mode_t mode,std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* \return vector of string names of loggers
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* HAVE_LOG4CPP */
|
||||||
|
|
||||||
|
// If Logger disable do nothing
|
||||||
|
#else /* ENABLE_GR_LOG */
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
typedef void* logger_ptr;
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger)
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
|
||||||
|
#define GR_CONFIG_LOGGER(config)
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name)
|
||||||
|
#define GR_SET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level)
|
||||||
|
#define GR_GET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level)
|
||||||
|
#define GR_ADD_APPENDER(name,appender)
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger,appender)
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_GET_LOGGER_NAMES(names)
|
||||||
|
#define GR_RESET_CONFIGURATION()
|
||||||
|
#define GR_DEBUG(name, msg)
|
||||||
|
#define GR_INFO(name, msg)
|
||||||
|
#define GR_NOTICE(name, msg)
|
||||||
|
#define GR_WARN(name, msg)
|
||||||
|
#define GR_ERROR(name, msg)
|
||||||
|
#define GR_ALERT(name, msg)
|
||||||
|
#define GR_CRIT(name, msg)
|
||||||
|
#define GR_FATAL(name, msg)
|
||||||
|
#define GR_EMERG(name, msg)
|
||||||
|
#define GR_ERRORIF(name, cond, msg)
|
||||||
|
#define GR_ASSERT(name, cond, msg)
|
||||||
|
#define GR_LOG_DEBUG(logger, msg)
|
||||||
|
#define GR_LOG_INFO(logger, msg)
|
||||||
|
#define GR_LOG_NOTICE(logger, msg)
|
||||||
|
#define GR_LOG_WARN(logger, msg)
|
||||||
|
#define GR_LOG_ERROR(logger, msg)
|
||||||
|
#define GR_LOG_ALERT(logger, msg)
|
||||||
|
#define GR_LOG_CRIT(logger, msg)
|
||||||
|
#define GR_LOG_FATAL(logger, msg)
|
||||||
|
#define GR_LOG_EMERG(logger, msg)
|
||||||
|
#define GR_LOG_ERRORIF(logger, cond, msg)
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg)
|
||||||
|
|
||||||
|
#endif /* ENABLE_GR_LOG */
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
// Even if logger is disabled we'll need for methods below to exist in python.
|
||||||
|
// The macros these call will be disabled if ENABLE_GR_LOG is undefined
|
||||||
|
|
||||||
|
/********************* Start Classes and Methods for Python ******************/
|
||||||
|
/*!
|
||||||
|
* \brief Logger class for referencing loggers in python. Not
|
||||||
|
* needed in C++ (use macros) Wraps and manipulates loggers for
|
||||||
|
* python as python has no macros
|
||||||
|
* \ingroup logging
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class logger
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*! \brief logger pointer to logger associated wiith this wrapper class */
|
||||||
|
logger_ptr d_logger;
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief contructor Provide name of logger to associate with this class
|
||||||
|
* \param logger_name Name of logger associated with class
|
||||||
|
*/
|
||||||
|
logger(std::string logger_name) {
|
||||||
|
GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief Destructor */
|
||||||
|
~logger(){;}
|
||||||
|
|
||||||
|
// Wrappers for logging macros
|
||||||
|
/*! \brief inline function, wrapper to set the logger level */
|
||||||
|
void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper to get the logger level */
|
||||||
|
void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */
|
||||||
|
void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */
|
||||||
|
void info(std::string msg){GR_LOG_INFO(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for NOTICE message */
|
||||||
|
void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */
|
||||||
|
void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */
|
||||||
|
void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for NOTICE message */
|
||||||
|
void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for ALERT message */
|
||||||
|
void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for FATAL message */
|
||||||
|
void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for EMERG message */
|
||||||
|
void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
|
||||||
|
void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
|
||||||
|
void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add appender to logger by
|
||||||
|
name (define appender in conf file) */
|
||||||
|
void add_appender(std::string appender) {
|
||||||
|
GR_LOG_ADD_APPENDER(d_logger, appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add console appender to logger */
|
||||||
|
void add_console_appender(std::string target,std::string pattern) {
|
||||||
|
GR_LOG_ADD_CONSOLE_APPENDER(d_logger, target, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add file appender to logger */
|
||||||
|
void add_file_appender(std::string filename, bool append, std::string pattern) {
|
||||||
|
GR_LOG_ADD_FILE_APPENDER(d_logger, filename, append, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add rolling file appender to logger */
|
||||||
|
void add_rollingfile_appender(std::string filename, size_t filesize,
|
||||||
|
int bkup_index, bool append, mode_t mode,
|
||||||
|
std::string pattern) {
|
||||||
|
GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize,
|
||||||
|
bkup_index,append,mode,pattern);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
/**************** Start Configuration Class and Methods for Python ************/
|
||||||
|
/*!
|
||||||
|
* \brief Function to call configuration macro from python.
|
||||||
|
* Note: Configuration is only updated if filename or watch_period has changed.
|
||||||
|
* \param config_filename Name of configuration file
|
||||||
|
* \param watch_period Seconds to wait between checking for changes in conf file.
|
||||||
|
* Watch_period defaults to 0 in which case the file is not watched for changes
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void gr_logger_config(const std::string config_filename,
|
||||||
|
unsigned int watch_period = 0);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to return logger names to python
|
||||||
|
* \return Vector of name strings
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to reset logger configuration from python
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void gr_logger_reset_config(void);
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_LOGGER_H */
|
|
@ -0,0 +1,733 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Author: Mark Plett
|
||||||
|
* Description:
|
||||||
|
* The gr::logger module wraps the log4cpp library for logging in gnuradio
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_LOGGER_H
|
||||||
|
#define INCLUDED_GR_LOGGER_H
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup logging
|
||||||
|
* \brief GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ENABLE_GR_LOG
|
||||||
|
#cmakedefine ENABLE_GR_LOG
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_LOG4CPP
|
||||||
|
#cmakedefine HAVE_LOG4CPP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned short mode_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <time.h>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
#ifdef ENABLE_GR_LOG
|
||||||
|
|
||||||
|
// We have three configurations... first logging to stdout/stderr
|
||||||
|
#ifndef HAVE_LOG4CPP
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
//#warning GR logging Enabled and using std::cout
|
||||||
|
typedef std::string logger_ptr;
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger)
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
|
||||||
|
#define GR_CONFIG_LOGGER(config)
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name)
|
||||||
|
#define GR_SET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level)
|
||||||
|
#define GR_GET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level)
|
||||||
|
#define GR_ADD_APPENDER(name,appender)
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger,appender)
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_GET_LOGGER_NAMES(names)
|
||||||
|
#define GR_RESET_CONFIGURATION()
|
||||||
|
#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl
|
||||||
|
#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl
|
||||||
|
#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl
|
||||||
|
#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl
|
||||||
|
#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl
|
||||||
|
#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl
|
||||||
|
#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
|
||||||
|
#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);}
|
||||||
|
#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl
|
||||||
|
#define GR_LOG_ERRORIF(logger, cond, msg) { \
|
||||||
|
if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg) { \
|
||||||
|
if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* HAVE_LOG4CPP */
|
||||||
|
|
||||||
|
// Second configuration...logging to log4cpp
|
||||||
|
#include <log4cpp/Category.hh>
|
||||||
|
#include <log4cpp/PropertyConfigurator.hh>
|
||||||
|
#include <log4cpp/FileAppender.hh>
|
||||||
|
#include <log4cpp/RollingFileAppender.hh>
|
||||||
|
#include <log4cpp/OstreamAppender.hh>
|
||||||
|
#include <log4cpp/PatternLayout.hh>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief GR_LOG macros
|
||||||
|
* \ingroup logging
|
||||||
|
*
|
||||||
|
* These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros
|
||||||
|
* are:
|
||||||
|
* LOG_DEBUG
|
||||||
|
* LOG_INFO
|
||||||
|
* LOG_WARN
|
||||||
|
* LOG_TRACE
|
||||||
|
* LOG_ERROR
|
||||||
|
* LOG_ALERT
|
||||||
|
* LOG_CRIT
|
||||||
|
* LOG_FATAL
|
||||||
|
* LOG_EMERG
|
||||||
|
*/
|
||||||
|
typedef log4cpp::Category* logger_ptr;
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros for Programmatic Configuration */
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger) \
|
||||||
|
gr::logger_ptr logger;
|
||||||
|
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name) \
|
||||||
|
logger = gr::logger_get_logger(name);
|
||||||
|
|
||||||
|
#define GR_CONFIG_LOGGER(config) \
|
||||||
|
gr::logger_config::load_config(config)
|
||||||
|
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \
|
||||||
|
gr::logger_config::load_config(config,period)
|
||||||
|
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name) \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name);
|
||||||
|
|
||||||
|
#define GR_SET_LEVEL(name, level) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_set_level(logger,level);}
|
||||||
|
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level) \
|
||||||
|
gr::logger_set_level(logger, level);
|
||||||
|
|
||||||
|
#define GR_GET_LEVEL(name, level) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_get_level(logger,level);}
|
||||||
|
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level) \
|
||||||
|
gr::logger_get_level(logger,level);
|
||||||
|
|
||||||
|
#define GR_ADD_APPENDER(name, appender) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_appender(logger,appender);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger, appender) { \
|
||||||
|
gr::logger_add_appender(logger, appender);}
|
||||||
|
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(name, target, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_console_appender(logger,target,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger, target, pattern) { \
|
||||||
|
gr::logger_add_console_appender(logger,target,pattern);}
|
||||||
|
|
||||||
|
#define GR_ADD_FILE_APPENDER(name, filename, append, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_file_appender(logger,filename,append,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger, filename, append, pattern) { \
|
||||||
|
gr::logger_add_file_appender(logger,filename,append,pattern);}
|
||||||
|
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name, filename, filesize, bkup_index, append, mode, pattern) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
|
||||||
|
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger, filename, filesize, bkup_index, append, mode, pattern) { \
|
||||||
|
gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
|
||||||
|
|
||||||
|
#define GR_GET_LOGGER_NAMES(names) { \
|
||||||
|
names = gr::logger_get_logger_names();}
|
||||||
|
|
||||||
|
#define GR_RESET_CONFIGURATION() \
|
||||||
|
gr::logger_config::reset_config();
|
||||||
|
|
||||||
|
/* Logger name referenced macros */
|
||||||
|
#define GR_DEBUG(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_INFO(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_NOTICE(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger << log4cpp::Priority::NOTICE << msg;}
|
||||||
|
|
||||||
|
#define GR_WARN(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ERROR(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_CRIT(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ALERT(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_FATAL(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_EMERG(name, msg) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_ERRORIF(name, cond, msg) { \
|
||||||
|
if((cond)) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GR_ASSERT(name, cond, msg) { \
|
||||||
|
if(!(cond)) { \
|
||||||
|
gr::logger_ptr logger = gr::logger_get_logger(name); \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} \
|
||||||
|
assert(0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LoggerPtr Referenced Macros */
|
||||||
|
#define GR_LOG_DEBUG(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_INFO(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::INFO << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_NOTICE(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_WARN(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::WARN << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ERROR(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_CRIT(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ALERT(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_FATAL(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_EMERG(logger, msg) { \
|
||||||
|
*logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;}
|
||||||
|
|
||||||
|
#define GR_LOG_ERRORIF(logger,cond, msg) { \
|
||||||
|
if((cond)) { \
|
||||||
|
*logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg) { \
|
||||||
|
if(!(cond)) { \
|
||||||
|
*logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol; \
|
||||||
|
assert(0);} \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Class to control configuration of logger.
|
||||||
|
* This is a singleton that cna launch a thread to wathc a config file for changes
|
||||||
|
* \ingroup logging
|
||||||
|
*/
|
||||||
|
class logger_config
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*! \brief filename of logger config file */
|
||||||
|
std::string filename;
|
||||||
|
/*! \brief Period (seconds) over which watcher thread checks config file for changes */
|
||||||
|
unsigned int watch_period;
|
||||||
|
/*! \brief Pointer to watch thread for config file changes */
|
||||||
|
boost::thread *watch_thread;
|
||||||
|
|
||||||
|
/*! \brief Watcher thread method
|
||||||
|
* /param filename Name of configuration file
|
||||||
|
* /param watch_period Seconds between checks for changes in config file
|
||||||
|
*/
|
||||||
|
static void watch_file(std::string filename,unsigned int watch_period);
|
||||||
|
|
||||||
|
static bool logger_configured;
|
||||||
|
|
||||||
|
logger_config()
|
||||||
|
{
|
||||||
|
} //!< Constructor
|
||||||
|
|
||||||
|
/*
|
||||||
|
rpcbasic_register_get<logger_config,std::string> rpc_get_filename;
|
||||||
|
rpcbasic_register_get<logger_config,int> rpc_get_watchperiod;
|
||||||
|
rpcbasic_register_get<logger_config,std::string> rpc_get_config;
|
||||||
|
rpcbasic_register_set<logger_config,std::string> rpc_set_config;
|
||||||
|
*/
|
||||||
|
|
||||||
|
logger_config(logger_config const&); //!<Copy constructor
|
||||||
|
void operator=(logger_config const&); //!<Assignment Operator
|
||||||
|
|
||||||
|
std::string get_filename4rpc() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
int get_watchperiod4rpc(){return watch_period;};
|
||||||
|
|
||||||
|
std::string get_config4rpc() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_config4rpc(std::string set) {
|
||||||
|
printf("Set string was:%s\n", set.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief destrcutor stops watch thread before exits */
|
||||||
|
~logger_config() {
|
||||||
|
stop_watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Instance getter for singleton. Only used by class. */
|
||||||
|
static logger_config& get_instance(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Getter for config filename */
|
||||||
|
static std::string get_filename();
|
||||||
|
/*! \brief Getter for watch period */
|
||||||
|
static unsigned int get_watch_period();
|
||||||
|
/*! \brief Method to load configuration
|
||||||
|
* /param filename Name of configuration file
|
||||||
|
* /param watch_period Seconds between checks for changes in config file
|
||||||
|
*/
|
||||||
|
static void load_config(std::string filename,unsigned int watch_period=0);
|
||||||
|
/*! \brief Method to stop watcher thread */
|
||||||
|
static void stop_watch();
|
||||||
|
/*! \brief method to reset logger configuration */
|
||||||
|
static void reset_config(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve a pointer to a logger by name
|
||||||
|
*
|
||||||
|
* Retrives a logger pointer
|
||||||
|
* \p name.
|
||||||
|
*
|
||||||
|
* \param name Name of the logger for which a pointer is requested
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API logger_ptr logger_get_logger(std::string name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Load logger's configuration file.
|
||||||
|
*
|
||||||
|
* Initialize the GNU Radio logger by loading the configuration file
|
||||||
|
* \p config_filename.
|
||||||
|
*
|
||||||
|
* \param config_filename The configuration file. Set to "" for the
|
||||||
|
* basic logger that outputs to the console.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API bool logger_load_config(const std::string &config_filename="");
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Reset logger's configuration file.
|
||||||
|
*
|
||||||
|
* Remove all appenders from loggers
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_reset_config(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the logger's output level.
|
||||||
|
*
|
||||||
|
* Sets the level of the logger. This takes a string that is
|
||||||
|
* translated to the standard levels and can be (case insensitive):
|
||||||
|
*
|
||||||
|
* \li off , notset
|
||||||
|
* \li debug
|
||||||
|
* \li info
|
||||||
|
* \li notice
|
||||||
|
* \li warn
|
||||||
|
* \li error
|
||||||
|
* \li crit
|
||||||
|
* \li alert
|
||||||
|
* \li fatal
|
||||||
|
* \li emerg
|
||||||
|
*
|
||||||
|
* \param logger the logger to set the level of.
|
||||||
|
* \param level string to set the level to.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
|
||||||
|
const std::string &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the logger's output level.
|
||||||
|
*
|
||||||
|
* Sets the level of the logger. This takes the actual Log4cpp::Priority
|
||||||
|
* data type, which can be:
|
||||||
|
*
|
||||||
|
* \li log4cpp::Priority::NOTSET
|
||||||
|
* \li log4cpp::Priority::DEBUG
|
||||||
|
* \li log4cpp::Priority::INFO
|
||||||
|
* \li log4cpp::Priority::NOTICE
|
||||||
|
* \li log4cpp::Priority::WARN
|
||||||
|
* \li log4cpp::Priority::ERROR
|
||||||
|
* \li log4cpp::Priority::CRIT
|
||||||
|
* \li log4cpp::Priority::ALERT
|
||||||
|
* \li log4cpp::Priority::FATAL
|
||||||
|
* \li log4cpp::Priority::EMERG
|
||||||
|
*
|
||||||
|
* \param logger the logger to set the level of.
|
||||||
|
* \param level new logger level of type Log4cpp::Priority
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_set_level(logger_ptr logger,
|
||||||
|
log4cpp::Priority::Value level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the logger's output level.
|
||||||
|
*
|
||||||
|
* Gets the level of the logger. This returns a string that
|
||||||
|
* corresponds to the standard levels and can be (case insensitive):
|
||||||
|
*
|
||||||
|
* \li notset
|
||||||
|
* \li debug
|
||||||
|
* \li info
|
||||||
|
* \li notice
|
||||||
|
* \li warn
|
||||||
|
* \li error
|
||||||
|
* \li crit
|
||||||
|
* \li alert
|
||||||
|
* \li fatal
|
||||||
|
* \li emerg
|
||||||
|
*
|
||||||
|
* \param logger the logger to get the level of.
|
||||||
|
* \param level string to get the level into.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_get_level(logger_ptr logger, std::string &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the logger's output level.
|
||||||
|
*
|
||||||
|
* Gets the level of the logger. This returns the actual Log4cpp::Level
|
||||||
|
* data type, which can be:
|
||||||
|
*
|
||||||
|
* \li log4cpp::Priority::NOTSET
|
||||||
|
* \li log4cpp::Priority::DEBUG
|
||||||
|
* \li log4cpp::Priority::INFO
|
||||||
|
* \li log4cpp::Priority::NOTICE
|
||||||
|
* \li log4cpp::Priority::WARN
|
||||||
|
* \li log4cpp::Priority::ERROR
|
||||||
|
* \li log4cpp::Priority::CRIT
|
||||||
|
* \li log4cpp::Priority::ALERT
|
||||||
|
* \li log4cpp::Priority::FATAL
|
||||||
|
* \li log4cpp::Priority::EMERG
|
||||||
|
*
|
||||||
|
* \param logger the logger to get the level of.
|
||||||
|
* \param level of the logger.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_get_level(logger_ptr logger,
|
||||||
|
log4cpp::Priority::Value &level);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param appender Name of appender to add to logger
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_appender(logger_ptr logger,
|
||||||
|
std::string appender);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* Add console appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param target Std target to write 'cout' or 'cerr' (default is cout)
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_console_appender(logger_ptr logger,
|
||||||
|
std::string target,
|
||||||
|
std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add file appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param filename File to which log will be written
|
||||||
|
* \param append Overwrite or append to log file
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_file_appender(logger_ptr logger,
|
||||||
|
std::string filename,
|
||||||
|
bool append, std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* \param logger Logger to which appender will be added
|
||||||
|
* \param filename File to which log will be written
|
||||||
|
* \param filesize Sizez of files to write
|
||||||
|
* \param bkup_index Number of files to write
|
||||||
|
* \param append Overwrite or append to log file
|
||||||
|
* \param mode Permissions to set on log file
|
||||||
|
* \param pattern Formating pattern for log messages
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void logger_add_rollingfile_appender(logger_ptr logger, std::string filename,
|
||||||
|
size_t filesize, int bkup_index, bool append,
|
||||||
|
mode_t mode,std::string pattern);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* Add rolling file appender to a given logger
|
||||||
|
*
|
||||||
|
* \return vector of string names of loggers
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* HAVE_LOG4CPP */
|
||||||
|
|
||||||
|
// If Logger disable do nothing
|
||||||
|
#else /* ENABLE_GR_LOG */
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
typedef void* logger_ptr;
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#define GR_LOG_DECLARE_LOGPTR(logger)
|
||||||
|
#define GR_LOG_ASSIGN_LOGPTR(logger,name)
|
||||||
|
#define GR_CONFIG_LOGGER(config)
|
||||||
|
#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
|
||||||
|
#define GR_LOG_GETLOGGER(logger, name)
|
||||||
|
#define GR_SET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_SET_LEVEL(logger, level)
|
||||||
|
#define GR_GET_LEVEL(name, level)
|
||||||
|
#define GR_LOG_GET_LEVEL(logger, level)
|
||||||
|
#define GR_ADD_APPENDER(name,appender)
|
||||||
|
#define GR_LOG_ADD_APPENDER(logger,appender)
|
||||||
|
#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
|
||||||
|
#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
|
||||||
|
#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
|
||||||
|
#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
|
||||||
|
#define GR_GET_LOGGER_NAMES(names)
|
||||||
|
#define GR_RESET_CONFIGURATION()
|
||||||
|
#define GR_DEBUG(name, msg)
|
||||||
|
#define GR_INFO(name, msg)
|
||||||
|
#define GR_NOTICE(name, msg)
|
||||||
|
#define GR_WARN(name, msg)
|
||||||
|
#define GR_ERROR(name, msg)
|
||||||
|
#define GR_ALERT(name, msg)
|
||||||
|
#define GR_CRIT(name, msg)
|
||||||
|
#define GR_FATAL(name, msg)
|
||||||
|
#define GR_EMERG(name, msg)
|
||||||
|
#define GR_ERRORIF(name, cond, msg)
|
||||||
|
#define GR_ASSERT(name, cond, msg)
|
||||||
|
#define GR_LOG_DEBUG(logger, msg)
|
||||||
|
#define GR_LOG_INFO(logger, msg)
|
||||||
|
#define GR_LOG_NOTICE(logger, msg)
|
||||||
|
#define GR_LOG_WARN(logger, msg)
|
||||||
|
#define GR_LOG_ERROR(logger, msg)
|
||||||
|
#define GR_LOG_ALERT(logger, msg)
|
||||||
|
#define GR_LOG_CRIT(logger, msg)
|
||||||
|
#define GR_LOG_FATAL(logger, msg)
|
||||||
|
#define GR_LOG_EMERG(logger, msg)
|
||||||
|
#define GR_LOG_ERRORIF(logger, cond, msg)
|
||||||
|
#define GR_LOG_ASSERT(logger, cond, msg)
|
||||||
|
|
||||||
|
#endif /* ENABLE_GR_LOG */
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
// Even if logger is disabled we'll need for methods below to exist in python.
|
||||||
|
// The macros these call will be disabled if ENABLE_GR_LOG is undefined
|
||||||
|
|
||||||
|
/********************* Start Classes and Methods for Python ******************/
|
||||||
|
/*!
|
||||||
|
* \brief Logger class for referencing loggers in python. Not
|
||||||
|
* needed in C++ (use macros) Wraps and manipulates loggers for
|
||||||
|
* python as python has no macros
|
||||||
|
* \ingroup logging
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class logger
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*! \brief logger pointer to logger associated wiith this wrapper class */
|
||||||
|
logger_ptr d_logger;
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief contructor Provide name of logger to associate with this class
|
||||||
|
* \param logger_name Name of logger associated with class
|
||||||
|
*/
|
||||||
|
logger(std::string logger_name) {
|
||||||
|
GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief Destructor */
|
||||||
|
~logger(){;}
|
||||||
|
|
||||||
|
// Wrappers for logging macros
|
||||||
|
/*! \brief inline function, wrapper to set the logger level */
|
||||||
|
void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper to get the logger level */
|
||||||
|
void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */
|
||||||
|
void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */
|
||||||
|
void info(std::string msg){GR_LOG_INFO(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for NOTICE message */
|
||||||
|
void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */
|
||||||
|
void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */
|
||||||
|
void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for NOTICE message */
|
||||||
|
void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for ALERT message */
|
||||||
|
void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for FATAL message */
|
||||||
|
void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for EMERG message */
|
||||||
|
void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
|
||||||
|
void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
|
||||||
|
void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add appender to logger by
|
||||||
|
name (define appender in conf file) */
|
||||||
|
void add_appender(std::string appender) {
|
||||||
|
GR_LOG_ADD_APPENDER(d_logger, appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add console appender to logger */
|
||||||
|
void add_console_appender(std::string target,std::string pattern) {
|
||||||
|
GR_LOG_ADD_CONSOLE_APPENDER(d_logger, target, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add file appender to logger */
|
||||||
|
void add_file_appender(std::string filename, bool append, std::string pattern) {
|
||||||
|
GR_LOG_ADD_FILE_APPENDER(d_logger, filename, append, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief inline function, Method to add rolling file appender to logger */
|
||||||
|
void add_rollingfile_appender(std::string filename, size_t filesize,
|
||||||
|
int bkup_index, bool append, mode_t mode,
|
||||||
|
std::string pattern) {
|
||||||
|
GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize,
|
||||||
|
bkup_index,append,mode,pattern);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
/**************** Start Configuration Class and Methods for Python ************/
|
||||||
|
/*!
|
||||||
|
* \brief Function to call configuration macro from python.
|
||||||
|
* Note: Configuration is only updated if filename or watch_period has changed.
|
||||||
|
* \param config_filename Name of configuration file
|
||||||
|
* \param watch_period Seconds to wait between checking for changes in conf file.
|
||||||
|
* Watch_period defaults to 0 in which case the file is not watched for changes
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void gr_logger_config(const std::string config_filename,
|
||||||
|
unsigned int watch_period = 0);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to return logger names to python
|
||||||
|
* \return Vector of name strings
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to reset logger configuration from python
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void gr_logger_reset_config(void);
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_LOGGER_H */
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2003,2005,2008,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mathematical odds and ends.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GR_MATH_H_
|
||||||
|
#define _GR_MATH_H_
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_power_of_2(long x)
|
||||||
|
{
|
||||||
|
return x != 0 && (x & (x-1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Fast arc tangent using table lookup and linear interpolation
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* \param y component of input vector
|
||||||
|
* \param x component of input vector
|
||||||
|
* \returns float angle angle of vector (x, y) in radians
|
||||||
|
*
|
||||||
|
* This function calculates the angle of the vector (x,y) based on a
|
||||||
|
* table lookup and linear interpolation. The table uses a 256 point
|
||||||
|
* table covering -45 to +45 degrees and uses symetry to determine
|
||||||
|
* the final angle value in the range of -180 to 180 degrees. Note
|
||||||
|
* that this function uses the small angle approximation for values
|
||||||
|
* close to zero. This routine calculates the arc tangent with an
|
||||||
|
* average error of +/- 0.045 degrees.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API float fast_atan2f(float y, float x);
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
fast_atan2f(gr_complex z)
|
||||||
|
{
|
||||||
|
return fast_atan2f(z.imag(), z.real());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This bounds x by +/- clip without a branch */
|
||||||
|
static inline float
|
||||||
|
branchless_clip(float x, float clip)
|
||||||
|
{
|
||||||
|
float x1 = fabsf(x+clip);
|
||||||
|
float x2 = fabsf(x-clip);
|
||||||
|
x1 -= x2;
|
||||||
|
return 0.5*x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
clip(float x, float clip)
|
||||||
|
{
|
||||||
|
float y = x;
|
||||||
|
if(x > clip)
|
||||||
|
y = clip;
|
||||||
|
else if(x < -clip)
|
||||||
|
y = -clip;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slicer Functions
|
||||||
|
static inline unsigned int
|
||||||
|
binary_slicer(float x)
|
||||||
|
{
|
||||||
|
if(x >= 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
quad_45deg_slicer(float r, float i)
|
||||||
|
{
|
||||||
|
unsigned int ret = 0;
|
||||||
|
if((r >= 0) && (i >= 0))
|
||||||
|
ret = 0;
|
||||||
|
else if((r < 0) && (i >= 0))
|
||||||
|
ret = 1;
|
||||||
|
else if((r < 0) && (i < 0))
|
||||||
|
ret = 2;
|
||||||
|
else
|
||||||
|
ret = 3;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
quad_0deg_slicer(float r, float i)
|
||||||
|
{
|
||||||
|
unsigned int ret = 0;
|
||||||
|
if(fabsf(r) > fabsf(i)) {
|
||||||
|
if(r > 0)
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
|
ret = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(i > 0)
|
||||||
|
ret = 1;
|
||||||
|
else
|
||||||
|
ret = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
quad_45deg_slicer(gr_complex x)
|
||||||
|
{
|
||||||
|
return quad_45deg_slicer(x.real(), x.imag());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
quad_0deg_slicer(gr_complex x)
|
||||||
|
{
|
||||||
|
return quad_0deg_slicer(x.real(), x.imag());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branchless Slicer Functions
|
||||||
|
static inline unsigned int
|
||||||
|
branchless_binary_slicer(float x)
|
||||||
|
{
|
||||||
|
return (x >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
branchless_quad_0deg_slicer(float r, float i)
|
||||||
|
{
|
||||||
|
unsigned int ret = 0;
|
||||||
|
ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10)
|
||||||
|
ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
branchless_quad_0deg_slicer(gr_complex x)
|
||||||
|
{
|
||||||
|
return branchless_quad_0deg_slicer(x.real(), x.imag());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
branchless_quad_45deg_slicer(float r, float i)
|
||||||
|
{
|
||||||
|
char ret = (r <= 0);
|
||||||
|
ret |= ((i <= 0) << 1);
|
||||||
|
return (ret ^ ((ret & 0x2) >> 0x1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
branchless_quad_45deg_slicer(gr_complex x)
|
||||||
|
{
|
||||||
|
return branchless_quad_45deg_slicer(x.real(), x.imag());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \param x any value
|
||||||
|
* \param pow2 must be a power of 2
|
||||||
|
* \returns \p x rounded down to a multiple of \p pow2.
|
||||||
|
*/
|
||||||
|
static inline size_t
|
||||||
|
p2_round_down(size_t x, size_t pow2)
|
||||||
|
{
|
||||||
|
return x & -pow2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \param x any value
|
||||||
|
* \param pow2 must be a power of 2
|
||||||
|
* \returns \p x rounded up to a multiple of \p pow2.
|
||||||
|
*/
|
||||||
|
static inline size_t
|
||||||
|
p2_round_up(size_t x, size_t pow2)
|
||||||
|
{
|
||||||
|
return p2_round_down(x + pow2 - 1, pow2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \param x any value
|
||||||
|
* \param pow2 must be a power of 2
|
||||||
|
* \returns \p x modulo \p pow2.
|
||||||
|
*/
|
||||||
|
static inline size_t
|
||||||
|
p2_modulo(size_t x, size_t pow2)
|
||||||
|
{
|
||||||
|
return x & (pow2 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \param x any value
|
||||||
|
* \param pow2 must be a power of 2
|
||||||
|
* \returns \p pow2 - (\p x modulo \p pow2).
|
||||||
|
*/
|
||||||
|
static inline size_t
|
||||||
|
p2_modulo_neg(size_t x, size_t pow2)
|
||||||
|
{
|
||||||
|
return pow2 - p2_modulo(x, pow2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* _GR_MATH_H_ */
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_MISC_H
|
||||||
|
#define INCLUDED_GR_MISC_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/types.h>
|
||||||
|
|
||||||
|
GR_RUNTIME_API unsigned int
|
||||||
|
gr_rounduppow2(unsigned int n);
|
||||||
|
|
||||||
|
// FIXME should be template
|
||||||
|
GR_RUNTIME_API void gr_zero_vector(std::vector<float> &v);
|
||||||
|
GR_RUNTIME_API void gr_zero_vector(std::vector<double> &v);
|
||||||
|
GR_RUNTIME_API void gr_zero_vector(std::vector<int> &v);
|
||||||
|
GR_RUNTIME_API void gr_zero_vector(std::vector<gr_complex> &v);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_MISC_H */
|
|
@ -0,0 +1,152 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_PREFS_H
|
||||||
|
#define INCLUDED_GR_PREFS_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
typedef std::map< std::string, std::map<std::string, std::string> > config_map_t;
|
||||||
|
typedef std::map< std::string, std::map<std::string, std::string> >::iterator config_map_itr;
|
||||||
|
typedef std::map<std::string, std::string> config_map_elem_t;
|
||||||
|
typedef std::map<std::string, std::string>::iterator config_map_elem_itr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Base class for representing user preferences a la windows INI files.
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* The real implementation is in Python, and is accessable from C++
|
||||||
|
* via the magic of SWIG directors.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API prefs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static prefs *singleton();
|
||||||
|
static void set_singleton(prefs *p);
|
||||||
|
|
||||||
|
prefs();
|
||||||
|
virtual ~prefs();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the configuration options as a string.
|
||||||
|
*/
|
||||||
|
std::string to_string();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Saves the configuration settings to
|
||||||
|
* ${HOME}/.gnuradio/config.conf.
|
||||||
|
*
|
||||||
|
* WARNING: this will overwrite your current config.conf file.
|
||||||
|
*/
|
||||||
|
void save();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Does \p section exist?
|
||||||
|
*/
|
||||||
|
virtual bool has_section(const std::string §ion);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Does \p option exist?
|
||||||
|
*/
|
||||||
|
virtual bool has_option(const std::string §ion,
|
||||||
|
const std::string &option);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If option exists return associated value; else
|
||||||
|
* default_val.
|
||||||
|
*/
|
||||||
|
virtual const std::string get_string(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
const std::string &default_val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set or add a string \p option to \p section with value
|
||||||
|
* \p val.
|
||||||
|
*/
|
||||||
|
virtual void set_string(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
const std::string &val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If option exists and value can be converted to bool,
|
||||||
|
* return it; else default_val.
|
||||||
|
*/
|
||||||
|
virtual bool get_bool(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
bool default_val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set or add a bool \p option to \p section with value \p val.
|
||||||
|
*/
|
||||||
|
virtual void set_bool(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
bool val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If option exists and value can be converted to long,
|
||||||
|
* return it; else default_val.
|
||||||
|
*/
|
||||||
|
virtual long get_long(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
long default_val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set or add a long \p option to \p section with value \p val.
|
||||||
|
*/
|
||||||
|
virtual void set_long(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
long val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If option exists and value can be converted to double,
|
||||||
|
* return it; else default_val.
|
||||||
|
*/
|
||||||
|
virtual double get_double(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
double default_val);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set or add a double \p option to \p section with value \p val.
|
||||||
|
*/
|
||||||
|
virtual void set_double(const std::string §ion,
|
||||||
|
const std::string &option,
|
||||||
|
double val);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual std::vector<std::string> _sys_prefs_filenames();
|
||||||
|
virtual void _read_files();
|
||||||
|
virtual void _convert_to_map(const std::string &conf);
|
||||||
|
virtual char * option_to_env(std::string section, std::string option);
|
||||||
|
|
||||||
|
private:
|
||||||
|
gr::thread::mutex d_mutex;
|
||||||
|
config_map_t d_config_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_PREFS_H */
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2002 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RANDOM_H
|
||||||
|
#define INCLUDED_GR_RANDOM_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
|
// While rand(3) specifies RAND_MAX, random(3) says that the output
|
||||||
|
// ranges from 0 to 2^31-1 but does not specify a macro to denote
|
||||||
|
// this. We define RANDOM_MAX for cleanliness. We must omit the
|
||||||
|
// definition for systems that have made the same choice. (Note that
|
||||||
|
// random(3) is from 4.2BSD, and not specified by POSIX.)
|
||||||
|
|
||||||
|
#ifndef RANDOM_MAX
|
||||||
|
static const int RANDOM_MAX = 2147483647; // 2^31-1
|
||||||
|
#endif /* RANDOM_MAX */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief pseudo random number generator
|
||||||
|
* \ingroup math_blk
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API random
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static const int NTAB = 32;
|
||||||
|
long d_seed;
|
||||||
|
long d_iy;
|
||||||
|
long d_iv[NTAB];
|
||||||
|
int d_iset;
|
||||||
|
float d_gset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
random(long seed=3021);
|
||||||
|
|
||||||
|
void reseed(long seed);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief uniform random deviate in the range [0.0, 1.0)
|
||||||
|
*/
|
||||||
|
float ran1();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief normally distributed deviate with zero mean and variance 1
|
||||||
|
*/
|
||||||
|
float gasdev();
|
||||||
|
|
||||||
|
float laplacian();
|
||||||
|
float impulse(float factor);
|
||||||
|
float rayleigh();
|
||||||
|
gr_complex rayleigh_complex();
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RANDOM_H */
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_REALTIME_H
|
||||||
|
#define INCLUDED_GR_REALTIME_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/realtime_impl.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If possible, enable high-priority "real time" scheduling.
|
||||||
|
* \ingroup misc
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API rt_status_t enable_realtime_scheduling();
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_REALTIME_H */
|
|
@ -0,0 +1,96 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2006,2008,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GNURADIO_REALTIME_H
|
||||||
|
#define INCLUDED_GNURADIO_REALTIME_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief System independent way to ask for realtime scheduling
|
||||||
|
*
|
||||||
|
* \sa sys_pri.h
|
||||||
|
*/
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RT_OK = 0,
|
||||||
|
RT_NOT_IMPLEMENTED,
|
||||||
|
RT_NO_PRIVS,
|
||||||
|
RT_OTHER_ERROR
|
||||||
|
} rt_status_t;
|
||||||
|
|
||||||
|
enum rt_sched_policy {
|
||||||
|
RT_SCHED_RR = 0, // round robin
|
||||||
|
RT_SCHED_FIFO = 1, // first in first out
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
/*
|
||||||
|
* Define the range for our virtual priorities (don't change
|
||||||
|
* these)
|
||||||
|
*
|
||||||
|
* Processes (or threads) with numerically higher priority values
|
||||||
|
* are scheduled before processes with numerically lower priority
|
||||||
|
* values. Thus, the value returned by rt_priority_max() will be
|
||||||
|
* greater than the value returned by rt_priority_min().
|
||||||
|
*/
|
||||||
|
static inline int rt_priority_min() { return 0; }
|
||||||
|
static inline int rt_priority_max() { return 15; }
|
||||||
|
static inline int rt_priority_default() { return 1; }
|
||||||
|
|
||||||
|
struct GR_RUNTIME_API rt_sched_param {
|
||||||
|
int priority;
|
||||||
|
rt_sched_policy policy;
|
||||||
|
|
||||||
|
rt_sched_param()
|
||||||
|
: priority(rt_priority_default()), policy(RT_SCHED_RR){}
|
||||||
|
|
||||||
|
rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR)
|
||||||
|
{
|
||||||
|
if(priority_ < rt_priority_min() || priority_ > rt_priority_max())
|
||||||
|
throw std::invalid_argument("rt_sched_param: priority out of range");
|
||||||
|
|
||||||
|
priority = priority_;
|
||||||
|
policy = policy_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief If possible, enable "realtime" scheduling.
|
||||||
|
* \ingroup misc
|
||||||
|
*
|
||||||
|
* In general, this means that the code will be scheduled before
|
||||||
|
* any non-realtime (normal) processes. Note that if your code
|
||||||
|
* contains an non-blocking infinite loop and you enable realtime
|
||||||
|
* scheduling, it's possible to hang the system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: If you change this, you need to change the code in
|
||||||
|
// gnuradio-runtime/swig/realtime.i, see note there.
|
||||||
|
GR_RUNTIME_API rt_status_t enable_realtime_scheduling(rt_sched_param = rt_sched_param());
|
||||||
|
|
||||||
|
} /* namespace impl */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GNURADIO_REALTIME_H */
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_TYPES_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_TYPES_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/types.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs for smart pointers we use throughout the runtime system
|
||||||
|
*/
|
||||||
|
class basic_block;
|
||||||
|
class block;
|
||||||
|
class block_detail;
|
||||||
|
class buffer;
|
||||||
|
class buffer_reader;
|
||||||
|
class hier_block2;
|
||||||
|
class flat_flowgraph;
|
||||||
|
class flowgraph;
|
||||||
|
class top_block;
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<basic_block> basic_block_sptr;
|
||||||
|
typedef boost::shared_ptr<block> block_sptr;
|
||||||
|
typedef boost::shared_ptr<block_detail> block_detail_sptr;
|
||||||
|
typedef boost::shared_ptr<buffer> buffer_sptr;
|
||||||
|
typedef boost::shared_ptr<buffer_reader> buffer_reader_sptr;
|
||||||
|
typedef boost::shared_ptr<hier_block2> hier_block2_sptr;
|
||||||
|
typedef boost::shared_ptr<flat_flowgraph> flat_flowgraph_sptr;
|
||||||
|
typedef boost::shared_ptr<flowgraph> flowgraph_sptr;
|
||||||
|
typedef boost::shared_ptr<top_block> top_block_sptr;
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_TYPES_H */
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2002,2004 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_SINCOS_H
|
||||||
|
#define INCLUDED_GR_SINCOS_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
// compute sine and cosine at the same time
|
||||||
|
GR_RUNTIME_API void sincos (double x, double *sin, double *cos);
|
||||||
|
GR_RUNTIME_API void sincosf (float x, float *sin, float *cos);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_SINCOS_H */
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2008,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_SPTR_MAGIC_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_SPTR_MAGIC_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
class basic_block;
|
||||||
|
class hier_block2;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace gnuradio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class GR_RUNTIME_API sptr_magic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static boost::shared_ptr<gr::basic_block> fetch_initial_sptr(gr::basic_block *p);
|
||||||
|
static void create_and_stash_initial_sptr(gr::hier_block2 *p);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief New! Improved! Standard method to get/create the
|
||||||
|
* boost::shared_ptr for a block.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
boost::shared_ptr<T>
|
||||||
|
get_initial_sptr(T *p)
|
||||||
|
{
|
||||||
|
return boost::dynamic_pointer_cast<T, gr::basic_block>
|
||||||
|
(detail::sptr_magic::fetch_initial_sptr(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_SPTR_MAGIC_H */
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_SYNC_BLOCK_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_SYNC_BLOCK_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief synchronous 1:1 input to output with history
|
||||||
|
* \ingroup base_blk
|
||||||
|
*
|
||||||
|
* Override work to provide the signal processing implementation.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API sync_block : public block
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
sync_block(void) {} // allows pure virtual interface sub-classes
|
||||||
|
sync_block(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief just like gr::block::general_work, only this arranges to
|
||||||
|
* call consume_each for you
|
||||||
|
*
|
||||||
|
* The user must override work to define the signal processing code
|
||||||
|
*/
|
||||||
|
virtual int work(int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items) = 0;
|
||||||
|
|
||||||
|
// gr::sync_block overrides these to assist work
|
||||||
|
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
|
||||||
|
int general_work(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
|
int fixed_rate_ninput_to_noutput(int ninput);
|
||||||
|
int fixed_rate_noutput_to_ninput(int noutput);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_SYNC_BLOCK_H */
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004, 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief synchronous N:1 input to output with history
|
||||||
|
* \ingroup base_blk
|
||||||
|
*
|
||||||
|
* Override work to provide the signal processing implementation.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API sync_decimator : public sync_block
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned d_decimation;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sync_decimator(void) {} // allows pure virtual interface sub-classes
|
||||||
|
sync_decimator(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature,
|
||||||
|
unsigned decimation);
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned decimation() const { return d_decimation; }
|
||||||
|
void set_decimation(unsigned decimation)
|
||||||
|
{
|
||||||
|
d_decimation = decimation;
|
||||||
|
set_relative_rate(1.0 / decimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gr::sync_decimator overrides these to assist work
|
||||||
|
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
|
||||||
|
int general_work(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
|
// derived classes should override work
|
||||||
|
|
||||||
|
int fixed_rate_ninput_to_noutput(int ninput);
|
||||||
|
int fixed_rate_noutput_to_ninput(int noutput);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H */
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2008,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H
|
||||||
|
#define INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief synchronous 1:N input to output with history
|
||||||
|
* \ingroup base_blk
|
||||||
|
*
|
||||||
|
* Override work to provide the signal processing implementation.
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API sync_interpolator : public sync_block
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned d_interpolation;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sync_interpolator(void) {} // allows pure virtual interface sub-classes
|
||||||
|
sync_interpolator(const std::string &name,
|
||||||
|
gr::io_signature::sptr input_signature,
|
||||||
|
gr::io_signature::sptr output_signature,
|
||||||
|
unsigned interpolation);
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned interpolation() const { return d_interpolation; }
|
||||||
|
void set_interpolation(unsigned interpolation)
|
||||||
|
{
|
||||||
|
d_interpolation = interpolation;
|
||||||
|
set_relative_rate(1.0 * interpolation);
|
||||||
|
set_output_multiple(interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gr::sync_interpolator overrides these to assist work
|
||||||
|
void forecast(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items_required);
|
||||||
|
int general_work(int noutput_items,
|
||||||
|
gr_vector_int &ninput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
|
// derived classes should override work
|
||||||
|
|
||||||
|
int fixed_rate_ninput_to_noutput(int ninput);
|
||||||
|
int fixed_rate_noutput_to_ninput(int noutput);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H */
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GR_SYS_PATHS_H
|
||||||
|
#define GR_SYS_PATHS_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
//! directory to create temporary files
|
||||||
|
GR_RUNTIME_API const char *tmp_path();
|
||||||
|
|
||||||
|
//! directory to store application data
|
||||||
|
GR_RUNTIME_API const char *appdata_path();
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* GR_SYS_PATHS_H */
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2009-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_THREAD_H
|
||||||
|
#define INCLUDED_THREAD_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <boost/thread/thread.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/thread/locks.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace thread {
|
||||||
|
|
||||||
|
typedef boost::thread thread;
|
||||||
|
typedef boost::mutex mutex;
|
||||||
|
typedef boost::unique_lock<boost::mutex> scoped_lock;
|
||||||
|
typedef boost::condition_variable condition_variable;
|
||||||
|
|
||||||
|
/*! \brief a system-dependent typedef for the underlying thread type.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
typedef HANDLE gr_thread_t;
|
||||||
|
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||||
|
typedef pthread_t gr_thread_t;
|
||||||
|
#else
|
||||||
|
typedef pthread_t gr_thread_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \brief Get the current thread's ID as a gr_thread_t
|
||||||
|
*
|
||||||
|
* We use this when setting the thread affinity or any other
|
||||||
|
* low-level thread settings. Can be called withing a GNU Radio
|
||||||
|
* block to get a reference to its current thread ID.
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API gr_thread_t get_current_thread_id();
|
||||||
|
|
||||||
|
/*! \brief Bind the current thread to a set of cores.
|
||||||
|
*
|
||||||
|
* Wrapper for system-dependent calls to set the affinity of the
|
||||||
|
* current thread to the processor mask. The mask is simply a
|
||||||
|
* 1-demensional vector containing the processor or core number
|
||||||
|
* from 0 to N-1 for N cores.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_bind_to_processor(const std::vector<int> &mask);
|
||||||
|
|
||||||
|
/*! \brief Convineince function to bind the current thread to a single core.
|
||||||
|
*
|
||||||
|
* Wrapper for system-dependent calls to set the affinity of the
|
||||||
|
* current thread to a given core from 0 to N-1 for N cores.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_bind_to_processor(int n);
|
||||||
|
|
||||||
|
/*! \brief Bind a thread to a set of cores.
|
||||||
|
*
|
||||||
|
* Wrapper for system-dependent calls to set the affinity of the
|
||||||
|
* given thread ID to the processor mask. The mask is simply a
|
||||||
|
* 1-demensional vector containing the processor or core number
|
||||||
|
* from 0 to N-1 for N cores.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_bind_to_processor(gr_thread_t thread,
|
||||||
|
const std::vector<int> &mask);
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Convineince function to bind the a thread to a single core.
|
||||||
|
*
|
||||||
|
* Wrapper for system-dependent calls to set the affinity of the
|
||||||
|
* given thread ID to a given core from 0 to N-1 for N cores.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_bind_to_processor(gr_thread_t thread,
|
||||||
|
unsigned int n);
|
||||||
|
|
||||||
|
/*! \brief Remove any thread-processor affinity for the current thread.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_unbind();
|
||||||
|
|
||||||
|
/*! \brief Remove any thread-processor affinity for a given thread ID.
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX; it is a nop call since OSX
|
||||||
|
* does not support the concept of thread affinity (and what they
|
||||||
|
* do support in this way since 10.5 is not what we want or can
|
||||||
|
* use in this fashion).
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API void thread_unbind(gr_thread_t thread);
|
||||||
|
|
||||||
|
/*! \brief get current thread priority for a given thread ID
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API int thread_priority(gr_thread_t thread);
|
||||||
|
|
||||||
|
/*! \brief get current thread priority for a given thread ID
|
||||||
|
*
|
||||||
|
* Note: this does not work on OSX
|
||||||
|
*/
|
||||||
|
GR_RUNTIME_API int set_thread_priority(gr_thread_t thread, int priority);
|
||||||
|
|
||||||
|
} /* namespace thread */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_THREAD_H */
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2008,2009,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_THREAD_BODY_WRAPPER_H
|
||||||
|
#define INCLUDED_THREAD_BODY_WRAPPER_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace thread {
|
||||||
|
|
||||||
|
GR_RUNTIME_API void mask_signals();
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
class thread_body_wrapper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
F d_f;
|
||||||
|
std::string d_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit thread_body_wrapper(F f, const std::string &name="")
|
||||||
|
: d_f(f), d_name(name) {}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
mask_signals();
|
||||||
|
|
||||||
|
try {
|
||||||
|
d_f();
|
||||||
|
}
|
||||||
|
catch(boost::thread_interrupted const &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch(std::exception const &e)
|
||||||
|
{
|
||||||
|
std::cerr << "thread[" << d_name << "]: "
|
||||||
|
<< e.what() << std::endl;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
std::cerr << "thread[" << d_name << "]: "
|
||||||
|
<< "caught unrecognized exception\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace thread */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_THREAD_BODY_WRAPPER_H */
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2003 William E. Kempf
|
||||||
|
* Copyright (C) 2007 Anthony Williams
|
||||||
|
* Copyright 2008,2009 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This was extracted from Boost 1.35.0 and fixed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_THREAD_GROUP_H
|
||||||
|
#define INCLUDED_THREAD_GROUP_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/thread/shared_mutex.hpp>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace thread {
|
||||||
|
|
||||||
|
class GR_RUNTIME_API thread_group : public boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
thread_group();
|
||||||
|
~thread_group();
|
||||||
|
|
||||||
|
boost::thread* create_thread(const boost::function0<void>& threadfunc);
|
||||||
|
void add_thread(boost::thread* thrd);
|
||||||
|
void remove_thread(boost::thread* thrd);
|
||||||
|
void join_all();
|
||||||
|
void interrupt_all();
|
||||||
|
size_t size() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<boost::thread*> m_threads;
|
||||||
|
mutable boost::shared_mutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace thread */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_THREAD_GROUP_H */
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2009,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_TOP_BLOCK_H
|
||||||
|
#define INCLUDED_GR_TOP_BLOCK_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/hier_block2.h>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
class top_block_impl;
|
||||||
|
|
||||||
|
GR_RUNTIME_API top_block_sptr make_top_block(const std::string &name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*\brief Top-level hierarchical block representing a flowgraph
|
||||||
|
* \ingroup container_blk
|
||||||
|
*/
|
||||||
|
class GR_RUNTIME_API top_block : public hier_block2
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend GR_RUNTIME_API top_block_sptr
|
||||||
|
make_top_block(const std::string &name);
|
||||||
|
|
||||||
|
top_block_impl *d_impl;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
top_block(const std::string &name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~top_block();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The simple interface to running a flowgraph.
|
||||||
|
*
|
||||||
|
* Calls start() then wait(). Used to run a flowgraph that will
|
||||||
|
* stop on its own, or when another thread will call stop().
|
||||||
|
*
|
||||||
|
* \param max_noutput_items the maximum number of output items
|
||||||
|
* allowed for any block in the flowgraph. This passes through to
|
||||||
|
* the start function; see that function for more details.
|
||||||
|
*/
|
||||||
|
void run(int max_noutput_items=100000000);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Start the contained flowgraph. Creates one or more threads to
|
||||||
|
* execute the flow graph. Returns to the caller once the threads
|
||||||
|
* are created. Calling start() on a top_block that is already
|
||||||
|
* started IS an error.
|
||||||
|
*
|
||||||
|
* \param max_noutput_items the maximum number of output items
|
||||||
|
* allowed for any block in the flowgraph; the noutput_items can
|
||||||
|
* always be less than this, but this will cap it as a
|
||||||
|
* maximum. Use this to adjust the maximum latency a flowgraph can
|
||||||
|
* exhibit.
|
||||||
|
*/
|
||||||
|
void start(int max_noutput_items=100000000);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Stop the running flowgraph. Notifies each thread created by the
|
||||||
|
* scheduler to shutdown, then returns to caller. Calling stop()
|
||||||
|
* on a top_block that is already stopped IS NOT an error.
|
||||||
|
*/
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Wait for a flowgraph to complete. Flowgraphs complete when
|
||||||
|
* either (1) all blocks indicate that they are done (typically
|
||||||
|
* only when using blocks.file_source, or blocks.head, or (2)
|
||||||
|
* after stop() has been called to request shutdown. Calling wait
|
||||||
|
* on a top_block that is not running IS NOT an error (wait
|
||||||
|
* returns w/o blocking).
|
||||||
|
*/
|
||||||
|
void wait();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Lock a flowgraph in preparation for reconfiguration. When an
|
||||||
|
* equal number of calls to lock() and unlock() have occurred, the
|
||||||
|
* flowgraph will be reconfigured.
|
||||||
|
*
|
||||||
|
* N.B. lock() and unlock() may not be called from a flowgraph
|
||||||
|
* thread (E.g., block::work method) or deadlock will occur
|
||||||
|
* when reconfiguration happens.
|
||||||
|
*/
|
||||||
|
virtual void lock();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Unlock a flowgraph in preparation for reconfiguration. When an
|
||||||
|
* equal number of calls to lock() and unlock() have occurred, the
|
||||||
|
* flowgraph will be reconfigured.
|
||||||
|
*
|
||||||
|
* N.B. lock() and unlock() may not be called from a flowgraph thread
|
||||||
|
* (E.g., block::work method) or deadlock will occur when
|
||||||
|
* reconfiguration happens.
|
||||||
|
*/
|
||||||
|
virtual void unlock();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns a string that lists the edge connections in the
|
||||||
|
* flattened flowgraph.
|
||||||
|
*/
|
||||||
|
std::string edge_list();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Displays flattened flowgraph edges and block connectivity
|
||||||
|
*/
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
//! Get the number of max noutput_items in the flowgraph
|
||||||
|
int max_noutput_items();
|
||||||
|
|
||||||
|
//! Set the maximum number of noutput_items in the flowgraph
|
||||||
|
void set_max_noutput_items(int nmax);
|
||||||
|
|
||||||
|
top_block_sptr to_top_block(); // Needed for Python type coercion
|
||||||
|
|
||||||
|
void setup_rpc();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline top_block_sptr cast_to_top_block_sptr(basic_block_sptr block) {
|
||||||
|
return boost::dynamic_pointer_cast<top_block, basic_block>(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespce gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_TOP_BLOCK_H */
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2008,2009,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_TPB_DETAIL_H
|
||||||
|
#define INCLUDED_GR_TPB_DETAIL_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
|
||||||
|
class block_detail;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief used by thread-per-block scheduler
|
||||||
|
*/
|
||||||
|
struct GR_RUNTIME_API tpb_detail {
|
||||||
|
gr::thread::mutex mutex; //< protects all vars
|
||||||
|
bool input_changed;
|
||||||
|
gr::thread::condition_variable input_cond;
|
||||||
|
bool output_changed;
|
||||||
|
gr::thread::condition_variable output_cond;
|
||||||
|
|
||||||
|
public:
|
||||||
|
tpb_detail()
|
||||||
|
: input_changed(false), output_changed(false) { }
|
||||||
|
|
||||||
|
//! Called by us to tell all our upstream blocks that their output
|
||||||
|
//! may have changed.
|
||||||
|
void notify_upstream(block_detail *d);
|
||||||
|
|
||||||
|
//! Called by us to tell all our downstream blocks that their
|
||||||
|
//! input may have changed.
|
||||||
|
void notify_downstream(block_detail *d);
|
||||||
|
|
||||||
|
//! Called by us to notify both upstream and downstream
|
||||||
|
void notify_neighbors(block_detail *d);
|
||||||
|
|
||||||
|
//! Called by pmt msg posters
|
||||||
|
void notify_msg() {
|
||||||
|
input_cond.notify_one();
|
||||||
|
output_cond.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Called by us
|
||||||
|
void clear_changed()
|
||||||
|
{
|
||||||
|
gr::thread::scoped_lock guard(mutex);
|
||||||
|
input_changed = false;
|
||||||
|
output_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Used by notify_downstream
|
||||||
|
void set_input_changed()
|
||||||
|
{
|
||||||
|
gr::thread::scoped_lock guard(mutex);
|
||||||
|
input_changed = true;
|
||||||
|
input_cond.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Used by notify_upstream
|
||||||
|
void set_output_changed()
|
||||||
|
{
|
||||||
|
gr::thread::scoped_lock guard(mutex);
|
||||||
|
output_changed = true;
|
||||||
|
output_cond.notify_one();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_TPB_DETAIL_H */
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2004,2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_TYPES_H
|
||||||
|
#define INCLUDED_GR_TYPES_H
|
||||||
|
|
||||||
|
#include <gnuradio/api.h>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
|
||||||
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
|
typedef std::vector<int> gr_vector_int;
|
||||||
|
typedef std::vector<unsigned int> gr_vector_uint;
|
||||||
|
typedef std::vector<float> gr_vector_float;
|
||||||
|
typedef std::vector<double> gr_vector_double;
|
||||||
|
typedef std::vector<void *> gr_vector_void_star;
|
||||||
|
typedef std::vector<const void *> gr_vector_const_void_star;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #include <config.h> must be placed beforehand
|
||||||
|
* in the source file including gnuradio/types.h for
|
||||||
|
* the following to work correctly
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int16_t gr_int16;
|
||||||
|
typedef int32_t gr_int32;
|
||||||
|
typedef int64_t gr_int64;
|
||||||
|
typedef uint16_t gr_uint16;
|
||||||
|
typedef uint32_t gr_uint32;
|
||||||
|
typedef uint64_t gr_uint64;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Note: these defaults may be wrong on 64-bit systems
|
||||||
|
*/
|
||||||
|
typedef short gr_int16;
|
||||||
|
typedef int gr_int32;
|
||||||
|
typedef long long gr_int64;
|
||||||
|
typedef unsigned short gr_uint16;
|
||||||
|
typedef unsigned int gr_uint32;
|
||||||
|
typedef unsigned long long gr_uint64;
|
||||||
|
#endif /* HAVE_STDINT_H */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_TYPES_H */
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_UHD_API_H
|
||||||
|
#define INCLUDED_GR_UHD_API_H
|
||||||
|
|
||||||
|
#include <uhd/config.hpp>
|
||||||
|
|
||||||
|
#ifdef gnuradio_uhd_EXPORTS
|
||||||
|
# define GR_UHD_API UHD_EXPORT
|
||||||
|
#else
|
||||||
|
# define GR_UHD_API UHD_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_UHD_API_H */
|
|
@ -0,0 +1,530 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_UHD_USRP_SINK_H
|
||||||
|
#define INCLUDED_GR_UHD_USRP_SINK_H
|
||||||
|
|
||||||
|
#include <gnuradio/uhd/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
#include <uhd/usrp/multi_usrp.hpp>
|
||||||
|
|
||||||
|
#ifndef INCLUDED_UHD_STREAM_HPP
|
||||||
|
namespace uhd {
|
||||||
|
struct GR_UHD_API stream_args_t
|
||||||
|
{
|
||||||
|
stream_args_t(const std::string &cpu = "",
|
||||||
|
const std::string &otw = "")
|
||||||
|
{
|
||||||
|
cpu_format = cpu;
|
||||||
|
otw_format = otw;
|
||||||
|
}
|
||||||
|
std::string cpu_format;
|
||||||
|
std::string otw_format;
|
||||||
|
device_addr_t args;
|
||||||
|
std::vector<size_t> channels;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
# define INCLUDED_UHD_STREAM_HPP
|
||||||
|
#else
|
||||||
|
# define GR_UHD_USE_STREAM_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace uhd {
|
||||||
|
|
||||||
|
class uhd_usrp_sink;
|
||||||
|
|
||||||
|
class GR_UHD_API usrp_sink : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// gr::uhd::usrp_sink::sptr
|
||||||
|
typedef boost::shared_ptr<usrp_sink> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Make a new USRP sink block.
|
||||||
|
* \ingroup uhd_blk
|
||||||
|
*
|
||||||
|
* The USRP sink block reads a stream and transmits the samples.
|
||||||
|
* The sink block also provides API calls for transmitter settings.
|
||||||
|
*
|
||||||
|
* TX Stream tagging:
|
||||||
|
*
|
||||||
|
* The following tag keys will be consumed by the work function:
|
||||||
|
* - pmt::string_to_symbol("tx_sob")
|
||||||
|
* - pmt::string_to_symbol("tx_eob")
|
||||||
|
* - pmt::string_to_symbol("tx_time")
|
||||||
|
*
|
||||||
|
* The sob and eob (start and end of burst) tag values are pmt booleans.
|
||||||
|
* When present, burst tags should be set to true (pmt::PMT_T).
|
||||||
|
*
|
||||||
|
* The timstamp tag value is a pmt tuple of the following:
|
||||||
|
* (uint64 seconds, and double fractional seconds).
|
||||||
|
*
|
||||||
|
* See the UHD manual for more detailed documentation:
|
||||||
|
* http://code.ettus.com/redmine/ettus/projects/uhd/wiki
|
||||||
|
*
|
||||||
|
* \param device_addr the address to identify the hardware
|
||||||
|
* \param io_type the desired input data type
|
||||||
|
* \param num_channels number of stream from the device
|
||||||
|
* \return a new USRP sink block object
|
||||||
|
*/
|
||||||
|
static sptr make(const ::uhd::device_addr_t &device_addr,
|
||||||
|
const ::uhd::io_type_t &io_type,
|
||||||
|
size_t num_channels);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Make a new USRP sink block.
|
||||||
|
*
|
||||||
|
* The USRP sink block reads a stream and transmits the samples.
|
||||||
|
* The sink block also provides API calls for transmitter settings.
|
||||||
|
*
|
||||||
|
* TX Stream tagging:
|
||||||
|
*
|
||||||
|
* The following tag keys will be consumed by the work function:
|
||||||
|
* - pmt::string_to_symbol("tx_sob")
|
||||||
|
* - pmt::string_to_symbol("tx_eob")
|
||||||
|
* - pmt::string_to_symbol("tx_time")
|
||||||
|
*
|
||||||
|
* The sob and eob (start and end of burst) tag values are pmt booleans.
|
||||||
|
* When present, burst tags should be set to true (pmt::PMT_T).
|
||||||
|
*
|
||||||
|
* The timstamp tag value is a pmt tuple of the following:
|
||||||
|
* (uint64 seconds, and double fractional seconds).
|
||||||
|
*
|
||||||
|
* See the UHD manual for more detailed documentation:
|
||||||
|
* http://code.ettus.com/redmine/ettus/projects/uhd/wiki
|
||||||
|
*
|
||||||
|
* \param device_addr the address to identify the hardware
|
||||||
|
* \param stream_args the IO format and channel specification
|
||||||
|
* \return a new USRP sink block object
|
||||||
|
*/
|
||||||
|
static sptr make(const ::uhd::device_addr_t &device_addr,
|
||||||
|
const ::uhd::stream_args_t &stream_args);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the start time for outgoing samples.
|
||||||
|
* To control when samples are transmitted,
|
||||||
|
* set this value before starting the flow graph.
|
||||||
|
* The value is cleared after each run.
|
||||||
|
* When not specified, the start time will be:
|
||||||
|
* - Immediately for the one channel case
|
||||||
|
* - in the near future for multi-channel
|
||||||
|
*
|
||||||
|
* \param time the absolute time for transmission to begin
|
||||||
|
*/
|
||||||
|
virtual void set_start_time(const ::uhd::time_spec_t &time) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns identifying information about this USRP's configuration.
|
||||||
|
* Returns motherboard ID, name, and serial.
|
||||||
|
* Returns daughterboard TX ID, subdev name and spec, serial, and antenna.
|
||||||
|
* \param chan channel index 0 to N-1
|
||||||
|
* \return TX info
|
||||||
|
*/
|
||||||
|
virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the frontend specification.
|
||||||
|
* \param spec the subdev spec markup string
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the TX frontend specification.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the frontend specification in use
|
||||||
|
*/
|
||||||
|
virtual std::string get_subdev_spec (size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the sample rate for the usrp device.
|
||||||
|
* \param rate a new rate in Sps
|
||||||
|
*/
|
||||||
|
virtual void set_samp_rate(double rate) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the sample rate for the usrp device.
|
||||||
|
* This is the actual sample rate and may differ from the rate set.
|
||||||
|
* \return the actual rate in Sps
|
||||||
|
*/
|
||||||
|
virtual double get_samp_rate(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the possible sample rates for the usrp device.
|
||||||
|
* \return a range of rates in Sps
|
||||||
|
*/
|
||||||
|
virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tune the usrp device to the desired center frequency.
|
||||||
|
* \param tune_request the tune request instructions
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a tune result with the actual frequencies
|
||||||
|
*/
|
||||||
|
virtual ::uhd::tune_result_t set_center_freq
|
||||||
|
(const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tune the usrp device to the desired center frequency.
|
||||||
|
* This is a wrapper around set center freq so that in this case,
|
||||||
|
* the user can pass a single frequency in the call through swig.
|
||||||
|
* \param freq the desired frequency in Hz
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a tune result with the actual frequencies
|
||||||
|
*/
|
||||||
|
::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
|
||||||
|
{
|
||||||
|
return set_center_freq(::uhd::tune_request_t(freq), chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the center frequency.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the frequency in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_center_freq(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the tunable frequency range.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the frequency range in Hz
|
||||||
|
*/
|
||||||
|
virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the gain for the dboard.
|
||||||
|
* \param gain the gain in dB
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_gain(double gain, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the named gain on the dboard.
|
||||||
|
* \param gain the gain in dB
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_gain(double gain,
|
||||||
|
const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual double get_gain(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting of named stage.
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual double get_gain(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting of named stage.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the settable gain range.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the gain range in dB
|
||||||
|
*/
|
||||||
|
virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the settable gain range.
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the gain range in dB
|
||||||
|
*/
|
||||||
|
virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the antenna to use.
|
||||||
|
* \param ant the antenna string
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_antenna(const std::string &ant,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the antenna in use.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the antenna string
|
||||||
|
*/
|
||||||
|
virtual std::string get_antenna(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible antennas.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a vector of antenna strings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the bandpass filter on the RF frontend.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \param bandwidth the filter bandwidth in Hz
|
||||||
|
*/
|
||||||
|
virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the bandpass filter setting on the RF frontend.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return bandwidth of the filter in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_bandwidth(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the bandpass filter range of the RF frontend.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the range of the filter bandwidth in Hz
|
||||||
|
*/
|
||||||
|
virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set a constant DC offset value.
|
||||||
|
* The value is complex to control both I and Q.
|
||||||
|
* \param offset the dc offset (1.0 is full-scale)
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_dc_offset(const std::complex<double> &offset,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the RX frontend IQ imbalance correction.
|
||||||
|
* Use this to adjust the magnitude and phase of I and Q.
|
||||||
|
*
|
||||||
|
* \param correction the complex correction (1.0 is full-scale)
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_iq_balance(const std::complex<double> &correction,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get an RF frontend sensor value.
|
||||||
|
* \param name the name of the sensor
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a sensor value object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::sensor_value_t get_sensor(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible RF frontend sensor names.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a vector of sensor names
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
//! DEPRECATED use get_sensor
|
||||||
|
::uhd::sensor_value_t get_dboard_sensor(const std::string &name,
|
||||||
|
size_t chan = 0)
|
||||||
|
{
|
||||||
|
return this->get_sensor(name, chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! DEPRECATED use get_sensor_names
|
||||||
|
std::vector<std::string> get_dboard_sensor_names(size_t chan = 0)
|
||||||
|
{
|
||||||
|
return this->get_sensor_names(chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a motherboard sensor value.
|
||||||
|
* \param name the name of the sensor
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return a sensor value object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible motherboard sensor names.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return a vector of sensor names
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the clock configuration.
|
||||||
|
* DEPRECATED for set_time/clock_source.
|
||||||
|
* \param clock_config the new configuration
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time source for the usrp device.
|
||||||
|
* This sets the method of time synchronization,
|
||||||
|
* typically a pulse per second or an encoded time.
|
||||||
|
* Typical options for source: external, MIMO.
|
||||||
|
* \param source a string representing the time source
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_time_source(const std::string &source,
|
||||||
|
const size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the currently set time source.
|
||||||
|
* \param mboard which motherboard to get the config
|
||||||
|
* \return the string representing the time source
|
||||||
|
*/
|
||||||
|
virtual std::string get_time_source(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible time sources.
|
||||||
|
* \param mboard which motherboard to get the list
|
||||||
|
* \return a vector of strings for possible settings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_time_sources(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the clock source for the usrp device.
|
||||||
|
* This sets the source for a 10 Mhz reference clock.
|
||||||
|
* Typical options for source: internal, external, MIMO.
|
||||||
|
* \param source a string representing the clock source
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_clock_source(const std::string &source,
|
||||||
|
const size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the currently set clock source.
|
||||||
|
* \param mboard which motherboard to get the config
|
||||||
|
* \return the string representing the clock source
|
||||||
|
*/
|
||||||
|
virtual std::string get_clock_source(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible clock sources.
|
||||||
|
* \param mboard which motherboard to get the list
|
||||||
|
* \return a vector of strings for possible settings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the master clock rate.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the clock rate in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_clock_rate(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the master clock rate.
|
||||||
|
* \param rate the new rate in Hz
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the current time registers.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the current usrp time
|
||||||
|
*/
|
||||||
|
virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the time when the last pps pulse occured.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the current usrp time
|
||||||
|
*/
|
||||||
|
virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the time registers immediately.
|
||||||
|
* \param time_spec the new time
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time registers at the next pps.
|
||||||
|
* \param time_spec the new time
|
||||||
|
*/
|
||||||
|
virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sync the time registers with an unknown pps edge.
|
||||||
|
* \param time_spec the new time
|
||||||
|
*/
|
||||||
|
virtual void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time at which the control commands will take effect.
|
||||||
|
*
|
||||||
|
* A timed command will back-pressure all subsequent timed commands,
|
||||||
|
* assuming that the subsequent commands occur within the time-window.
|
||||||
|
* If the time spec is late, the command will be activated upon arrival.
|
||||||
|
*
|
||||||
|
* \param time_spec the time at which the next command will activate
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_command_time(const ::uhd::time_spec_t &time_spec,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Clear the command time so future commands are sent ASAP.
|
||||||
|
*
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void clear_command_time(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get access to the underlying uhd dboard iface object.
|
||||||
|
* \return the dboard_iface object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get access to the underlying uhd device object.
|
||||||
|
* \return the multi usrp device object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Perform write on the user configuration register bus. These
|
||||||
|
* only exist if the user has implemented custom setting
|
||||||
|
* registers in the device FPGA.
|
||||||
|
* \param addr 8-bit register address
|
||||||
|
* \param data 32-bit register value
|
||||||
|
* \param mboard which motherboard to set the user register
|
||||||
|
*/
|
||||||
|
virtual void set_user_register(const uint8_t addr,
|
||||||
|
const uint32_t data,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace uhd */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_UHD_USRP_SINK_H */
|
|
@ -0,0 +1,581 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_GR_UHD_USRP_SOURCE_H
|
||||||
|
#define INCLUDED_GR_UHD_USRP_SOURCE_H
|
||||||
|
|
||||||
|
#include <gnuradio/uhd/api.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
#include <uhd/usrp/multi_usrp.hpp>
|
||||||
|
|
||||||
|
#ifndef INCLUDED_UHD_STREAM_HPP
|
||||||
|
namespace uhd {
|
||||||
|
struct GR_UHD_API stream_args_t
|
||||||
|
{
|
||||||
|
stream_args_t(const std::string &cpu = "",
|
||||||
|
const std::string &otw = "")
|
||||||
|
{
|
||||||
|
cpu_format = cpu;
|
||||||
|
otw_format = otw;
|
||||||
|
}
|
||||||
|
std::string cpu_format;
|
||||||
|
std::string otw_format;
|
||||||
|
device_addr_t args;
|
||||||
|
std::vector<size_t> channels;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
# define INCLUDED_UHD_STREAM_HPP
|
||||||
|
#else
|
||||||
|
# define GR_UHD_USE_STREAM_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gr {
|
||||||
|
namespace uhd {
|
||||||
|
|
||||||
|
class uhd_usrp_source;
|
||||||
|
|
||||||
|
class GR_UHD_API usrp_source : virtual public sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// gr::uhd::usrp_source::sptr
|
||||||
|
typedef boost::shared_ptr<usrp_source> sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Make a new USRP source block.
|
||||||
|
* \ingroup uhd_blk
|
||||||
|
*
|
||||||
|
* The USRP source block receives samples and writes to a stream.
|
||||||
|
* The source block also provides API calls for receiver settings.
|
||||||
|
*
|
||||||
|
* RX Stream tagging:
|
||||||
|
*
|
||||||
|
* The following tag keys will be produced by the work function:
|
||||||
|
* - pmt::string_to_symbol("rx_time")
|
||||||
|
* - pmt::string_to_symbol("rx_rate")
|
||||||
|
* - pmt::string_to_symbol("rx_freq")
|
||||||
|
*
|
||||||
|
* The timstamp tag value is a pmt tuple of the following:
|
||||||
|
* (uint64 seconds, and double fractional seconds).
|
||||||
|
* A timestamp tag is produced at start() and after overflows.
|
||||||
|
*
|
||||||
|
* The sample rate and center frequency tags are doubles,
|
||||||
|
* representing the sample rate in Sps and frequency in Hz.
|
||||||
|
* These tags are produced upon the user changing parameters.
|
||||||
|
*
|
||||||
|
* See the UHD manual for more detailed documentation:
|
||||||
|
* http://code.ettus.com/redmine/ettus/projects/uhd/wiki
|
||||||
|
*
|
||||||
|
* \param device_addr the address to identify the hardware
|
||||||
|
* \param io_type the desired output data type
|
||||||
|
* \param num_channels number of stream from the device
|
||||||
|
* \return a new USRP source block object
|
||||||
|
*/
|
||||||
|
static sptr make(const ::uhd::device_addr_t &device_addr,
|
||||||
|
const ::uhd::io_type_t &io_type,
|
||||||
|
size_t num_channels);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Make a new USRP source block.
|
||||||
|
*
|
||||||
|
* The USRP source block receives samples and writes to a stream.
|
||||||
|
* The source block also provides API calls for receiver settings.
|
||||||
|
*
|
||||||
|
* RX Stream tagging:
|
||||||
|
*
|
||||||
|
* The following tag keys will be produced by the work function:
|
||||||
|
* - pmt::string_to_symbol("rx_time")
|
||||||
|
*
|
||||||
|
* The timstamp tag value is a pmt tuple of the following:
|
||||||
|
* (uint64 seconds, and double fractional seconds).
|
||||||
|
* A timestamp tag is produced at start() and after overflows.
|
||||||
|
*
|
||||||
|
* See the UHD manual for more detailed documentation:
|
||||||
|
* http://code.ettus.com/redmine/ettus/projects/uhd/wiki
|
||||||
|
*
|
||||||
|
* \param device_addr the address to identify the hardware
|
||||||
|
* \param stream_args the IO format and channel specification
|
||||||
|
* \return a new USRP source block object
|
||||||
|
*/
|
||||||
|
static sptr make(const ::uhd::device_addr_t &device_addr,
|
||||||
|
const ::uhd::stream_args_t &stream_args);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the start time for incoming samples.
|
||||||
|
* To control when samples are received,
|
||||||
|
* set this value before starting the flow graph.
|
||||||
|
* The value is cleared after each run.
|
||||||
|
* When not specified, the start time will be:
|
||||||
|
* - Immediately for the one channel case
|
||||||
|
* - in the near future for multi-channel
|
||||||
|
*
|
||||||
|
* \param time the absolute time for reception to begin
|
||||||
|
*/
|
||||||
|
virtual void set_start_time(const ::uhd::time_spec_t &time) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* *Advanced use only:*
|
||||||
|
* Issue a stream command to all channels in this source block.
|
||||||
|
*
|
||||||
|
* This method is intended to override the default "always on"
|
||||||
|
* behavior. After starting the flow graph, the user should
|
||||||
|
* call stop() on this block, then issue any desired arbitrary
|
||||||
|
* stream_cmd_t structs to the device. The USRP will be able to
|
||||||
|
* enqueue several stream commands in the FPGA.
|
||||||
|
*
|
||||||
|
* \param cmd the stream command to issue to all source channels
|
||||||
|
*/
|
||||||
|
virtual void issue_stream_cmd(const ::uhd::stream_cmd_t &cmd) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns identifying information about this USRP's configuration.
|
||||||
|
* Returns motherboard ID, name, and serial.
|
||||||
|
* Returns daughterboard RX ID, subdev name and spec, serial, and antenna.
|
||||||
|
* \param chan channel index 0 to N-1
|
||||||
|
* \return RX info
|
||||||
|
*/
|
||||||
|
virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the frontend specification.
|
||||||
|
* \param spec the subdev spec markup string
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the RX frontend specification.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the frontend specification in use
|
||||||
|
*/
|
||||||
|
virtual std::string get_subdev_spec(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the sample rate for the usrp device.
|
||||||
|
* \param rate a new rate in Sps
|
||||||
|
*/
|
||||||
|
virtual void set_samp_rate(double rate) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the sample rate for the usrp device.
|
||||||
|
* This is the actual sample rate and may differ from the rate set.
|
||||||
|
* \return the actual rate in Sps
|
||||||
|
*/
|
||||||
|
virtual double get_samp_rate(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the possible sample rates for the usrp device.
|
||||||
|
* \return a range of rates in Sps
|
||||||
|
*/
|
||||||
|
virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tune the usrp device to the desired center frequency.
|
||||||
|
* \param tune_request the tune request instructions
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a tune result with the actual frequencies
|
||||||
|
*/
|
||||||
|
virtual ::uhd::tune_result_t set_center_freq
|
||||||
|
(const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tune the usrp device to the desired center frequency.
|
||||||
|
* This is a wrapper around set center freq so that in this case,
|
||||||
|
* the user can pass a single frequency in the call through swig.
|
||||||
|
* \param freq the desired frequency in Hz
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a tune result with the actual frequencies
|
||||||
|
*/
|
||||||
|
::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
|
||||||
|
{
|
||||||
|
return set_center_freq(::uhd::tune_request_t(freq), chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the center frequency.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the frequency in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_center_freq(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the tunable frequency range.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the frequency range in Hz
|
||||||
|
*/
|
||||||
|
virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the gain for the dboard.
|
||||||
|
* \param gain the gain in dB
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_gain(double gain, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the named gain on the dboard.
|
||||||
|
* \param gain the gain in dB
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_gain(double gain,
|
||||||
|
const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual double get_gain(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting of named stage.
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual double get_gain(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the actual dboard gain setting of named stage.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the actual gain in dB
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the settable gain range.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the gain range in dB
|
||||||
|
*/
|
||||||
|
virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the settable gain range.
|
||||||
|
* \param name the name of the gain stage
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the gain range in dB
|
||||||
|
*/
|
||||||
|
virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the antenna to use.
|
||||||
|
* \param ant the antenna string
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_antenna(const std::string &ant,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the antenna in use.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the antenna string
|
||||||
|
*/
|
||||||
|
virtual std::string get_antenna(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible antennas.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a vector of antenna strings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the bandpass filter on the RF frontend.
|
||||||
|
* \param bandwidth the filter bandwidth in Hz
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the bandpass filter setting on the RF frontend.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return bandwidth of the filter in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_bandwidth(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the bandpass filter range of the RF frontend.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return the range of the filter bandwidth in Hz
|
||||||
|
*/
|
||||||
|
virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enable/disable the automatic DC offset correction.
|
||||||
|
* The automatic correction subtracts out the long-run average.
|
||||||
|
*
|
||||||
|
* When disabled, the averaging option operation is halted.
|
||||||
|
* Once halted, the average value will be held constant until
|
||||||
|
* the user re-enables the automatic correction or overrides the
|
||||||
|
* value by manually setting the offset.
|
||||||
|
*
|
||||||
|
* \param enb true to enable automatic DC offset correction
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_auto_dc_offset(const bool enb, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set a constant DC offset value.
|
||||||
|
* The value is complex to control both I and Q.
|
||||||
|
* Only set this when automatic correction is disabled.
|
||||||
|
* \param offset the dc offset (1.0 is full-scale)
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_dc_offset(const std::complex<double> &offset, size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the RX frontend IQ imbalance correction.
|
||||||
|
* Use this to adjust the magnitude and phase of I and Q.
|
||||||
|
*
|
||||||
|
* \param correction the complex correction value
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
*/
|
||||||
|
virtual void set_iq_balance(const std::complex<double> &correction,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a RF frontend sensor value.
|
||||||
|
* \param name the name of the sensor
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a sensor value object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::sensor_value_t get_sensor(const std::string &name,
|
||||||
|
size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible RF frontend sensor names.
|
||||||
|
* \param chan the channel index 0 to N-1
|
||||||
|
* \return a vector of sensor names
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
//! DEPRECATED use get_sensor
|
||||||
|
::uhd::sensor_value_t get_dboard_sensor(const std::string &name,
|
||||||
|
size_t chan = 0)
|
||||||
|
{
|
||||||
|
return this->get_sensor(name, chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! DEPRECATED use get_sensor_names
|
||||||
|
std::vector<std::string> get_dboard_sensor_names(size_t chan = 0)
|
||||||
|
{
|
||||||
|
return this->get_sensor_names(chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a motherboard sensor value.
|
||||||
|
* \param name the name of the sensor
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return a sensor value object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible motherboard sensor names.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return a vector of sensor names
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the clock configuration.
|
||||||
|
* DEPRECATED for set_time/clock_source.
|
||||||
|
* \param clock_config the new configuration
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time source for the usrp device.
|
||||||
|
* This sets the method of time synchronization,
|
||||||
|
* typically a pulse per second or an encoded time.
|
||||||
|
* Typical options for source: external, MIMO.
|
||||||
|
* \param source a string representing the time source
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_time_source(const std::string &source,
|
||||||
|
const size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the currently set time source.
|
||||||
|
* \param mboard which motherboard to get the config
|
||||||
|
* \return the string representing the time source
|
||||||
|
*/
|
||||||
|
virtual std::string get_time_source(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible time sources.
|
||||||
|
* \param mboard which motherboard to get the list
|
||||||
|
* \return a vector of strings for possible settings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_time_sources(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the clock source for the usrp device.
|
||||||
|
* This sets the source for a 10 Mhz reference clock.
|
||||||
|
* Typical options for source: internal, external, MIMO.
|
||||||
|
* \param source a string representing the clock source
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_clock_source(const std::string &source,
|
||||||
|
const size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the currently set clock source.
|
||||||
|
* \param mboard which motherboard to get the config
|
||||||
|
* \return the string representing the clock source
|
||||||
|
*/
|
||||||
|
virtual std::string get_clock_source(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get a list of possible clock sources.
|
||||||
|
* \param mboard which motherboard to get the list
|
||||||
|
* \return a vector of strings for possible settings
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the master clock rate.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the clock rate in Hz
|
||||||
|
*/
|
||||||
|
virtual double get_clock_rate(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the master clock rate.
|
||||||
|
* \param rate the new rate in Hz
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the current time registers.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the current usrp time
|
||||||
|
*/
|
||||||
|
virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the time when the last pps pulse occured.
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
* \return the current usrp time
|
||||||
|
*/
|
||||||
|
virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the time registers immediately.
|
||||||
|
* \param time_spec the new time
|
||||||
|
* \param mboard the motherboard index 0 to M-1
|
||||||
|
*/
|
||||||
|
virtual void set_time_now(const ::uhd::time_spec_t &time_spec,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time registers at the next pps.
|
||||||
|
* \param time_spec the new time
|
||||||
|
*/
|
||||||
|
virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sync the time registers with an unknown pps edge.
|
||||||
|
* \param time_spec the new time
|
||||||
|
*/
|
||||||
|
virtual void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the time at which the control commands will take effect.
|
||||||
|
*
|
||||||
|
* A timed command will back-pressure all subsequent timed
|
||||||
|
* commands, assuming that the subsequent commands occur within
|
||||||
|
* the time-window. If the time spec is late, the command will
|
||||||
|
* be activated upon arrival.
|
||||||
|
*
|
||||||
|
* \param time_spec the time at which the next command will activate
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void set_command_time(const ::uhd::time_spec_t &time_spec,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Clear the command time so future commands are sent ASAP.
|
||||||
|
*
|
||||||
|
* \param mboard which motherboard to set the config
|
||||||
|
*/
|
||||||
|
virtual void clear_command_time(size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get access to the underlying uhd dboard iface object.
|
||||||
|
* \return the dboard_iface object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get access to the underlying uhd device object.
|
||||||
|
* \return the multi usrp device object
|
||||||
|
*/
|
||||||
|
virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Perform write on the user configuration register bus. These
|
||||||
|
* only exist if the user has implemented custom setting
|
||||||
|
* registers in the device FPGA.
|
||||||
|
* \param addr 8-bit register address
|
||||||
|
* \param data 32-bit register value
|
||||||
|
* \param mboard which motherboard to set the user register
|
||||||
|
*/
|
||||||
|
virtual void set_user_register(const uint8_t addr,
|
||||||
|
const uint32_t data,
|
||||||
|
size_t mboard = 0) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Convenience function for finite data acquisition.
|
||||||
|
* This is not to be used with the scheduler; rather,
|
||||||
|
* one can request samples from the USRP in python.
|
||||||
|
* //TODO assumes fc32
|
||||||
|
* \param nsamps the number of samples
|
||||||
|
* \return a vector of complex float samples
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::complex<float> >
|
||||||
|
finite_acquisition(const size_t nsamps) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Convenience function for finite data acquisition. This is the
|
||||||
|
* multi-channel version of finite_acquisition; This is not to
|
||||||
|
* be used with the scheduler; rather, one can request samples
|
||||||
|
* from the USRP in python.
|
||||||
|
* //TODO assumes fc32
|
||||||
|
* \param nsamps the number of samples per channel
|
||||||
|
* \return a vector of buffers, where each buffer represents a channel
|
||||||
|
*/
|
||||||
|
virtual std::vector<std::vector<std::complex<float> > >
|
||||||
|
finite_acquisition_v(const size_t nsamps) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace uhd */
|
||||||
|
} /* namespace gr */
|
||||||
|
|
||||||
|
#endif /* INCLUDED_GR_UHD_USRP_SOURCE_H */
|
|
@ -254,7 +254,7 @@ public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the bandpass filter on the radio frontend.
|
* Set the bandpass filter on the radio frontend.
|
||||||
* \param bandwidth the filter bandwidth in Hz
|
* \param bandwidth the filter bandwidth in Hz, set to 0 for automatic selection
|
||||||
* \param chan the channel index 0 to N-1
|
* \param chan the channel index 0 to N-1
|
||||||
* \return the actual filter bandwidth in Hz
|
* \return the actual filter bandwidth in Hz
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -289,7 +289,7 @@ public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the bandpass filter on the radio frontend.
|
* Set the bandpass filter on the radio frontend.
|
||||||
* \param bandwidth the filter bandwidth in Hz
|
* \param bandwidth the filter bandwidth in Hz, set to 0 for automatic selection
|
||||||
* \param chan the channel index 0 to N-1
|
* \param chan the channel index 0 to N-1
|
||||||
* \return the actual filter bandwidth in Hz
|
* \return the actual filter bandwidth in Hz
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -49,6 +49,176 @@ GR_OSMOSDR_APPEND_LIBS(
|
||||||
${GNURADIO_BLOCKS_LIBRARIES}
|
${GNURADIO_BLOCKS_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Set up built-in GNU Radio runtime component
|
||||||
|
########################################################################
|
||||||
|
GR_REGISTER_COMPONENT("Built-in GNU Radio runtime" ENABLE_RUNTIME RUNTIME_MODE)
|
||||||
|
if(ENABLE_RUNTIME)
|
||||||
|
|
||||||
|
message(STATUS "")
|
||||||
|
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/ConfigChecks.cmake)
|
||||||
|
|
||||||
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/runtime)
|
||||||
|
|
||||||
|
GR_OSMOSDR_APPEND_SRCS(
|
||||||
|
runtime/math/fast_atan2f.cc
|
||||||
|
runtime/math/fxpt.cc
|
||||||
|
runtime/math/random.cc
|
||||||
|
runtime/math/sincos.cc
|
||||||
|
|
||||||
|
runtime/thread/thread.cc
|
||||||
|
runtime/thread/thread_body_wrapper.cc
|
||||||
|
runtime/thread/thread_group.cc
|
||||||
|
|
||||||
|
runtime/basic_block.cc
|
||||||
|
runtime/block.cc
|
||||||
|
runtime/block_detail.cc
|
||||||
|
runtime/block_executor.cc
|
||||||
|
runtime/block_gateway_impl.cc
|
||||||
|
runtime/block_registry.cc
|
||||||
|
runtime/buffer.cc
|
||||||
|
runtime/circular_file.cc
|
||||||
|
runtime/feval.cc
|
||||||
|
runtime/flat_flowgraph.cc
|
||||||
|
runtime/flowgraph.cc
|
||||||
|
runtime/hier_block2.cc
|
||||||
|
runtime/hier_block2_detail.cc
|
||||||
|
runtime/high_res_timer.cc
|
||||||
|
runtime/io_signature.cc
|
||||||
|
runtime/local_sighandler.cc
|
||||||
|
runtime/logger.cc
|
||||||
|
runtime/misc.cc
|
||||||
|
runtime/pagesize.cc
|
||||||
|
runtime/prefs.cc
|
||||||
|
runtime/realtime.cc
|
||||||
|
runtime/realtime_impl.cc
|
||||||
|
runtime/scheduler.cc
|
||||||
|
runtime/scheduler_sts.cc
|
||||||
|
runtime/scheduler_tpb.cc
|
||||||
|
runtime/single_threaded_scheduler.cc
|
||||||
|
runtime/sptr_magic.cc
|
||||||
|
runtime/sync_block.cc
|
||||||
|
runtime/sys_paths.cc
|
||||||
|
runtime/top_block.cc
|
||||||
|
runtime/top_block_impl.cc
|
||||||
|
runtime/tpb_detail.cc
|
||||||
|
runtime/tpb_thread_body.cc
|
||||||
|
runtime/vmcircbuf.cc
|
||||||
|
runtime/vmcircbuf_createfilemapping.cc
|
||||||
|
runtime/vmcircbuf_mmap_shm_open.cc
|
||||||
|
runtime/vmcircbuf_mmap_tmpfile.cc
|
||||||
|
runtime/vmcircbuf_prefs.cc
|
||||||
|
runtime/vmcircbuf_sysv_shm.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-Dgnuradio_runtime_EXPORTS)
|
||||||
|
|
||||||
|
GR_OSMOSDR_APPEND_SRCS(
|
||||||
|
runtime/blocks/file_source_impl.cc
|
||||||
|
runtime/blocks/throttle_impl.cc
|
||||||
|
runtime/blocks/null_sink_impl.cc
|
||||||
|
runtime/blocks/null_source_impl.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(GNURADIO_BLOCKS_FOUND TRUE)
|
||||||
|
ADD_DEFINITIONS(-Dgnuradio_blocks_EXPORTS)
|
||||||
|
|
||||||
|
if(UHD_FOUND)
|
||||||
|
|
||||||
|
GR_OSMOSDR_APPEND_SRCS(
|
||||||
|
runtime/uhd/usrp_sink_impl.cc
|
||||||
|
runtime/uhd/usrp_source_impl.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(GNURADIO_UHD_FOUND TRUE)
|
||||||
|
ADD_DEFINITIONS(-Dgnuradio_uhd_EXPORTS)
|
||||||
|
|
||||||
|
endif(UHD_FOUND)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Handle the generated constants
|
||||||
|
########################################################################
|
||||||
|
MACRO (TODAY RESULT)
|
||||||
|
IF (WIN32)
|
||||||
|
EXECUTE_PROCESS(COMMAND "date" "/T" OUTPUT_VARIABLE ${RESULT})
|
||||||
|
string(REGEX REPLACE "(..)/(..)/(....).*" "\\1.\\2.\\3"
|
||||||
|
${RESULT} ${${RESULT}})
|
||||||
|
ELSEIF(UNIX)
|
||||||
|
EXECUTE_PROCESS(COMMAND "date" "+%d/%m/%Y" OUTPUT_VARIABLE ${RESULT})
|
||||||
|
string(REGEX REPLACE "(..)/(..)/(....).*" "\\1.\\2.\\3"
|
||||||
|
${RESULT} ${${RESULT}})
|
||||||
|
ELSE (WIN32)
|
||||||
|
MESSAGE(SEND_ERROR "date not implemented")
|
||||||
|
SET(${RESULT} 00.00.0000)
|
||||||
|
ENDIF (WIN32)
|
||||||
|
ENDMACRO (TODAY)
|
||||||
|
|
||||||
|
TODAY(BUILD_DATE)
|
||||||
|
|
||||||
|
set(GR_VERSION "built-in")
|
||||||
|
|
||||||
|
message(STATUS "Loading prefix ${prefix} into constants...")
|
||||||
|
message(STATUS "Loading SYSCONFDIR ${SYSCONFDIR} into constants...")
|
||||||
|
message(STATUS "Loading GR_PREFSDIR ${GR_PREFSDIR} into constants...")
|
||||||
|
message(STATUS "Loading build date \"${BUILD_DATE}\" into constants...")
|
||||||
|
message(STATUS "Loading version \"${GR_VERSION}\" into constants...")
|
||||||
|
|
||||||
|
#double escape for windows backslash path separators
|
||||||
|
string(REPLACE "\\" "\\\\" prefix ${prefix})
|
||||||
|
string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR})
|
||||||
|
string(REPLACE "\\" "\\\\" GR_PREFSDIR ${GR_PREFSDIR})
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/runtime/constants.cc.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/constants.cc
|
||||||
|
@ONLY)
|
||||||
|
|
||||||
|
GR_OSMOSDR_APPEND_SRCS(${CMAKE_CURRENT_BINARY_DIR}/constants.cc)
|
||||||
|
|
||||||
|
# PowerPC workaround for posix_memalign
|
||||||
|
# Might not be needed, but we'll keep it for now.
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
|
||||||
|
GR_OSMOSDR_APPEND_SRCS(runtime/posix_memalign.cc)
|
||||||
|
endif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines.
|
||||||
|
# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1
|
||||||
|
########################################################################
|
||||||
|
if(WIN32)
|
||||||
|
OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF)
|
||||||
|
else(WIN32)
|
||||||
|
OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.")
|
||||||
|
|
||||||
|
if(TRY_SHM_VMCIRCBUF)
|
||||||
|
ADD_DEFINITIONS( -DTRY_SHM_VMCIRCBUF )
|
||||||
|
endif(TRY_SHM_VMCIRCBUF)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Add libraries for winsock2.h on Windows
|
||||||
|
########################################################################
|
||||||
|
CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
|
||||||
|
if(HAVE_WINDOWS_H)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/cmake/msvc)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_WINDOWS_H -DUSING_WINSOCK -DWIN32_LEAN_AND_MEAN)
|
||||||
|
ADD_DEFINITIONS(-DNOMINMAX -D_USE_MATH_DEFINES)
|
||||||
|
ADD_DEFINITIONS(/MP -D_CRT_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE)
|
||||||
|
MESSAGE(STATUS "Adding windows libs to gnuradio osmosdr lib...")
|
||||||
|
GR_OSMOSDR_APPEND_LIBS(WS2_32.lib WSock32.lib)
|
||||||
|
endif(HAVE_WINDOWS_H)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Need to link with librt for shm_*
|
||||||
|
########################################################################
|
||||||
|
if(LINUX)
|
||||||
|
GR_OSMOSDR_APPEND_LIBS(rt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif(ENABLE_RUNTIME)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Setup IQBalance component
|
# Setup IQBalance component
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -101,7 +271,7 @@ endif(ENABLE_RTL)
|
||||||
########################################################################
|
########################################################################
|
||||||
# Setup RTL_TCP component
|
# Setup RTL_TCP component
|
||||||
########################################################################
|
########################################################################
|
||||||
GR_REGISTER_COMPONENT("RTLSDR TCP Client" ENABLE_RTL_TCP GNURADIO_BLOCKS_FOUND)
|
GR_REGISTER_COMPONENT("RTLSDR TCP Client" ENABLE_RTL_TCP)
|
||||||
if(ENABLE_RTL_TCP)
|
if(ENABLE_RTL_TCP)
|
||||||
GR_INCLUDE_SUBDIRECTORY(rtl_tcp)
|
GR_INCLUDE_SUBDIRECTORY(rtl_tcp)
|
||||||
endif(ENABLE_RTL_TCP)
|
endif(ENABLE_RTL_TCP)
|
||||||
|
@ -138,6 +308,22 @@ if(ENABLE_BLADERF)
|
||||||
GR_INCLUDE_SUBDIRECTORY(bladerf)
|
GR_INCLUDE_SUBDIRECTORY(bladerf)
|
||||||
endif(ENABLE_BLADERF)
|
endif(ENABLE_BLADERF)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Setup RFSPACE component
|
||||||
|
########################################################################
|
||||||
|
GR_REGISTER_COMPONENT("RFSPACE Receivers" ENABLE_RFSPACE)
|
||||||
|
if(ENABLE_RFSPACE)
|
||||||
|
GR_INCLUDE_SUBDIRECTORY(rfspace)
|
||||||
|
endif(ENABLE_RFSPACE)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Setup AIRSPY component
|
||||||
|
########################################################################
|
||||||
|
GR_REGISTER_COMPONENT("AIRSPY Receiver" ENABLE_AIRSPY LIBAIRSPY_FOUND)
|
||||||
|
if(ENABLE_AIRSPY)
|
||||||
|
GR_INCLUDE_SUBDIRECTORY(airspy)
|
||||||
|
endif(ENABLE_AIRSPY)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Setup configuration file
|
# Setup configuration file
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
# Copyright 2010-2013 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This file is part of GNU Radio
|
||||||
|
#
|
||||||
|
# GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
INCLUDE(GrMiscUtils)
|
||||||
|
INCLUDE(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
IF(MSVC) #add this directory for our provided headers
|
||||||
|
LIST(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/msvc)
|
||||||
|
ENDIF(MSVC)
|
||||||
|
|
||||||
|
#GR_CHECK_HDR_N_DEF(netdb.h HAVE_NETDB_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(sys/time.h HAVE_SYS_TIME_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(sys/types.h HAVE_SYS_TYPES_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(sys/select.h HAVE_SYS_SELECT_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(io.h HAVE_IO_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(sys/mman.h HAVE_SYS_MMAN_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(sys/ipc.h HAVE_SYS_IPC_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(sys/shm.h HAVE_SYS_SHM_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(signal.h HAVE_SIGNAL_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(netinet/in.h HAVE_NETINET_IN_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(arpa/inet.h HAVE_ARPA_INET_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(byteswap.h HAVE_BYTESWAP_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(linux/ppdev.h HAVE_LINUX_PPDEV_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(dev/ppbus/ppi.h HAVE_DEV_PPBUS_PPI_H)
|
||||||
|
GR_CHECK_HDR_N_DEF(unistd.h HAVE_UNISTD_H)
|
||||||
|
#GR_CHECK_HDR_N_DEF(malloc.h HAVE_MALLOC_H)
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){snprintf(0, 0, 0); return 0;}
|
||||||
|
" HAVE_SNPRINTF
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SNPRINTF)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <signal.h>
|
||||||
|
int main(){sigaction(0, 0, 0); return 0;}
|
||||||
|
" HAVE_SIGACTION
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SIGACTION)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sys/select.h>
|
||||||
|
int main(){select(0, 0, 0, 0, 0); return 0;}
|
||||||
|
" HAVE_SELECT
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SELECT)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <unistd.h>
|
||||||
|
int main(){sysconf(0); return 0;}
|
||||||
|
" HAVE_SYSCONF
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SYSCONF)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <unistd.h>
|
||||||
|
int main(){getpagesize(); return 0;}
|
||||||
|
" HAVE_GETPAGESIZE
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_GETPAGESIZE)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <Winbase.h>
|
||||||
|
int main(){Sleep(0); return 0;}
|
||||||
|
" HAVE_SSLEEP
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SSLEEP)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <time.h>
|
||||||
|
int main(){nanosleep(0, 0); return 0;}
|
||||||
|
" HAVE_NANOSLEEP
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_NANOSLEEP)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sys/time.h>
|
||||||
|
int main(){gettimeofday(0, 0); return 0;}
|
||||||
|
" HAVE_GETTIMEOFDAY
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_GETTIMEOFDAY)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main(){posix_memalign(0, 0, 0); return 0;}
|
||||||
|
" HAVE_POSIX_MEMALIGN
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_POSIX_MEMALIGN)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <malloc.h>
|
||||||
|
int main(){valloc(0); return 0;}
|
||||||
|
" HAVE_VALLOC
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_VALLOC)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DALIGNED_MALLOC=0)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES -lpthread)
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <signal.h>
|
||||||
|
int main(){pthread_sigmask(0, 0, 0); return 0;}
|
||||||
|
" HAVE_PTHREAD_SIGMASK
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_PTHREAD_SIGMASK)
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <windows.h>
|
||||||
|
int main(){
|
||||||
|
HANDLE handle;
|
||||||
|
int size;
|
||||||
|
LPCTSTR lpName;
|
||||||
|
handle = CreateFileMapping(
|
||||||
|
INVALID_HANDLE_VALUE, // use paging file
|
||||||
|
NULL, // default security
|
||||||
|
PAGE_READWRITE, // read/write access
|
||||||
|
0, // max. object size
|
||||||
|
size, // buffer size
|
||||||
|
lpName); // name of mapping object
|
||||||
|
return 0;
|
||||||
|
} " HAVE_CREATEFILEMAPPING
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_CREATEFILEMAPPING)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES -lrt)
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
int main(){shm_open(0, 0, 0); return 0;}
|
||||||
|
" HAVE_SHM_OPEN
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SHM_OPEN)
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <math.h>
|
||||||
|
int main(){double x, sin, cos; sincos(x, &sin, &cos); return 0;}
|
||||||
|
" HAVE_SINCOS
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SINCOS)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <math.h>
|
||||||
|
int main(){float x, sin, cos; sincosf(x, &sin, &cos); return 0;}
|
||||||
|
" HAVE_SINCOSF
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SINCOSF)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <math.h>
|
||||||
|
int main(){sinf(0); return 0;}
|
||||||
|
" HAVE_SINF
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_SINF)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <math.h>
|
||||||
|
int main(){cosf(0); return 0;}
|
||||||
|
" HAVE_COSF
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_COSF)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
CHECK_CXX_SOURCE_COMPILES("
|
||||||
|
#include <sys/mman.h>
|
||||||
|
int main(){mmap(0, 0, 0, 0, 0, 0); return 0;}
|
||||||
|
" HAVE_MMAP
|
||||||
|
)
|
||||||
|
GR_ADD_COND_DEF(HAVE_MMAP)
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Copyright 2012 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This file is part of GNU Radio
|
||||||
|
#
|
||||||
|
# GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# This file included, use CMake directory variables
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${LIBAIRSPY_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(airspy_srcs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/airspy_source_c.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Append gnuradio-osmosdr library sources
|
||||||
|
########################################################################
|
||||||
|
list(APPEND gr_osmosdr_srcs ${airspy_srcs})
|
||||||
|
list(APPEND gr_osmosdr_libs ${LIBAIRSPY_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES})
|
|
@ -0,0 +1,609 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* config.h is generated by configure. It contains the results
|
||||||
|
* of probing for features, options etc. It should be the first
|
||||||
|
* file included in your .cc file.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/assign.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/detail/endian.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/thread/thread.hpp>
|
||||||
|
|
||||||
|
#include <gnuradio/io_signature.h>
|
||||||
|
|
||||||
|
#include "airspy_source_c.h"
|
||||||
|
|
||||||
|
#include "arg_helpers.h"
|
||||||
|
|
||||||
|
using namespace boost::assign;
|
||||||
|
|
||||||
|
#define AIRSPY_THROW_ON_ERROR(ret, msg) \
|
||||||
|
if ( ret != AIRSPY_SUCCESS ) \
|
||||||
|
throw std::runtime_error( boost::str( boost::format(msg " (%d) %s") \
|
||||||
|
% ret % airspy_error_name((enum airspy_error)ret) ) );
|
||||||
|
|
||||||
|
#define AIRSPY_FUNC_STR(func, arg) \
|
||||||
|
boost::str(boost::format(func "(%d)") % arg) + " has failed"
|
||||||
|
|
||||||
|
int airspy_source_c::_usage = 0;
|
||||||
|
boost::mutex airspy_source_c::_usage_mutex;
|
||||||
|
|
||||||
|
airspy_source_c_sptr make_airspy_source_c (const std::string & args)
|
||||||
|
{
|
||||||
|
return gnuradio::get_initial_sptr(new airspy_source_c (args));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specify constraints on number of input and output streams.
|
||||||
|
* This info is used to construct the input and output signatures
|
||||||
|
* (2nd & 3rd args to gr::block's constructor). The input and
|
||||||
|
* output signatures are used by the runtime system to
|
||||||
|
* check that a valid number and type of inputs and outputs
|
||||||
|
* are connected to this block. In this case, we accept
|
||||||
|
* only 0 input and 1 output.
|
||||||
|
*/
|
||||||
|
static const int MIN_IN = 0; // mininum number of input streams
|
||||||
|
static const int MAX_IN = 0; // maximum number of input streams
|
||||||
|
static const int MIN_OUT = 1; // minimum number of output streams
|
||||||
|
static const int MAX_OUT = 1; // maximum number of output streams
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The private constructor
|
||||||
|
*/
|
||||||
|
airspy_source_c::airspy_source_c (const std::string &args)
|
||||||
|
: gr::sync_block ("airspy_source_c",
|
||||||
|
gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
|
||||||
|
gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
|
||||||
|
_dev(NULL),
|
||||||
|
_sample_rate(0),
|
||||||
|
_center_freq(0),
|
||||||
|
_freq_corr(0),
|
||||||
|
_auto_gain(false),
|
||||||
|
_lna_gain(0),
|
||||||
|
_mix_gain(0),
|
||||||
|
_vga_gain(0),
|
||||||
|
_bandwidth(0)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dict_t dict = params_to_dict(args);
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
airspy_init(); /* call only once before the first open */
|
||||||
|
|
||||||
|
_usage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dev = NULL;
|
||||||
|
ret = airspy_open( &_dev );
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to open AirSpy device")
|
||||||
|
|
||||||
|
uint8_t board_id;
|
||||||
|
ret = airspy_board_id_read( _dev, &board_id );
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to get AirSpy board id")
|
||||||
|
|
||||||
|
char version[40];
|
||||||
|
memset(version, 0, sizeof(version));
|
||||||
|
ret = airspy_version_string_read( _dev, version, sizeof(version));
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to read version string")
|
||||||
|
#if 0
|
||||||
|
read_partid_serialno_t serial_number;
|
||||||
|
ret = airspy_board_partid_serialno_read( _dev, &serial_number );
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to read serial number")
|
||||||
|
#endif
|
||||||
|
std::cerr << "Using " << airspy_board_id_name(airspy_board_id(board_id)) << " "
|
||||||
|
<< "with firmware " << version << " "
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
set_center_freq( (get_freq_range().start() + get_freq_range().stop()) / 2.0 );
|
||||||
|
set_sample_rate( get_sample_rates().start() );
|
||||||
|
set_bandwidth( 0 );
|
||||||
|
|
||||||
|
set_gain( 8 ); /* preset to a reasonable default (non-GRC use case) */
|
||||||
|
|
||||||
|
set_mix_gain( 5 ); /* preset to a reasonable default (non-GRC use case) */
|
||||||
|
|
||||||
|
set_if_gain( 0 ); /* preset to a reasonable default (non-GRC use case) */
|
||||||
|
|
||||||
|
_fifo = new boost::circular_buffer<gr_complex>(5000000);
|
||||||
|
if (!_fifo) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"Failed to allocate a sample FIFO!" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our virtual destructor.
|
||||||
|
*/
|
||||||
|
airspy_source_c::~airspy_source_c ()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
if ( airspy_is_streaming( _dev ) == AIRSPY_TRUE )
|
||||||
|
{
|
||||||
|
ret = airspy_stop_rx( _dev );
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to stop RX streaming")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = airspy_close( _dev );
|
||||||
|
AIRSPY_THROW_ON_ERROR(ret, "Failed to close AirSpy")
|
||||||
|
_dev = NULL;
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
_usage--;
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
airspy_exit(); /* call only once after last close */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fifo)
|
||||||
|
{
|
||||||
|
delete _fifo;
|
||||||
|
_fifo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int airspy_source_c::_airspy_rx_callback(airspy_transfer *transfer)
|
||||||
|
{
|
||||||
|
airspy_source_c *obj = (airspy_source_c *)transfer->ctx;
|
||||||
|
|
||||||
|
return obj->airspy_rx_callback((float *)transfer->samples, transfer->sample_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int airspy_source_c::airspy_rx_callback(void *samples, int sample_count)
|
||||||
|
{
|
||||||
|
size_t i, n_avail, to_copy, num_samples = sample_count;
|
||||||
|
float *sample = (float *)samples;
|
||||||
|
|
||||||
|
_fifo_lock.lock();
|
||||||
|
|
||||||
|
n_avail = _fifo->capacity() - _fifo->size();
|
||||||
|
to_copy = (n_avail < num_samples ? n_avail : num_samples);
|
||||||
|
|
||||||
|
for (i = 0; i < to_copy; i++ )
|
||||||
|
{
|
||||||
|
/* Push sample to the fifo */
|
||||||
|
_fifo->push_back( gr_complex( *sample, *(sample+1) ) );
|
||||||
|
|
||||||
|
/* offset to the next I+Q sample */
|
||||||
|
sample += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fifo_lock.unlock();
|
||||||
|
|
||||||
|
/* We have made some new samples available to the consumer in work() */
|
||||||
|
if (to_copy) {
|
||||||
|
//std::cerr << "+" << std::flush;
|
||||||
|
_samp_avail.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicate overrun, if neccesary */
|
||||||
|
if (to_copy < num_samples)
|
||||||
|
std::cerr << "O" << std::flush;
|
||||||
|
|
||||||
|
return 0; // TODO: return -1 on error/stop
|
||||||
|
}
|
||||||
|
|
||||||
|
bool airspy_source_c::start()
|
||||||
|
{
|
||||||
|
if ( ! _dev )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int ret = airspy_start_rx( _dev, _airspy_rx_callback, (void *)this );
|
||||||
|
if ( ret != AIRSPY_SUCCESS ) {
|
||||||
|
std::cerr << "Failed to start RX streaming (" << ret << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool airspy_source_c::stop()
|
||||||
|
{
|
||||||
|
if ( ! _dev )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int ret = airspy_stop_rx( _dev );
|
||||||
|
if ( ret != AIRSPY_SUCCESS ) {
|
||||||
|
std::cerr << "Failed to stop RX streaming (" << ret << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int airspy_source_c::work( int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items )
|
||||||
|
{
|
||||||
|
gr_complex *out = (gr_complex *)output_items[0];
|
||||||
|
|
||||||
|
bool running = false;
|
||||||
|
|
||||||
|
if ( _dev )
|
||||||
|
running = (airspy_is_streaming( _dev ) == AIRSPY_TRUE);
|
||||||
|
|
||||||
|
if ( ! running )
|
||||||
|
return WORK_DONE;
|
||||||
|
|
||||||
|
boost::unique_lock<boost::mutex> lock(_fifo_lock);
|
||||||
|
|
||||||
|
/* Wait until we have the requested number of samples */
|
||||||
|
int n_samples_avail = _fifo->size();
|
||||||
|
|
||||||
|
while (n_samples_avail < noutput_items) {
|
||||||
|
_samp_avail.wait(lock);
|
||||||
|
n_samples_avail = _fifo->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < noutput_items; ++i) {
|
||||||
|
out[i] = _fifo->at(0);
|
||||||
|
_fifo->pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::cerr << "-" << std::flush;
|
||||||
|
|
||||||
|
return noutput_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> airspy_source_c::get_devices()
|
||||||
|
{
|
||||||
|
std::vector<std::string> devices;
|
||||||
|
std::string label;
|
||||||
|
#if 0
|
||||||
|
for (unsigned int i = 0; i < 1 /* TODO: missing libairspy api */; i++) {
|
||||||
|
std::string args = "airspy=" + boost::lexical_cast< std::string >( i );
|
||||||
|
|
||||||
|
label.clear();
|
||||||
|
|
||||||
|
label = "AirSpy"; /* TODO: missing libairspy api */
|
||||||
|
|
||||||
|
boost::algorithm::trim(label);
|
||||||
|
|
||||||
|
args += ",label='" + label + "'";
|
||||||
|
devices.push_back( args );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
airspy_init(); /* call only once before the first open */
|
||||||
|
|
||||||
|
_usage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
airspy_device *dev = NULL;
|
||||||
|
ret = airspy_open(&dev);
|
||||||
|
if ( AIRSPY_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
std::string args = "airspy=0";
|
||||||
|
|
||||||
|
label = "AirSpy";
|
||||||
|
|
||||||
|
uint8_t board_id;
|
||||||
|
ret = airspy_board_id_read( dev, &board_id );
|
||||||
|
if ( AIRSPY_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
label += std::string(" ") + airspy_board_id_name(airspy_board_id(board_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
args += ",label='" + label + "'";
|
||||||
|
devices.push_back( args );
|
||||||
|
|
||||||
|
ret = airspy_close(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
_usage--;
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
airspy_exit(); /* call only once after last close */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t airspy_source_c::get_num_channels()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmosdr::meta_range_t airspy_source_c::get_sample_rates()
|
||||||
|
{
|
||||||
|
osmosdr::meta_range_t range;
|
||||||
|
|
||||||
|
range += osmosdr::range_t( 10e6 );
|
||||||
|
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_sample_rate( double rate )
|
||||||
|
{
|
||||||
|
int ret = AIRSPY_SUCCESS;
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
// ret = airspy_set_sample_rate( _dev, rate );
|
||||||
|
if ( AIRSPY_SUCCESS == ret ) {
|
||||||
|
//_sample_rate = rate;
|
||||||
|
_sample_rate = get_sample_rates().start();
|
||||||
|
} else {
|
||||||
|
AIRSPY_THROW_ON_ERROR( ret, AIRSPY_FUNC_STR( "airspy_set_sample_rate", rate ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_sample_rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_sample_rate()
|
||||||
|
{
|
||||||
|
return _sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmosdr::freq_range_t airspy_source_c::get_freq_range( size_t chan )
|
||||||
|
{
|
||||||
|
osmosdr::freq_range_t range;
|
||||||
|
|
||||||
|
range += osmosdr::range_t( 24e6, 1766e6 );
|
||||||
|
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_center_freq( double freq, size_t chan )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#define APPLY_PPM_CORR(val, ppm) ((val) * (1.0 + (ppm) * 0.000001))
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
double corr_freq = APPLY_PPM_CORR( freq, _freq_corr );
|
||||||
|
ret = airspy_set_freq( _dev, uint64_t(corr_freq) );
|
||||||
|
if ( AIRSPY_SUCCESS == ret ) {
|
||||||
|
_center_freq = freq;
|
||||||
|
} else {
|
||||||
|
AIRSPY_THROW_ON_ERROR( ret, AIRSPY_FUNC_STR( "airspy_set_freq", corr_freq ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_center_freq( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_center_freq( size_t chan )
|
||||||
|
{
|
||||||
|
return _center_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_freq_corr( double ppm, size_t chan )
|
||||||
|
{
|
||||||
|
_freq_corr = ppm;
|
||||||
|
|
||||||
|
set_center_freq( _center_freq );
|
||||||
|
|
||||||
|
return get_freq_corr( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_freq_corr( size_t chan )
|
||||||
|
{
|
||||||
|
return _freq_corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> airspy_source_c::get_gain_names( size_t chan )
|
||||||
|
{
|
||||||
|
std::vector< std::string > names;
|
||||||
|
|
||||||
|
names += "LNA";
|
||||||
|
names += "MIX";
|
||||||
|
names += "IF";
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmosdr::gain_range_t airspy_source_c::get_gain_range( size_t chan )
|
||||||
|
{
|
||||||
|
return get_gain_range( "LNA", chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
osmosdr::gain_range_t airspy_source_c::get_gain_range( const std::string & name, size_t chan )
|
||||||
|
{
|
||||||
|
if ( "LNA" == name ) {
|
||||||
|
return osmosdr::gain_range_t( 0, 15, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "MIX" == name ) {
|
||||||
|
return osmosdr::gain_range_t( 0, 15, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "IF" == name ) {
|
||||||
|
return osmosdr::gain_range_t( 0, 15, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return osmosdr::gain_range_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool airspy_source_c::set_gain_mode( bool automatic, size_t chan )
|
||||||
|
{
|
||||||
|
_auto_gain = automatic;
|
||||||
|
|
||||||
|
return get_gain_mode(chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool airspy_source_c::get_gain_mode( size_t chan )
|
||||||
|
{
|
||||||
|
return _auto_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_gain( double gain, size_t chan )
|
||||||
|
{
|
||||||
|
int ret = AIRSPY_SUCCESS;
|
||||||
|
osmosdr::gain_range_t gains = get_gain_range( "LNA", chan );
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
double clip_gain = gains.clip( gain, true );
|
||||||
|
uint8_t value = clip_gain;
|
||||||
|
|
||||||
|
ret = airspy_set_lna_gain( _dev, value );
|
||||||
|
if ( AIRSPY_SUCCESS == ret ) {
|
||||||
|
_lna_gain = clip_gain;
|
||||||
|
} else {
|
||||||
|
// AIRSPY_THROW_ON_ERROR( ret, AIRSPY_FUNC_STR( "airspy_set_lna_gain", value ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _lna_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_gain( double gain, const std::string & name, size_t chan)
|
||||||
|
{
|
||||||
|
if ( "LNA" == name ) {
|
||||||
|
return set_gain( gain, chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "MIX" == name ) {
|
||||||
|
return set_mix_gain( gain, chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "IF" == name ) {
|
||||||
|
return set_if_gain( gain, chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_gain( gain, chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_gain( size_t chan )
|
||||||
|
{
|
||||||
|
return _lna_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_gain( const std::string & name, size_t chan )
|
||||||
|
{
|
||||||
|
if ( "LNA" == name ) {
|
||||||
|
return get_gain( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "MIX" == name ) {
|
||||||
|
return _mix_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( "IF" == name ) {
|
||||||
|
return _vga_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_gain( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_mix_gain(double gain, size_t chan)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
osmosdr::gain_range_t gains = get_gain_range( "MIX", chan );
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
double clip_gain = gains.clip( gain, true );
|
||||||
|
uint8_t value = clip_gain;
|
||||||
|
|
||||||
|
ret = airspy_set_mixer_gain( _dev, value );
|
||||||
|
if ( AIRSPY_SUCCESS == ret ) {
|
||||||
|
_mix_gain = clip_gain;
|
||||||
|
} else {
|
||||||
|
// AIRSPY_THROW_ON_ERROR( ret, AIRSPY_FUNC_STR( "airspy_set_mixer_gain", value ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _mix_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_if_gain(double gain, size_t chan)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
osmosdr::gain_range_t gains = get_gain_range( "MIX", chan );
|
||||||
|
|
||||||
|
if (_dev) {
|
||||||
|
double clip_gain = gains.clip( gain, true );
|
||||||
|
uint8_t value = clip_gain;
|
||||||
|
|
||||||
|
ret = airspy_set_vga_gain( _dev, value );
|
||||||
|
if ( AIRSPY_SUCCESS == ret ) {
|
||||||
|
_vga_gain = clip_gain;
|
||||||
|
} else {
|
||||||
|
// AIRSPY_THROW_ON_ERROR( ret, AIRSPY_FUNC_STR( "airspy_set_vga_gain", value ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _vga_gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector< std::string > airspy_source_c::get_antennas( size_t chan )
|
||||||
|
{
|
||||||
|
std::vector< std::string > antennas;
|
||||||
|
|
||||||
|
antennas += get_antenna( chan );
|
||||||
|
|
||||||
|
return antennas;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string airspy_source_c::set_antenna( const std::string & antenna, size_t chan )
|
||||||
|
{
|
||||||
|
return get_antenna( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string airspy_source_c::get_antenna( size_t chan )
|
||||||
|
{
|
||||||
|
return "RX";
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::set_bandwidth( double bandwidth, size_t chan )
|
||||||
|
{
|
||||||
|
return get_bandwidth( chan );
|
||||||
|
}
|
||||||
|
|
||||||
|
double airspy_source_c::get_bandwidth( size_t chan )
|
||||||
|
{
|
||||||
|
return 10e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmosdr::freq_range_t airspy_source_c::get_bandwidth_range( size_t chan )
|
||||||
|
{
|
||||||
|
osmosdr::freq_range_t bandwidths;
|
||||||
|
|
||||||
|
bandwidths += osmosdr::range_t( get_bandwidth( chan ) );
|
||||||
|
|
||||||
|
return bandwidths;
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GNU Radio
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDED_AIRSPY_SOURCE_C_H
|
||||||
|
#define INCLUDED_AIRSPY_SOURCE_C_H
|
||||||
|
|
||||||
|
#include <boost/circular_buffer.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
#include <libairspy/airspy.h>
|
||||||
|
|
||||||
|
#include "source_iface.h"
|
||||||
|
|
||||||
|
class airspy_source_c;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use boost::shared_ptr's instead of raw pointers for all access
|
||||||
|
* to gr::blocks (and many other data structures). The shared_ptr gets
|
||||||
|
* us transparent reference counting, which greatly simplifies storage
|
||||||
|
* management issues. This is especially helpful in our hybrid
|
||||||
|
* C++ / Python system.
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
|
||||||
|
*
|
||||||
|
* As a convention, the _sptr suffix indicates a boost::shared_ptr
|
||||||
|
*/
|
||||||
|
typedef boost::shared_ptr<airspy_source_c> airspy_source_c_sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return a shared_ptr to a new instance of airspy_source_c.
|
||||||
|
*
|
||||||
|
* To avoid accidental use of raw pointers, airspy_source_c's
|
||||||
|
* constructor is private. make_airspy_source_c is the public
|
||||||
|
* interface for creating new instances.
|
||||||
|
*/
|
||||||
|
airspy_source_c_sptr make_airspy_source_c (const std::string & args = "");
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Provides a stream of complex samples.
|
||||||
|
* \ingroup block
|
||||||
|
*/
|
||||||
|
class airspy_source_c :
|
||||||
|
public gr::sync_block,
|
||||||
|
public source_iface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The friend declaration allows make_airspy_source_c to
|
||||||
|
// access the private constructor.
|
||||||
|
|
||||||
|
friend airspy_source_c_sptr make_airspy_source_c (const std::string & args);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Provides a stream of complex samples.
|
||||||
|
*/
|
||||||
|
airspy_source_c (const std::string & args); // private constructor
|
||||||
|
|
||||||
|
public:
|
||||||
|
~airspy_source_c (); // public destructor
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool stop();
|
||||||
|
|
||||||
|
int work( int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items );
|
||||||
|
|
||||||
|
static std::vector< std::string > get_devices();
|
||||||
|
|
||||||
|
size_t get_num_channels( void );
|
||||||
|
|
||||||
|
osmosdr::meta_range_t get_sample_rates( void );
|
||||||
|
double set_sample_rate( double rate );
|
||||||
|
double get_sample_rate( void );
|
||||||
|
|
||||||
|
osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
|
||||||
|
double set_center_freq( double freq, size_t chan = 0 );
|
||||||
|
double get_center_freq( size_t chan = 0 );
|
||||||
|
double set_freq_corr( double ppm, size_t chan = 0 );
|
||||||
|
double get_freq_corr( size_t chan = 0 );
|
||||||
|
|
||||||
|
std::vector<std::string> get_gain_names( size_t chan = 0 );
|
||||||
|
osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
|
||||||
|
osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
|
||||||
|
bool set_gain_mode( bool automatic, size_t chan = 0 );
|
||||||
|
bool get_gain_mode( size_t chan = 0 );
|
||||||
|
double set_gain( double gain, size_t chan = 0 );
|
||||||
|
double set_gain( double gain, const std::string & name, size_t chan = 0 );
|
||||||
|
double get_gain( size_t chan = 0 );
|
||||||
|
double get_gain( const std::string & name, size_t chan = 0 );
|
||||||
|
|
||||||
|
double set_mix_gain(double gain, size_t chan = 0 );
|
||||||
|
double set_if_gain( double gain, size_t chan = 0 );
|
||||||
|
|
||||||
|
std::vector< std::string > get_antennas( size_t chan = 0 );
|
||||||
|
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
||||||
|
std::string get_antenna( size_t chan = 0 );
|
||||||
|
|
||||||
|
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
||||||
|
double get_bandwidth( size_t chan = 0 );
|
||||||
|
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _airspy_rx_callback(airspy_transfer* transfer);
|
||||||
|
int airspy_rx_callback(void *samples, int sample_count);
|
||||||
|
|
||||||
|
static int _usage;
|
||||||
|
static boost::mutex _usage_mutex;
|
||||||
|
|
||||||
|
airspy_device *_dev;
|
||||||
|
|
||||||
|
boost::circular_buffer<gr_complex> *_fifo;
|
||||||
|
boost::mutex _fifo_lock;
|
||||||
|
boost::condition_variable _samp_avail;
|
||||||
|
|
||||||
|
double _sample_rate;
|
||||||
|
double _center_freq;
|
||||||
|
double _freq_corr;
|
||||||
|
bool _auto_gain;
|
||||||
|
double _lna_gain;
|
||||||
|
double _mix_gain;
|
||||||
|
double _vga_gain;
|
||||||
|
double _bandwidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* INCLUDED_AIRSPY_SOURCE_C_H */
|
|
@ -102,7 +102,7 @@ struct is_nchan_argument
|
||||||
{
|
{
|
||||||
bool operator ()(const std::string &str)
|
bool operator ()(const std::string &str)
|
||||||
{
|
{
|
||||||
return str.find("nchan=") == 0;
|
return str.find("numchan=") == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ inline gr::io_signature::sptr args_to_io_signature( const std::string &args )
|
||||||
|
|
||||||
BOOST_FOREACH( std::string arg, arg_list )
|
BOOST_FOREACH( std::string arg, arg_list )
|
||||||
{
|
{
|
||||||
if ( arg.find( "nchan=" ) == 0 ) // try to parse global nchan value
|
if ( arg.find( "numchan=" ) == 0 ) // try to parse global nchan value
|
||||||
{
|
{
|
||||||
pair_t pair = param_to_pair( arg );
|
pair_t pair = param_to_pair( arg );
|
||||||
max_nchan = boost::lexical_cast<size_t>( pair.second );
|
max_nchan = boost::lexical_cast<size_t>( pair.second );
|
||||||
|
|
|
@ -37,4 +37,3 @@ set(bladerf_srcs
|
||||||
########################################################################
|
########################################################################
|
||||||
list(APPEND gr_osmosdr_srcs ${bladerf_srcs})
|
list(APPEND gr_osmosdr_srcs ${bladerf_srcs})
|
||||||
list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES})
|
list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES})
|
||||||
|
|
||||||
|
|
|
@ -36,55 +36,277 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/assign.hpp>
|
#include <boost/assign.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include "bladerf_common.h"
|
#include "bladerf_common.h"
|
||||||
|
|
||||||
#define BLADERF_FIFO_SIZE_ENV "BLADERF_SAMPLE_FIFO_SIZE"
|
#define NUM_BUFFERS 32
|
||||||
|
#define NUM_SAMPLES_PER_BUFFER (4 * 1024)
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
bladerf_common::bladerf_common() : running(true)
|
boost::mutex bladerf_common::_devs_mutex;
|
||||||
|
std::list<boost::weak_ptr<struct bladerf> > bladerf_common::_devs;
|
||||||
|
|
||||||
|
bladerf_common::bladerf_common() : _is_running(false) {}
|
||||||
|
bladerf_common::~bladerf_common() {}
|
||||||
|
|
||||||
|
bladerf_sptr bladerf_common:: get_cached_device(struct bladerf_devinfo devinfo)
|
||||||
{
|
{
|
||||||
const char *env_fifo_size;
|
/* Lock to _devs must be aquired by caller */
|
||||||
size_t fifo_size;
|
BOOST_FOREACH( boost::weak_ptr<struct bladerf> dev, _devs )
|
||||||
|
{
|
||||||
|
struct bladerf_devinfo other_devinfo;
|
||||||
|
|
||||||
/* 1 Sample = i,q (2 int16_t's) */
|
int rv = bladerf_get_devinfo(bladerf_sptr(dev).get(), &other_devinfo);
|
||||||
this->raw_sample_buf = new int16_t[2 * BLADERF_SAMPLE_BLOCK_SIZE];
|
if (rv < 0)
|
||||||
if (!raw_sample_buf) {
|
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) +
|
"Failed to get devinfo for cached device.");
|
||||||
" has failed to allocate a raw sample buffer!" );
|
|
||||||
}
|
|
||||||
|
|
||||||
env_fifo_size = getenv(BLADERF_FIFO_SIZE_ENV);
|
if (bladerf_devinfo_matches(&devinfo, &other_devinfo)) {
|
||||||
fifo_size = BLADERF_SAMPLE_FIFO_SIZE;
|
return bladerf_sptr(dev);
|
||||||
|
|
||||||
if (env_fifo_size != NULL) {
|
|
||||||
try {
|
|
||||||
fifo_size = boost::lexical_cast<size_t>(env_fifo_size);
|
|
||||||
} catch (const boost::bad_lexical_cast &e) {
|
|
||||||
std::cerr << "Warning: \"" << BLADERF_FIFO_SIZE_ENV
|
|
||||||
<< "\" is invalid" << "... defaulting to "
|
|
||||||
<< fifo_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fifo_size < BLADERF_SAMPLE_FIFO_MIN_SIZE) {
|
|
||||||
fifo_size = BLADERF_SAMPLE_FIFO_MIN_SIZE;
|
|
||||||
std::cerr << "Warning: \"" << BLADERF_FIFO_SIZE_ENV
|
|
||||||
<< "\" is too small" << "... defaulting to "
|
|
||||||
<< BLADERF_SAMPLE_FIFO_MIN_SIZE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->sample_fifo = new boost::circular_buffer<gr_complex>(fifo_size);
|
return bladerf_sptr();
|
||||||
if (!this->sample_fifo)
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) +
|
|
||||||
" has failed to allocate a sample FIFO!" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bladerf_common::~bladerf_common()
|
void bladerf_common::close(void* dev)
|
||||||
{
|
{
|
||||||
delete[] this->raw_sample_buf;
|
boost::unique_lock<boost::mutex> lock(_devs_mutex);
|
||||||
delete this->sample_fifo;
|
|
||||||
|
std::list<boost::weak_ptr<struct bladerf> >::iterator it;
|
||||||
|
for (it = _devs.begin(); it != _devs.end(); ++it)
|
||||||
|
if ( (*it).expired() == 0 )
|
||||||
|
_devs.erase(it);
|
||||||
|
|
||||||
|
bladerf_close((struct bladerf *)dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
bladerf_sptr bladerf_common::open(const std::string &device_name)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
struct bladerf *raw_dev;
|
||||||
|
struct bladerf_devinfo devinfo;
|
||||||
|
|
||||||
|
boost::unique_lock<boost::mutex> lock(_devs_mutex);
|
||||||
|
|
||||||
|
rv = bladerf_get_devinfo_from_str(device_name.c_str(), &devinfo);
|
||||||
|
if (rv < 0)
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||||
|
"Failed to get devinfo for '" + device_name + "'");
|
||||||
|
|
||||||
|
bladerf_sptr cached_dev = get_cached_device(devinfo);
|
||||||
|
|
||||||
|
if (cached_dev)
|
||||||
|
return cached_dev;
|
||||||
|
|
||||||
|
rv = bladerf_open_with_devinfo(&raw_dev, &devinfo);
|
||||||
|
if (rv < 0)
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||||
|
"Failed to open device for '" + device_name + "'");
|
||||||
|
|
||||||
|
bladerf_sptr dev = bladerf_sptr(raw_dev, bladerf_common::close);
|
||||||
|
|
||||||
|
_devs.push_back(boost::weak_ptr<struct bladerf>(dev));
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_common::set_loopback_mode(const std::string &loopback)
|
||||||
|
{
|
||||||
|
bladerf_loopback mode;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (loopback == "bb_txlpf_rxvga2") {
|
||||||
|
mode = BLADERF_LB_BB_TXLPF_RXVGA2;
|
||||||
|
} else if (loopback == "bb_txlpf_rxlpf") {
|
||||||
|
mode = BLADERF_LB_BB_TXLPF_RXLPF;
|
||||||
|
} else if (loopback == "bb_txvga1_rxvga2") {
|
||||||
|
mode = BLADERF_LB_BB_TXVGA1_RXVGA2;
|
||||||
|
} else if (loopback == "bb_txvga1_rxlpf") {
|
||||||
|
mode = BLADERF_LB_BB_TXVGA1_RXLPF;
|
||||||
|
} else if (loopback == "rf_lna1") {
|
||||||
|
mode = BLADERF_LB_RF_LNA1;
|
||||||
|
} else if (loopback == "rf_lna2") {
|
||||||
|
mode = BLADERF_LB_RF_LNA2;
|
||||||
|
} else if (loopback == "rf_lna3") {
|
||||||
|
mode = BLADERF_LB_RF_LNA3;
|
||||||
|
} else if (loopback == "none") {
|
||||||
|
mode = BLADERF_LB_NONE;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error( _pfx + "Invalid loopback mode:" + loopback );
|
||||||
|
}
|
||||||
|
|
||||||
|
status = bladerf_set_loopback( _dev.get(), mode);
|
||||||
|
if ( status != 0 ) {
|
||||||
|
throw std::runtime_error( _pfx + "Failed to set loopback mode: " +
|
||||||
|
bladerf_strerror(status) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_common::set_verbosity(const std::string &verbosity)
|
||||||
|
{
|
||||||
|
bladerf_log_level l;
|
||||||
|
|
||||||
|
if (verbosity == "verbose") {
|
||||||
|
l = BLADERF_LOG_LEVEL_VERBOSE;
|
||||||
|
} else if (verbosity == "debug") {
|
||||||
|
l = BLADERF_LOG_LEVEL_DEBUG;
|
||||||
|
} else if (verbosity == "info") {
|
||||||
|
l = BLADERF_LOG_LEVEL_INFO;
|
||||||
|
} else if (verbosity == "warning") {
|
||||||
|
l = BLADERF_LOG_LEVEL_WARNING;
|
||||||
|
} else if (verbosity == "error") {
|
||||||
|
l = BLADERF_LOG_LEVEL_ERROR;
|
||||||
|
} else if (verbosity == "critical") {
|
||||||
|
l = BLADERF_LOG_LEVEL_CRITICAL;
|
||||||
|
} else if (verbosity == "silent") {
|
||||||
|
l = BLADERF_LOG_LEVEL_SILENT;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error( _pfx + "Invalid log level: " + verbosity );
|
||||||
|
}
|
||||||
|
|
||||||
|
bladerf_log_set_verbosity(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_common::init(dict_t &dict, const char *type)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int device_number = 0;
|
||||||
|
std::string device_name;
|
||||||
|
struct bladerf_version ver;
|
||||||
|
char serial[BLADERF_SERIAL_LENGTH];
|
||||||
|
|
||||||
|
_pfx = std::string("[bladeRF ") + std::string(type) + std::string("] ");
|
||||||
|
|
||||||
|
if (dict.count("bladerf"))
|
||||||
|
{
|
||||||
|
std::string value = dict["bladerf"];
|
||||||
|
if ( value.length() )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
device_number = boost::lexical_cast< unsigned int >( value );
|
||||||
|
} catch ( std::exception &ex ) {
|
||||||
|
throw std::runtime_error( _pfx + "Failed to use '" + value +
|
||||||
|
"' as device number: " + ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
|
||||||
|
|
||||||
|
try {
|
||||||
|
_dev = open(device_name);
|
||||||
|
} catch(...) {
|
||||||
|
throw std::runtime_error( _pfx + "Failed to open bladeRF device " +
|
||||||
|
device_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load an FPGA */
|
||||||
|
if ( dict.count("fpga") )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( dict.count("fpga-reload") == 0 &&
|
||||||
|
bladerf_is_fpga_configured( _dev.get() ) == 1 ) {
|
||||||
|
|
||||||
|
std::cerr << _pfx << "FPGA is already loaded. Set fpga-reload=1 "
|
||||||
|
<< "to force a reload." << std::endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::string fpga = dict["fpga"];
|
||||||
|
|
||||||
|
std::cerr << _pfx << "Loading FPGA bitstream " << fpga << "..." << std::endl;
|
||||||
|
ret = bladerf_load_fpga( _dev.get(), fpga.c_str() );
|
||||||
|
if ( ret != 0 )
|
||||||
|
std::cerr << _pfx << "bladerf_load_fpga has failed with " << ret << std::endl;
|
||||||
|
else
|
||||||
|
std::cerr << _pfx << "The FPGA bitstream has been successfully loaded." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bladerf_is_fpga_configured( _dev.get() ) != 1 )
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << _pfx << "The FPGA is not configured! "
|
||||||
|
<< "Provide device argument fpga=/path/to/the/bitstream.rbf to load it.";
|
||||||
|
|
||||||
|
throw std::runtime_error( oss.str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dict.count("loopback") )
|
||||||
|
set_loopback_mode( dict["loopback"] );
|
||||||
|
else
|
||||||
|
set_loopback_mode( "none" );
|
||||||
|
|
||||||
|
if ( dict.count("verbosity") )
|
||||||
|
set_verbosity( dict["verbosity"] );
|
||||||
|
|
||||||
|
|
||||||
|
/* Show some info about the device we've opened */
|
||||||
|
std::cerr << _pfx << "Using nuand LLC bladeRF #" << device_number;
|
||||||
|
|
||||||
|
if ( bladerf_get_serial( _dev.get(), serial ) == 0 )
|
||||||
|
{
|
||||||
|
std::string strser(serial);
|
||||||
|
|
||||||
|
if ( strser.length() == 32 )
|
||||||
|
strser.replace( 4, 24, "..." );
|
||||||
|
|
||||||
|
std::cerr << " SN " << strser;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bladerf_fw_version( _dev.get(), &ver ) == 0 )
|
||||||
|
std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch;
|
||||||
|
|
||||||
|
if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 )
|
||||||
|
std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch;
|
||||||
|
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
/* Initialize buffer and sample configuration */
|
||||||
|
_num_buffers = 0;
|
||||||
|
if (dict.count("buffers")) {
|
||||||
|
_num_buffers = boost::lexical_cast< size_t >( dict["buffers"] );
|
||||||
|
}
|
||||||
|
|
||||||
|
_samples_per_buffer = 0;
|
||||||
|
if (dict.count("buflen")) {
|
||||||
|
_samples_per_buffer = boost::lexical_cast< size_t >( dict["buflen"] );
|
||||||
|
}
|
||||||
|
|
||||||
|
_num_transfers = 0;
|
||||||
|
if (dict.count("transfers")) {
|
||||||
|
_num_transfers = boost::lexical_cast< size_t >( dict["transfers"] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Require value to be >= 2 so we can ensure we have twice as many
|
||||||
|
* buffers as transfers */
|
||||||
|
if (_num_buffers <= 1) {
|
||||||
|
_num_buffers = NUM_BUFFERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == _samples_per_buffer) {
|
||||||
|
_samples_per_buffer = NUM_SAMPLES_PER_BUFFER;
|
||||||
|
} else {
|
||||||
|
if (_samples_per_buffer < 1024 || _samples_per_buffer % 1024 != 0) {
|
||||||
|
|
||||||
|
/* 0 likely implies the user did not specify this, so don't warn */
|
||||||
|
if (_samples_per_buffer != 0 ) {
|
||||||
|
std::cerr << _pfx << "Invalid \"buflen\" value. "
|
||||||
|
<< "A multiple of 1024 is required. Defaulting to "
|
||||||
|
<< NUM_SAMPLES_PER_BUFFER << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
_samples_per_buffer = NUM_SAMPLES_PER_BUFFER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (_num_transfers == 0 || _num_transfers > (_num_buffers / 2)) {
|
||||||
|
_num_transfers = _num_buffers / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osmosdr::freq_range_t bladerf_common::freq_range()
|
osmosdr::freq_range_t bladerf_common::freq_range()
|
||||||
|
@ -116,33 +338,41 @@ osmosdr::freq_range_t bladerf_common::filter_bandwidths()
|
||||||
2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
|
2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
|
||||||
|
|
||||||
BOOST_FOREACH( double half_bw, half_bandwidths )
|
BOOST_FOREACH( double half_bw, half_bandwidths )
|
||||||
bandwidths += osmosdr::range_t( half_bw * 2.e6 );
|
bandwidths += osmosdr::range_t( half_bw * 2e6 );
|
||||||
|
|
||||||
return bandwidths;
|
return bandwidths;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< std::string > bladerf_common::devices()
|
std::vector< std::string > bladerf_common::devices()
|
||||||
{
|
{
|
||||||
struct ::bladerf_devinfo *devices;
|
struct bladerf_devinfo *devices;
|
||||||
ssize_t n_devices;
|
ssize_t n_devices;
|
||||||
std::vector< std::string > ret;
|
std::vector< std::string > ret;
|
||||||
|
|
||||||
n_devices = bladerf_get_device_list(&devices);
|
n_devices = bladerf_get_device_list(&devices);
|
||||||
|
|
||||||
if (n_devices > 0) {
|
if (n_devices > 0)
|
||||||
for (ssize_t i = 0; i < n_devices; i++) {
|
{
|
||||||
|
for (ssize_t i = 0; i < n_devices; i++)
|
||||||
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
std::string dev(devices[i].path);
|
std::string serial(devices[i].serial);
|
||||||
|
|
||||||
s << "bladerf=" << dev.substr(dev.find_first_of("01234567890")) << ","
|
s << "bladerf=" << devices[i].instance << ","
|
||||||
<< "label='nuand bladeRF SN " << std::setfill('0') << std::setw(16)
|
<< "label='nuand bladeRF";
|
||||||
<< devices[i].serial << "'";
|
|
||||||
|
if ( serial.length() == 32 )
|
||||||
|
serial.replace( 4, 24, "..." );
|
||||||
|
|
||||||
|
if ( serial.length() )
|
||||||
|
s << " SN " << serial;
|
||||||
|
|
||||||
|
s << "'";
|
||||||
|
|
||||||
ret.push_back(s.str());
|
ret.push_back(s.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bladerf_free_device_list(devices, n_devices);
|
bladerf_free_device_list(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -150,12 +380,83 @@ std::vector< std::string > bladerf_common::devices()
|
||||||
|
|
||||||
bool bladerf_common::is_running()
|
bool bladerf_common::is_running()
|
||||||
{
|
{
|
||||||
boost::shared_lock<boost::shared_mutex> lock(this->state_lock);
|
boost::shared_lock<boost::shared_mutex> lock(_state_lock);
|
||||||
return this->running;
|
|
||||||
|
return _is_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bladerf_common::set_running(bool is_running)
|
void bladerf_common::set_running( bool is_running )
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::shared_mutex> lock(this->state_lock);
|
boost::unique_lock<boost::shared_mutex> lock(_state_lock);
|
||||||
this->running = is_running;
|
|
||||||
|
_is_running = is_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bladerf_common::set_sample_rate( bladerf_module module, double rate )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct bladerf_rational_rate rational_rate, actual;
|
||||||
|
|
||||||
|
rational_rate.integer = (uint32_t)rate;
|
||||||
|
rational_rate.den = 10000;
|
||||||
|
rational_rate.num = (rate - rational_rate.integer) * rational_rate.den;
|
||||||
|
|
||||||
|
status = bladerf_set_rational_sample_rate( _dev.get(), module,
|
||||||
|
&rational_rate, &actual );
|
||||||
|
|
||||||
|
if ( status != 0 ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"Failed to set integer rate:" +
|
||||||
|
std::string(bladerf_strerror(status)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual.integer + actual.num / (double)actual.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bladerf_common::get_sample_rate( bladerf_module module )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
double ret = 0.0;
|
||||||
|
struct bladerf_rational_rate rate;
|
||||||
|
|
||||||
|
|
||||||
|
status = bladerf_get_rational_sample_rate( _dev.get(), module, &rate );
|
||||||
|
|
||||||
|
if ( status != 0 ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) +
|
||||||
|
"Failed to get sample rate:" +
|
||||||
|
std::string(bladerf_strerror(status)) );
|
||||||
|
} else {
|
||||||
|
ret = rate.integer + rate.num / (double)rate.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bladerf_common::set_dc_offset(bladerf_module module, const std::complex<double> &offset, size_t chan)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int16_t val_i, val_q;
|
||||||
|
|
||||||
|
val_i = (int16_t)(offset.real() * DCOFF_SCALE);
|
||||||
|
val_q = (int16_t)(offset.imag() * DCOFF_SCALE);
|
||||||
|
|
||||||
|
ret = bladerf_set_correction(_dev.get(), module, BLADERF_CORR_LMS_DCOFF_I, val_i);
|
||||||
|
ret |= bladerf_set_correction(_dev.get(), module, BLADERF_CORR_LMS_DCOFF_Q, val_q);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bladerf_common::set_iq_balance(bladerf_module module, const std::complex<double> &balance, size_t chan)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int16_t val_gain, val_phase;
|
||||||
|
|
||||||
|
val_gain = (int16_t)(balance.real() * GAIN_SCALE);
|
||||||
|
val_phase = (int16_t)(balance.imag() * PHASE_SCALE);
|
||||||
|
|
||||||
|
ret = bladerf_set_correction(_dev.get(), module, BLADERF_CORR_FPGA_GAIN, val_gain);
|
||||||
|
ret |= bladerf_set_correction(_dev.get(), module, BLADERF_CORR_FPGA_PHASE, val_phase);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,33 +28,39 @@
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/shared_mutex.hpp>
|
#include <boost/thread/shared_mutex.hpp>
|
||||||
#include <boost/thread/condition_variable.hpp>
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <boost/assign.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
#include <gnuradio/gr_complex.h>
|
#include <gnuradio/gr_complex.h>
|
||||||
|
|
||||||
#include <libbladeRF.h>
|
#include <libbladeRF.h>
|
||||||
|
|
||||||
#include "osmosdr/ranges.h"
|
#include "osmosdr/ranges.h"
|
||||||
|
#include "arg_helpers.h"
|
||||||
|
|
||||||
/* We currently read/write 1024 samples (pairs of 16-bit signed ints) */
|
/* We currently read/write 1024 samples (pairs of 16-bit signed ints) */
|
||||||
#define BLADERF_SAMPLE_BLOCK_SIZE (1024)
|
#define BLADERF_SAMPLE_BLOCK_SIZE (1024)
|
||||||
|
|
||||||
/*
|
typedef boost::shared_ptr<struct bladerf> bladerf_sptr;
|
||||||
* Default size of sample FIFO, in entries.
|
|
||||||
* This can be overridden by the environment variable BLADERF_SAMPLE_FIFO_SIZE.
|
|
||||||
*/
|
|
||||||
#ifndef BLADERF_SAMPLE_FIFO_SIZE
|
|
||||||
# define BLADERF_SAMPLE_FIFO_SIZE (2 * 1024 * 1024)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BLADERF_SAMPLE_FIFO_MIN_SIZE (3 * BLADERF_SAMPLE_BLOCK_SIZE)
|
|
||||||
|
|
||||||
class bladerf_common
|
class bladerf_common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bladerf_common();
|
bladerf_common();
|
||||||
~bladerf_common();
|
virtual ~bladerf_common();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/* Handle initialized and parameters common to both source & sink */
|
||||||
|
void init(dict_t &dict, const char *type);
|
||||||
|
|
||||||
|
double set_sample_rate(bladerf_module module, double rate);
|
||||||
|
double get_sample_rate(bladerf_module module);
|
||||||
|
|
||||||
|
int set_dc_offset(bladerf_module module, const std::complex<double> &offset, size_t chan);
|
||||||
|
int set_iq_balance(bladerf_module module, const std::complex<double> &balance, size_t chan);
|
||||||
|
|
||||||
osmosdr::freq_range_t freq_range();
|
osmosdr::freq_range_t freq_range();
|
||||||
osmosdr::meta_range_t sample_rates();
|
osmosdr::meta_range_t sample_rates();
|
||||||
osmosdr::freq_range_t filter_bandwidths();
|
osmosdr::freq_range_t filter_bandwidths();
|
||||||
|
@ -64,15 +70,42 @@ protected:
|
||||||
bool is_running();
|
bool is_running();
|
||||||
void set_running(bool is_running);
|
void set_running(bool is_running);
|
||||||
|
|
||||||
bladerf *dev;
|
bladerf_sptr _dev;
|
||||||
|
|
||||||
|
void **_buffers;
|
||||||
|
struct bladerf_stream *_stream;
|
||||||
|
size_t _num_buffers;
|
||||||
|
size_t _buf_index;
|
||||||
|
size_t _samples_per_buffer;
|
||||||
|
size_t _num_transfers;
|
||||||
|
|
||||||
|
gr::thread::thread _thread;
|
||||||
|
|
||||||
|
osmosdr::gain_range_t _vga1_range;
|
||||||
|
osmosdr::gain_range_t _vga2_range;
|
||||||
|
|
||||||
|
std::string _pfx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BladeRF IQ correction parameters
|
||||||
|
*/
|
||||||
|
static const int16_t DCOFF_SCALE = 2048;
|
||||||
|
static const int16_t GAIN_SCALE = 4096;
|
||||||
|
static const int16_t PHASE_SCALE = 4096;
|
||||||
|
|
||||||
int16_t *raw_sample_buf;
|
|
||||||
boost::circular_buffer<gr_complex> *sample_fifo;
|
|
||||||
boost::mutex sample_fifo_lock;
|
|
||||||
boost::condition_variable samples_available;
|
|
||||||
private:
|
private:
|
||||||
bool running;
|
void set_verbosity(const std::string &verbosity);
|
||||||
boost::shared_mutex state_lock;
|
void set_loopback_mode(const std::string &loopback);
|
||||||
|
bladerf_sptr open(const std::string &device_name);
|
||||||
|
|
||||||
|
bool _is_running;
|
||||||
|
boost::shared_mutex _state_lock;
|
||||||
|
|
||||||
|
static boost::mutex _devs_mutex;
|
||||||
|
static std::list<boost::weak_ptr<struct bladerf> > _devs;
|
||||||
|
|
||||||
|
static bladerf_sptr get_cached_device(struct bladerf_devinfo devinfo);
|
||||||
|
static void close(void *dev); /* called by shared_ptr */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,96 +72,22 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
|
||||||
gr::io_signature::make (MIN_IN, MAX_IN, sizeof (gr_complex)),
|
gr::io_signature::make (MIN_IN, MAX_IN, sizeof (gr_complex)),
|
||||||
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
unsigned int device_number = 0;
|
|
||||||
std::string device_name;
|
|
||||||
|
|
||||||
dict_t dict = params_to_dict(args);
|
dict_t dict = params_to_dict(args);
|
||||||
|
|
||||||
if (dict.count("bladerf"))
|
/* Perform src/sink agnostic initializations */
|
||||||
{
|
init(dict, "source");
|
||||||
std::string value = dict["bladerf"];
|
|
||||||
if ( value.length() )
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
device_number = boost::lexical_cast< unsigned int >( value );
|
|
||||||
} catch ( std::exception &ex ) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"Failed to use '" + value + "' as device number: " + ex.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
device_name = boost::str(boost::format( "/dev/bladerf%d" ) % device_number);
|
|
||||||
|
|
||||||
/* Open a handle to the device */
|
|
||||||
this->dev = bladerf_open( device_name.c_str() );
|
|
||||||
if( NULL == this->dev ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"failed to open bladeRF device " + device_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dict.count("fpga"))
|
|
||||||
{
|
|
||||||
std::string fpga = dict["fpga"];
|
|
||||||
|
|
||||||
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
|
|
||||||
ret = bladerf_load_fpga( this->dev, fpga.c_str() );
|
|
||||||
if ( ret != 0 )
|
|
||||||
std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl;
|
|
||||||
else
|
|
||||||
std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dict.count("fw"))
|
|
||||||
{
|
|
||||||
std::string fw = dict["fw"];
|
|
||||||
|
|
||||||
std::cerr << "Flashing firmware image " << fw << "..., "
|
|
||||||
<< "DO NOT INTERRUPT!"
|
|
||||||
<< std::endl;
|
|
||||||
ret = bladerf_flash_firmware( this->dev, fw.c_str() );
|
|
||||||
if ( ret != 0 )
|
|
||||||
std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
|
|
||||||
else
|
|
||||||
std::cerr << "The firmare has been successfully flashed, "
|
|
||||||
<< "please power cycle the bladeRF before using it."
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "Using nuand LLC bladeRF #" << device_number;
|
|
||||||
|
|
||||||
u_int64_t serial;
|
|
||||||
if ( bladerf_get_serial( this->dev, &serial ) == 0 )
|
|
||||||
std::cerr << " SN " << std::setfill('0') << std::setw(16) << serial;
|
|
||||||
|
|
||||||
unsigned int major, minor;
|
|
||||||
if ( bladerf_get_fw_version( this->dev, &major, &minor) == 0 )
|
|
||||||
std::cerr << " FW v" << major << "." << minor;
|
|
||||||
|
|
||||||
if ( bladerf_get_fpga_version( this->dev, &major, &minor) == 0 )
|
|
||||||
std::cerr << " FPGA v" << major << "." << minor;
|
|
||||||
|
|
||||||
std::cerr << std::endl;
|
|
||||||
|
|
||||||
if ( bladerf_is_fpga_configured( this->dev ) != 1 )
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: The FPGA is not configured! "
|
|
||||||
<< "Use the device argument fpga=/path/to/the/bitstream.rbf to load it."
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the range of VGA1, VGA1GAINT[7:0] */
|
/* Set the range of VGA1, VGA1GAINT[7:0] */
|
||||||
this->vga1_range = osmosdr::gain_range_t( -35, -4, 1 );
|
_vga1_range = osmosdr::gain_range_t( -35, -4, 1 );
|
||||||
|
|
||||||
/* Set the range of VGA2, VGA2GAIN[4:0] */
|
/* Set the range of VGA2, VGA2GAIN[4:0] */
|
||||||
this->vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
|
_vga2_range = osmosdr::gain_range_t( 0, 25, 1 );
|
||||||
|
|
||||||
ret = bladerf_enable_module(this->dev, TX, true);
|
_filled = new bool[_num_buffers];
|
||||||
if ( ret != 0 )
|
if (!_filled) {
|
||||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"Failed to allocate _filled[]" );
|
||||||
this->thread = gr::thread::thread(write_task_dispatch, this);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -171,128 +97,195 @@ bladerf_sink_c::~bladerf_sink_c ()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
this->set_running(false);
|
if( is_running() == true ) {
|
||||||
this->thread.join();
|
std::cerr << _pfx << "Still running when destructor called!"
|
||||||
|
<< std::endl;
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
ret = bladerf_enable_module(this->dev, TX, false);
|
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false );
|
||||||
if ( ret != 0 )
|
if ( ret != 0 )
|
||||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
std::cerr << _pfx << "bladerf_enable_module failed:"
|
||||||
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
|
|
||||||
/* Close the device */
|
/* Release stream resources */
|
||||||
bladerf_close( this->dev );
|
bladerf_deinit_stream(_stream);
|
||||||
|
|
||||||
|
delete[] _filled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bladerf_sink_c::write_task_dispatch(bladerf_sink_c *obj)
|
void *bladerf_sink_c::stream_callback( struct bladerf *dev,
|
||||||
|
struct bladerf_stream *stream,
|
||||||
|
struct bladerf_metadata *metadata,
|
||||||
|
void *samples,
|
||||||
|
size_t num_samples,
|
||||||
|
void *user_data )
|
||||||
{
|
{
|
||||||
obj->write_task();
|
bladerf_sink_c *obj = (bladerf_sink_c *) user_data;
|
||||||
|
return obj->get_next_buffer( samples, num_samples );
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t buffer2index(void **buffers, void *current, size_t num_buffers)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < num_buffers; ++i) {
|
||||||
|
if (static_cast<char*>(current) == static_cast<char*>(buffers[i]))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"Has hit unexpected condition");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the next full buffer to pass down to the device */
|
||||||
|
void *bladerf_sink_c::get_next_buffer( void *samples, size_t num_samples)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
bool running;
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(_buf_status_lock);
|
||||||
|
|
||||||
|
/* Mark the incoming buffer empty and notify work() */
|
||||||
|
if (samples) {
|
||||||
|
size_t buffer_emptied_index = buffer2index(_buffers, samples, _num_buffers);
|
||||||
|
|
||||||
|
_filled[buffer_emptied_index] = false;
|
||||||
|
_buffer_emptied.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for our next buffer to become filled */
|
||||||
|
while ((running = is_running()) && !_filled[_next_to_tx]) {
|
||||||
|
_buffer_filled.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
ret = _buffers[_next_to_tx];
|
||||||
|
_next_to_tx = (_next_to_tx + 1) % _num_buffers;
|
||||||
|
} else {
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bladerf_sink_c::write_task()
|
void bladerf_sink_c::write_task()
|
||||||
{
|
{
|
||||||
int i, n_samples_avail, n_samples;
|
int status;
|
||||||
int16_t *p;
|
|
||||||
gr_complex sample;
|
|
||||||
|
|
||||||
while ( this->is_running() )
|
/* Start stream and stay there until we kill the stream */
|
||||||
{
|
set_running(true);
|
||||||
|
status = bladerf_stream(_stream, BLADERF_MODULE_TX);
|
||||||
|
|
||||||
{
|
if ( status < 0 ) {
|
||||||
/* Lock the circular buffer */
|
set_running(false);
|
||||||
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
|
std::cerr << _pfx << "Sink stream error: "
|
||||||
|
<< bladerf_strerror(status) << std::endl;
|
||||||
|
|
||||||
/* Check to make sure we have samples available */
|
if ( status == BLADERF_ERR_TIMEOUT ) {
|
||||||
n_samples_avail = this->sample_fifo->size();
|
std::cerr << _pfx << "Try adjusting your sample rate or the "
|
||||||
while( n_samples_avail < BLADERF_SAMPLE_BLOCK_SIZE ) {
|
<< "\"buffers\", \"buflen\", and \"transfers\" parameters. "
|
||||||
/* Wait until there is at least a block size of samples ready */
|
<< std::endl;
|
||||||
this->samples_available.wait(lock);
|
|
||||||
n_samples_avail = this->sample_fifo->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pop samples from circular buffer, write samples to outgoing buffer */
|
|
||||||
int16_t *p = this->raw_sample_buf;
|
|
||||||
for( i = 0; i < BLADERF_SAMPLE_BLOCK_SIZE; ++i ) {
|
|
||||||
sample = this->sample_fifo->at(0);
|
|
||||||
this->sample_fifo->pop_front();
|
|
||||||
*p++ = 0xa000 | (int16_t)(real(sample)*2000);
|
|
||||||
*p++ = 0x5000 | (int16_t)(imag(sample)*2000);
|
|
||||||
}
|
|
||||||
} /* Give up the lock by leaving the scope ...*/
|
|
||||||
|
|
||||||
/* Notify that we've just popped some samples */
|
|
||||||
this->samples_available.notify_one();
|
|
||||||
|
|
||||||
/* Samples are available to write out */
|
|
||||||
n_samples = bladerf_send_c16(this->dev, this->raw_sample_buf,
|
|
||||||
BLADERF_SAMPLE_BLOCK_SIZE);
|
|
||||||
|
|
||||||
/* Check n_samples return value */
|
|
||||||
if( n_samples < 0 ) {
|
|
||||||
std::cerr << "Failed to write samples: "
|
|
||||||
<< bladerf_strerror(n_samples) << std::endl;
|
|
||||||
this->set_running(false);
|
|
||||||
} else {
|
|
||||||
if(n_samples != BLADERF_SAMPLE_BLOCK_SIZE) {
|
|
||||||
if(n_samples > BLADERF_SAMPLE_BLOCK_SIZE) {
|
|
||||||
std::cerr << "Warning: sent bloated sample block of "
|
|
||||||
<< n_samples << " samples!" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Warning: sent truncated sample block of "
|
|
||||||
<< n_samples << " samples!" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bladerf_sink_c::start()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Initialize the stream */
|
||||||
|
ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback,
|
||||||
|
&_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q11,
|
||||||
|
_samples_per_buffer, _num_transfers, this );
|
||||||
|
if ( ret != 0 ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"bladerf_init_stream failed" ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize buffer management */
|
||||||
|
_buf_index = _next_to_tx = 0;
|
||||||
|
_next_value = static_cast<int16_t*>(_buffers[0]);
|
||||||
|
_samples_left = _samples_per_buffer;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _num_buffers; ++i) {
|
||||||
|
_filled[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, true );
|
||||||
|
if ( ret != 0 ) {
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||||
|
"bladerf_enable_module has failed:" + bladerf_strerror(ret) );
|
||||||
|
}
|
||||||
|
|
||||||
|
_thread = gr::thread::thread( boost::bind(&bladerf_sink_c::write_task, this) );
|
||||||
|
while(is_running() == false) {
|
||||||
|
/* Not quite started up just yet, so wait for a short period of time */
|
||||||
|
boost::this_thread::sleep( boost::posix_time::milliseconds(1) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bladerf_sink_c::stop()
|
||||||
|
{
|
||||||
|
set_running(false);
|
||||||
|
_thread.join();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int bladerf_sink_c::work( int noutput_items,
|
int bladerf_sink_c::work( int noutput_items,
|
||||||
gr_vector_const_void_star &input_items,
|
gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items )
|
gr_vector_void_star &output_items )
|
||||||
{
|
{
|
||||||
int n_space_avail, to_copy, limit, i;
|
|
||||||
const gr_complex *in = (const gr_complex *) input_items[0];
|
const gr_complex *in = (const gr_complex *) input_items[0];
|
||||||
|
int num_samples;
|
||||||
|
bool running = is_running();
|
||||||
|
|
||||||
if ( ! this->is_running() )
|
/* Total samples we want to process */
|
||||||
return WORK_DONE;
|
num_samples = noutput_items;
|
||||||
|
|
||||||
if( noutput_items >= 0 ) {
|
/* While there are still samples to copy out ... */
|
||||||
/* Total samples we want to process */
|
while (running && num_samples > 0) {
|
||||||
to_copy = noutput_items;
|
|
||||||
|
|
||||||
/* While there are still samples to copy out ... */
|
while (_samples_left && num_samples) {
|
||||||
while( to_copy > 0 ) {
|
|
||||||
|
/* Scale and sign extend I and then Q */
|
||||||
|
*_next_value = (int16_t)(real(*in) * 2000);
|
||||||
|
_next_value++;
|
||||||
|
|
||||||
|
*_next_value = (int16_t)(imag(*in) * 2000);
|
||||||
|
_next_value++;
|
||||||
|
|
||||||
|
/* Advance to next sample */
|
||||||
|
in++;
|
||||||
|
num_samples--;
|
||||||
|
_samples_left--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance to the next buffer if the current one is filled */
|
||||||
|
if (_samples_left == 0) {
|
||||||
{
|
{
|
||||||
/* Acquire the circular buffer lock */
|
boost::unique_lock<boost::mutex> lock(_buf_status_lock);
|
||||||
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
|
|
||||||
|
|
||||||
/* Check to see how much space is available */
|
_filled[_buf_index] = true;
|
||||||
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
|
_buf_index = (_buf_index + 1) % _num_buffers;
|
||||||
|
_next_value = static_cast<int16_t*>(_buffers[_buf_index]);
|
||||||
|
_samples_left = _samples_per_buffer;
|
||||||
|
|
||||||
while (n_space_avail == 0) {
|
/* Signal that we have filled a buffer */
|
||||||
this->samples_available.wait(lock);
|
_buffer_filled.notify_one();
|
||||||
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
|
|
||||||
|
/* Wait here if the next buffer isn't full. The callback will
|
||||||
|
* signal us when it has freed up a buffer */
|
||||||
|
while (_filled[_buf_index] && running) {
|
||||||
|
_buffer_emptied.wait(lock);
|
||||||
|
running = is_running();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Limit ourselves to either the number of output items ...
|
|
||||||
... or whatever space is available */
|
|
||||||
limit = (n_space_avail < noutput_items ? n_space_avail : noutput_items);
|
|
||||||
|
|
||||||
/* Consume! */
|
|
||||||
for( i = 0; i < limit; i++ ) {
|
|
||||||
this->sample_fifo->push_back(*in++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrement the amount we need to copy */
|
|
||||||
to_copy -= limit;
|
|
||||||
|
|
||||||
} /* Unlock by leaving the scope */
|
|
||||||
|
|
||||||
/* Notify that we've just added some samples */
|
|
||||||
this->samples_available.notify_one();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return noutput_items;
|
return running ? noutput_items : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> bladerf_sink_c::get_devices()
|
std::vector<std::string> bladerf_sink_c::get_devices()
|
||||||
|
@ -308,55 +301,22 @@ size_t bladerf_sink_c::get_num_channels()
|
||||||
|
|
||||||
osmosdr::meta_range_t bladerf_sink_c::get_sample_rates()
|
osmosdr::meta_range_t bladerf_sink_c::get_sample_rates()
|
||||||
{
|
{
|
||||||
return this->sample_rates();
|
return sample_rates();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_sink_c::set_sample_rate(double rate)
|
double bladerf_sink_c::set_sample_rate(double rate)
|
||||||
{
|
{
|
||||||
int ret;
|
return bladerf_common::set_sample_rate(BLADERF_MODULE_TX, rate);
|
||||||
uint32_t actual;
|
|
||||||
/* Set the Si5338 to be 2x this sample rate */
|
|
||||||
|
|
||||||
/* Check to see if the sample rate is an integer */
|
|
||||||
if( (uint32_t)round(rate) == (uint32_t)rate )
|
|
||||||
{
|
|
||||||
ret = bladerf_set_sample_rate( this->dev, TX, (uint32_t)rate, &actual );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to set integer rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* TODO: Fractional sample rate */
|
|
||||||
ret = bladerf_set_sample_rate( this->dev, TX, (uint32_t)rate, &actual );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to set fractional rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_sample_rate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_sink_c::get_sample_rate()
|
double bladerf_sink_c::get_sample_rate()
|
||||||
{
|
{
|
||||||
int ret;
|
return bladerf_common::get_sample_rate(BLADERF_MODULE_TX);
|
||||||
unsigned int rate = 0;
|
|
||||||
|
|
||||||
ret = bladerf_get_sample_rate( this->dev, TX, &rate );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to get sample rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return (double)rate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osmosdr::freq_range_t bladerf_sink_c::get_freq_range( size_t chan )
|
osmosdr::freq_range_t bladerf_sink_c::get_freq_range( size_t chan )
|
||||||
{
|
{
|
||||||
return this->freq_range();
|
return freq_range();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_sink_c::set_center_freq( double freq, size_t chan )
|
double bladerf_sink_c::set_center_freq( double freq, size_t chan )
|
||||||
|
@ -368,13 +328,12 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan )
|
||||||
freq > get_freq_range( chan ).stop() ) {
|
freq > get_freq_range( chan ).stop() ) {
|
||||||
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
||||||
} else {
|
} else {
|
||||||
ret = bladerf_set_frequency( this->dev, TX, (uint32_t)freq );
|
ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_TX, (uint32_t)freq );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"failed to set center frequency " +
|
"Failed to set center frequency " +
|
||||||
boost::lexical_cast<std::string>(freq) +
|
boost::lexical_cast<std::string>(freq) +
|
||||||
", error " +
|
":" + std::string(bladerf_strerror(ret)));
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,11 +345,11 @@ double bladerf_sink_c::get_center_freq( size_t chan )
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bladerf_get_frequency( this->dev, TX, &freq );
|
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_TX, &freq );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"failed to get center frequency, error " +
|
"Failed to get center frequency:" +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)freq;
|
return (double)freq;
|
||||||
|
@ -429,12 +388,12 @@ osmosdr::gain_range_t bladerf_sink_c::get_gain_range( const std::string & name,
|
||||||
osmosdr::gain_range_t range;
|
osmosdr::gain_range_t range;
|
||||||
|
|
||||||
if( name == "VGA1" ) {
|
if( name == "VGA1" ) {
|
||||||
range = this->vga1_range;
|
range = _vga1_range;
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
range = this->vga2_range;
|
range = _vga2_range;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested an invalid gain element " + name );
|
"Requested an invalid gain element " + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
|
@ -460,20 +419,20 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if( name == "VGA1" ) {
|
if( name == "VGA1" ) {
|
||||||
ret = bladerf_set_txvga1( this->dev, (int)gain );
|
ret = bladerf_set_txvga1( _dev.get(), (int)gain );
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
ret = bladerf_set_txvga2( this->dev, (int)gain );
|
ret = bladerf_set_txvga2( _dev.get(), (int)gain );
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested to set the gain "
|
"Requested to set the gain " +
|
||||||
"of an unknown gain element " + name );
|
"of an unknown gain element " + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||||
"could not set " + name + " gain, error " +
|
"Could not set " + name + " gain, error " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_gain( name, chan );
|
return get_gain( name, chan );
|
||||||
|
@ -490,20 +449,20 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan )
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if( name == "VGA1" ) {
|
if( name == "VGA1" ) {
|
||||||
ret = bladerf_get_txvga1( this->dev, &g );
|
ret = bladerf_get_txvga1( _dev.get(), &g );
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
ret = bladerf_get_txvga2( this->dev, &g );
|
ret = bladerf_get_txvga2( _dev.get(), &g );
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested to get the gain "
|
"Requested to get the gain " +
|
||||||
"of an unknown gain element " + name );
|
"of an unknown gain element " + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not get " + name + " gain, error " +
|
"Could not get " + name + " gain, error " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)g;
|
return (double)g;
|
||||||
|
@ -540,19 +499,48 @@ std::string bladerf_sink_c::get_antenna( size_t chan )
|
||||||
return "TX";
|
return "TX";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bladerf_sink_c::set_dc_offset( const std::complex<double> &offset, size_t chan )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = bladerf_common::set_dc_offset(BLADERF_MODULE_TX, offset, chan);
|
||||||
|
|
||||||
|
if( ret ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"could not set dc offset: " +
|
||||||
|
std::string(bladerf_strerror(ret)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_sink_c::set_iq_balance( const std::complex<double> &balance, size_t chan )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = bladerf_common::set_iq_balance(BLADERF_MODULE_TX, balance, chan);
|
||||||
|
|
||||||
|
if( ret ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"could not set iq balance: " +
|
||||||
|
std::string(bladerf_strerror(ret)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan )
|
double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t actual;
|
uint32_t actual;
|
||||||
|
|
||||||
ret = bladerf_set_bandwidth( this->dev, TX, (uint32_t)bandwidth, &actual );
|
if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
|
||||||
|
bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */
|
||||||
|
|
||||||
|
ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not set bandwidth, error " +
|
"could not set bandwidth:" +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->get_bandwidth();
|
return get_bandwidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_sink_c::get_bandwidth( size_t chan )
|
double bladerf_sink_c::get_bandwidth( size_t chan )
|
||||||
|
@ -560,11 +548,11 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
|
||||||
uint32_t bandwidth;
|
uint32_t bandwidth;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bladerf_get_bandwidth( this->dev, TX, &bandwidth );
|
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_TX, &bandwidth );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not get bandwidth, error " +
|
"could not get bandwidth: " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)bandwidth;
|
return (double)bandwidth;
|
||||||
|
@ -572,5 +560,5 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
|
||||||
|
|
||||||
osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range( size_t chan )
|
osmosdr::freq_range_t bladerf_sink_c::get_bandwidth_range( size_t chan )
|
||||||
{
|
{
|
||||||
return this->filter_bandwidths();
|
return filter_bandwidths();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include <gnuradio/block.h>
|
#include <gnuradio/block.h>
|
||||||
#include <gnuradio/sync_block.h>
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
#include <libbladeRF.h>
|
|
||||||
|
|
||||||
#include "osmosdr/ranges.h"
|
#include "osmosdr/ranges.h"
|
||||||
#include "sink_iface.h"
|
#include "sink_iface.h"
|
||||||
#include "bladerf_common.h"
|
#include "bladerf_common.h"
|
||||||
|
@ -70,6 +68,9 @@ private:
|
||||||
public:
|
public:
|
||||||
~bladerf_sink_c (); // public destructor
|
~bladerf_sink_c (); // public destructor
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool stop();
|
||||||
|
|
||||||
int work( int noutput_items,
|
int work( int noutput_items,
|
||||||
gr_vector_const_void_star &input_items,
|
gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items );
|
gr_vector_void_star &output_items );
|
||||||
|
@ -104,17 +105,48 @@ public:
|
||||||
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
||||||
std::string get_antenna( size_t chan = 0 );
|
std::string get_antenna( size_t chan = 0 );
|
||||||
|
|
||||||
|
void set_dc_offset( const std::complex<double> &offset, size_t chan );
|
||||||
|
void set_iq_balance( const std::complex<double> &balance, size_t chan );
|
||||||
|
|
||||||
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
||||||
double get_bandwidth( size_t chan = 0 );
|
double get_bandwidth( size_t chan = 0 );
|
||||||
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||||
|
|
||||||
private:
|
private: /* functions */
|
||||||
static void write_task_dispatch(bladerf_sink_c *obj);
|
static void *stream_callback( struct bladerf *_dev,
|
||||||
|
struct bladerf_stream *stream,
|
||||||
|
struct bladerf_metadata *metadata,
|
||||||
|
void *samples,
|
||||||
|
size_t num_samples,
|
||||||
|
void *user_data );
|
||||||
|
|
||||||
|
void *get_next_buffer(void *samples, size_t num_samples);
|
||||||
|
|
||||||
void write_task();
|
void write_task();
|
||||||
|
|
||||||
gr::thread::thread thread;
|
private: /* members */
|
||||||
osmosdr::gain_range_t vga1_range;
|
|
||||||
osmosdr::gain_range_t vga2_range;
|
/* Array denoting whether each buffer is filled with data and ready to TX */
|
||||||
|
bool *_filled;
|
||||||
|
|
||||||
|
/* Acquire while updating _filled, and signalling/waiting on
|
||||||
|
* _buffer_emptied and _buffer_filled */
|
||||||
|
boost::mutex _buf_status_lock;
|
||||||
|
|
||||||
|
/* work() may block waiting for the stream callback to empty (consume) a
|
||||||
|
* buffer. The callback uses this to signal when it has emptied a buffer. */
|
||||||
|
boost::condition_variable _buffer_emptied;
|
||||||
|
|
||||||
|
/* The stream callback may block waiting for work() to fill (produce) a
|
||||||
|
* buffer. work() uses this to signal that it has filled a buffer. */
|
||||||
|
boost::condition_variable _buffer_filled;
|
||||||
|
|
||||||
|
/* These values are only to be updated and accessed from within work() */
|
||||||
|
int16_t *_next_value; /* I/Q value insertion point in current buffer */
|
||||||
|
size_t _samples_left; /* # of samples left to fill in our current buffer */
|
||||||
|
|
||||||
|
/* This should only be accessed and updated from TX callbacks */
|
||||||
|
size_t _next_to_tx; /* Next buffer to transmit */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDED_BLADERF_SINK_C_H */
|
#endif /* INCLUDED_BLADERF_SINK_C_H */
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
|
|
||||||
#include "arg_helpers.h"
|
#include "arg_helpers.h"
|
||||||
#include "bladerf_source_c.h"
|
#include "bladerf_source_c.h"
|
||||||
|
#include "osmosdr/source.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default size of sample FIFO, in entries.
|
||||||
|
*/
|
||||||
|
#define BLADERF_SAMPLE_FIFO_SIZE (2 * 1024 * 1024)
|
||||||
|
|
||||||
|
#define BLADERF_SAMPLE_FIFO_MIN_SIZE (3 * BLADERF_SAMPLE_BLOCK_SIZE)
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
|
@ -73,98 +81,78 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
|
||||||
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int device_number = 0;
|
size_t fifo_size;
|
||||||
std::string device_name;
|
std::string device_name;
|
||||||
|
struct bladerf_version fpga_version;
|
||||||
|
|
||||||
dict_t dict = params_to_dict(args);
|
dict_t dict = params_to_dict(args);
|
||||||
|
|
||||||
if (dict.count("bladerf"))
|
init(dict, "source");
|
||||||
{
|
|
||||||
std::string value = dict["bladerf"];
|
fifo_size = BLADERF_SAMPLE_FIFO_SIZE;
|
||||||
if ( value.length() )
|
if (dict.count("fifo")) {
|
||||||
{
|
try {
|
||||||
try {
|
fifo_size = boost::lexical_cast<size_t>(dict["fifo"]);
|
||||||
device_number = boost::lexical_cast< unsigned int >( value );
|
} catch (const boost::bad_lexical_cast &e) {
|
||||||
} catch ( std::exception &ex ) {
|
std::cerr << _pfx << "Warning: \"fifo\" value is invalid. Defaulting to "
|
||||||
throw std::runtime_error(
|
<< fifo_size;
|
||||||
"Failed to use '" + value + "' as device number: " + ex.what());
|
}
|
||||||
}
|
|
||||||
|
if (fifo_size < BLADERF_SAMPLE_FIFO_MIN_SIZE) {
|
||||||
|
fifo_size = BLADERF_SAMPLE_FIFO_MIN_SIZE;
|
||||||
|
std::cerr << _pfx << "Warning: \"fifo\" value is too small. Defaulting to "
|
||||||
|
<< BLADERF_SAMPLE_FIFO_MIN_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
device_name = boost::str(boost::format( "/dev/bladerf%d" ) % device_number);
|
_fifo = new boost::circular_buffer<gr_complex>(fifo_size);
|
||||||
|
if (!_fifo) {
|
||||||
/* Open a handle to the device */
|
|
||||||
this->dev = bladerf_open( device_name.c_str() );
|
|
||||||
if( NULL == this->dev ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"failed to open bladeRF device " + device_name );
|
"Failed to allocate a sample FIFO!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict.count("fpga"))
|
if (dict.count("sampling"))
|
||||||
{
|
{
|
||||||
std::string fpga = dict["fpga"];
|
std::string sampling = dict["sampling"];
|
||||||
|
|
||||||
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
|
std::cerr << _pfx << "Setting bladerf sampling to " << sampling << std::endl;
|
||||||
ret = bladerf_load_fpga( this->dev, fpga.c_str() );
|
if( sampling == "internal") {
|
||||||
if ( ret != 0 )
|
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_INTERNAL );
|
||||||
std::cerr << "bladerf_load_fpga has returned with " << ret << std::endl;
|
if ( ret != 0 )
|
||||||
else
|
std::cerr << _pfx << "Problem while setting sampling mode:"
|
||||||
std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl;
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
}
|
} else if( sampling == "external" ) {
|
||||||
|
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_EXTERNAL );
|
||||||
if (dict.count("fw"))
|
if ( ret != 0 )
|
||||||
{
|
std::cerr << _pfx << "Problem while setting sampling mode:"
|
||||||
std::string fw = dict["fw"];
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
|
} else {
|
||||||
std::cerr << "Flashing firmware image " << fw << "..., "
|
std::cerr << _pfx << "Invalid sampling mode " << sampling << std::endl;
|
||||||
<< "DO NOT INTERRUPT!"
|
}
|
||||||
<< std::endl;
|
|
||||||
ret = bladerf_flash_firmware( this->dev, fw.c_str() );
|
|
||||||
if ( ret != 0 )
|
|
||||||
std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
|
|
||||||
else
|
|
||||||
std::cerr << "The firmare has been successfully flashed, "
|
|
||||||
<< "please power cycle the bladeRF before using it."
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "Using nuand LLC bladeRF #" << device_number;
|
|
||||||
|
|
||||||
u_int64_t serial;
|
|
||||||
if ( bladerf_get_serial( this->dev, &serial ) == 0 )
|
|
||||||
std::cerr << " SN " << std::setfill('0') << std::setw(16) << serial;
|
|
||||||
|
|
||||||
unsigned int major, minor;
|
|
||||||
if ( bladerf_get_fw_version( this->dev, &major, &minor) == 0 )
|
|
||||||
std::cerr << " FW v" << major << "." << minor;
|
|
||||||
|
|
||||||
if ( bladerf_get_fpga_version( this->dev, &major, &minor) == 0 )
|
|
||||||
std::cerr << " FPGA v" << major << "." << minor;
|
|
||||||
|
|
||||||
std::cerr << std::endl;
|
|
||||||
|
|
||||||
if ( bladerf_is_fpga_configured( this->dev ) != 1 )
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: The FPGA is not configured! "
|
|
||||||
<< "Use the device argument fpga=/path/to/the/bitstream.rbf to load it."
|
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the range of LNA, G_LNA_RXFE[1:0] */
|
/* Set the range of LNA, G_LNA_RXFE[1:0] */
|
||||||
this->lna_range = osmosdr::gain_range_t( 0, 6, 3 );
|
_lna_range = osmosdr::gain_range_t( 0, 6, 3 );
|
||||||
|
|
||||||
/* Set the range of VGA1, RFB_TIA_RXFE[6:0], nonlinear mapping done inside the lib */
|
/* Set the range of VGA1, RFB_TIA_RXFE[6:0], nonlinear mapping done inside the lib */
|
||||||
this->vga1_range = osmosdr::gain_range_t( 5, 30, 1 );
|
_vga1_range = osmosdr::gain_range_t( 5, 30, 1 );
|
||||||
|
|
||||||
/* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */
|
/* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */
|
||||||
this->vga2_range = osmosdr::gain_range_t( 0, 60, 3 );
|
_vga2_range = osmosdr::gain_range_t( 0, 30, 3 );
|
||||||
|
|
||||||
ret = bladerf_enable_module(this->dev, RX, true);
|
|
||||||
if ( ret != 0 )
|
|
||||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
|
||||||
|
|
||||||
this->thread = gr::thread::thread(read_task_dispatch, this);
|
/* Warn user about using an old FPGA version, as we no longer strip off the
|
||||||
|
* markers that were pressent in the pre-v0.0.1 FPGA */
|
||||||
|
if (bladerf_fpga_version( _dev.get(), &fpga_version ) != 0) {
|
||||||
|
std::cerr << _pfx << "Failed to get FPGA version" << std::endl;
|
||||||
|
} else if ( fpga_version.major <= 0 &&
|
||||||
|
fpga_version.minor <= 0 &&
|
||||||
|
fpga_version.patch < 1 ) {
|
||||||
|
|
||||||
|
std::cerr << _pfx << "Warning: FPGA version v0.0.1 or later is required. "
|
||||||
|
<< "Using an earlier FPGA version will result in misinterpeted samples. "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,116 +162,158 @@ bladerf_source_c::~bladerf_source_c ()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
this->set_running(false);
|
if (is_running()) {
|
||||||
this->thread.join();
|
std::cerr << _pfx << "Still running when destructor called!"
|
||||||
|
<< std::endl;
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
ret = bladerf_enable_module(this->dev, RX, false);
|
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, false );
|
||||||
if ( ret != 0 )
|
if ( ret != 0 )
|
||||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
std::cerr << _pfx << "bladerf_enable_module failed: "
|
||||||
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
|
|
||||||
/* Close the device */
|
/* Release stream resources */
|
||||||
bladerf_close( this->dev );
|
bladerf_deinit_stream(_stream);
|
||||||
|
|
||||||
|
delete _fifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bladerf_source_c::read_task_dispatch(bladerf_source_c *obj)
|
void *bladerf_source_c::stream_callback( struct bladerf *dev,
|
||||||
|
struct bladerf_stream *stream,
|
||||||
|
struct bladerf_metadata *metadata,
|
||||||
|
void *samples,
|
||||||
|
size_t num_samples,
|
||||||
|
void *user_data )
|
||||||
{
|
{
|
||||||
obj->read_task();
|
bladerf_source_c *obj = (bladerf_source_c *) user_data;
|
||||||
|
|
||||||
|
if ( ! obj->is_running() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return obj->stream_task( samples, num_samples );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert & push samples to the sample fifo */
|
||||||
|
void *bladerf_source_c::stream_task( void *samples, size_t num_samples )
|
||||||
|
{
|
||||||
|
size_t i, n_avail, to_copy;
|
||||||
|
int16_t *sample = (int16_t *)samples;
|
||||||
|
void *ret;
|
||||||
|
const float scaling = 1.0f / 2048.0f;
|
||||||
|
|
||||||
|
ret = _buffers[_buf_index];
|
||||||
|
_buf_index = (_buf_index + 1) % _num_buffers;
|
||||||
|
|
||||||
|
_fifo_lock.lock();
|
||||||
|
|
||||||
|
n_avail = _fifo->capacity() - _fifo->size();
|
||||||
|
to_copy = (n_avail < num_samples ? n_avail : num_samples);
|
||||||
|
|
||||||
|
for(i = 0; i < to_copy; i++ ) {
|
||||||
|
/* Push sample to the fifo */
|
||||||
|
_fifo->push_back( gr_complex( *sample * scaling,
|
||||||
|
*(sample+1) * scaling) );
|
||||||
|
|
||||||
|
/* offset to the next I+Q sample */
|
||||||
|
sample += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fifo_lock.unlock();
|
||||||
|
|
||||||
|
/* We have made some new samples available to the consumer in work() */
|
||||||
|
if (to_copy) {
|
||||||
|
//std::cerr << "+" << std::flush;
|
||||||
|
_samp_avail.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicate overrun, if neccesary */
|
||||||
|
if (to_copy < num_samples)
|
||||||
|
std::cerr << "O" << std::flush;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bladerf_source_c::read_task()
|
void bladerf_source_c::read_task()
|
||||||
{
|
{
|
||||||
int16_t si, sq, *next_val;
|
int status;
|
||||||
ssize_t n_samples;
|
|
||||||
size_t n_avail, to_copy;
|
|
||||||
|
|
||||||
while ( this->is_running() )
|
set_running( true );
|
||||||
{
|
|
||||||
|
|
||||||
n_samples = bladerf_read_c16(this->dev, this->raw_sample_buf,
|
/* Start stream and stay there until we kill the stream */
|
||||||
BLADERF_SAMPLE_BLOCK_SIZE);
|
status = bladerf_stream(_stream, BLADERF_MODULE_RX);
|
||||||
|
|
||||||
if (n_samples < 0) {
|
if ( status < 0 ) {
|
||||||
std::cerr << "Failed to read samples: "
|
set_running( false );
|
||||||
<< bladerf_strerror(n_samples) << std::endl;
|
std::cerr << "Source stream error: " << bladerf_strerror(status) << std::endl;
|
||||||
this->set_running(false);
|
|
||||||
} else {
|
|
||||||
if (n_samples != BLADERF_SAMPLE_BLOCK_SIZE) {
|
|
||||||
if (n_samples > BLADERF_SAMPLE_BLOCK_SIZE) {
|
|
||||||
std::cerr << "Warning: received bloated sample block of "
|
|
||||||
<< n_samples << " bytes!"<< std::endl;
|
|
||||||
} else {
|
|
||||||
std::cerr << "Warning: received truncated sample block of "
|
|
||||||
<< n_samples << " bytes!"<< std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//std::cerr << "+" << std::flush;
|
if ( status == BLADERF_ERR_TIMEOUT ) {
|
||||||
|
std::cerr << _pfx << "Try adjusting your sample rate or the "
|
||||||
next_val = this->raw_sample_buf;
|
<< "\"buffers\", \"buflen\", and \"transfers\" parameters. "
|
||||||
|
<< std::endl;
|
||||||
this->sample_fifo_lock.lock();
|
|
||||||
n_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
|
|
||||||
to_copy = (n_avail < (size_t)n_samples ? n_avail : (size_t)n_samples);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < to_copy; ++i) {
|
|
||||||
si = *next_val++ & 0xfff;
|
|
||||||
sq = *next_val++ & 0xfff;
|
|
||||||
|
|
||||||
/* Sign extend the 12-bit IQ values, if needed */
|
|
||||||
if( si & 0x800 ) si |= 0xf000;
|
|
||||||
if( sq & 0x800 ) sq |= 0xf000;
|
|
||||||
|
|
||||||
gr_complex sample((float)si * (1.0f/2048.0f),
|
|
||||||
(float)sq * (1.0f/2048.0f));
|
|
||||||
|
|
||||||
this->sample_fifo->push_back(sample);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->sample_fifo_lock.unlock();
|
|
||||||
|
|
||||||
/* We have made some new samples available to the consumer in work() */
|
|
||||||
if (to_copy) {
|
|
||||||
this->samples_available.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indicate overrun, if neccesary */
|
|
||||||
if (to_copy < (size_t)n_samples) {
|
|
||||||
std::cerr << "O" << std::flush;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main work function, pull samples from the driver */
|
bool bladerf_source_c::start()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Initialize the stream */
|
||||||
|
_buf_index = 0;
|
||||||
|
ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback,
|
||||||
|
&_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q11,
|
||||||
|
_samples_per_buffer, _num_buffers, this );
|
||||||
|
if ( ret != 0 )
|
||||||
|
std::cerr << _pfx << "bladerf_init_stream failed: "
|
||||||
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
|
|
||||||
|
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, true );
|
||||||
|
if ( ret != 0 )
|
||||||
|
std::cerr << _pfx << "bladerf_enable_module failed:"
|
||||||
|
<< bladerf_strerror(ret) << std::endl;
|
||||||
|
|
||||||
|
_thread = gr::thread::thread( boost::bind(&bladerf_source_c::read_task, this) );
|
||||||
|
|
||||||
|
while( is_running() == false ) {
|
||||||
|
boost::this_thread::sleep( boost::posix_time::milliseconds(1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bladerf_source_c::stop()
|
||||||
|
{
|
||||||
|
set_running(false);
|
||||||
|
_thread.join();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main work function, pull samples from the sample fifo */
|
||||||
int bladerf_source_c::work( int noutput_items,
|
int bladerf_source_c::work( int noutput_items,
|
||||||
gr_vector_const_void_star &input_items,
|
gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items )
|
gr_vector_void_star &output_items )
|
||||||
{
|
{
|
||||||
int n_samples_avail;
|
if ( ! is_running() )
|
||||||
|
|
||||||
if ( ! this->is_running() )
|
|
||||||
return WORK_DONE;
|
return WORK_DONE;
|
||||||
|
|
||||||
if( noutput_items >= 0 ) {
|
if( noutput_items > 0 ) {
|
||||||
gr_complex *out = (gr_complex *)output_items[0];
|
gr_complex *out = (gr_complex *)output_items[0];
|
||||||
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
|
|
||||||
|
boost::unique_lock<boost::mutex> lock(_fifo_lock);
|
||||||
|
|
||||||
/* Wait until we have the requested number of samples */
|
/* Wait until we have the requested number of samples */
|
||||||
n_samples_avail = this->sample_fifo->size();
|
int n_samples_avail = _fifo->size();
|
||||||
|
|
||||||
while (n_samples_avail < noutput_items) {
|
while (n_samples_avail < noutput_items) {
|
||||||
this->samples_available.wait(lock);
|
_samp_avail.wait(lock);
|
||||||
n_samples_avail = this->sample_fifo->size();
|
n_samples_avail = _fifo->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < noutput_items; ++i) {
|
for(int i = 0; i < noutput_items; ++i) {
|
||||||
out[i] = this->sample_fifo->at(0);
|
out[i] = _fifo->at(0);
|
||||||
this->sample_fifo->pop_front();
|
_fifo->pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cerr << "-" << std::flush;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return noutput_items;
|
return noutput_items;
|
||||||
|
@ -302,55 +332,22 @@ size_t bladerf_source_c::get_num_channels()
|
||||||
|
|
||||||
osmosdr::meta_range_t bladerf_source_c::get_sample_rates()
|
osmosdr::meta_range_t bladerf_source_c::get_sample_rates()
|
||||||
{
|
{
|
||||||
return this->sample_rates();
|
return sample_rates();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_source_c::set_sample_rate( double rate )
|
double bladerf_source_c::set_sample_rate( double rate )
|
||||||
{
|
{
|
||||||
int ret;
|
return bladerf_common::set_sample_rate( BLADERF_MODULE_RX, rate);
|
||||||
uint32_t actual;
|
|
||||||
/* Set the Si5338 to be 2x this sample rate */
|
|
||||||
|
|
||||||
/* Check to see if the sample rate is an integer */
|
|
||||||
if( (uint32_t)round(rate) == (uint32_t)rate )
|
|
||||||
{
|
|
||||||
ret = bladerf_set_sample_rate( this->dev, RX, (uint32_t)rate, &actual );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to set integer rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* TODO: Fractional sample rate */
|
|
||||||
ret = bladerf_set_sample_rate( this->dev, RX, (uint32_t)rate, &actual );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to set fractional rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_sample_rate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_source_c::get_sample_rate()
|
double bladerf_source_c::get_sample_rate()
|
||||||
{
|
{
|
||||||
int ret;
|
return bladerf_common::get_sample_rate( BLADERF_MODULE_RX );
|
||||||
unsigned int rate = 0;
|
|
||||||
|
|
||||||
ret = bladerf_get_sample_rate( this->dev, RX, &rate );
|
|
||||||
if( ret ) {
|
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
|
||||||
"has failed to get sample rate, error " +
|
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return (double)rate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osmosdr::freq_range_t bladerf_source_c::get_freq_range( size_t chan )
|
osmosdr::freq_range_t bladerf_source_c::get_freq_range( size_t chan )
|
||||||
{
|
{
|
||||||
return this->freq_range();
|
return freq_range();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_source_c::set_center_freq( double freq, size_t chan )
|
double bladerf_source_c::set_center_freq( double freq, size_t chan )
|
||||||
|
@ -362,13 +359,12 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan )
|
||||||
freq > get_freq_range( chan ).stop() ) {
|
freq > get_freq_range( chan ).stop() ) {
|
||||||
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
||||||
} else {
|
} else {
|
||||||
ret = bladerf_set_frequency( this->dev, RX, (uint32_t)freq );
|
ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_RX, (uint32_t)freq );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"failed to set center frequency " +
|
"failed to set center frequency " +
|
||||||
boost::lexical_cast<std::string>(freq) +
|
boost::lexical_cast<std::string>(freq) + ": " +
|
||||||
", error " +
|
std::string(bladerf_strerror(ret)) );
|
||||||
boost::lexical_cast<std::string>(ret) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,11 +376,11 @@ double bladerf_source_c::get_center_freq( size_t chan )
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bladerf_get_frequency( this->dev, RX, &freq );
|
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_RX, &freq );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"failed to get center frequency, error " +
|
"failed to get center frequency: " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)freq;
|
return (double)freq;
|
||||||
|
@ -423,11 +419,11 @@ osmosdr::gain_range_t bladerf_source_c::get_gain_range( const std::string & name
|
||||||
osmosdr::gain_range_t range;
|
osmosdr::gain_range_t range;
|
||||||
|
|
||||||
if( name == "LNA" ) {
|
if( name == "LNA" ) {
|
||||||
range = this->lna_range;
|
range = _lna_range;
|
||||||
} else if( name == "VGA1" ) {
|
} else if( name == "VGA1" ) {
|
||||||
range = this->vga1_range;
|
range = _vga1_range;
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
range = this->vga2_range;
|
range = _vga2_range;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested an invalid gain element " + name );
|
"requested an invalid gain element " + name );
|
||||||
|
@ -460,22 +456,19 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t
|
||||||
|
|
||||||
if( name == "LNA" ) {
|
if( name == "LNA" ) {
|
||||||
bladerf_lna_gain g;
|
bladerf_lna_gain g;
|
||||||
if( gain == 0.0 ) {
|
|
||||||
g = LNA_BYPASS;
|
if ( gain >= 6.0f )
|
||||||
} else if( gain == 3.0 ) {
|
g = BLADERF_LNA_GAIN_MAX;
|
||||||
g = LNA_MID;
|
else if ( gain >= 3.0f )
|
||||||
} else if( gain == 6.0 ) {
|
g = BLADERF_LNA_GAIN_MID;
|
||||||
g = LNA_MAX;
|
else /* gain < 3.0f */
|
||||||
} else {
|
g = BLADERF_LNA_GAIN_BYPASS;
|
||||||
std::cerr << "Invalid LNA gain requested: " << gain << ", "
|
|
||||||
<< "setting to LNA_MAX (6dB)" << std::endl;
|
ret = bladerf_set_lna_gain( _dev.get(), g );
|
||||||
g = LNA_MAX;
|
|
||||||
}
|
|
||||||
ret = bladerf_set_lna_gain( this->dev, g );
|
|
||||||
} else if( name == "VGA1" ) {
|
} else if( name == "VGA1" ) {
|
||||||
ret = bladerf_set_rxvga1( this->dev, (int)gain );
|
ret = bladerf_set_rxvga1( _dev.get(), (int)gain );
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
ret = bladerf_set_rxvga2( this->dev, (int)gain );
|
ret = bladerf_set_rxvga2( _dev.get(), (int)gain );
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested to set the gain "
|
"requested to set the gain "
|
||||||
|
@ -485,8 +478,8 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not set " + name + " gain, error " +
|
"could not set " + name + " gain: " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_gain( name, chan );
|
return get_gain( name, chan );
|
||||||
|
@ -505,12 +498,12 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan )
|
||||||
|
|
||||||
if( name == "LNA" ) {
|
if( name == "LNA" ) {
|
||||||
bladerf_lna_gain lna_g;
|
bladerf_lna_gain lna_g;
|
||||||
ret = bladerf_get_lna_gain( this->dev, &lna_g );
|
ret = bladerf_get_lna_gain( _dev.get(), &lna_g );
|
||||||
g = lna_g == LNA_BYPASS ? 0 : lna_g == LNA_MID ? 3 : 6;
|
g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6;
|
||||||
} else if( name == "VGA1" ) {
|
} else if( name == "VGA1" ) {
|
||||||
ret = bladerf_get_rxvga1( this->dev, &g );
|
ret = bladerf_get_rxvga1( _dev.get(), &g );
|
||||||
} else if( name == "VGA2" ) {
|
} else if( name == "VGA2" ) {
|
||||||
ret = bladerf_get_rxvga2( this->dev, &g );
|
ret = bladerf_get_rxvga2( _dev.get(), &g );
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"requested to get the gain "
|
"requested to get the gain "
|
||||||
|
@ -520,8 +513,8 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan )
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not get " + name + " gain, error " +
|
"could not get " + name + " gain: " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)g;
|
return (double)g;
|
||||||
|
@ -558,19 +551,74 @@ std::string bladerf_source_c::get_antenna( size_t chan )
|
||||||
return "RX";
|
return "RX";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bladerf_source_c::set_dc_offset_mode( int mode, size_t chan )
|
||||||
|
{
|
||||||
|
if ( osmosdr::source::DCOffsetOff == mode ) {
|
||||||
|
//_src->set_auto_dc_offset( false, chan );
|
||||||
|
set_dc_offset( std::complex<double>(0.0, 0.0), chan ); /* reset to default for off-state */
|
||||||
|
} else if ( osmosdr::source::DCOffsetManual == mode ) {
|
||||||
|
//_src->set_auto_dc_offset( false, chan ); /* disable auto mode, but keep correcting with last known values */
|
||||||
|
} else if ( osmosdr::source::DCOffsetAutomatic == mode ) {
|
||||||
|
//_src->set_auto_dc_offset( true, chan );
|
||||||
|
std::cerr << "Automatic DC correction mode is not implemented." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_source_c::set_dc_offset( const std::complex<double> &offset, size_t chan )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = bladerf_common::set_dc_offset(BLADERF_MODULE_RX, offset, chan);
|
||||||
|
|
||||||
|
if( ret ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"could not set dc offset: " +
|
||||||
|
std::string(bladerf_strerror(ret)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_source_c::set_iq_balance_mode( int mode, size_t chan )
|
||||||
|
{
|
||||||
|
if ( osmosdr::source::IQBalanceOff == mode ) {
|
||||||
|
//_src->set_auto_iq_balance( false, chan );
|
||||||
|
set_iq_balance( std::complex<double>(0.0, 0.0), chan ); /* reset to default for off-state */
|
||||||
|
} else if ( osmosdr::source::IQBalanceManual == mode ) {
|
||||||
|
//_src->set_auto_iq_balance( false, chan ); /* disable auto mode, but keep correcting with last known values */
|
||||||
|
} else if ( osmosdr::source::IQBalanceAutomatic == mode ) {
|
||||||
|
//_src->set_auto_iq_balance( true, chan );
|
||||||
|
std::cerr << "Automatic IQ correction mode is not implemented." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bladerf_source_c::set_iq_balance( const std::complex<double> &balance, size_t chan )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = bladerf_common::set_iq_balance(BLADERF_MODULE_RX, balance, chan);
|
||||||
|
|
||||||
|
if( ret ) {
|
||||||
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
|
"could not set iq balance: " +
|
||||||
|
std::string(bladerf_strerror(ret)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan )
|
double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t actual;
|
uint32_t actual;
|
||||||
|
|
||||||
ret = bladerf_set_bandwidth( this->dev, RX, (uint32_t)bandwidth, &actual );
|
if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
|
||||||
|
bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */
|
||||||
|
|
||||||
|
ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not set bandwidth, error " +
|
"could not set bandwidth: " +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->get_bandwidth();
|
return get_bandwidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bladerf_source_c::get_bandwidth( size_t chan )
|
double bladerf_source_c::get_bandwidth( size_t chan )
|
||||||
|
@ -578,11 +626,11 @@ double bladerf_source_c::get_bandwidth( size_t chan )
|
||||||
uint32_t bandwidth;
|
uint32_t bandwidth;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bladerf_get_bandwidth( this->dev, RX, &bandwidth );
|
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_RX, &bandwidth );
|
||||||
if( ret ) {
|
if( ret ) {
|
||||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||||
"could not get bandwidth, error " +
|
"could not get bandwidth:" +
|
||||||
boost::lexical_cast<std::string>(ret) );
|
std::string(bladerf_strerror(ret)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double)bandwidth;
|
return (double)bandwidth;
|
||||||
|
@ -590,5 +638,5 @@ double bladerf_source_c::get_bandwidth( size_t chan )
|
||||||
|
|
||||||
osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range( size_t chan )
|
osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range( size_t chan )
|
||||||
{
|
{
|
||||||
return this->filter_bandwidths();
|
return filter_bandwidths();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include <gnuradio/block.h>
|
#include <gnuradio/block.h>
|
||||||
#include <gnuradio/sync_block.h>
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
#include <libbladeRF.h>
|
|
||||||
|
|
||||||
#include "osmosdr/ranges.h"
|
#include "osmosdr/ranges.h"
|
||||||
#include "source_iface.h"
|
#include "source_iface.h"
|
||||||
#include "bladerf_common.h"
|
#include "bladerf_common.h"
|
||||||
|
@ -70,6 +68,9 @@ private:
|
||||||
public:
|
public:
|
||||||
~bladerf_source_c (); // public destructor
|
~bladerf_source_c (); // public destructor
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool stop();
|
||||||
|
|
||||||
int work( int noutput_items,
|
int work( int noutput_items,
|
||||||
gr_vector_const_void_star &input_items,
|
gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items );
|
gr_vector_void_star &output_items );
|
||||||
|
@ -104,18 +105,41 @@ public:
|
||||||
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
||||||
std::string get_antenna( size_t chan = 0 );
|
std::string get_antenna( size_t chan = 0 );
|
||||||
|
|
||||||
|
void set_dc_offset_mode( int mode, size_t chan = 0 );
|
||||||
|
void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 );
|
||||||
|
|
||||||
|
void set_iq_balance_mode( int mode, size_t chan = 0 );
|
||||||
|
void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 );
|
||||||
|
|
||||||
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
||||||
double get_bandwidth( size_t chan = 0 );
|
double get_bandwidth( size_t chan = 0 );
|
||||||
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||||
|
|
||||||
private:
|
private: /* functions */
|
||||||
static void read_task_dispatch(bladerf_source_c *obj);
|
static void *stream_callback( struct bladerf *_dev,
|
||||||
|
struct bladerf_stream *stream,
|
||||||
|
struct bladerf_metadata *metadata,
|
||||||
|
void *samples,
|
||||||
|
size_t num_samples,
|
||||||
|
void *user_data );
|
||||||
|
|
||||||
|
void *stream_task(void *samples, size_t num_samples);
|
||||||
|
|
||||||
void read_task();
|
void read_task();
|
||||||
|
|
||||||
gr::thread::thread thread;
|
private: /* members */
|
||||||
osmosdr::gain_range_t lna_range;
|
osmosdr::gain_range_t _lna_range;
|
||||||
osmosdr::gain_range_t vga1_range;
|
|
||||||
osmosdr::gain_range_t vga2_range;
|
/* The stream callback converts SC16Q11 samples from the bladeRF to gr_complex
|
||||||
|
* values, and adds them to this FIFO. work() fetches the gr_complex values
|
||||||
|
* from this queue */
|
||||||
|
boost::circular_buffer<gr_complex> *_fifo;
|
||||||
|
boost::mutex _fifo_lock;
|
||||||
|
|
||||||
|
/* work() will block if the stream callback hasn't produced samples. The
|
||||||
|
* callback uses this to notify work of the availability of samples */
|
||||||
|
boost::condition_variable _samp_avail;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDED_BLADERF_SOURCE_C_H */
|
#endif /* INCLUDED_BLADERF_SOURCE_C_H */
|
||||||
|
|
|
@ -13,5 +13,7 @@
|
||||||
#cmakedefine ENABLE_MIRI
|
#cmakedefine ENABLE_MIRI
|
||||||
#cmakedefine ENABLE_HACKRF
|
#cmakedefine ENABLE_HACKRF
|
||||||
#cmakedefine ENABLE_BLADERF
|
#cmakedefine ENABLE_BLADERF
|
||||||
|
#cmakedefine ENABLE_RFSPACE
|
||||||
|
#cmakedefine ENABLE_AIRSPY
|
||||||
|
|
||||||
#endif // CONFIG_H_IN
|
#endif // CONFIG_H_IN
|
||||||
|
|
|
@ -66,6 +66,14 @@
|
||||||
#include <bladerf_source_c.h>
|
#include <bladerf_source_c.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_RFSPACE
|
||||||
|
#include <rfspace_source_c.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_AIRSPY
|
||||||
|
#include <airspy_source_c.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "arg_helpers.h"
|
#include "arg_helpers.h"
|
||||||
|
|
||||||
using namespace osmosdr;
|
using namespace osmosdr;
|
||||||
|
@ -115,6 +123,11 @@ devices_t device::find(const device_t &hint)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(_device_mutex);
|
boost::mutex::scoped_lock lock(_device_mutex);
|
||||||
|
|
||||||
|
bool fake = true;
|
||||||
|
|
||||||
|
if ( hint.count("nofake") )
|
||||||
|
fake = false;
|
||||||
|
|
||||||
devices_t devices;
|
devices_t devices;
|
||||||
|
|
||||||
#ifdef ENABLE_OSMOSDR
|
#ifdef ENABLE_OSMOSDR
|
||||||
|
@ -144,17 +157,25 @@ devices_t device::find(const device_t &hint)
|
||||||
#ifdef ENABLE_HACKRF
|
#ifdef ENABLE_HACKRF
|
||||||
BOOST_FOREACH( std::string dev, hackrf_source_c::get_devices() )
|
BOOST_FOREACH( std::string dev, hackrf_source_c::get_devices() )
|
||||||
devices.push_back( device_t(dev) );
|
devices.push_back( device_t(dev) );
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_RFSPACE
|
||||||
|
BOOST_FOREACH( std::string dev, rfspace_source_c::get_devices( fake ) )
|
||||||
|
devices.push_back( device_t(dev) );
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_AIRSPY
|
||||||
|
BOOST_FOREACH( std::string dev, airspy_source_c::get_devices() )
|
||||||
|
devices.push_back( device_t(dev) );
|
||||||
#endif
|
#endif
|
||||||
/* software-only sources should be appended at the very end,
|
/* software-only sources should be appended at the very end,
|
||||||
* hopefully resulting in hardware sources to be shown first
|
* hopefully resulting in hardware sources to be shown first
|
||||||
* in a graphical interface etc... */
|
* in a graphical interface etc... */
|
||||||
|
|
||||||
#ifdef ENABLE_RTL_TCP
|
#ifdef ENABLE_RTL_TCP
|
||||||
BOOST_FOREACH( std::string dev, rtl_tcp_source_c::get_devices() )
|
BOOST_FOREACH( std::string dev, rtl_tcp_source_c::get_devices( fake ) )
|
||||||
devices.push_back( device_t(dev) );
|
devices.push_back( device_t(dev) );
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_FILE
|
#ifdef ENABLE_FILE
|
||||||
BOOST_FOREACH( std::string dev, file_source_c::get_devices() )
|
BOOST_FOREACH( std::string dev, file_source_c::get_devices( fake ) )
|
||||||
devices.push_back( device_t(dev) );
|
devices.push_back( device_t(dev) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <boost/assign.hpp>
|
#include <boost/assign.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include <gnuradio/io_signature.h>
|
#include <gnuradio/io_signature.h>
|
||||||
#include <gnuradio/blocks/file_source.h>
|
#include <gnuradio/blocks/file_source.h>
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
|
|
||||||
#include "file_source_c.h"
|
#include "file_source_c.h"
|
||||||
|
|
||||||
|
@ -73,19 +73,21 @@ file_source_c::file_source_c(const std::string &args) :
|
||||||
if (_freq < 0)
|
if (_freq < 0)
|
||||||
throw std::runtime_error("Parameter 'freq' may not be negative.");
|
throw std::runtime_error("Parameter 'freq' may not be negative.");
|
||||||
|
|
||||||
if (0 == _rate)
|
if (0 == _rate && throttle)
|
||||||
throw std::runtime_error("Parameter 'rate' is missing in arguments.");
|
throw std::runtime_error("Parameter 'rate' is missing in arguments.");
|
||||||
|
|
||||||
|
_file_rate = _rate;
|
||||||
|
|
||||||
gr::blocks::file_source::sptr src = \
|
gr::blocks::file_source::sptr src = \
|
||||||
gr::blocks::file_source::make( sizeof(gr_complex),
|
gr::blocks::file_source::make( sizeof(gr_complex),
|
||||||
filename.c_str(),
|
filename.c_str(),
|
||||||
repeat );
|
repeat );
|
||||||
|
|
||||||
if (throttle) {
|
_throttle = gr::blocks::throttle::make( sizeof(gr_complex), _file_rate );
|
||||||
gr::blocks::throttle::sptr throttle = gr::blocks::throttle::make( sizeof(gr_complex), _rate );
|
|
||||||
|
|
||||||
connect( src, 0, throttle, 0 );
|
if (throttle) {
|
||||||
connect( throttle, 0, self(), 0 );
|
connect( src, 0, _throttle, 0 );
|
||||||
|
connect( _throttle, 0, self(), 0 );
|
||||||
} else {
|
} else {
|
||||||
connect( src, 0, self(), 0 );
|
connect( src, 0, self(), 0 );
|
||||||
}
|
}
|
||||||
|
@ -100,13 +102,17 @@ std::string file_source_c::name()
|
||||||
return "IQ File Source";
|
return "IQ File Source";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> file_source_c::get_devices()
|
std::vector<std::string> file_source_c::get_devices( bool fake )
|
||||||
{
|
{
|
||||||
std::vector<std::string> devices;
|
std::vector<std::string> devices;
|
||||||
|
|
||||||
std::string args = "file='/path/to/your/file',rate=1e6,freq=100e6,repeat=true,throttle=true";
|
if ( fake )
|
||||||
args += ",label='Complex Sampled (IQ) File'";
|
{
|
||||||
devices.push_back( args );
|
std::string args = "file='/path/to/your/file'";
|
||||||
|
args += ",rate=1e6,freq=100e6,repeat=true,throttle=true";
|
||||||
|
args += ",label='Complex Sampled (IQ) File'";
|
||||||
|
devices.push_back( args );
|
||||||
|
}
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
@ -120,13 +126,24 @@ osmosdr::meta_range_t file_source_c::get_sample_rates( void )
|
||||||
{
|
{
|
||||||
osmosdr::meta_range_t range;
|
osmosdr::meta_range_t range;
|
||||||
|
|
||||||
range += osmosdr::range_t( get_sample_rate() );
|
range += osmosdr::range_t( _file_rate ); /* always return file's original rate */
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
double file_source_c::set_sample_rate( double rate )
|
double file_source_c::set_sample_rate( double rate )
|
||||||
{
|
{
|
||||||
|
if ( _file_rate != rate )
|
||||||
|
{
|
||||||
|
std::cerr << boost::format("WARNING: Overriding original sample rate of %g with %g")
|
||||||
|
% _file_rate % rate
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
_throttle->set_sample_rate( rate );
|
||||||
|
|
||||||
|
_rate = rate;
|
||||||
|
|
||||||
return get_sample_rate();
|
return get_sample_rate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define FILE_SOURCE_C_H
|
#define FILE_SOURCE_C_H
|
||||||
|
|
||||||
#include <gnuradio/hier_block2.h>
|
#include <gnuradio/hier_block2.h>
|
||||||
|
#include <gnuradio/blocks/throttle.h>
|
||||||
|
|
||||||
#include "source_iface.h"
|
#include "source_iface.h"
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public:
|
||||||
|
|
||||||
std::string name();
|
std::string name();
|
||||||
|
|
||||||
static std::vector< std::string > get_devices();
|
static std::vector< std::string > get_devices( bool fake = false );
|
||||||
|
|
||||||
size_t get_num_channels( void );
|
size_t get_num_channels( void );
|
||||||
|
|
||||||
|
@ -71,6 +72,8 @@ public:
|
||||||
std::string get_antenna( size_t chan = 0 );
|
std::string get_antenna( size_t chan = 0 );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
gr::blocks::throttle::sptr _throttle;
|
||||||
|
double _file_rate;
|
||||||
double _freq, _rate;
|
double _freq, _rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
||||||
#define BUF_NUM 32
|
#define BUF_NUM 15
|
||||||
|
|
||||||
#define BYTES_PER_SAMPLE 2 /* HackRF device consumes 8 bit unsigned IQ data */
|
#define BYTES_PER_SAMPLE 2 /* HackRF device consumes 8 bit unsigned IQ data */
|
||||||
|
|
||||||
|
@ -159,7 +159,8 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
|
||||||
_freq_corr(0),
|
_freq_corr(0),
|
||||||
_auto_gain(false),
|
_auto_gain(false),
|
||||||
_amp_gain(0),
|
_amp_gain(0),
|
||||||
_vga_gain(0)
|
_vga_gain(0),
|
||||||
|
_bandwidth(0)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -208,10 +209,11 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_sample_rate( get_sample_rates().start() );
|
set_center_freq( (get_freq_range().start() + get_freq_range().stop()) / 2.0 );
|
||||||
set_sample_rate( 10e6 );
|
set_sample_rate( get_sample_rates().start() );
|
||||||
|
set_bandwidth( 0 );
|
||||||
|
|
||||||
set_gain( 0 ); /* disable AMP gain stage by default */
|
set_gain( 14 ); /* enable AMP gain stage by default */
|
||||||
|
|
||||||
set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */
|
set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */
|
||||||
|
|
||||||
|
@ -448,7 +450,7 @@ std::vector<std::string> hackrf_sink_c::get_devices()
|
||||||
{
|
{
|
||||||
std::vector<std::string> devices;
|
std::vector<std::string> devices;
|
||||||
std::string label;
|
std::string label;
|
||||||
|
#if 0
|
||||||
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; i++) {
|
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; i++) {
|
||||||
std::string args = "hackrf=" + boost::lexical_cast< std::string >( i );
|
std::string args = "hackrf=" + boost::lexical_cast< std::string >( i );
|
||||||
|
|
||||||
|
@ -461,7 +463,49 @@ std::vector<std::string> hackrf_sink_c::get_devices()
|
||||||
args += ",label='" + label + "'";
|
args += ",label='" + label + "'";
|
||||||
devices.push_back( args );
|
devices.push_back( args );
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
hackrf_init(); /* call only once before the first open */
|
||||||
|
|
||||||
|
_usage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
hackrf_device *dev = NULL;
|
||||||
|
ret = hackrf_open(&dev);
|
||||||
|
if ( HACKRF_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
std::string args = "hackrf=0";
|
||||||
|
|
||||||
|
label = "HackRF";
|
||||||
|
|
||||||
|
uint8_t board_id;
|
||||||
|
ret = hackrf_board_id_read( dev, &board_id );
|
||||||
|
if ( HACKRF_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
label += std::string(" ") + hackrf_board_id_name(hackrf_board_id(board_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
args += ",label='" + label + "'";
|
||||||
|
devices.push_back( args );
|
||||||
|
|
||||||
|
ret = hackrf_close(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
_usage--;
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
hackrf_exit(); /* call only once after last close */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +539,7 @@ double hackrf_sink_c::set_sample_rate( double rate )
|
||||||
ret = hackrf_set_sample_rate( _dev, rate );
|
ret = hackrf_set_sample_rate( _dev, rate );
|
||||||
if ( HACKRF_SUCCESS == ret ) {
|
if ( HACKRF_SUCCESS == ret ) {
|
||||||
_sample_rate = rate;
|
_sample_rate = rate;
|
||||||
set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
|
//set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
|
||||||
} else {
|
} else {
|
||||||
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "hackrf_source_c.h"
|
#include <stdexcept>
|
||||||
#include <gnuradio/io_signature.h>
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/assign.hpp>
|
#include <boost/assign.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
@ -36,15 +36,16 @@
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <gnuradio/io_signature.h>
|
||||||
#include <iostream>
|
|
||||||
|
#include "hackrf_source_c.h"
|
||||||
|
|
||||||
#include "arg_helpers.h"
|
#include "arg_helpers.h"
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
||||||
#define BUF_NUM 32
|
#define BUF_NUM 15
|
||||||
|
|
||||||
#define BYTES_PER_SAMPLE 2 /* HackRF device produces 8 bit unsigned IQ data */
|
#define BYTES_PER_SAMPLE 2 /* HackRF device produces 8 bit unsigned IQ data */
|
||||||
|
|
||||||
|
@ -93,7 +94,8 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
|
||||||
_auto_gain(false),
|
_auto_gain(false),
|
||||||
_amp_gain(0),
|
_amp_gain(0),
|
||||||
_lna_gain(0),
|
_lna_gain(0),
|
||||||
_vga_gain(0)
|
_vga_gain(0),
|
||||||
|
_bandwidth(0)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -162,10 +164,11 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_sample_rate( get_sample_rates().start() );
|
set_center_freq( (get_freq_range().start() + get_freq_range().stop()) / 2.0 );
|
||||||
set_sample_rate( 10e6 );
|
set_sample_rate( get_sample_rates().start() );
|
||||||
|
set_bandwidth( 0 );
|
||||||
|
|
||||||
set_gain( 0 ); /* disable AMP gain stage by default */
|
set_gain( 14 ); /* enable AMP gain stage by default */
|
||||||
|
|
||||||
set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */
|
set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */
|
||||||
|
|
||||||
|
@ -340,7 +343,7 @@ std::vector<std::string> hackrf_source_c::get_devices()
|
||||||
{
|
{
|
||||||
std::vector<std::string> devices;
|
std::vector<std::string> devices;
|
||||||
std::string label;
|
std::string label;
|
||||||
|
#if 0
|
||||||
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; i++) {
|
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; i++) {
|
||||||
std::string args = "hackrf=" + boost::lexical_cast< std::string >( i );
|
std::string args = "hackrf=" + boost::lexical_cast< std::string >( i );
|
||||||
|
|
||||||
|
@ -353,7 +356,49 @@ std::vector<std::string> hackrf_source_c::get_devices()
|
||||||
args += ",label='" + label + "'";
|
args += ",label='" + label + "'";
|
||||||
devices.push_back( args );
|
devices.push_back( args );
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
hackrf_init(); /* call only once before the first open */
|
||||||
|
|
||||||
|
_usage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
hackrf_device *dev = NULL;
|
||||||
|
ret = hackrf_open(&dev);
|
||||||
|
if ( HACKRF_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
std::string args = "hackrf=0";
|
||||||
|
|
||||||
|
label = "HackRF";
|
||||||
|
|
||||||
|
uint8_t board_id;
|
||||||
|
ret = hackrf_board_id_read( dev, &board_id );
|
||||||
|
if ( HACKRF_SUCCESS == ret )
|
||||||
|
{
|
||||||
|
label += std::string(" ") + hackrf_board_id_name(hackrf_board_id(board_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
args += ",label='" + label + "'";
|
||||||
|
devices.push_back( args );
|
||||||
|
|
||||||
|
ret = hackrf_close(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _usage_mutex );
|
||||||
|
|
||||||
|
_usage--;
|
||||||
|
|
||||||
|
if ( _usage == 0 )
|
||||||
|
hackrf_exit(); /* call only once after last close */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +432,7 @@ double hackrf_source_c::set_sample_rate( double rate )
|
||||||
ret = hackrf_set_sample_rate( _dev, rate );
|
ret = hackrf_set_sample_rate( _dev, rate );
|
||||||
if ( HACKRF_SUCCESS == ret ) {
|
if ( HACKRF_SUCCESS == ret ) {
|
||||||
_sample_rate = rate;
|
_sample_rate = rate;
|
||||||
set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
|
//set_bandwidth( 0.0 ); /* bandwidth of 0 means automatic filter selection */
|
||||||
} else {
|
} else {
|
||||||
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${LIBMIRISDR_INCLUDE_DIR}
|
${LIBMIRISDR_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(mirisdr_srcs
|
set(mirisdr_srcs
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
#define BUF_SIZE 2304 * 8 * 2
|
#define BUF_SIZE 2304 * 8 * 2
|
||||||
#define BUF_NUM 32
|
#define BUF_NUM 15
|
||||||
#define BUF_SKIP 1 // buffers to skip due to garbage
|
#define BUF_SKIP 1 // buffers to skip due to garbage
|
||||||
|
|
||||||
#define BYTES_PER_SAMPLE 4 // mirisdr device delivers 16 bit signed IQ data
|
#define BYTES_PER_SAMPLE 4 // mirisdr device delivers 16 bit signed IQ data
|
||||||
|
@ -210,7 +210,7 @@ void miri_source_c::_mirisdr_wait(miri_source_c *obj)
|
||||||
|
|
||||||
void miri_source_c::mirisdr_wait()
|
void miri_source_c::mirisdr_wait()
|
||||||
{
|
{
|
||||||
int ret = mirisdr_read_async( _dev, _mirisdr_callback, (void *)this, 0, BUF_SIZE );
|
int ret = mirisdr_read_async( _dev, _mirisdr_callback, (void *)this, _buf_num, BUF_SIZE );
|
||||||
|
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${LIBOSMOSDR_INCLUDE_DIR}
|
${LIBOSMOSDR_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(osmosdr_srcs
|
set(osmosdr_srcs
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
#define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */
|
||||||
#define BUF_NUM 32
|
#define BUF_NUM 15
|
||||||
#define BUF_SKIP 1 // buffers to skip due to garbage
|
#define BUF_SKIP 1 // buffers to skip due to garbage
|
||||||
|
|
||||||
#define BYTES_PER_SAMPLE 4 // osmosdr device delivers 16 bit signed IQ data
|
#define BYTES_PER_SAMPLE 4 // osmosdr device delivers 16 bit signed IQ data
|
||||||
|
@ -203,7 +203,7 @@ void osmosdr_src_c::_osmosdr_wait(osmosdr_src_c *obj)
|
||||||
|
|
||||||
void osmosdr_src_c::osmosdr_wait()
|
void osmosdr_src_c::osmosdr_wait()
|
||||||
{
|
{
|
||||||
int ret = osmosdr_read_async( _dev, _osmosdr_callback, (void *)this, 0, _buf_len );
|
int ret = osmosdr_read_async( _dev, _osmosdr_callback, (void *)this, _buf_num, _buf_len );
|
||||||
|
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Copyright 2012 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This file is part of GNU Radio
|
||||||
|
#
|
||||||
|
# GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# This file included, use CMake directory variables
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(rfspace_srcs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rfspace_source_c.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Append gnuradio-osmosdr library sources
|
||||||
|
########################################################################
|
||||||
|
list(APPEND gr_osmosdr_srcs ${rfspace_srcs})
|
||||||
|
#list(APPEND gr_osmosdr_libs ...)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,174 @@
|
||||||
|
/* -*- c++ -*- */
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
|
||||||
|
*
|
||||||
|
* GNU Radio is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GNU Radio is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Radio; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDED_RFSPACE_SOURCE_C_H
|
||||||
|
#define INCLUDED_RFSPACE_SOURCE_C_H
|
||||||
|
|
||||||
|
//#define USE_ASIO
|
||||||
|
|
||||||
|
#ifdef USE_ASIO
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#endif
|
||||||
|
#include <gnuradio/thread/thread.h>
|
||||||
|
#include <gnuradio/block.h>
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
|
||||||
|
#include <boost/circular_buffer.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
|
||||||
|
#include "osmosdr/ranges.h"
|
||||||
|
#include "source_iface.h"
|
||||||
|
#ifdef USE_ASIO
|
||||||
|
using boost::asio::ip::tcp;
|
||||||
|
using boost::asio::ip::udp;
|
||||||
|
#endif
|
||||||
|
class rfspace_source_c;
|
||||||
|
|
||||||
|
#ifndef SOCKET
|
||||||
|
#define SOCKET int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use boost::shared_ptr's instead of raw pointers for all access
|
||||||
|
* to gr_blocks (and many other data structures). The shared_ptr gets
|
||||||
|
* us transparent reference counting, which greatly simplifies storage
|
||||||
|
* management issues. This is especially helpful in our hybrid
|
||||||
|
* C++ / Python system.
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
|
||||||
|
*
|
||||||
|
* As a convention, the _sptr suffix indicates a boost::shared_ptr
|
||||||
|
*/
|
||||||
|
typedef boost::shared_ptr<rfspace_source_c> rfspace_source_c_sptr;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return a shared_ptr to a new instance of rfspace_source_c.
|
||||||
|
*
|
||||||
|
* To avoid accidental use of raw pointers, rfspace_source_c's
|
||||||
|
* constructor is private. rfspace_make_source_c is the public
|
||||||
|
* interface for creating new instances.
|
||||||
|
*/
|
||||||
|
rfspace_source_c_sptr make_rfspace_source_c (const std::string & args = "");
|
||||||
|
|
||||||
|
class rfspace_source_c :
|
||||||
|
public gr::sync_block,
|
||||||
|
public source_iface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The friend declaration allows rfspace_make_source_c to
|
||||||
|
// access the private constructor.
|
||||||
|
friend rfspace_source_c_sptr make_rfspace_source_c (const std::string & args);
|
||||||
|
|
||||||
|
rfspace_source_c (const std::string & args); // private constructor
|
||||||
|
|
||||||
|
public:
|
||||||
|
~rfspace_source_c (); // public destructor
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool stop();
|
||||||
|
|
||||||
|
int work(int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items );
|
||||||
|
|
||||||
|
static std::vector< std::string > get_devices( bool fake = false );
|
||||||
|
|
||||||
|
size_t get_num_channels( void );
|
||||||
|
|
||||||
|
osmosdr::meta_range_t get_sample_rates( void );
|
||||||
|
double set_sample_rate( double rate );
|
||||||
|
double get_sample_rate( void );
|
||||||
|
|
||||||
|
osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
|
||||||
|
double set_center_freq( double freq, size_t chan = 0 );
|
||||||
|
double get_center_freq( size_t chan = 0 );
|
||||||
|
double set_freq_corr( double ppm, size_t chan = 0 );
|
||||||
|
double get_freq_corr( size_t chan = 0 );
|
||||||
|
|
||||||
|
std::vector<std::string> get_gain_names( size_t chan = 0 );
|
||||||
|
osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
|
||||||
|
osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
|
||||||
|
bool set_gain_mode( bool automatic, size_t chan = 0 );
|
||||||
|
bool get_gain_mode( size_t chan = 0 );
|
||||||
|
double set_gain( double gain, size_t chan = 0 );
|
||||||
|
double set_gain( double gain, const std::string & name, size_t chan = 0 );
|
||||||
|
double get_gain( size_t chan = 0 );
|
||||||
|
double get_gain( const std::string & name, size_t chan = 0 );
|
||||||
|
|
||||||
|
std::vector< std::string > get_antennas( size_t chan = 0 );
|
||||||
|
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
|
||||||
|
std::string get_antenna( size_t chan = 0 );
|
||||||
|
|
||||||
|
double set_bandwidth( double bandwidth, size_t chan = 0 );
|
||||||
|
double get_bandwidth( size_t chan = 0 );
|
||||||
|
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||||
|
|
||||||
|
private: /* functions */
|
||||||
|
void apply_channel( unsigned char *cmd, size_t chan = 0 );
|
||||||
|
|
||||||
|
bool transaction( const unsigned char *cmd, size_t size );
|
||||||
|
|
||||||
|
bool transaction( const unsigned char *cmd, size_t size,
|
||||||
|
std::vector< unsigned char > &response );
|
||||||
|
|
||||||
|
void usb_read_task();
|
||||||
|
|
||||||
|
private: /* members */
|
||||||
|
enum radio_type
|
||||||
|
{
|
||||||
|
RADIO_UNKNOWN = 0,
|
||||||
|
RFSPACE_SDR_IQ,
|
||||||
|
RFSPACE_SDR_IP,
|
||||||
|
RFSPACE_NETSDR
|
||||||
|
};
|
||||||
|
|
||||||
|
radio_type _radio;
|
||||||
|
|
||||||
|
#ifdef USE_ASIO
|
||||||
|
boost::asio::io_service _io_service;
|
||||||
|
tcp::resolver _resolver;
|
||||||
|
tcp::socket _t;
|
||||||
|
udp::socket _u;
|
||||||
|
#else
|
||||||
|
SOCKET _tcp;
|
||||||
|
SOCKET _udp;
|
||||||
|
#endif
|
||||||
|
int _usb;
|
||||||
|
bool _running;
|
||||||
|
bool _keep_running;
|
||||||
|
uint16_t _sequence;
|
||||||
|
|
||||||
|
size_t _nchan;
|
||||||
|
double _sample_rate;
|
||||||
|
double _bandwidth;
|
||||||
|
|
||||||
|
gr::thread::thread _thread;
|
||||||
|
bool _run_usb_read_task;
|
||||||
|
|
||||||
|
boost::circular_buffer<gr_complex> *_fifo;
|
||||||
|
boost::mutex _fifo_lock;
|
||||||
|
boost::condition_variable _samp_avail;
|
||||||
|
|
||||||
|
std::vector< unsigned char > _resp;
|
||||||
|
boost::mutex _resp_lock;
|
||||||
|
boost::condition_variable _resp_avail;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* INCLUDED_RFSPACE_SOURCE_C_H */
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${LIBRTLSDR_INCLUDE_DIR}
|
${LIBRTLSDR_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(rtl_srcs
|
set(rtl_srcs
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue