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}")
|
||||
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(-Wextra)
|
||||
ADD_DEFINITIONS(-Wno-unused)
|
||||
ADD_DEFINITIONS(-Wno-unused-parameter)
|
||||
ADD_DEFINITIONS(-Wsign-compare)
|
||||
#ADD_DEFINITIONS(-Wconversion)
|
||||
#ADD_DEFINITIONS(-pedantic)
|
||||
|
@ -86,7 +90,7 @@ ELSEIF(MSVC)
|
|||
ADD_DEFINITIONS(/arch:AVX)
|
||||
ADD_DEFINITIONS(-DUSE_AVX)
|
||||
ENDIF()
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
ENDIF()
|
||||
|
||||
########################################################################
|
||||
# Setup boost
|
||||
|
@ -97,6 +101,7 @@ MESSAGE(STATUS "Configuring Boost C++ Libraries...")
|
|||
SET(BOOST_REQUIRED_COMPONENTS
|
||||
thread
|
||||
system
|
||||
filesystem
|
||||
)
|
||||
|
||||
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(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
|
||||
########################################################################
|
||||
|
@ -154,12 +179,48 @@ find_package(LibOsmoSDR)
|
|||
find_package(LibRTLSDR)
|
||||
find_package(LibMiriSDR)
|
||||
find_package(LibHackRF)
|
||||
find_package(LibAIRSPY)
|
||||
find_package(LibbladeRF)
|
||||
find_package(Doxygen)
|
||||
|
||||
set(PYTHON_RUNTIME_CHECK TRUE)
|
||||
|
||||
if(NOT GNURADIO_RUNTIME_FOUND)
|
||||
message(FATAL_ERROR "GnuRadio Runtime required to build " ${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
message(STATUS "Enabling built-in GNU Radio runtime...")
|
||||
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
|
||||
|
@ -211,10 +272,11 @@ if(SWIG_FOUND)
|
|||
endif(SWIG_FOUND)
|
||||
|
||||
include(GrComponent)
|
||||
GR_REGISTER_COMPONENT("Python support" ENABLE_PYTHON
|
||||
GR_REGISTER_COMPONENT("Python bindings" ENABLE_PYTHON
|
||||
PYTHONLIBS_FOUND
|
||||
SWIG_FOUND
|
||||
SWIG_VERSION_CHECK
|
||||
PYTHON_RUNTIME_CHECK
|
||||
)
|
||||
|
||||
########################################################################
|
||||
|
|
13
README
13
README
|
@ -4,13 +4,16 @@ as well supports:
|
|||
* FUNcube Dongle through libgnuradio-fcd
|
||||
* FUNcube Dongle Pro+ through gr-fcdproplus
|
||||
* 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
|
||||
* RTL-TCP spectrum server (see librtlsdr project)
|
||||
* MSi2500 based DVB-T dongles through libmirisdr
|
||||
* 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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
properly installed. The build system of gr-osmosdr will recognize them and
|
||||
enable specific source/sink components thereafter.
|
||||
|
|
289
apps/osmocom_fft
289
apps/osmocom_fft
|
@ -66,12 +66,18 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
help="Set sample rate (bandwidth), minimum by default")
|
||||
parser.add_option("-f", "--center-freq", type="eng_float", default=None,
|
||||
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)")
|
||||
parser.add_option("-g", "--gain", type="eng_float", default=None,
|
||||
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,
|
||||
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,
|
||||
help="Enable oscilloscope display")
|
||||
parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
|
||||
|
@ -111,16 +117,29 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
options.samp_rate = self.src.get_sample_rates().start()
|
||||
|
||||
if options.gain is None:
|
||||
gain = self.src.get_gain()
|
||||
if gain is None:
|
||||
# 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:
|
||||
freq = self.src.get_center_freq()
|
||||
if freq != 0:
|
||||
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)
|
||||
self.src.set_bandwidth(input_rate)
|
||||
|
||||
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[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
|
||||
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(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
|
||||
#for key in (SAMP_RATE_KEY, BWIDTH_KEY, CENTER_FREQ_KEY, FREQ_CORR_KEY):
|
||||
#print 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,
|
||||
fft_size=options.fft_size,
|
||||
sample_rate=input_rate,
|
||||
|
@ -189,6 +227,12 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
|
||||
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
|
||||
if not(self.set_freq(options.center_freq)):
|
||||
self._set_status_msg("Failed to set initial frequency")
|
||||
|
@ -201,7 +245,8 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
|
||||
def _build_gui(self, vbox):
|
||||
|
||||
vbox.Add(self.scope.win, 0, wx.EXPAND)
|
||||
if hasattr(self.scope, 'win'):
|
||||
vbox.Add(self.scope.win, 1, wx.EXPAND)
|
||||
vbox.AddSpacer(3)
|
||||
|
||||
# add control area at the bottom
|
||||
|
@ -227,7 +272,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
# Add frequency controls to top window sizer
|
||||
vbox.Add(fc_vbox, 0, wx.EXPAND)
|
||||
vbox.AddSpacer(5)
|
||||
vbox.AddStretchSpacer()
|
||||
|
||||
freq_hbox.AddSpacer(3)
|
||||
forms.text_box(
|
||||
|
@ -240,6 +284,8 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
)
|
||||
freq_hbox.AddSpacer(5)
|
||||
|
||||
try: # range.start() == range.stop() in file= mode
|
||||
|
||||
forms.slider(
|
||||
parent=self.panel, sizer=freq_hbox,
|
||||
proportion=3,
|
||||
|
@ -247,10 +293,15 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
key=CENTER_FREQ_KEY,
|
||||
minimum=self[FREQ_RANGE_KEY].start(),
|
||||
maximum=self[FREQ_RANGE_KEY].stop(),
|
||||
num_steps=101,
|
||||
num_steps=1000,
|
||||
)
|
||||
freq_hbox.AddSpacer(3)
|
||||
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
if self[FREQ_CORR_KEY] != None: # show frequency correction scrollbar
|
||||
|
||||
corr_hbox.AddSpacer(3)
|
||||
forms.text_box(
|
||||
parent=self.panel, sizer=corr_hbox,
|
||||
|
@ -286,7 +337,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
# Add gain controls to top window sizer
|
||||
vbox.Add(gc_vbox, 0, wx.EXPAND)
|
||||
vbox.AddSpacer(5)
|
||||
vbox.AddStretchSpacer()
|
||||
|
||||
for gain_name in self.get_gain_names():
|
||||
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),
|
||||
minimum=range.start(),
|
||||
maximum=range.stop(),
|
||||
step_size=range.step(),
|
||||
step_size=range.step() or (range.stop() - range.start())/10,
|
||||
)
|
||||
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.AddSpacer(5)
|
||||
vbox.AddStretchSpacer()
|
||||
|
||||
bwidth_hbox.AddSpacer(3)
|
||||
forms.text_box(
|
||||
|
@ -357,7 +406,7 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
key=BWIDTH_KEY,
|
||||
minimum=bw_range.start(),
|
||||
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)
|
||||
|
||||
|
@ -381,7 +430,6 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
# Add frequency controls to top window sizer
|
||||
vbox.Add(sr_vbox, 0, wx.EXPAND)
|
||||
vbox.AddSpacer(5)
|
||||
vbox.AddStretchSpacer()
|
||||
|
||||
sr_hbox.AddSpacer(3)
|
||||
forms.text_box(
|
||||
|
@ -405,11 +453,228 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
#)
|
||||
#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):
|
||||
samp_rate = self.src.set_sample_rate(samp_rate)
|
||||
if hasattr(self.scope, 'set_sample_rate'):
|
||||
self.scope.set_sample_rate(samp_rate)
|
||||
if self._verbose:
|
||||
print "Set sample rate to:", samp_rate
|
||||
|
||||
try:
|
||||
self[BWIDTH_KEY] = self.set_bandwidth(samp_rate)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
return samp_rate
|
||||
|
||||
def get_gain_names(self):
|
||||
|
@ -436,6 +701,8 @@ class app_top_block(stdgui2.std_top_block, pubsub):
|
|||
if self._verbose:
|
||||
print "Set bandwidth to:", bw
|
||||
|
||||
return bw
|
||||
|
||||
def set_freq_from_callback(self, freq):
|
||||
freq = self.src.set_center_freq(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)
|
||||
|
||||
if not self.options.oscilloscope:
|
||||
if hasattr(self.scope, 'set_baseband_freq'):
|
||||
self.scope.set_baseband_freq(freq)
|
||||
|
||||
if freq is not None:
|
||||
|
|
|
@ -314,6 +314,130 @@ class app_gui(pubsub):
|
|||
except RuntimeError:
|
||||
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
|
||||
##################################################
|
||||
|
|
|
@ -33,6 +33,10 @@ WAVEFORM2_FREQ_KEY = 'waveform2_freq'
|
|||
FREQ_RANGE_KEY = 'freq_range'
|
||||
GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
|
||||
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'
|
||||
|
||||
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(1, 1, gr.sizeof_gr_complex)) # Output signature
|
||||
|
||||
self._bits = blocks.vector_source_b(self.gen_gsm_seq(), True)
|
||||
|
||||
self._symb_rate = 270833
|
||||
self._symb_rate = 13e6 / 48;
|
||||
self._samples_per_symbol = 2
|
||||
|
||||
bits_per_symbol = 1
|
||||
self._pack = blocks.unpacked_to_packed_bb(bits_per_symbol, gr.GR_MSB_FIRST)
|
||||
self._data = blocks.vector_source_b(self.gen_gsm_seq(), True, 2)
|
||||
self._split = blocks.vector_to_streams(gr.sizeof_char*1, 2)
|
||||
|
||||
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._symb_rate * self._samples_per_symbol) / sample_rate )
|
||||
|
||||
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):
|
||||
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],
|
||||
list(numpy.random.randint(0, 2, 58)),
|
||||
[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):
|
||||
return \
|
||||
|
@ -135,6 +147,12 @@ class top_block(gr.top_block, pubsub):
|
|||
self[WAVEFORM_OFFSET_KEY] = options.offset
|
||||
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
|
||||
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(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
|
||||
for key in (SAMP_RATE_KEY, GAIN_KEY, BWIDTH_KEY,
|
||||
TX_FREQ_KEY, FREQ_CORR_KEY, AMPLITUDE_KEY,
|
||||
|
@ -240,6 +263,28 @@ class top_block(gr.top_block, pubsub):
|
|||
if self._verbose:
|
||||
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):
|
||||
if freq is None:
|
||||
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)
|
||||
pkg_check_modules (LIBMIRISDR_PKG libmirisdr)
|
||||
find_path(LIBMIRISDR_INCLUDE_DIR NAMES mirisdr.h
|
||||
find_path(LIBMIRISDR_INCLUDE_DIRS NAMES mirisdr.h
|
||||
PATHS
|
||||
${LIBMIRISDR_PKG_INCLUDE_DIRS}
|
||||
/usr/include
|
||||
|
@ -14,14 +14,14 @@ if(NOT LIBMIRISDR_FOUND)
|
|||
/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")
|
||||
message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIR}, ${LIBMIRISDR_LIBRARIES}")
|
||||
else(LIBMIRISDR_INCLUDE_DIR AND LIBMIRISDR_LIBRARIES)
|
||||
message(STATUS "Found libmirisdr: ${LIBMIRISDR_INCLUDE_DIRS}, ${LIBMIRISDR_LIBRARIES}")
|
||||
else(LIBMIRISDR_INCLUDE_DIRS AND LIBMIRISDR_LIBRARIES)
|
||||
set(LIBMIRISDR_FOUND FALSE CACHE INTERNAL "libmirisdr 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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
if(NOT LIBOSMOSDR_FOUND)
|
||||
pkg_check_modules (LIBOSMOSDR_PKG libosmosdr)
|
||||
find_path(LIBOSMOSDR_INCLUDE_DIR NAMES osmosdr.h
|
||||
find_path(LIBOSMOSDR_INCLUDE_DIRS NAMES osmosdr.h
|
||||
PATHS
|
||||
${LIBOSMOSDR_PKG_INCLUDE_DIRS}
|
||||
/usr/include
|
||||
|
@ -14,14 +14,14 @@ if(NOT LIBOSMOSDR_FOUND)
|
|||
/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")
|
||||
message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIR}, ${LIBOSMOSDR_LIBRARIES}")
|
||||
else(LIBOSMOSDR_INCLUDE_DIR AND LIBOSMOSDR_LIBRARIES)
|
||||
message(STATUS "Found libosmosdr: ${LIBOSMOSDR_INCLUDE_DIRS}, ${LIBOSMOSDR_LIBRARIES}")
|
||||
else(LIBOSMOSDR_INCLUDE_DIRS AND LIBOSMOSDR_LIBRARIES)
|
||||
set(LIBOSMOSDR_FOUND FALSE CACHE INTERNAL "libosmosdr 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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
if(NOT LIBRTLSDR_FOUND)
|
||||
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
|
||||
${LIBRTLSDR_PKG_INCLUDE_DIRS}
|
||||
/usr/include
|
||||
|
@ -14,14 +14,14 @@ if(NOT LIBRTLSDR_FOUND)
|
|||
/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")
|
||||
message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIR}, ${LIBRTLSDR_LIBRARIES}")
|
||||
else(LIBRTLSDR_INCLUDE_DIR AND LIBRTLSDR_LIBRARIES)
|
||||
message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIRS}, ${LIBRTLSDR_LIBRARIES}")
|
||||
else(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES)
|
||||
set(LIBRTLSDR_FOUND FALSE CACHE INTERNAL "librtlsdr 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)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
if(NOT LIBBLADERF_FOUND)
|
||||
pkg_check_modules (LIBBLADERF_PKG libbladeRF)
|
||||
find_path(LIBBLADERF_INCLUDE_DIR NAMES libbladeRF.h
|
||||
find_path(LIBBLADERF_INCLUDE_DIRS NAMES libbladeRF.h
|
||||
PATHS
|
||||
${LIBBLADERF_PKG_INCLUDE_DIRS}
|
||||
/usr/include
|
||||
|
@ -14,14 +14,14 @@ if(NOT LIBBLADERF_FOUND)
|
|||
/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")
|
||||
message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIR}, ${LIBBLADERF_LIBRARIES}")
|
||||
else(LIBBLADERF_INCLUDE_DIR AND LIBBLADERF_LIBRARIES)
|
||||
message(STATUS "Found libbladeRF: ${LIBBLADERF_INCLUDE_DIRS}, ${LIBBLADERF_LIBRARIES}")
|
||||
else(LIBBLADERF_INCLUDE_DIRS AND LIBBLADERF_LIBRARIES)
|
||||
set(LIBBLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF 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)
|
||||
|
|
|
@ -48,8 +48,15 @@ else(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
|
||||
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)
|
||||
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_LIBRARY_DIRS - directories for the library path
|
||||
# GR_TEST_PYTHON_DIRS - directories for the python path
|
||||
# GR_TEST_ENVIRONS - other environment key/value pairs
|
||||
########################################################################
|
||||
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?
|
||||
|
||||
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
|
||||
#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}")
|
||||
|
||||
#generate a bat file that sets the environment and runs the test
|
||||
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)
|
||||
file(WRITE ${sh_file} "#!${SHELL}\n")
|
||||
#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@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/@GR_LIBRARY_DIR@
|
||||
includedir=${prefix}/@GR_INCLUDE_DIR@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: @CPACK_PACKAGE_NAME@
|
||||
Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@
|
||||
URL: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
||||
Version: @CPACK_PACKAGE_VERSION@
|
||||
Requires: gnuradio-runtime gnuradio-blocks
|
||||
Requires.private: @GR_OSMOSDR_PC_REQUIRES@
|
||||
Requires: @GR_OSMOSDR_PC_REQUIRES@
|
||||
Requires.private:
|
||||
Conflicts:
|
||||
Cflags: -I${includedir} @GR_OSMOSDR_PC_CFLAGS@
|
||||
Libs: -L${libdir} -lgnuradio-osmosdr
|
||||
|
|
|
@ -26,7 +26,7 @@ MAIN_TMPL = """\
|
|||
<category>$($sourk.title())s</category>
|
||||
<throttle>1</throttle>
|
||||
<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)
|
||||
#for $n in range($max_nchan)
|
||||
\#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 Pro+ through gr-fcdproplus
|
||||
* 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
|
||||
* RTL-TCP spectrum server (see librtlsdr project)
|
||||
* MSi2500 based DVB-T dongles through libmirisdr
|
||||
* gnuradio .cfile input through libgnuradio-blocks
|
||||
* RFSPACE SDR-IQ, SDR-IP, NetSDR (incl. X2 option)
|
||||
* AirSpy Wideband Receiver through libairspy
|
||||
#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.
|
||||
|
||||
|
@ -145,22 +146,22 @@ Lines ending with ... mean it's possible to bind devices together by specifying
|
|||
|
||||
#if $sourk == 'source':
|
||||
fcd=0[,device=hw:2][,type=2]
|
||||
hackrf=0[,buffers=32]
|
||||
miri=0[,buffers=32] ...
|
||||
rtl=serial_number ...
|
||||
rtl=0[,rtl_xtal=28.8e6][,tuner_xtal=28.8e6] ...
|
||||
rtl=1[,buffers=32][,buflen=N*512] ...
|
||||
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] ...
|
||||
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] ...
|
||||
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
|
||||
#if $sourk == 'sink':
|
||||
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\\\\''] ...
|
||||
#end if
|
||||
|
||||
Num Channels:
|
||||
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
|
||||
* 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
|
||||
* \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.
|
||||
* \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
|
||||
* \return the actual filter bandwidth in Hz
|
||||
*/
|
||||
|
|
|
@ -289,7 +289,7 @@ public:
|
|||
|
||||
/*!
|
||||
* 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
|
||||
* \return the actual filter bandwidth in Hz
|
||||
*/
|
||||
|
|
|
@ -49,6 +49,176 @@ GR_OSMOSDR_APPEND_LIBS(
|
|||
${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
|
||||
########################################################################
|
||||
|
@ -101,7 +271,7 @@ endif(ENABLE_RTL)
|
|||
########################################################################
|
||||
# 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)
|
||||
GR_INCLUDE_SUBDIRECTORY(rtl_tcp)
|
||||
endif(ENABLE_RTL_TCP)
|
||||
|
@ -138,6 +308,22 @@ if(ENABLE_BLADERF)
|
|||
GR_INCLUDE_SUBDIRECTORY(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
|
||||
########################################################################
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
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_libs ${LIBBLADERF_LIBRARIES})
|
||||
|
||||
|
|
|
@ -36,55 +36,277 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#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;
|
||||
|
||||
bladerf_common::bladerf_common() : running(true)
|
||||
{
|
||||
const char *env_fifo_size;
|
||||
size_t fifo_size;
|
||||
boost::mutex bladerf_common::_devs_mutex;
|
||||
std::list<boost::weak_ptr<struct bladerf> > bladerf_common::_devs;
|
||||
|
||||
/* 1 Sample = i,q (2 int16_t's) */
|
||||
this->raw_sample_buf = new int16_t[2 * BLADERF_SAMPLE_BLOCK_SIZE];
|
||||
if (!raw_sample_buf) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) +
|
||||
" has failed to allocate a raw sample buffer!" );
|
||||
bladerf_common::bladerf_common() : _is_running(false) {}
|
||||
bladerf_common::~bladerf_common() {}
|
||||
|
||||
bladerf_sptr bladerf_common:: get_cached_device(struct bladerf_devinfo devinfo)
|
||||
{
|
||||
/* Lock to _devs must be aquired by caller */
|
||||
BOOST_FOREACH( boost::weak_ptr<struct bladerf> dev, _devs )
|
||||
{
|
||||
struct bladerf_devinfo other_devinfo;
|
||||
|
||||
int rv = bladerf_get_devinfo(bladerf_sptr(dev).get(), &other_devinfo);
|
||||
if (rv < 0)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||
"Failed to get devinfo for cached device.");
|
||||
|
||||
if (bladerf_devinfo_matches(&devinfo, &other_devinfo)) {
|
||||
return bladerf_sptr(dev);
|
||||
}
|
||||
}
|
||||
|
||||
env_fifo_size = getenv(BLADERF_FIFO_SIZE_ENV);
|
||||
fifo_size = BLADERF_SAMPLE_FIFO_SIZE;
|
||||
return bladerf_sptr();
|
||||
}
|
||||
|
||||
if (env_fifo_size != NULL) {
|
||||
void bladerf_common::close(void* dev)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(_devs_mutex);
|
||||
|
||||
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 {
|
||||
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;
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
if (!this->sample_fifo)
|
||||
throw std::runtime_error( std::string(__FUNCTION__) +
|
||||
" has failed to allocate a sample FIFO!" );
|
||||
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 );
|
||||
}
|
||||
|
||||
bladerf_common::~bladerf_common()
|
||||
/* Load an FPGA */
|
||||
if ( dict.count("fpga") )
|
||||
{
|
||||
delete[] this->raw_sample_buf;
|
||||
delete this->sample_fifo;
|
||||
|
||||
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()
|
||||
|
@ -116,33 +338,41 @@ osmosdr::freq_range_t bladerf_common::filter_bandwidths()
|
|||
2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14;
|
||||
|
||||
BOOST_FOREACH( double half_bw, half_bandwidths )
|
||||
bandwidths += osmosdr::range_t( half_bw * 2.e6 );
|
||||
bandwidths += osmosdr::range_t( half_bw * 2e6 );
|
||||
|
||||
return bandwidths;
|
||||
}
|
||||
|
||||
std::vector< std::string > bladerf_common::devices()
|
||||
{
|
||||
struct ::bladerf_devinfo *devices;
|
||||
struct bladerf_devinfo *devices;
|
||||
ssize_t n_devices;
|
||||
std::vector< std::string > ret;
|
||||
|
||||
n_devices = bladerf_get_device_list(&devices);
|
||||
|
||||
if (n_devices > 0) {
|
||||
for (ssize_t i = 0; i < n_devices; i++) {
|
||||
|
||||
if (n_devices > 0)
|
||||
{
|
||||
for (ssize_t i = 0; i < n_devices; i++)
|
||||
{
|
||||
std::stringstream s;
|
||||
std::string dev(devices[i].path);
|
||||
std::string serial(devices[i].serial);
|
||||
|
||||
s << "bladerf=" << dev.substr(dev.find_first_of("01234567890")) << ","
|
||||
<< "label='nuand bladeRF SN " << std::setfill('0') << std::setw(16)
|
||||
<< devices[i].serial << "'";
|
||||
s << "bladerf=" << devices[i].instance << ","
|
||||
<< "label='nuand bladeRF";
|
||||
|
||||
if ( serial.length() == 32 )
|
||||
serial.replace( 4, 24, "..." );
|
||||
|
||||
if ( serial.length() )
|
||||
s << " SN " << serial;
|
||||
|
||||
s << "'";
|
||||
|
||||
ret.push_back(s.str());
|
||||
}
|
||||
|
||||
bladerf_free_device_list(devices, n_devices);
|
||||
bladerf_free_device_list(devices);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -150,12 +380,83 @@ std::vector< std::string > bladerf_common::devices()
|
|||
|
||||
bool bladerf_common::is_running()
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(this->state_lock);
|
||||
return this->running;
|
||||
boost::shared_lock<boost::shared_mutex> lock(_state_lock);
|
||||
|
||||
return _is_running;
|
||||
}
|
||||
|
||||
void bladerf_common::set_running( bool is_running )
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lock(this->state_lock);
|
||||
this->running = is_running;
|
||||
boost::unique_lock<boost::shared_mutex> lock(_state_lock);
|
||||
|
||||
_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/shared_mutex.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 <libbladeRF.h>
|
||||
|
||||
#include "osmosdr/ranges.h"
|
||||
#include "arg_helpers.h"
|
||||
|
||||
/* We currently read/write 1024 samples (pairs of 16-bit signed ints) */
|
||||
#define BLADERF_SAMPLE_BLOCK_SIZE (1024)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
typedef boost::shared_ptr<struct bladerf> bladerf_sptr;
|
||||
|
||||
class bladerf_common
|
||||
{
|
||||
public:
|
||||
bladerf_common();
|
||||
~bladerf_common();
|
||||
virtual ~bladerf_common();
|
||||
|
||||
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::meta_range_t sample_rates();
|
||||
osmosdr::freq_range_t filter_bandwidths();
|
||||
|
@ -64,15 +70,42 @@ protected:
|
|||
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:
|
||||
bool running;
|
||||
boost::shared_mutex state_lock;
|
||||
void set_verbosity(const std::string &verbosity);
|
||||
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
|
||||
|
|
|
@ -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_OUT, MAX_OUT, sizeof (gr_complex)))
|
||||
{
|
||||
int ret;
|
||||
unsigned int device_number = 0;
|
||||
std::string device_name;
|
||||
|
||||
dict_t dict = params_to_dict(args);
|
||||
|
||||
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(
|
||||
"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;
|
||||
}
|
||||
/* Perform src/sink agnostic initializations */
|
||||
init(dict, "source");
|
||||
|
||||
/* 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] */
|
||||
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);
|
||||
if ( ret != 0 )
|
||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
||||
|
||||
this->thread = gr::thread::thread(write_task_dispatch, this);
|
||||
_filled = new bool[_num_buffers];
|
||||
if (!_filled) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"Failed to allocate _filled[]" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -171,128 +97,195 @@ bladerf_sink_c::~bladerf_sink_c ()
|
|||
{
|
||||
int ret;
|
||||
|
||||
this->set_running(false);
|
||||
this->thread.join();
|
||||
|
||||
ret = bladerf_enable_module(this->dev, TX, false);
|
||||
if ( ret != 0 )
|
||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
||||
|
||||
/* Close the device */
|
||||
bladerf_close( this->dev );
|
||||
if( is_running() == true ) {
|
||||
std::cerr << _pfx << "Still running when destructor called!"
|
||||
<< std::endl;
|
||||
stop();
|
||||
}
|
||||
|
||||
void bladerf_sink_c::write_task_dispatch(bladerf_sink_c *obj)
|
||||
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false );
|
||||
if ( ret != 0 )
|
||||
std::cerr << _pfx << "bladerf_enable_module failed:"
|
||||
<< bladerf_strerror(ret) << std::endl;
|
||||
|
||||
/* Release stream resources */
|
||||
bladerf_deinit_stream(_stream);
|
||||
|
||||
delete[] _filled;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
int i, n_samples_avail, n_samples;
|
||||
int16_t *p;
|
||||
gr_complex sample;
|
||||
int status;
|
||||
|
||||
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 ) {
|
||||
set_running(false);
|
||||
std::cerr << _pfx << "Sink stream error: "
|
||||
<< bladerf_strerror(status) << std::endl;
|
||||
|
||||
if ( status == BLADERF_ERR_TIMEOUT ) {
|
||||
std::cerr << _pfx << "Try adjusting your sample rate or the "
|
||||
<< "\"buffers\", \"buflen\", and \"transfers\" parameters. "
|
||||
<< 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()
|
||||
{
|
||||
/* Lock the circular buffer */
|
||||
boost::unique_lock<boost::mutex> lock(this->sample_fifo_lock);
|
||||
|
||||
/* Check to make sure we have samples available */
|
||||
n_samples_avail = this->sample_fifo->size();
|
||||
while( n_samples_avail < BLADERF_SAMPLE_BLOCK_SIZE ) {
|
||||
/* Wait until there is at least a block size of samples ready */
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
set_running(false);
|
||||
_thread.join();
|
||||
return true;
|
||||
}
|
||||
|
||||
int bladerf_sink_c::work( int noutput_items,
|
||||
gr_vector_const_void_star &input_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];
|
||||
int num_samples;
|
||||
bool running = is_running();
|
||||
|
||||
if ( ! this->is_running() )
|
||||
return WORK_DONE;
|
||||
|
||||
if( noutput_items >= 0 ) {
|
||||
/* Total samples we want to process */
|
||||
to_copy = noutput_items;
|
||||
num_samples = noutput_items;
|
||||
|
||||
/* While there are still samples to copy out ... */
|
||||
while( to_copy > 0 ) {
|
||||
while (running && num_samples > 0) {
|
||||
|
||||
while (_samples_left && num_samples) {
|
||||
|
||||
/* 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(this->sample_fifo_lock);
|
||||
boost::unique_lock<boost::mutex> lock(_buf_status_lock);
|
||||
|
||||
/* Check to see how much space is available */
|
||||
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
|
||||
_filled[_buf_index] = true;
|
||||
_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) {
|
||||
this->samples_available.wait(lock);
|
||||
n_space_avail = this->sample_fifo->capacity() - this->sample_fifo->size();
|
||||
/* Signal that we have filled a buffer */
|
||||
_buffer_filled.notify_one();
|
||||
|
||||
/* 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()
|
||||
|
@ -308,55 +301,22 @@ size_t bladerf_sink_c::get_num_channels()
|
|||
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
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();
|
||||
return bladerf_common::set_sample_rate(BLADERF_MODULE_TX, rate);
|
||||
}
|
||||
|
||||
double bladerf_sink_c::get_sample_rate()
|
||||
{
|
||||
int ret;
|
||||
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;
|
||||
return bladerf_common::get_sample_rate(BLADERF_MODULE_TX);
|
||||
}
|
||||
|
||||
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 )
|
||||
|
@ -368,13 +328,12 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan )
|
|||
freq > get_freq_range( chan ).stop() ) {
|
||||
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
||||
} 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 ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"failed to set center frequency " +
|
||||
"Failed to set center frequency " +
|
||||
boost::lexical_cast<std::string>(freq) +
|
||||
", error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
":" + std::string(bladerf_strerror(ret)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,11 +345,11 @@ double bladerf_sink_c::get_center_freq( size_t chan )
|
|||
uint32_t freq;
|
||||
int ret;
|
||||
|
||||
ret = bladerf_get_frequency( this->dev, TX, &freq );
|
||||
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_TX, &freq );
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"failed to get center frequency, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"Failed to get center frequency:" +
|
||||
std::string(bladerf_strerror(ret)));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if( name == "VGA1" ) {
|
||||
range = this->vga1_range;
|
||||
range = _vga1_range;
|
||||
} else if( name == "VGA2" ) {
|
||||
range = this->vga2_range;
|
||||
range = _vga2_range;
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"requested an invalid gain element " + name );
|
||||
"Requested an invalid gain element " + name );
|
||||
}
|
||||
|
||||
return range;
|
||||
|
@ -460,20 +419,20 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c
|
|||
int ret = 0;
|
||||
|
||||
if( name == "VGA1" ) {
|
||||
ret = bladerf_set_txvga1( this->dev, (int)gain );
|
||||
ret = bladerf_set_txvga1( _dev.get(), (int)gain );
|
||||
} else if( name == "VGA2" ) {
|
||||
ret = bladerf_set_txvga2( this->dev, (int)gain );
|
||||
ret = bladerf_set_txvga2( _dev.get(), (int)gain );
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"requested to set the gain "
|
||||
"Requested to set the gain " +
|
||||
"of an unknown gain element " + name );
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
if( ret ) {
|
||||
throw std::runtime_error(std::string(__FUNCTION__) + " " +
|
||||
"could not set " + name + " gain, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"Could not set " + name + " gain, error " +
|
||||
std::string(bladerf_strerror(ret)));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if( name == "VGA1" ) {
|
||||
ret = bladerf_get_txvga1( this->dev, &g );
|
||||
ret = bladerf_get_txvga1( _dev.get(), &g );
|
||||
} else if( name == "VGA2" ) {
|
||||
ret = bladerf_get_txvga2( this->dev, &g );
|
||||
ret = bladerf_get_txvga2( _dev.get(), &g );
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"requested to get the gain "
|
||||
"Requested to get the gain " +
|
||||
"of an unknown gain element " + name );
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not get " + name + " gain, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"Could not get " + name + " gain, error " +
|
||||
std::string(bladerf_strerror(ret)));
|
||||
}
|
||||
|
||||
return (double)g;
|
||||
|
@ -540,19 +499,48 @@ std::string bladerf_sink_c::get_antenna( size_t chan )
|
|||
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 )
|
||||
{
|
||||
int ret;
|
||||
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 ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not set bandwidth, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not set bandwidth:" +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
return this->get_bandwidth();
|
||||
return get_bandwidth();
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
ret = bladerf_get_bandwidth( this->dev, TX, &bandwidth );
|
||||
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_TX, &bandwidth );
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not get bandwidth, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not get bandwidth: " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
return this->filter_bandwidths();
|
||||
return filter_bandwidths();
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include <gnuradio/block.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
#include <libbladeRF.h>
|
||||
|
||||
#include "osmosdr/ranges.h"
|
||||
#include "sink_iface.h"
|
||||
#include "bladerf_common.h"
|
||||
|
@ -70,6 +68,9 @@ private:
|
|||
public:
|
||||
~bladerf_sink_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 );
|
||||
|
@ -104,17 +105,48 @@ public:
|
|||
std::string set_antenna( const std::string & 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 get_bandwidth( size_t chan = 0 );
|
||||
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||
|
||||
private:
|
||||
static void write_task_dispatch(bladerf_sink_c *obj);
|
||||
private: /* functions */
|
||||
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();
|
||||
|
||||
gr::thread::thread thread;
|
||||
osmosdr::gain_range_t vga1_range;
|
||||
osmosdr::gain_range_t vga2_range;
|
||||
private: /* members */
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -38,6 +38,14 @@
|
|||
|
||||
#include "arg_helpers.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;
|
||||
|
||||
|
@ -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)))
|
||||
{
|
||||
int ret;
|
||||
unsigned int device_number = 0;
|
||||
size_t fifo_size;
|
||||
std::string device_name;
|
||||
struct bladerf_version fpga_version;
|
||||
|
||||
dict_t dict = params_to_dict(args);
|
||||
|
||||
if (dict.count("bladerf"))
|
||||
{
|
||||
std::string value = dict["bladerf"];
|
||||
if ( value.length() )
|
||||
{
|
||||
init(dict, "source");
|
||||
|
||||
fifo_size = BLADERF_SAMPLE_FIFO_SIZE;
|
||||
if (dict.count("fifo")) {
|
||||
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());
|
||||
fifo_size = boost::lexical_cast<size_t>(dict["fifo"]);
|
||||
} catch (const boost::bad_lexical_cast &e) {
|
||||
std::cerr << _pfx << "Warning: \"fifo\" value is invalid. Defaulting to "
|
||||
<< fifo_size;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Open a handle to the device */
|
||||
this->dev = bladerf_open( device_name.c_str() );
|
||||
if( NULL == this->dev ) {
|
||||
_fifo = new boost::circular_buffer<gr_complex>(fifo_size);
|
||||
if (!_fifo) {
|
||||
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;
|
||||
ret = bladerf_load_fpga( this->dev, fpga.c_str() );
|
||||
std::cerr << _pfx << "Setting bladerf sampling to " << sampling << std::endl;
|
||||
if( sampling == "internal") {
|
||||
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_INTERNAL );
|
||||
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() );
|
||||
std::cerr << _pfx << "Problem while setting sampling mode:"
|
||||
<< bladerf_strerror(ret) << std::endl;
|
||||
} else if( sampling == "external" ) {
|
||||
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_EXTERNAL );
|
||||
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 << _pfx << "Problem while setting sampling mode:"
|
||||
<< bladerf_strerror(ret) << std::endl;
|
||||
} else {
|
||||
std::cerr << _pfx << "Invalid sampling mode " << sampling << 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] */
|
||||
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 */
|
||||
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 */
|
||||
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;
|
||||
|
||||
this->set_running(false);
|
||||
this->thread.join();
|
||||
|
||||
ret = bladerf_enable_module(this->dev, RX, false);
|
||||
if ( ret != 0 )
|
||||
std::cerr << "bladerf_enable_module has returned with " << ret << std::endl;
|
||||
|
||||
/* Close the device */
|
||||
bladerf_close( this->dev );
|
||||
if (is_running()) {
|
||||
std::cerr << _pfx << "Still running when destructor called!"
|
||||
<< std::endl;
|
||||
stop();
|
||||
}
|
||||
|
||||
void bladerf_source_c::read_task_dispatch(bladerf_source_c *obj)
|
||||
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, false );
|
||||
if ( ret != 0 )
|
||||
std::cerr << _pfx << "bladerf_enable_module failed: "
|
||||
<< bladerf_strerror(ret) << std::endl;
|
||||
|
||||
/* Release stream resources */
|
||||
bladerf_deinit_stream(_stream);
|
||||
|
||||
delete _fifo;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
int16_t si, sq, *next_val;
|
||||
ssize_t n_samples;
|
||||
size_t n_avail, to_copy;
|
||||
int status;
|
||||
|
||||
while ( this->is_running() )
|
||||
set_running( true );
|
||||
|
||||
/* Start stream and stay there until we kill the stream */
|
||||
status = bladerf_stream(_stream, BLADERF_MODULE_RX);
|
||||
|
||||
if ( status < 0 ) {
|
||||
set_running( false );
|
||||
std::cerr << "Source stream error: " << bladerf_strerror(status) << std::endl;
|
||||
|
||||
if ( status == BLADERF_ERR_TIMEOUT ) {
|
||||
std::cerr << _pfx << "Try adjusting your sample rate or the "
|
||||
<< "\"buffers\", \"buflen\", and \"transfers\" parameters. "
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bladerf_source_c::start()
|
||||
{
|
||||
int ret;
|
||||
|
||||
n_samples = bladerf_read_c16(this->dev, this->raw_sample_buf,
|
||||
BLADERF_SAMPLE_BLOCK_SIZE);
|
||||
/* 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;
|
||||
|
||||
if (n_samples < 0) {
|
||||
std::cerr << "Failed to read 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: 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 {
|
||||
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;
|
||||
|
||||
//std::cerr << "+" << std::flush;
|
||||
_thread = gr::thread::thread( boost::bind(&bladerf_source_c::read_task, this) );
|
||||
|
||||
next_val = this->raw_sample_buf;
|
||||
|
||||
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);
|
||||
while( is_running() == false ) {
|
||||
boost::this_thread::sleep( boost::posix_time::milliseconds(1) );
|
||||
}
|
||||
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Indicate overrun, if neccesary */
|
||||
if (to_copy < (size_t)n_samples) {
|
||||
std::cerr << "O" << std::flush;
|
||||
}
|
||||
}
|
||||
bool bladerf_source_c::stop()
|
||||
{
|
||||
set_running(false);
|
||||
_thread.join();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Main work function, pull samples from the driver */
|
||||
/* Main work function, pull samples from the sample fifo */
|
||||
int bladerf_source_c::work( int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items )
|
||||
{
|
||||
int n_samples_avail;
|
||||
|
||||
if ( ! this->is_running() )
|
||||
if ( ! is_running() )
|
||||
return WORK_DONE;
|
||||
|
||||
if( noutput_items >= 0 ) {
|
||||
if( noutput_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 */
|
||||
n_samples_avail = this->sample_fifo->size();
|
||||
int n_samples_avail = _fifo->size();
|
||||
|
||||
while (n_samples_avail < noutput_items) {
|
||||
this->samples_available.wait(lock);
|
||||
n_samples_avail = this->sample_fifo->size();
|
||||
_samp_avail.wait(lock);
|
||||
n_samples_avail = _fifo->size();
|
||||
}
|
||||
|
||||
for(int i = 0; i < noutput_items; ++i) {
|
||||
out[i] = this->sample_fifo->at(0);
|
||||
this->sample_fifo->pop_front();
|
||||
out[i] = _fifo->at(0);
|
||||
_fifo->pop_front();
|
||||
}
|
||||
|
||||
//std::cerr << "-" << std::flush;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return this->sample_rates();
|
||||
return sample_rates();
|
||||
}
|
||||
|
||||
double bladerf_source_c::set_sample_rate( double rate )
|
||||
{
|
||||
int ret;
|
||||
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();
|
||||
return bladerf_common::set_sample_rate( BLADERF_MODULE_RX, rate);
|
||||
}
|
||||
|
||||
double bladerf_source_c::get_sample_rate()
|
||||
{
|
||||
int ret;
|
||||
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;
|
||||
return bladerf_common::get_sample_rate( BLADERF_MODULE_RX );
|
||||
}
|
||||
|
||||
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 )
|
||||
|
@ -362,13 +359,12 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan )
|
|||
freq > get_freq_range( chan ).stop() ) {
|
||||
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
|
||||
} 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 ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"failed to set center frequency " +
|
||||
boost::lexical_cast<std::string>(freq) +
|
||||
", error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
boost::lexical_cast<std::string>(freq) + ": " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,11 +376,11 @@ double bladerf_source_c::get_center_freq( size_t chan )
|
|||
uint32_t freq;
|
||||
int ret;
|
||||
|
||||
ret = bladerf_get_frequency( this->dev, RX, &freq );
|
||||
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_RX, &freq );
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"failed to get center frequency, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"failed to get center frequency: " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if( name == "LNA" ) {
|
||||
range = this->lna_range;
|
||||
range = _lna_range;
|
||||
} else if( name == "VGA1" ) {
|
||||
range = this->vga1_range;
|
||||
range = _vga1_range;
|
||||
} else if( name == "VGA2" ) {
|
||||
range = this->vga2_range;
|
||||
range = _vga2_range;
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"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" ) {
|
||||
bladerf_lna_gain g;
|
||||
if( gain == 0.0 ) {
|
||||
g = LNA_BYPASS;
|
||||
} else if( gain == 3.0 ) {
|
||||
g = LNA_MID;
|
||||
} else if( gain == 6.0 ) {
|
||||
g = LNA_MAX;
|
||||
} else {
|
||||
std::cerr << "Invalid LNA gain requested: " << gain << ", "
|
||||
<< "setting to LNA_MAX (6dB)" << std::endl;
|
||||
g = LNA_MAX;
|
||||
}
|
||||
ret = bladerf_set_lna_gain( this->dev, g );
|
||||
|
||||
if ( gain >= 6.0f )
|
||||
g = BLADERF_LNA_GAIN_MAX;
|
||||
else if ( gain >= 3.0f )
|
||||
g = BLADERF_LNA_GAIN_MID;
|
||||
else /* gain < 3.0f */
|
||||
g = BLADERF_LNA_GAIN_BYPASS;
|
||||
|
||||
ret = bladerf_set_lna_gain( _dev.get(), g );
|
||||
} else if( name == "VGA1" ) {
|
||||
ret = bladerf_set_rxvga1( this->dev, (int)gain );
|
||||
ret = bladerf_set_rxvga1( _dev.get(), (int)gain );
|
||||
} else if( name == "VGA2" ) {
|
||||
ret = bladerf_set_rxvga2( this->dev, (int)gain );
|
||||
ret = bladerf_set_rxvga2( _dev.get(), (int)gain );
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"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 */
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not set " + name + " gain, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not set " + name + " gain: " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
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" ) {
|
||||
bladerf_lna_gain lna_g;
|
||||
ret = bladerf_get_lna_gain( this->dev, &lna_g );
|
||||
g = lna_g == LNA_BYPASS ? 0 : lna_g == LNA_MID ? 3 : 6;
|
||||
ret = bladerf_get_lna_gain( _dev.get(), &lna_g );
|
||||
g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6;
|
||||
} else if( name == "VGA1" ) {
|
||||
ret = bladerf_get_rxvga1( this->dev, &g );
|
||||
ret = bladerf_get_rxvga1( _dev.get(), &g );
|
||||
} else if( name == "VGA2" ) {
|
||||
ret = bladerf_get_rxvga2( this->dev, &g );
|
||||
ret = bladerf_get_rxvga2( _dev.get(), &g );
|
||||
} else {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"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 */
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not get " + name + " gain, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not get " + name + " gain: " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
return (double)g;
|
||||
|
@ -558,19 +551,74 @@ std::string bladerf_source_c::get_antenna( size_t chan )
|
|||
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 )
|
||||
{
|
||||
int ret;
|
||||
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 ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not set bandwidth, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not set bandwidth: " +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
return this->get_bandwidth();
|
||||
return get_bandwidth();
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
ret = bladerf_get_bandwidth( this->dev, RX, &bandwidth );
|
||||
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_RX, &bandwidth );
|
||||
if( ret ) {
|
||||
throw std::runtime_error( std::string(__FUNCTION__) + " " +
|
||||
"could not get bandwidth, error " +
|
||||
boost::lexical_cast<std::string>(ret) );
|
||||
"could not get bandwidth:" +
|
||||
std::string(bladerf_strerror(ret)) );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
return this->filter_bandwidths();
|
||||
return filter_bandwidths();
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include <gnuradio/block.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
#include <libbladeRF.h>
|
||||
|
||||
#include "osmosdr/ranges.h"
|
||||
#include "source_iface.h"
|
||||
#include "bladerf_common.h"
|
||||
|
@ -70,6 +68,9 @@ private:
|
|||
public:
|
||||
~bladerf_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 );
|
||||
|
@ -104,18 +105,41 @@ public:
|
|||
std::string set_antenna( const std::string & 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 get_bandwidth( size_t chan = 0 );
|
||||
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
|
||||
|
||||
private:
|
||||
static void read_task_dispatch(bladerf_source_c *obj);
|
||||
private: /* functions */
|
||||
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();
|
||||
|
||||
gr::thread::thread thread;
|
||||
osmosdr::gain_range_t lna_range;
|
||||
osmosdr::gain_range_t vga1_range;
|
||||
osmosdr::gain_range_t vga2_range;
|
||||
private: /* members */
|
||||
osmosdr::gain_range_t _lna_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 */
|
||||
|
|
|
@ -13,5 +13,7 @@
|
|||
#cmakedefine ENABLE_MIRI
|
||||
#cmakedefine ENABLE_HACKRF
|
||||
#cmakedefine ENABLE_BLADERF
|
||||
#cmakedefine ENABLE_RFSPACE
|
||||
#cmakedefine ENABLE_AIRSPY
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
|
|
@ -66,6 +66,14 @@
|
|||
#include <bladerf_source_c.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_RFSPACE
|
||||
#include <rfspace_source_c.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AIRSPY
|
||||
#include <airspy_source_c.h>
|
||||
#endif
|
||||
|
||||
#include "arg_helpers.h"
|
||||
|
||||
using namespace osmosdr;
|
||||
|
@ -115,6 +123,11 @@ devices_t device::find(const device_t &hint)
|
|||
{
|
||||
boost::mutex::scoped_lock lock(_device_mutex);
|
||||
|
||||
bool fake = true;
|
||||
|
||||
if ( hint.count("nofake") )
|
||||
fake = false;
|
||||
|
||||
devices_t devices;
|
||||
|
||||
#ifdef ENABLE_OSMOSDR
|
||||
|
@ -144,17 +157,25 @@ devices_t device::find(const device_t &hint)
|
|||
#ifdef ENABLE_HACKRF
|
||||
BOOST_FOREACH( std::string dev, hackrf_source_c::get_devices() )
|
||||
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
|
||||
/* software-only sources should be appended at the very end,
|
||||
* hopefully resulting in hardware sources to be shown first
|
||||
* in a graphical interface etc... */
|
||||
|
||||
#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) );
|
||||
#endif
|
||||
#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) );
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/blocks/file_source.h>
|
||||
#include <gnuradio/blocks/throttle.h>
|
||||
|
||||
#include "file_source_c.h"
|
||||
|
||||
|
@ -73,19 +73,21 @@ file_source_c::file_source_c(const std::string &args) :
|
|||
if (_freq < 0)
|
||||
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.");
|
||||
|
||||
_file_rate = _rate;
|
||||
|
||||
gr::blocks::file_source::sptr src = \
|
||||
gr::blocks::file_source::make( sizeof(gr_complex),
|
||||
filename.c_str(),
|
||||
repeat );
|
||||
|
||||
if (throttle) {
|
||||
gr::blocks::throttle::sptr throttle = gr::blocks::throttle::make( sizeof(gr_complex), _rate );
|
||||
_throttle = gr::blocks::throttle::make( sizeof(gr_complex), _file_rate );
|
||||
|
||||
connect( src, 0, throttle, 0 );
|
||||
connect( throttle, 0, self(), 0 );
|
||||
if (throttle) {
|
||||
connect( src, 0, _throttle, 0 );
|
||||
connect( _throttle, 0, self(), 0 );
|
||||
} else {
|
||||
connect( src, 0, self(), 0 );
|
||||
}
|
||||
|
@ -100,13 +102,17 @@ std::string file_source_c::name()
|
|||
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::string args = "file='/path/to/your/file',rate=1e6,freq=100e6,repeat=true,throttle=true";
|
||||
if ( fake )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -120,13 +126,24 @@ osmosdr::meta_range_t file_source_c::get_sample_rates( void )
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define FILE_SOURCE_C_H
|
||||
|
||||
#include <gnuradio/hier_block2.h>
|
||||
#include <gnuradio/blocks/throttle.h>
|
||||
|
||||
#include "source_iface.h"
|
||||
|
||||
|
@ -44,7 +45,7 @@ public:
|
|||
|
||||
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 );
|
||||
|
||||
|
@ -71,6 +72,8 @@ public:
|
|||
std::string get_antenna( size_t chan = 0 );
|
||||
|
||||
private:
|
||||
gr::blocks::throttle::sptr _throttle;
|
||||
double _file_rate;
|
||||
double _freq, _rate;
|
||||
};
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
using namespace boost::assign;
|
||||
|
||||
#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 */
|
||||
|
||||
|
@ -159,7 +159,8 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
|
|||
_freq_corr(0),
|
||||
_auto_gain(false),
|
||||
_amp_gain(0),
|
||||
_vga_gain(0)
|
||||
_vga_gain(0),
|
||||
_bandwidth(0)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -208,10 +209,11 @@ hackrf_sink_c::hackrf_sink_c (const std::string &args)
|
|||
<< std::endl;
|
||||
}
|
||||
|
||||
// set_sample_rate( get_sample_rates().start() );
|
||||
set_sample_rate( 10e6 );
|
||||
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( 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) */
|
||||
|
||||
|
@ -448,7 +450,7 @@ std::vector<std::string> hackrf_sink_c::get_devices()
|
|||
{
|
||||
std::vector<std::string> devices;
|
||||
std::string label;
|
||||
|
||||
#if 0
|
||||
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; 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 + "'";
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -495,7 +539,7 @@ double hackrf_sink_c::set_sample_rate( double rate )
|
|||
ret = hackrf_set_sample_rate( _dev, rate );
|
||||
if ( HACKRF_SUCCESS == ret ) {
|
||||
_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 {
|
||||
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "hackrf_source_c.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
@ -36,15 +36,16 @@
|
|||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
#include "hackrf_source_c.h"
|
||||
|
||||
#include "arg_helpers.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
#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 */
|
||||
|
||||
|
@ -93,7 +94,8 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
|
|||
_auto_gain(false),
|
||||
_amp_gain(0),
|
||||
_lna_gain(0),
|
||||
_vga_gain(0)
|
||||
_vga_gain(0),
|
||||
_bandwidth(0)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -162,10 +164,11 @@ hackrf_source_c::hackrf_source_c (const std::string &args)
|
|||
<< std::endl;
|
||||
}
|
||||
|
||||
// set_sample_rate( get_sample_rates().start() );
|
||||
set_sample_rate( 10e6 );
|
||||
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( 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) */
|
||||
|
||||
|
@ -340,7 +343,7 @@ std::vector<std::string> hackrf_source_c::get_devices()
|
|||
{
|
||||
std::vector<std::string> devices;
|
||||
std::string label;
|
||||
|
||||
#if 0
|
||||
for (unsigned int i = 0; i < 1 /* TODO: missing libhackrf api */; 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 + "'";
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -387,7 +432,7 @@ double hackrf_source_c::set_sample_rate( double rate )
|
|||
ret = hackrf_set_sample_rate( _dev, rate );
|
||||
if ( HACKRF_SUCCESS == ret ) {
|
||||
_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 {
|
||||
HACKRF_THROW_ON_ERROR( ret, HACKRF_FUNC_STR( "hackrf_set_sample_rate", rate ) )
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBMIRISDR_INCLUDE_DIR}
|
||||
${LIBMIRISDR_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(mirisdr_srcs
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
using namespace boost::assign;
|
||||
|
||||
#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 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()
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBOSMOSDR_INCLUDE_DIR}
|
||||
${LIBOSMOSDR_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(osmosdr_srcs
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
using namespace boost::assign;
|
||||
|
||||
#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 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()
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -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(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBRTLSDR_INCLUDE_DIR}
|
||||
${LIBRTLSDR_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(rtl_srcs
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue