Compare commits

...

71 Commits

Author SHA1 Message Date
Jon Szymaniak fe99478a0c bladeRF: RXVGA2 range is [0, 30]
While the RXVGA2 gain can technically go up to 60 dB, the LMS6002D
datasheet recommends it be clamped to 30dB. libbladeRF clamps to a max
of 30dB, so there's no use in setting max to 60 dB here.
2014-02-16 09:10:08 +01:00
Jon Szymaniak b7360fc879 bladerf: Added 'verbosity' and 'loopback' device parameters
The 'verbosity' parameter may be used to increase or suppress output from
libbladeRF. The available log levels are, in order of decreasing
verbosity are:
    verbose, debug, info, warning, critical, silent

The 'loopback' parameter may be used to put the bladeRF into one of the
supported loopback modes.  The valid modes are listed below. Their
descriptions may be found in the libbladeRF documentation:

      bb_txlpf_rxvga2, bb_txlpf_rxlpf bb_txvga1_rxvga2, bb_txvga1_rxlpf
      rf_lna1, rf_lna2, rf_lna3
2014-02-16 09:10:04 +01:00
Dimitri Stolnikov 99c9e5ead9 osmosdr/rtl/miri/hackrf: use 15 buffers by default
folowing rtl-sdr commit 89f73b183f2dac9c0dd75beca4cf2f77f20c4a36

So far we had 32 * 256KB which was a bit overkill, 15 are more than
enough.

15 was chosen instead of 16 because at least on Linux there seems to be
a system-wide limit of 63 transfers (when they are 256KB large), so 4
dongles can be used on a single machine without lowering the default
transfer number.
2014-02-16 09:10:01 +01:00
Dimitri Stolnikov 9d85dcf6d1 airspy: add support for AirSpy wideband receiver
Requires https://github.com/airspy/host

Usage example:

osmocom_fft -a airspy

The following named gain stages are available:

LNA: 0 to 15, step 1
MIX: 0 to 15, step 1
IF: 0 to 15, step 1

At the moment the gains are not in dB but gain indices internal to R820t
tuner.
2014-02-16 09:09:55 +01:00
Dimitri Stolnikov 0e99eb95f7 rfspace: properly cover the absense of a serial number 2014-01-26 19:55:36 +01:00
Brian Padalino 98a6e7604f bladeRF: Modifying correction calls.
Modifying correction function calls to match libbladeRF API.
2014-01-26 17:36:56 +01:00
Jon Szymaniak 9964a5e6a9 bladerf: Removed sign extension and masking of samples
This is no longer required as of FPGA v0.0.1, and has been removed to
remove some unnecessary computation on samples.
2014-01-26 17:36:53 +01:00
Jon Szymaniak 9a8710757f bladerf: Updates for libbladeRF v0.11.0 API changes 2014-01-26 17:36:50 +01:00
Jon Szymaniak 0ee06038ae bladerf: Use rational sample rate functions
libbladeRF provides accessors for rational sample rates, which the
integer sample rate functions use under the hood. Therefore, there's no
need to check if the requested rate contains a fractional portion and
switch between the two sets of functions.
2014-01-26 17:36:47 +01:00
Jon Szymaniak 1905cdc64c bladerf: Added start()/stop() implementations 2014-01-26 17:36:43 +01:00
Dimitri Stolnikov a734c1ae85 osmocom_fft: print the exception thrown in DC/IQ correction setters 2014-01-26 17:36:38 +01:00
Dimitri Stolnikov d7557d9432 osmocom_siggen: add controls for DC offset and IQ imbalance correction 2014-01-26 17:36:35 +01:00
Dimitri Stolnikov 9701906aaf bladerf: shorten the serial number that is being shown to the user 2014-01-26 17:36:32 +01:00
Dimitri Stolnikov 27a5e07ba3 bladerf: implement DC offset and IQ imbalance correction
This patch has been provided by Brent J.
2014-01-26 17:36:29 +01:00
Dimitri Stolnikov 22705c89cf bladerf: FX3 firmware loading not supported from within gr-osmosdr 2014-01-26 17:36:25 +01:00
Dimitri Stolnikov f78d79398f bladerf: prepare functions to control DC offset / IQ balance (WIP) 2014-01-26 17:36:22 +01:00
Dimitri Stolnikov 6b61662b37 apps/osmocom_fft: gui to set DC offset / IQ imbalance correction mode 2014-01-26 17:36:16 +01:00
Dimitri Stolnikov 2a54ac2aed rfspace: add missing header for basename() 2014-01-26 17:36:12 +01:00
Sylvain Munaut 81c53bf547 osmocom_fft: Properly set initial sample rate for fosphor output
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2014-01-26 17:36:07 +01:00
Dimitri Stolnikov 9b76d230e9 rfspace: add support for RFSPACE SDR-IQ and SDR-IP
Usage example:

osmocom_fft -a sdr-iq=/dev/ttyUSB0
osmocom_fft -a sdr-ip=host[:port]
osmocom_fft -a netsdr=host[:port][,nchan=2]

The following named gain stages are available:

SDR-IQ: ATT: -20 to +10 dB, in 10dB steps
SDR-IP: ATT: -30 to 0 dB, in 10dB steps

The ftdi_sio driver is being used for SDR-IQ. It creates a character
device of the form:

crw-rw---- 1 root dialout 188, 0 Dec 19 22:14 /dev/ttyUSB0

To be able to open the device without root permissions add yourself to
the "dialout" group or do a "chmod 666 /dev/ttyUSB0" after pluggin in.
2014-01-26 17:35:59 +01:00
Dimitri Stolnikov c7a77e88d9 device: implement "nofake" hint to exclude dummy devices from discovery
usage example:

osmosdr::device_t hint( "nofake" );
osmosdr::devices_t devs = osmosdr::device::find( hint );
2014-01-26 17:35:55 +01:00
Dimitri Stolnikov 411a2b683b cmake: pull updates from gnuradio master 2014-01-26 17:35:51 +01:00
Dimitri Stolnikov 8984357be5 add UmTRX to the list of supported devices
requires Fairwaves' port of the Ettus UHD library:

https://github.com/fairwaves/UHD-Fairwaves
2014-01-26 17:35:38 +01:00
Dimitri Stolnikov e48f8cf2c9 file: add missing include for boost::format 2014-01-26 17:35:33 +01:00
Steve Markgraf 19556d00da rtl/rtl_tcp: add 2.56e6 as 'good' sample rate
Several tests have shown that this is the
highest sample rate where no samples
are being dropped on rtl devices.

Signed-off-by: Steve Markgraf <steve@steve-m.de>
2014-01-26 17:35:28 +01:00
Dimitri Stolnikov 505c19f82e apps/osmocom_fft: recover when .step property is not given for a range 2014-01-26 17:35:20 +01:00
Dimitri Stolnikov 8522c4edf2 sink/source: fix error message when unable to connect blocks internally 2014-01-26 17:35:16 +01:00
Dimitri Stolnikov 2bd29cbe99 netsdr: implement sample rate change in run mode 2014-01-26 17:34:55 +01:00
Steve Markgraf eb3865010d rtl: add R828D tuner
Signed-off-by: Steve Markgraf <steve@steve-m.de>
2013-11-04 21:22:11 +01:00
Dimitri Stolnikov 8c5e74c213 netsdr: replace boost asio sockets with native bsd sockets
until we find out what's exactly interfering with fosphor when using
python based flowgraphs (osmocom_fft). c++ flowgraphs are not affected.
2013-11-04 21:22:07 +01:00
Jon Szymaniak dd35921292 bladerf: Don't reload the FPGA unless the force-reload param is set 2013-11-04 21:22:00 +01:00
Jon Szymaniak e735418224 bladerf: Moved initializations to bladerf_common.c, misc. cleanup
Common parameter handling has been moved into bladerf_common::init().

The buflen parameter is now in units of samples, not bytes. This
deviates from the other gr-osmosdr items. However, with the requirement
that buffers be in multiples of 1024 samples, this makes specifying this
parameter a bit easier. The user shouldn't need to know we're operating
on SC16Q12 values under the hood, and have to calculate accordingly.

To avoid confusion when both a bladeRF source and sink are in a flow
graph a [bladeRF source/sink] prefix has been added to output. Error
number have been replaced with bladeRF string representations of these
error values.

Firmware flashing has been removed. The bladeRF-cli or bladeRF-flash
tools are the preferred route for firmware upgrades.
2013-11-04 21:21:54 +01:00
Jon Szymaniak 3ef7394f61 bladerf: Moved no longer "common" items out of bladerf_common
The gr_complex FIFO is no longer used on the TX side, so it doesn't
really make sense to have it in bladerf_common. The associated items
have been moved into bladerf_source, and some renaming has been done in
bladerf_sink to tidy up.

Pending further performance tests of the bladerf_source, the _fifo
member (boost::circular_buffer) may need to be replaced.
2013-11-04 21:21:48 +01:00
Daniel Gröber 0d75ab353d bladerf: Added device caching, this enables full-duplex operation. 2013-11-04 21:21:44 +01:00
Sylvain Munaut 49a3772491 osmocom_fft: Make the scope area fill all available space
The control area is now fixed / packed

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2013-10-26 21:27:47 +02:00
Sylvain Munaut 2cbc1e14e0 osmocom_fft: Use the new WX version of fosphor sink
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2013-10-26 21:27:43 +02:00
Dimitri Stolnikov 0ee591f163 netsdr: add support for RFSPACE NetSDR receiver
- implements broadcast UDP based device discovery
- prints device information (serial/versions) on startup
- reads available frequency range(s) from the device
- integrity checks of IQ stream using sequence numbers
- automatic bandpass or a wideband lowpass selectable

The following named gain stages are available:

ATT: -30 to 0 dB, in 10dB steps

Known limitations:

- setting the sample rate is possible only before the
  flowgraph has been started
2013-10-26 15:09:43 +02:00
Dimitri Stolnikov 8f86bd2dca apps/osmocom_fft: use reasonable defaults for gain & center frequency 2013-10-26 15:05:47 +02:00
Dimitri Stolnikov f7640dc11c bladerf: remove unused variable 2013-10-25 23:45:48 +02:00
Dimitri Stolnikov 26acce3d35 use numchan instead of nchan to prevent ambiguity...
..when specifying total number of channels offered by the block
2013-10-25 23:45:30 +02:00
Dimitri Stolnikov dd7d584137 hackrf: implement device discovery
Unfortunately libhackrf still doesn't offer a way to enumerate devices
*or* to open a specific device by index or it's serial number. Thus we
have implemented a rather hack-ish way to detect the presence of a
device by trying to open it and closing right after that.
2013-10-25 23:45:24 +02:00
Dimitri Stolnikov 68481ac40d uhd: improve device discovery 2013-10-25 23:45:20 +02:00
Dimitri Stolnikov 860962e501 file: allow changing the sample rate when throttle=true
this is dangerous from signal processing perspective and should be used
with caution.
2013-10-20 18:51:44 +02:00
Dimitri Stolnikov 8300354c05 cmake: fix flag passing to Clang compiler 2013-10-19 16:36:39 +02:00
Dimitri Stolnikov 2934d8512b apps: catch corner cases for file= mode in osmocom_fft
verified for gqrx and sdrangerlove as well:

file=/tmp/lte.cfile,rate=40e6,freq=1815e6,repeat=true,throttle=true
2013-10-18 19:47:21 +02:00
Sylvain Munaut 5534662c0c apps/osmocom_fft: Add option to use fosphor for the main display
Currently the GLFW variant as it's all that's available currently

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2013-10-17 21:27:41 +02:00
Dimitri Stolnikov f61734e58b cmake: make uhd component optional in standalone mode 2013-10-05 12:08:27 +02:00
Dimitri Stolnikov d81936d907 bladerf: use newstyle version getters 2013-10-04 18:31:39 +02:00
Dimitri Stolnikov 7b199a8b95 bladerf: make source less picky wrt rf gain 2013-10-03 14:37:02 +02:00
Dimitri Stolnikov 1f44c44054 source/sink: initialize sample rate cache variable
Thanks to Jiří Pinkava for bringing this up.
2013-10-03 14:25:28 +02:00
Dimitri Stolnikov 56281a6a30 source/sink: fix automatic bandwidth selection 2013-10-03 14:20:31 +02:00
Dimitri Stolnikov 882cac8465 rtl: don't try to parse empty device index values 2013-09-28 13:46:36 +02:00
Dimitri Stolnikov 217872a785 apps: filter bandwidth follows sample rate in osmocom_fft 2013-09-28 13:40:03 +02:00
Dimitri Stolnikov b97cac30c6 updated header documentation for bandwidth setter 2013-09-28 13:35:26 +02:00
Dimitri Stolnikov d8534d8721 bladerf: implement automatic bandwidth selection 2013-09-28 13:33:30 +02:00
Dimitri Stolnikov 851e94b82f hackrf: enable AMP gain stage by default 2013-09-28 13:29:03 +02:00
Dimitri Stolnikov a279fb1455 hackrf: don't set automatic bandwidth on samplerate change
automatic bandwidth selection may be triggered by calling
set_bandwidth(0) after changing the sample rate
2013-09-28 13:27:58 +02:00
Jon Szymaniak cbf791469c bladeRF: Refactored buffering scheme in sink
Removed the use of an intermediate sample FIFO in the sink
implementation. Note the the FIFO has not been moved out of
bladerf_common --> bladerf_source_c in this commit.

work() now handles converting samples from complex to SC16_Q12, and filling
"transmit-ready" buffers. The callbacks are now only responsible for
marking the provided buffer free, and returning the next buffer.

It appears that a small deadlock issues remains in this changest, which
can be induced by:
 1: Using a small sample rate (160Khz)
 2: Switching back and forth between sinusoid <-> GSM burst

 In this case, it appears that work() is blocked waiting for a buffer to
 become free. More investigation here is required...
2013-09-28 00:05:32 +02:00
Dimitri Stolnikov 0690c077d2 bladerf: migration to async api (WIP)
receive works, transmit locks up in work() after few seconds
2013-09-28 00:05:25 +02:00
Dimitri Stolnikov 154100a11f cmake: drop gnuradio-pmt dependency in .pc file 2013-09-20 21:37:58 +02:00
Sylvain Munaut 970658c071 apps: Improve the GSM burst generation
Not sure the power window is really aligned to the samples yet though.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2013-09-12 23:50:05 +02:00
Frederik M.J. Vestre cdeb105495 Support setting external sampling to bladerf 2013-08-29 23:37:20 +02:00
Dimitri Stolnikov 6fe392546a bladerf: follow recent API changes
tested against aea04c5f119288370166ece05166a8a4157da6fa
2013-08-27 22:40:52 +02:00
Dimitri Stolnikov e65dd08785 cmake: use *_INCLUDE_DIRS in modules 2013-08-13 20:10:51 +02:00
Dimitri Stolnikov 80f72d52ea grc: move around documentation 2013-08-04 22:31:44 +02:00
Dimitri Stolnikov bdc8f22132 uhd: use gr-uhd by default, fall back to built-in code if not found 2013-08-04 10:16:06 +02:00
Dimitri Stolnikov 6e29bf179f rtl_tcp: remove gr-blocks usage for float-to-complex conversion
thanks to Hoernchen for the initial patch
2013-08-04 00:20:29 +02:00
Dimitri Stolnikov bd800ed89e file: import file_source to make it independent from gr blocks 2013-08-04 00:10:40 +02:00
Dimitri Stolnikov f4fd3a176a runtime: always export runtime and blocks symbols 2013-08-03 21:51:51 +02:00
Dimitri Stolnikov 3df0e00276 uhd: import gr-uhd code to be independent from gnuradio-runtime
stripped stream tags support due to lack of pmt
2013-08-03 21:05:18 +02:00
Dimitri Stolnikov be1314af10 runtime: import minimal gr runtime for standalone mode (wip)
stripped pmt and message infrastructure, no logging, no nothing...
2013-08-03 21:00:47 +02:00
201 changed files with 27540 additions and 785 deletions

View File

@ -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
View File

@ -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.

View File

@ -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:

View File

@ -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
##################################################

View File

@ -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]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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

58
cmake/msvc/config.h Normal file
View File

@ -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_ ]

301
cmake/msvc/inttypes.h Normal file
View File

@ -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_ ]

45
cmake/msvc/stdbool.h Normal file
View File

@ -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

251
cmake/msvc/stdint.h Normal file
View File

@ -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_ ]

69
cmake/msvc/sys/time.h Normal file
View File

@ -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_

10
cmake/msvc/unistd.h Normal file
View File

@ -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_ ]

View File

@ -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

View File

@ -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.

View File

@ -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
*/

View File

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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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 &section);
/*!
* \brief Does \p option exist?
*/
virtual bool has_option(const std::string &section,
const std::string &option);
/*!
* \brief If option exists return associated value; else
* default_val.
*/
virtual const std::string get_string(const std::string &section,
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 &section,
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 &section,
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 &section,
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 &section,
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 &section,
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 &section,
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 &section,
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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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
########################################################################

204
lib/ConfigChecks.cmake Normal file
View 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)

37
lib/airspy/CMakeLists.txt Normal file
View File

@ -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})

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 );

View File

@ -37,4 +37,3 @@ set(bladerf_srcs
########################################################################
list(APPEND gr_osmosdr_srcs ${bladerf_srcs})
list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES})

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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 */

View File

@ -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();
}

View File

@ -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 */

View File

@ -13,5 +13,7 @@
#cmakedefine ENABLE_MIRI
#cmakedefine ENABLE_HACKRF
#cmakedefine ENABLE_BLADERF
#cmakedefine ENABLE_RFSPACE
#cmakedefine ENABLE_AIRSPY
#endif // CONFIG_H_IN

View File

@ -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

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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 ) )
}

View File

@ -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 ) )
}

View File

@ -23,7 +23,7 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBMIRISDR_INCLUDE_DIR}
${LIBMIRISDR_INCLUDE_DIRS}
)
set(mirisdr_srcs

View File

@ -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;

View File

@ -23,7 +23,7 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${LIBOSMOSDR_INCLUDE_DIR}
${LIBOSMOSDR_INCLUDE_DIRS}
)
set(osmosdr_srcs

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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