osmocom-sdr
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
September 2019
- 7 participants
- 7 discussions
Hello,
the attached patch allows to set the clock_source on uhd devices in
programs like gqrx.
Bye
1
1
gr-fosphor install troubles:" Unable to share spectrum VBO into OpenCL context" openCL/GL sharing
by Aaron Giles 30 Nov '19
by Aaron Giles 30 Nov '19
30 Nov '19
>Yeah, the nVidia driver is annoying ... it used to work and they broke
>it a few years ago and they don't care enough to fix it.
>And since I got a new laptop a few years back, I don't have a nvidia
>card to debug or work around it.
I compared fosphor to the nVidia OpenCL Simple OpenGL Interop example [1]
and noticed that fosphor calls glMapBuffer/glUnmapBuffer to clear the
spectrum vbo between the calls to glBufferData and clCreateFromGLBuffer.
If I eliminate the map/memset/unmap here by removing the call to
gl_vbo_clear in gl_deferred_init [2], then clCreateFromGLBuffer returns
CL_SUCCESS and fosphor appears to work with CL/GL sharing. It is not clear
to me if clearing the vbo_spectrum is necessary here, since
cl_queue_clear_buffers later initializes the mem_spectrum buffer to the
noise floor.
I'm using an nvidia GTX 1650 with version 430.50 of the nvidia drivers
under Linux Mint 18. A friend of mine tested the GTX 1060 and also had
success with this workaround.
Aaron
[1]
http://developer.download.nvidia.com/compute/DevZone/OpenCL/Projects/oclSim…
[2]
https://git.osmocom.org/gr-fosphor/tree/lib/fosphor/gl.c#n235
2
2
Dear Osmocom SDR community,
Dear Dimitri,
the situation around gr-osmosdr has been deteriorating for years.
Among other things, I notice:
* there has not been a tagged release since 2014
* patches (e.g. fixing clang support) are not merged
* there is no support for gnuradio 3.8
I raised at least some of this both on-list (in June 2018 at
http://lists.osmocom.org/pipermail/osmocom-sdr/2018-June/001766.html)
and off-list in personal discussions, e.g. at CCCamp2019
It is clear that technically there are alternatives these days
(mainly SoapySDR, which didn't exist when gr-osmosdr started in 2012).
However, at the same time I'm seeing plenty of users asking about gr3.8
support, as there are [probably] lots of existing applications which
are not ported to other input blocks. As the overall Osmocom project
leader, this puts me in a difficult position: I've never been involved
with gr-osmosdr myself, but I get various related e-mail which show that
there are users, and that they are struggling by a lack of maintenance.
It appears that original author and maintainer Dimitri has lost time
and/or interest in maintaining gr-osmosdr. That's very sad, but it is a
fact that people have a limited amount of time, and priorities change.
I'd like to thank Dimitri and all other gr-osmosdr
developers/contributors for what they have done so far.
But what has unfortunately been missed here during the last 1-2 years is
passing the project over to a new maintainer or group of maintainers.
Just because the original author is not around anymore, it doesn't mean
the project has to die. So with this message, I'm publicly calling for
some other community member[s] to step up and become maintainer[s] of
gr-osmosdr.
Who is interested in gr-osmosdr and willing to maintain it, possibly in
a team with other interested folks?
I would be more than happy to provide the respective accounts/access on
the osmocom.org redmine as well as the official osmocom.org upstream
repository.
There's a list of open issues at http://osmocom.org/projects/gr-osmosdr/issues
I know there are also many forks on github, including
* https://github.com/igorauad/gr-osmosdr/tree/gr3.8 gr3.8 support
* https://github.com/xtrx-sdr/gr-osmosdr/ with xtrx support
* https://github.com/zhovner/gr-osmosdr and https://github.com/Sevyls/gr-osmosdr
with clang/MacOS related fix
* https://github.com/wirstrom/gr-osmosdr with soapy end-of-burst fix
* https://github.com/thegildedturtle/gr-osmosdr hackrf raspi signedness fix?
* https://github.com/ScanOC/gr-osmosdr print AirSpy serial number on connect
* https://github.com/romeojulietthotel/gr-osmosdr cosmetics
* https://github.com/racerxdl/gr-osmosdr spyserver support?
* https://github.com/rascustoms/gr-osmosdr airspy related patches
* https://github.com/newdreamlj/gr-osmosdr bladerf multi stream fix
* https://github.com/Lukeekul/gr-osmosdr bladerf pass source/sink args
* https://github.com/IW0HDV/gr-osmosdr perseus HF support
* https://github.com/dl1ksv/gr-osmosdr rs-hfiq support
* https://github.com/carpikes/gr-osmosdr/ hackRF AVX/SSE performance
* https://github.com/aports-ugly/gr-osmosdr gr3.8 + xtrx support
* https://github.com/amungo/gr-osmosdr ADSDR support
* https://github.com/0pq76r/gr-osmosdr/commits/master expose rtl-sdr gain stages
So there's no shortage of interesting fixes and features to investigate
and/or merge, even beyond the 'make a release and port to gr3.8'.
Thanks in advance!
Regards,
Harald
--
- Harald Welte <laforge(a)gnumonks.org> http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
(ETSI EN 300 175-7 Ch. A6)
2
1
Hi everyone,
I've created a branch of fosphor with the goal of making it compatible with
GNU Radio 3.8 (specifically the maint-3.8 branch). I've branched fosphor
from
https://github.com/osmocom/gr-fosphor/tree/gr38-qt5.
My branch is located at
https://github.com/the-aerospace-corporation/gr-fosphor/tree/gr38-qt5-aero
The changes are updates to the cmake scripts and modules, most of which are
derived directly from the 3.8 module porting guide located at
https://wiki.gnuradio.org/index.php/GNU_Radio_3.8_OOT_Module_Porting_Guide
Development was performed in Ubuntu 18.04 with GNU Radio installed using
pybombs and Python 3 support as described at
https://github.com/gnuradio/gnuradio
and using a prefix-based GNU Radio install. The updated fosphor branch has
been tested with NVidia and Intel OpenCL. At this point GLFW works but QT
does not.
To build and install the updated fosphor branch, install GNU Radio 3.8 from
the maint-3.8 branch, install all dependencies as described at the fosphor
wiki, then execute
git clone https://github.com/the-aerospace-corporation/gr-fosphor
cd gr-fosphor
git checkout gr38-qt5-aero
mkdir build
cd build
cmake ..
make
make install
I'm interested in the process for merging my updates back to the official
repository. For instance, additional testing using different platforms
might be a good idea.
Best,
Terry Ferrett, Signal Processing and Estimation Engineer
The Aerospace Corporation <https://aerospace.org/>, El Segundo, CA
2
1
gr-fosphor install troubles:" Unable to share spectrum VBO into OpenCL context" openCL/GL sharing
by Paul Bongaerts 18 Sep '19
by Paul Bongaerts 18 Sep '19
18 Sep '19
Hello,
I'm experiencing trouble installing gr-fosphor on my new laptop using
ubuntu 18.04 LTS
Fist installed opengl/cl drivers, gnu-radio over the package manager, and
gr-fosphor also with package manager,
After that tried building gr-fosphor from source like described in the
osmocom wiki.
Also tried fresh ubuntu install with gnuradio an gr-fosphor using
pybombs.this seems to fail the same.
Although my old laptop runs fosphor (3.7.13.4) fine under just intel's
openclas well as my old workstation with just nvidia fosphor, (3.8.0.0)
This new install won't with either combination i try.
who can help me out or point me in the right direction solving this?
Thanks in advance, Paul
Here is a description of what i did on the last try :
Installed ubuntu 18.04 Lts Desktop >> Default settings, 3th party drivers
enabled.
Update:
*sudo apt-get updatesudo apt-get upgrade*
Installed nvidia driver 4.30 on: "Additional Drivers" tab in "Software &
Updates":
*software-properties-gtk*
(Apply and reboot)
Installed gnuradio via package manager:
*sudo apt install gnuradio*
Installed clinfo / glxinfo:
*sudo apt install clinfo mesa-utils*
Download and install latest intel opencl runtime:
*sudo apt-get install lsb-corewget
http://registrationcenter-download.intel.com/*****/****/**/****/**/l_opencl…
<http://registrationcenter-download.intel.com/*****/****/**/****/**/l_opencl…>tar
xvzf l_opencl_p_18.1.0.015.tgz cd l_opencl_p_18.1.0.015/sudo
./install_GUI.sh*
(Follow steps with Defaults)
Check clinfo:
*clinfo Number of platforms 2 Platform Name
NVIDIA CUDA Platform Vendor
NVIDIA Corporation Platform Version
OpenCL 1.2 CUDA 10.2.120 Platform Profile
FULL_PROFILE Platform Extensions
cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics
cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics
cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing
cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll
cl_nv_copy_opts cl_nv_create_buffer Platform Extensions function suffix
NV Platform Name Intel(R) CPU
Runtime for OpenCL(TM) Applications Platform Vendor
Intel(R) Corporation Platform Version
OpenCL 2.1 LINUX Platform Profile
FULL_PROFILE Platform Extensions cl_khr_icd
cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics
cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics
cl_khr_byte_addressable_store cl_khr_depth_images cl_khr_3d_image_writes
cl_intel_exec_by_local_thread cl_khr_spir cl_khr_fp64
cl_khr_image2d_from_buffer cl_intel_vec_len_hint Platform Host timer
resolution 1ns Platform Extensions function suffix
INTEL*
Check glxinfo:
*glxinfo*
*name of display: :0 display: :0 screen: 0 direct rendering: Yes server
glx vendor string: NVIDIA Corporation server glx version string: 1.4 server
glx extensions: GLX_ARB_context_flush_control, GLX_ARB_create_context,
GLX_ARB_create_context_no_error, GLX_ARB_create_context_profile,
GLX_ARB_create_context_robustness, GLX_ARB_fbconfig_float,
GLX_ARB_multisample, GLX_EXT_buffer_age,
GLX_EXT_create_context_es2_profile, GLX_EXT_create_context_es_profile,
GLX_EXT_framebuffer_sRGB, GLX_EXT_import_context, GLX_EXT_libglvnd,
GLX_EXT_stereo_tree, GLX_EXT_swap_control, GLX_EXT_swap_control_tear,
GLX_EXT_texture_from_pixmap, GLX_EXT_visual_info, GLX_EXT_visual_rating,
GLX_NV_copy_image, GLX_NV_delay_before_swap, GLX_NV_float_buffer,
GLX_NV_robustness_video_memory_purge, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer,
GLX_SGI_swap_control, GLX_SGI_video_sync client glx vendor string:
NVIDIA Corporation client glx version string: 1.4 client glx extensions:
GLX_ARB_context_flush_control, GLX_ARB_create_context,
GLX_ARB_create_context_no_error, GLX_ARB_create_context_profile,
GLX_ARB_create_context_robustness, GLX_ARB_fbconfig_float,
GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_buffer_age,
GLX_EXT_create_context_es2_profile, GLX_EXT_create_context_es_profile,
GLX_EXT_fbconfig_packed_float, GLX_EXT_framebuffer_sRGB,
GLX_EXT_import_context, GLX_EXT_stereo_tree, GLX_EXT_swap_control,
GLX_EXT_swap_control_tear, GLX_EXT_texture_from_pixmap,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_NV_copy_buffer,
GLX_NV_copy_image, GLX_NV_delay_before_swap, GLX_NV_float_buffer,
GLX_NV_multisample_coverage, GLX_NV_present_video,
GLX_NV_robustness_video_memory_purge, GLX_NV_swap_group,
GLX_NV_video_capture, GLX_NV_video_out, GLX_SGIX_fbconfig,
GLX_SGIX_pbuffer, GLX_SGI_swap_control, GLX_SGI_video_sync GLX version:
1.4 GLX extensions: GLX_ARB_context_flush_control,
GLX_ARB_create_context, GLX_ARB_create_context_no_error,
GLX_ARB_create_context_profile, GLX_ARB_create_context_robustness,
GLX_ARB_fbconfig_float, GLX_ARB_get_proc_address, GLX_ARB_multisample,
GLX_EXT_buffer_age, GLX_EXT_create_context_es2_profile,
GLX_EXT_create_context_es_profile, GLX_EXT_framebuffer_sRGB,
GLX_EXT_import_context, GLX_EXT_stereo_tree, GLX_EXT_swap_control,
GLX_EXT_swap_control_tear, GLX_EXT_texture_from_pixmap,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_NV_copy_image,
GLX_NV_delay_before_swap, GLX_NV_float_buffer,
GLX_NV_robustness_video_memory_purge, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer,
GLX_SGI_swap_control, GLX_SGI_video_sync Memory info
(GL_NVX_gpu_memory_info): Dedicated video memory: 2048 MB Total
available memory: 2048 MB Currently available dedicated video memory:
1710 MB OpenGL vendor string: NVIDIA Corporation OpenGL renderer string:
GeForce MX250/PCIe/SSE2 OpenGL core profile version string: 4.6.0 NVIDIA
430.26 OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL core profile context flags: (none) OpenGL core profile profile mask:
core profile OpenGL core profile extensions: GL_AMD_multi_draw_indirect,
GL_AMD_sea........................*
Run volk to create profile:
* volk_profile*
Execute a gnuradio-companion flowgraph
(FastNoiseSource>Throttle>FosphorSink):
* GLFW No Gui error: Executing: /usr/bin/python -u /home/paul/top_block.py
Press Enter to quit: [+] Selected device: GeForce MX250 [!] CL Error (-5,
/build/gr-fosphor-D4UWhK/gr-fosphor-3.7.0.2.7b6b996/lib/fosphor/cl.c:480):
Unable to share spectrum VBO into OpenCL context >>> Done*
QT Gui error:
*Executing: /usr/bin/python -u /home/paul/top_block.py File
"/home/paul/top_block.py", line 75 self.fosphor_qt_sink_c_0 = Template
error: #set $win = 'self._%s_win'%$id ^
SyntaxError: invalid syntax >>> Done (return code 1*)
WX Gui error:
*Executing: /usr/bin/python -u /home/paul/top_block.py Warning: failed to
XInitThreads() [xcb] Unknown request in queue while dequeuing [xcb] Most
likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that. python: ../../src/xcb_io.c:165:
dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
>>> Done*
Install from source:
Install GnuRadio 3.7.x build dependencies:
*sudo apt install cmake git g++ libboost-all-dev python-dev python-mako
python-numpy python-wxgtk3.0 python-sphinx python-cheetah swig libzmq3-dev
libfftw3-dev libgsl-dev libcppunit-dev doxygen libcomedi-dev
libqt4-opengl-dev python-qt4 libqwt-dev libsdl1.2-dev libusb-1.0-0-dev
python-gtk2 python-lxml pkg-config python-sip-dev*
Install GLFW build dependencies:
*sudo apt-get install git cmake xorg-dev libglu1-mesa-dev*
Install glfw from source:
*git clone https://github.com/glfw/glfw <https://github.com/glfw/glfw>cd
glfwmkdir buildcd buildcmake ../ -DBUILD_SHARED_LIBS=truemakesudo make
installsudo ldconfig*
Install gr-fosphor build dependencies:
*sudo apt-get install nvidia-opencl-dev opencl-headerssudo apt-get install
nvidia-modprobesudo apt-get install gnuradio-dev opencl-headers
libboost-system-dev libboost-thread-dev*
Install gr-fosphor from source:
*git clone git://git.osmocom.org/gr-fosphor
<http://git.osmocom.org/gr-fosphor>cd gr-fosphorcd buildcmake ../makesudo
make installsudo ldconfig*
After reading
https://lists.gnu.org/archive/html/discuss-gnuradio/2018-08/msg00019.html
and https://lists.osmocom.org/pipermail/osmocom-sdr/2017-June/001594.html :
nano gr-fosphor/lib/fosphor/private.h
Change: #define FLG_FOSPHOR_USE_CLGL_SHARING (0<<0) :
recompile and install:
*cd gr-fosphorcd buildcmake ../makesudo make installsudo ldconfig*
Tried (0<<0) (1<<0) (1<<1) (0<<1) All combinations keep giving the same
errors as before.
l
2
3
GNURADIO AttributeError when instantiating OSMOSDR source in my OOT module (C++)
by Thabet GHARBI 13 Sep '19
by Thabet GHARBI 13 Sep '19
13 Sep '19
Hello,
I'm creating a GNU Radio OOT module in C++ language, in which I instantiate
an osmosdr source. The syntax is : osmosdr::source ::sptr m_source =
osmosdr::source::make();
I also implement other blocks in my design.
In CMakeLists.txt file, I specify all these components:
set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FFT OSMOSDR)
find_package(Gnuradio-osdmosdr REQUIRED)
include_directories(
...
${GNURADIO_OSMOSDR_INCLUDE_DIRS}
)
link_directories(
...
${GNURADIO_OSMOSDR_LIBRARY_DIRS}
)
In cmake/Modules folder, I copied the FindGnuradio-osmosdr.cmake file from
gqrx project.
The logs of cmake command show that the osmosdr library is found:
-- checking for module 'gnuradio-osmosdr'
-- Found gnuradio-osmosdr, version v0.1.4-127-g4d83c606
-- Found GNURADIO_OSMOSDR: /usr/local/lib/libgnuradio-osmosdr.so
After compiling the module (cmake .. -> make -> make install -> ldconfig),
I got the error 'AttributeError: 'module' object has no attribute 'test'. I
analysed the undefined symbol, and it was due to osmosdr module.
Any suggestion to solve this problem?
PS:
- I'm working on Ubuntu 16.04 (VM), gnuradio 3.7.9, cmake 3.5.1
- In GRC, the osmosdr source and sink work fine
Thanks.
1
0
From: Sergey Kostanbaev <sergey.kostanbaev(a)gmail.com>
This patch adds support for XTRX. You can find additional
information on the XTRX at https://xtrx.io/.
The patch adds the dependency for libxtrx which required for
interfacing with the device. Sources of libxtrx and its
dependencies are available at:
https://github.com/xtrx-sdr
Usage example:
osmocom_fft -a "xtrx;"
---
CMakeLists.txt | 7 +-
README | 3 +-
cmake/Modules/FindLibXTRX.cmake | 27 ++
grc/gen_osmosdr_blocks.py | 4 +-
lib/CMakeLists.txt | 8 +
lib/config.h.in | 1 +
lib/sink_impl.cc | 15 +
lib/source_impl.cc | 17 +
lib/xtrx/CMakeLists.txt | 39 +++
lib/xtrx/xtrx_obj.cc | 135 ++++++++
lib/xtrx/xtrx_obj.h | 66 ++++
lib/xtrx/xtrx_sink_c.cc | 501 +++++++++++++++++++++++++++
lib/xtrx/xtrx_sink_c.h | 130 +++++++
lib/xtrx/xtrx_source_c.cc | 583 ++++++++++++++++++++++++++++++++
lib/xtrx/xtrx_source_c.h | 128 +++++++
15 files changed, 1659 insertions(+), 5 deletions(-)
create mode 100644 cmake/Modules/FindLibXTRX.cmake
create mode 100644 lib/xtrx/CMakeLists.txt
create mode 100644 lib/xtrx/xtrx_obj.cc
create mode 100644 lib/xtrx/xtrx_obj.h
create mode 100644 lib/xtrx/xtrx_sink_c.cc
create mode 100644 lib/xtrx/xtrx_sink_c.h
create mode 100644 lib/xtrx/xtrx_source_c.cc
create mode 100644 lib/xtrx/xtrx_source_c.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af21291..24d8566 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -173,6 +173,7 @@ find_package(Volk)
find_package(LibbladeRF)
find_package(SoapySDR NO_MODULE)
find_package(LibFreeSRP)
+find_package(LibXTRX)
find_package(Doxygen)
if(NOT GNURADIO_RUNTIME_FOUND)
@@ -183,8 +184,8 @@ endif()
# Setup the include and linker paths
########################################################################
include_directories(
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib
${Boost_INCLUDE_DIRS}
${GNURADIO_ALL_INCLUDE_DIRS}
)
@@ -202,7 +203,7 @@ set(GR_OSMOSDR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL
# Create uninstall target
########################################################################
configure_file(
- ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
diff --git a/README b/README
index 67fa475..d423185 100644
--- a/README
+++ b/README
@@ -15,7 +15,8 @@ as well supports:
* 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
+ * Fairwaves UmTRX through Fairwaves' module for UHD
+ * Fairwaves XTRX through libxtrx
* Red Pitaya SDR transceiver (http://bazaar.redpitaya.com)
* FreeSRP through libfreesrp
diff --git a/cmake/Modules/FindLibXTRX.cmake b/cmake/Modules/FindLibXTRX.cmake
new file mode 100644
index 0000000..e7681d1
--- /dev/null
+++ b/cmake/Modules/FindLibXTRX.cmake
@@ -0,0 +1,27 @@
+if(NOT LIBXTRX_FOUND)
+ pkg_check_modules (LIBXTRX_PKG libxtrx)
+ find_path(LIBXTRX_INCLUDE_DIRS NAMES xtrx_api.h
+ PATHS
+ ${LIBXTRX_PKG_INCLUDE_DIRS}
+ /usr/include
+ /usr/local/include
+ )
+
+ find_library(LIBXTRX_LIBRARIES NAMES xtrx
+ PATHS
+ ${LIBXTRX_PKG_LIBRARY_DIRS}
+ /usr/lib
+ /usr/local/lib
+ )
+
+if(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
+ set(LIBXTRX_FOUND TRUE CACHE INTERNAL "libxtrx found")
+ message(STATUS "Found libxtrx: ${LIBXTRX_INCLUDE_DIRS}, ${LIBXTRX_LIBRARIES}")
+else(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
+ set(LIBXTRX_FOUND FALSE CACHE INTERNAL "libxtrx found")
+ message(STATUS "libxtrx not found.")
+endif(LIBXTRX_INCLUDE_DIRS AND LIBXTRX_LIBRARIES)
+
+mark_as_advanced(LIBXTRX_LIBRARIES LIBXTRX_INCLUDE_DIRS)
+
+endif(NOT LIBXTRX_FOUND)
diff --git a/grc/gen_osmosdr_blocks.py b/grc/gen_osmosdr_blocks.py
index d1f2b1a..c1a5b30 100644
--- a/grc/gen_osmosdr_blocks.py
+++ b/grc/gen_osmosdr_blocks.py
@@ -227,7 +227,8 @@ While primarily being developed for the OsmoSDR hardware, this block as well sup
* 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
+ * Fairwaves XTRX through libxtrx
+ * Fairwaves UmTRX through Fairwaves' module for UHD
* Red Pitaya SDR transceiver (http://bazaar.redpitaya.com)
* FreeSRP through libfreesrp library
@@ -269,6 +270,7 @@ Lines ending with ... mean it's possible to bind devices together by specifying
hackrf=0[,buffers=32][,bias=0|1][,bias_tx=0|1]
bladerf=0[,tamer=internal|external|external_1pps][,smb=25e6]
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
+ xtrx
Num Channels:
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index dbb175a..a9fe524 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -254,6 +254,14 @@ if(ENABLE_FREESRP)
GR_INCLUDE_SUBDIRECTORY(freesrp)
endif(ENABLE_FREESRP)
+########################################################################
+# Setup XTRX component
+########################################################################
+GR_REGISTER_COMPONENT("XTRX SDR" ENABLE_XTRX LIBXTRX_FOUND)
+if(ENABLE_XTRX)
+GR_INCLUDE_SUBDIRECTORY(xtrx)
+endif(ENABLE_XTRX)
+
########################################################################
# Setup configuration file
########################################################################
diff --git a/lib/config.h.in b/lib/config.h.in
index 42e72f1..4f5e4c3 100644
--- a/lib/config.h.in
+++ b/lib/config.h.in
@@ -19,6 +19,7 @@
#cmakedefine ENABLE_SOAPY
#cmakedefine ENABLE_REDPITAYA
#cmakedefine ENABLE_FREESRP
+#cmakedefine ENABLE_XTRX
//provide NAN define for MSVC older than VC12
#if defined(_MSC_VER) && (_MSC_VER < 1800)
diff --git a/lib/sink_impl.cc b/lib/sink_impl.cc
index 877b31f..34f9670 100644
--- a/lib/sink_impl.cc
+++ b/lib/sink_impl.cc
@@ -48,6 +48,9 @@
#ifdef ENABLE_FREESRP
#include <freesrp_sink_c.h>
#endif
+#ifdef ENABLE_XTRX
+#include "xtrx_sink_c.h"
+#endif
#ifdef ENABLE_FILE
#include "file_sink_c.h"
#endif
@@ -99,6 +102,9 @@ sink_impl::sink_impl( const std::string &args )
#ifdef ENABLE_FREESRP
dev_types.push_back("freesrp");
#endif
+#ifdef ENABLE_XTRX
+ dev_types.push_back("xtrx");
+#endif
#ifdef ENABLE_FILE
dev_types.push_back("file");
#endif
@@ -147,6 +153,9 @@ sink_impl::sink_impl( const std::string &args )
BOOST_FOREACH( std::string dev, freesrp_sink_c::get_devices() )
dev_list.push_back( dev );
#endif
+#ifdef ENABLE_XTRX
+ BOOST_FOREACH( std::string dev, xtrx_sink_c::get_devices() )
+#endif
#ifdef ENABLE_FILE
BOOST_FOREACH( std::string dev, file_sink_c::get_devices() )
dev_list.push_back( dev );
@@ -209,6 +218,12 @@ sink_impl::sink_impl( const std::string &args )
block = sink; iface = sink.get();
}
#endif
+#ifdef ENABLE_XTRX
+ if ( dict.count("xtrx") ) {
+ xtrx_sink_c_sptr sink = make_xtrx_sink_c( arg );
+ block = sink; iface = sink.get();
+ }
+#endif
#ifdef ENABLE_FILE
if ( dict.count("file") ) {
file_sink_c_sptr sink = make_file_sink_c( arg );
diff --git a/lib/source_impl.cc b/lib/source_impl.cc
index a8a3cec..04dcf99 100644
--- a/lib/source_impl.cc
+++ b/lib/source_impl.cc
@@ -91,6 +91,9 @@
#ifdef ENABLE_FREESRP
#include <freesrp_source_c.h>
#endif
+#ifdef ENABLE_XTRX
+#include <xtrx_source_c.h>
+#endif
#include "arg_helpers.h"
#include "source_impl.h"
@@ -165,6 +168,9 @@ source_impl::source_impl( const std::string &args )
#endif
#ifdef ENABLE_FREESRP
dev_types.push_back("freesrp");
+#endif
+#ifdef ENABLE_XTRX
+ dev_types.push_back("xtrx");
#endif
std::cerr << "gr-osmosdr "
<< GR_OSMOSDR_VERSION << " (" << GR_OSMOSDR_LIBVER << ") "
@@ -245,6 +251,10 @@ source_impl::source_impl( const std::string &args )
BOOST_FOREACH( std::string dev, freesrp_source_c::get_devices() )
dev_list.push_back( dev );
#endif
+#ifdef ENABLE_XTRX
+ BOOST_FOREACH( std::string dev, xtrx_source_c::get_devices() )
+ dev_list.push_back( dev );
+#endif
// std::cerr << std::endl;
// BOOST_FOREACH( std::string dev, dev_list )
@@ -376,6 +386,13 @@ source_impl::source_impl( const std::string &args )
}
#endif
+#ifdef ENABLE_XTRX
+ if ( dict.count("xtrx") ) {
+ xtrx_source_c_sptr src = make_xtrx_source_c( arg );
+ block = src; iface = src.get();
+ }
+#endif
+
if ( iface != NULL && long(block.get()) != 0 ) {
_devs.push_back( iface );
diff --git a/lib/xtrx/CMakeLists.txt b/lib/xtrx/CMakeLists.txt
new file mode 100644
index 0000000..5eb2947
--- /dev/null
+++ b/lib/xtrx/CMakeLists.txt
@@ -0,0 +1,39 @@
+# 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}
+ ${LIBXTRX_INCLUDE_DIRS}
+)
+
+set(xtrx_srcs
+ ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_obj.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_source_c.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/xtrx_sink_c.cc
+)
+
+########################################################################
+# Append gnuradio-osmosdr library sources
+########################################################################
+list(APPEND gr_osmosdr_srcs ${xtrx_srcs})
+list(APPEND gr_osmosdr_libs ${LIBXTRX_LIBRARIES})
diff --git a/lib/xtrx/xtrx_obj.cc b/lib/xtrx/xtrx_obj.cc
new file mode 100644
index 0000000..1225a4c
--- /dev/null
+++ b/lib/xtrx/xtrx_obj.cc
@@ -0,0 +1,135 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2017 Sergey Kostanbaev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 "xtrx_obj.h"
+#include <iostream>
+#include <sstream>
+#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+static std::map<std::string, xtrx_obj_sptr> s_objects;
+
+xtrx_obj_sptr xtrx_obj::get(const char* xtrx_dev)
+{
+ std::map<std::string, xtrx_obj_sptr>::iterator i;
+ std::string name(xtrx_dev);
+
+ i = s_objects.find(name);
+ if (i == s_objects.end()) {
+ // No such object
+ s_objects[name].reset(new xtrx_obj(name));
+ }
+
+ return s_objects[name];
+}
+
+void xtrx_obj::clear_all()
+{
+ s_objects.clear();
+}
+
+std::vector<std::string> xtrx_obj::get_devices()
+{
+ std::vector<std::string> devices;
+ // TODO
+ devices.push_back("/dev/xtrx0");
+ return devices;
+}
+
+
+xtrx_obj::xtrx_obj(const std::string &path)
+ : _run(false)
+ , _vio(0)
+ , _sink_rate(0)
+ , _sink_master(0)
+ , _source_rate(0)
+ , _source_master(0)
+ , _flags(0)
+{
+ int res = xtrx_open_string(path.c_str(), &_obj);
+ if (res < 0) {
+ std::stringstream message;
+ message << "Couldn't open " ": Error: " << -res;
+
+ throw std::runtime_error( message.str() );
+ }
+
+ _devices = res;
+}
+
+double xtrx_obj::set_smaplerate(double rate, double master, bool sink, unsigned flags)
+{
+ boost::mutex::scoped_lock lock(mtx);
+
+ if (sink) {
+ _sink_rate = rate;
+ _sink_master = master;
+ } else {
+ _source_rate = rate;
+ _source_master = master;
+ }
+ _flags |= flags | XTRX_SAMPLERATE_FORCE_UPDATE;
+
+ if (_sink_master != 0 && _source_master != 0 && _sink_master != _source_master) {
+ std::stringstream message;
+ message << "Can't operate on diferrent master settings for XTRX sink and source"
+ " sink_master " << _sink_master << " source_master" << _source_master;
+
+ throw std::runtime_error( message.str() );
+ }
+
+ double rxrate = 0, txrate = 0;
+ double actmaster = (_source_master > 0) ? _source_master : _sink_master;
+ int res = xtrx_set_samplerate(_obj,
+ actmaster,
+ _source_rate,
+ _sink_rate,
+ _flags,
+ NULL,
+ &rxrate,
+ &txrate);
+ if (res) {
+ std::cerr << "Unable to set samplerate, error=" << res << std::endl;
+ if (sink)
+ return _sink_rate;
+ return _source_rate;
+ }
+
+ if (_vio) {
+ xtrx_val_set(_obj, XTRX_TRX, XTRX_CH_AB, XTRX_LMS7_VIO, _vio);
+ }
+
+ if (sink)
+ return txrate;
+ return rxrate;
+}
+
+xtrx_obj::~xtrx_obj()
+{
+ if (_obj) {
+ if (_run) {
+ //boost::mutex::scoped_lock lock(mtx);
+ xtrx_stop(_obj, XTRX_TRX);
+ }
+ xtrx_close(_obj);
+ }
+}
+
+
diff --git a/lib/xtrx/xtrx_obj.h b/lib/xtrx/xtrx_obj.h
new file mode 100644
index 0000000..1c61242
--- /dev/null
+++ b/lib/xtrx/xtrx_obj.h
@@ -0,0 +1,66 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2017 Sergey Kostanbaev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 XTRX_OBJ_H
+#define XTRX_OBJ_H
+
+#include <boost/shared_ptr.hpp>
+#include <xtrx_api.h>
+#include <map>
+#include <vector>
+#include <boost/thread/mutex.hpp>
+
+class xtrx_obj;
+
+typedef boost::shared_ptr<xtrx_obj> xtrx_obj_sptr;
+
+class xtrx_obj
+{
+public:
+ xtrx_obj(const std::string& path);
+ ~xtrx_obj();
+
+ static std::vector<std::string> get_devices();
+
+ static xtrx_obj_sptr get(const char* xtrx_dev);
+ static void clear_all();
+
+ xtrx_dev* dev() { return _obj; }
+ unsigned dev_count() { return _devices; }
+
+ double set_smaplerate(double rate, double master, bool sink, unsigned flags);
+
+ void set_vio(unsigned vio) { _vio = vio; }
+
+ boost::mutex mtx;
+protected:
+ xtrx_dev* _obj;
+ bool _run;
+ unsigned _vio;
+
+ double _sink_rate;
+ double _sink_master;
+ double _source_rate;
+ double _source_master;
+
+ unsigned _flags;
+ unsigned _devices;
+};
+
+#endif // XTRX_OBJ_H
diff --git a/lib/xtrx/xtrx_sink_c.cc b/lib/xtrx/xtrx_sink_c.cc
new file mode 100644
index 0000000..d9a7c1f
--- /dev/null
+++ b/lib/xtrx/xtrx_sink_c.cc
@@ -0,0 +1,501 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 <fstream>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include <boost/assign.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <gnuradio/io_signature.h>
+#include <gnuradio/blocks/deinterleave.h>
+#include <gnuradio/blocks/float_to_complex.h>
+
+#include "xtrx_sink_c.h"
+
+#include "arg_helpers.h"
+
+static const int max_burstsz = 4096;
+using namespace boost::assign;
+
+xtrx_sink_c_sptr make_xtrx_sink_c(const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new xtrx_sink_c(args));
+}
+
+static size_t parse_nchan(const std::string &args)
+{
+ size_t nchan = 1;
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("nchan"))
+ nchan = boost::lexical_cast< size_t >( dict["nchan"] );
+
+ if (nchan < 1)
+ nchan = 1;
+
+ return nchan;
+}
+
+xtrx_sink_c::xtrx_sink_c(const std::string &args) :
+ gr::sync_block("xtrx_sink_c",
+ gr::io_signature::make(parse_nchan(args),
+ parse_nchan(args),
+ sizeof(gr_complex)),
+ gr::io_signature::make(0, 0, 0)),
+ _sample_flags(0),
+ _rate(0),
+ _master(0),
+ _freq(0),
+ _corr(0),
+ _bandwidth(0),
+ _dsp(0),
+ _auto_gain(false),
+ _otw(XTRX_WF_16),
+ _mimo_mode(false),
+ _gain_tx(0),
+ _channels(parse_nchan(args)),
+ _ts(8192),
+ _swap_ab(false),
+ _swap_iq(false),
+ _tdd(false),
+ _allow_dis(false),
+ _dev("")
+{
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("master")) {
+ _master = boost::lexical_cast< double >( dict["master"]);
+ }
+
+ std::cerr << args.c_str() << std::endl;
+
+ int loglevel = 2;
+ if (dict.count("loglevel")) {
+ loglevel = boost::lexical_cast< int >( dict["loglevel"] );
+ }
+
+ if (dict.count("txdelay")) {
+ _ts += 8192 * boost::lexical_cast< int >( dict["txdelay"] );
+ }
+
+ if (dict.count("allowdis")) {
+ _allow_dis = boost::lexical_cast< bool >( dict["allowdis"] );
+ }
+
+ if (dict.count("swap_ab")) {
+ _swap_ab = true;
+ std::cerr << "xtrx_sink_c: swap AB channels" << std::endl;
+ }
+
+ if (dict.count("swap_iq")) {
+ _swap_iq = true;
+ std::cerr << "xtrx_sink_c: swap IQ" << std::endl;
+ }
+
+ if (dict.count("sfl")) {
+ _sample_flags = boost::lexical_cast< unsigned >( dict["sfl"] );
+ }
+
+ if (dict.count("tdd")) {
+ _tdd = true;
+ std::cerr << "xtrx_sink_c: TDD mode" << std::endl;
+ }
+
+ if (dict.count("dsp")) {
+ _dsp = boost::lexical_cast< double >( dict["dsp"] );
+ std::cerr << "xtrx_sink_c: DSP:" << _dsp;
+ }
+
+ if (dict.count("dev")) {
+ _dev = dict["dev"];
+ std::cerr << "xtrx_sink_c: XTRX device string `" << _dev.c_str() << "`" << std::endl;
+ }
+
+ xtrx_log_setlevel(loglevel, NULL);
+ _xtrx = xtrx_obj::get(_dev.c_str() );
+ if (_xtrx->dev_count() * 2 == _channels) {
+ _mimo_mode = true;
+ } else if (_xtrx->dev_count() != _channels) {
+ throw std::runtime_error("Number of requested channels != number of devices");
+ }
+ if (dict.count("refclk")) {
+ xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
+ }
+ if (dict.count("extclk")) {
+ xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
+ }
+
+ std::cerr << "xtrx_sink_c::xtrx_sink_c()" << std::endl;
+ set_alignment(32);
+ set_output_multiple(max_burstsz);
+}
+
+xtrx_sink_c::~xtrx_sink_c()
+{
+ std::cerr << "xtrx_sink_c::~xtrx_sink_c()" << std::endl;
+}
+
+std::string xtrx_sink_c::name()
+{
+ return "GrLibXTRX";
+}
+
+size_t xtrx_sink_c::get_num_channels( void )
+{
+ return input_signature()->max_streams();
+}
+
+osmosdr::meta_range_t xtrx_sink_c::get_sample_rates( void )
+{
+ osmosdr::meta_range_t range;
+ range += osmosdr::range_t( 1000000, 160000000, 1 );
+ return range;
+}
+
+double xtrx_sink_c::set_sample_rate( double rate )
+{
+ std::cerr << "Set sample rate " << rate << std::endl;
+ _rate = _xtrx->set_smaplerate(rate, _master, true, _sample_flags);
+ return get_sample_rate();
+}
+
+double xtrx_sink_c::get_sample_rate( void )
+{
+ return _rate;
+}
+
+osmosdr::freq_range_t xtrx_sink_c::get_freq_range( size_t chan )
+{
+ osmosdr::freq_range_t range;
+ range += osmosdr::range_t( double(0.03e9), double(3.8e9), 1); // as far as we know
+ return range;
+}
+
+double xtrx_sink_c::set_center_freq( double freq, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ _freq = freq;
+ double corr_freq = (freq)*(1.0 + (_corr) * 0.000001);
+
+ std::cerr << "TX Set freq " << freq << std::endl;
+ xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
+
+ int res = xtrx_tune_ex(_xtrx->dev(), (_tdd) ? XTRX_TUNE_TX_AND_RX_TDD : XTRX_TUNE_TX_FDD, xchan, corr_freq - _dsp, &_freq);
+ if (res) {
+ std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
+ }
+
+ res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_TX, xchan, _dsp, NULL);
+ return get_center_freq(chan);
+}
+
+double xtrx_sink_c::get_center_freq( size_t chan )
+{
+ return _freq + _dsp;
+}
+
+double xtrx_sink_c::set_freq_corr( double ppm, size_t chan )
+{
+ _corr = ppm;
+
+ set_center_freq(_freq, chan);
+
+ return get_freq_corr( chan );
+}
+
+double xtrx_sink_c::get_freq_corr( size_t chan )
+{
+ return _corr;
+}
+
+
+static const std::vector<std::string> s_lna_list = boost::assign::list_of("TX");
+
+std::vector<std::string> xtrx_sink_c::get_gain_names( size_t chan )
+{
+ return s_lna_list;
+}
+
+osmosdr::gain_range_t xtrx_sink_c::get_gain_range( size_t chan )
+{
+ return get_gain_range("TX", chan);
+}
+
+osmosdr::gain_range_t xtrx_sink_c::get_gain_range( const std::string & name, size_t chan )
+{
+ osmosdr::gain_range_t range;
+ range += osmosdr::range_t( -31, 0, 1 );
+ return range;
+}
+
+bool xtrx_sink_c::set_gain_mode( bool automatic, size_t chan )
+{
+ _auto_gain = automatic;
+ return get_gain_mode(chan);
+}
+
+bool xtrx_sink_c::get_gain_mode( size_t chan )
+{
+ return _auto_gain;
+}
+
+double xtrx_sink_c::set_gain( double gain, size_t chan )
+{
+ return set_gain(gain, "TX", chan);
+}
+
+double xtrx_sink_c::set_gain( double igain, const std::string & name, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ osmosdr::gain_range_t gains = xtrx_sink_c::get_gain_range( name, chan );
+ double gain = gains.clip(igain);
+ double actual_gain;
+
+ std::cerr << "Set TX gain: " << igain << std::endl;
+
+ int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+ XTRX_TX_PAD_GAIN, gain, &actual_gain);
+ if (res) {
+ std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
+ }
+
+ _gain_tx = actual_gain;
+ return actual_gain;
+}
+
+double xtrx_sink_c::get_gain( size_t chan )
+{
+ return get_gain("TX");
+}
+
+double xtrx_sink_c::get_gain( const std::string & name, size_t chan )
+{
+ return _gain_tx;
+}
+
+double xtrx_sink_c::set_bandwidth( double bandwidth, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+ std::cerr << "Set bandwidth " << bandwidth << " chan " << chan << std::endl;
+
+ if (bandwidth <= 0.0) {
+ bandwidth = get_sample_rate() * 0.75;
+ if (bandwidth < 0.5e6) {
+ bandwidth = 0.5e6;
+ }
+ }
+
+ int res = xtrx_tune_tx_bandwidth(_xtrx->dev(),
+ (xtrx_channel_t)(XTRX_CH_A << chan),
+ bandwidth, &_bandwidth);
+ if (res) {
+ std::cerr << "Can't set bandwidth: " << res << std::endl;
+ }
+ return get_bandwidth(chan);
+}
+
+double xtrx_sink_c::get_bandwidth( size_t chan )
+{
+ return _bandwidth;
+}
+
+
+static const std::map<std::string, xtrx_antenna_t> s_ant_map = boost::assign::map_list_of
+ ("AUTO", XTRX_TX_AUTO)
+ ("B1", XTRX_TX_H)
+ ("B2", XTRX_TX_W)
+ ("TXH", XTRX_TX_H)
+ ("TXW", XTRX_TX_W)
+ ;
+static const std::map<xtrx_antenna_t, std::string> s_ant_map_r = boost::assign::map_list_of
+ (XTRX_TX_H, "TXH")
+ (XTRX_TX_W, "TXW")
+ (XTRX_TX_AUTO, "AUTO")
+ ;
+
+static xtrx_antenna_t get_ant_type(const std::string& name)
+{
+ std::map<std::string, xtrx_antenna_t>::const_iterator it;
+
+ it = s_ant_map.find(name);
+ if (it != s_ant_map.end()) {
+ return it->second;
+ }
+
+ return XTRX_TX_AUTO;
+}
+
+static const std::vector<std::string> s_ant_list = boost::assign::list_of
+ ("AUTO")("TXH")("TXW")
+ ;
+
+
+std::vector< std::string > xtrx_sink_c::get_antennas( size_t chan )
+{
+ return s_ant_list;
+}
+
+std::string xtrx_sink_c::set_antenna( const std::string & antenna, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+ _ant = get_ant_type(antenna);
+
+ std::cerr << "Set antenna " << antenna << std::endl;
+
+ int res = xtrx_set_antenna_ex(_xtrx->dev(),
+ (xtrx_channel_t)(XTRX_CH_A << chan),
+ _ant);
+ if (res) {
+ std::cerr << "Can't set antenna: " << antenna << std::endl;
+ }
+ return get_antenna( chan );
+}
+
+std::string xtrx_sink_c::get_antenna( size_t chan )
+{
+ return s_ant_map_r.find(_ant)->second;
+}
+
+void xtrx_sink_c::tag_process(int ninput_items)
+{
+ std::sort(_tags.begin(), _tags.end(), gr::tag_t::offset_compare);
+
+ const uint64_t samp0_count = this->nitems_read(0);
+ uint64_t max_count = samp0_count + ninput_items;
+
+ bool found_time_tag = false;
+ BOOST_FOREACH(const gr::tag_t &my_tag, _tags) {
+ const uint64_t my_tag_count = my_tag.offset;
+ const pmt::pmt_t &key = my_tag.key;
+ const pmt::pmt_t &value = my_tag.value;
+
+ if (my_tag_count >= max_count) {
+ break;
+ } else if(pmt::equal(key, TIME_KEY)) {
+ //if (my_tag_count != samp0_count) {
+ // max_count = my_tag_count;
+ // break;
+ //}
+ found_time_tag = true;
+ //_metadata.has_time_spec = true;
+ //_metadata.time_spec = ::uhd::time_spec_t
+ // (pmt::to_uint64(pmt::tuple_ref(value, 0)),
+ // pmt::to_double(pmt::tuple_ref(value, 1)));
+ uint64_t seconds = pmt::to_uint64(pmt::tuple_ref(value, 0));
+ double fractional = pmt::to_double(pmt::tuple_ref(value, 1));
+
+ std::cerr << "TX_TIME: " << seconds << ":" << fractional << std::endl;
+ }
+ } // end foreach
+
+ if (found_time_tag) {
+ //_metadata.has_time_spec = true;
+ }
+}
+
+int xtrx_sink_c::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ int ninput_items = noutput_items;
+ const uint64_t samp0_count = nitems_read(0);
+ get_tags_in_range(_tags, 0, samp0_count, samp0_count + ninput_items);
+ if (!_tags.empty())
+ tag_process(ninput_items);
+
+ xtrx_send_ex_info_t nfo;
+ nfo.samples = noutput_items;
+ nfo.buffer_count = input_items.size();
+ nfo.buffers = &input_items[0];
+ nfo.flags = XTRX_TX_DONT_BUFFER;
+ if (!_allow_dis)
+ nfo.flags |= XTRX_TX_NO_DISCARD;
+ nfo.ts = _ts;
+ nfo.timeout = 0;
+
+ int res = xtrx_send_sync_ex(_xtrx->dev(), &nfo);
+ if (res) {
+ std::cerr << "Err: " << res << std::endl;
+
+ std::stringstream message;
+ message << "xtrx_send_burst_sync error: " << -res;
+ throw std::runtime_error( message.str() );
+ }
+
+ _ts += noutput_items;
+ for (unsigned i = 0; i < input_items.size(); i++) {
+ consume(i, noutput_items);
+ }
+ return 0;
+}
+
+bool xtrx_sink_c::start()
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ xtrx_run_params_t params;
+ xtrx_run_params_init(¶ms);
+
+ params.dir = XTRX_TX;
+ if (!_mimo_mode)
+ params.tx.flags |= XTRX_RSP_SISO_MODE;
+
+ if (_swap_ab)
+ params.tx.flags |= XTRX_RSP_SWAP_AB;
+
+ if (_swap_iq)
+ params.tx.flags |= XTRX_RSP_SWAP_IQ;
+
+ params.tx.hfmt = XTRX_IQ_FLOAT32;
+ params.tx.wfmt = _otw;
+ params.tx.chs = XTRX_CH_AB;
+ params.tx.paketsize = 0;
+ params.rx_stream_start = 256*1024;
+
+ int res = xtrx_run_ex(_xtrx->dev(), ¶ms);
+ if (res) {
+ std::cerr << "Got error: " << res << std::endl;
+ }
+
+ return res == 0;
+}
+
+bool xtrx_sink_c::stop()
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ //TODO:
+ std::cerr << "xtrx_sink_c::stop()" << std::endl;
+ int res = xtrx_stop(_xtrx->dev(), XTRX_TX);
+ if (res) {
+ std::cerr << "Got error: " << res << std::endl;
+ }
+
+ return res == 0;
+}
diff --git a/lib/xtrx/xtrx_sink_c.h b/lib/xtrx/xtrx_sink_c.h
new file mode 100644
index 0000000..8a041e6
--- /dev/null
+++ b/lib/xtrx/xtrx_sink_c.h
@@ -0,0 +1,130 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Sergey Kostanabev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 XTRX_SINK_C_H
+#define XTRX_SINK_C_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/sync_block.h>
+
+#include "sink_iface.h"
+#include "xtrx_obj.h"
+
+
+static const pmt::pmt_t SOB_KEY = pmt::string_to_symbol("tx_sob");
+static const pmt::pmt_t EOB_KEY = pmt::string_to_symbol("tx_eob");
+static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("tx_time");
+static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("tx_freq");
+static const pmt::pmt_t COMMAND_KEY = pmt::string_to_symbol("tx_command");
+
+class xtrx_sink_c;
+
+typedef boost::shared_ptr< xtrx_sink_c > xtrx_sink_c_sptr;
+
+xtrx_sink_c_sptr make_xtrx_sink_c( const std::string & args = "" );
+
+class xtrx_sink_c :
+ public gr::sync_block,
+ public sink_iface
+{
+private:
+ friend xtrx_sink_c_sptr make_xtrx_sink_c(const std::string &args);
+
+ xtrx_sink_c(const std::string &args);
+
+public:
+ ~xtrx_sink_c();
+
+ std::string name();
+
+ static std::vector< std::string > get_devices( bool fake = false ) { return xtrx_obj::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 );
+
+ 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 );
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ bool start();
+ bool stop();
+
+ void tag_process(int ninput_items);
+
+private:
+ xtrx_obj_sptr _xtrx;
+ std::vector<gr::tag_t> _tags;
+
+ unsigned _sample_flags;
+ double _rate;
+ double _master;
+ double _freq;
+ double _corr;
+ double _bandwidth;
+ double _dsp;
+ bool _auto_gain;
+
+ xtrx_wire_format_t _otw;
+ bool _mimo_mode;
+
+ int _gain_tx;
+
+ unsigned _channels;
+ xtrx_antenna_t _ant;
+
+ uint64_t _ts;
+
+ bool _swap_ab;
+ bool _swap_iq;
+
+ bool _tdd;
+ bool _allow_dis;
+
+ std::string _dev;
+};
+
+#endif // xtrx_sink_c_H
+
diff --git a/lib/xtrx/xtrx_source_c.cc b/lib/xtrx/xtrx_source_c.cc
new file mode 100644
index 0000000..6b0611e
--- /dev/null
+++ b/lib/xtrx/xtrx_source_c.cc
@@ -0,0 +1,583 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 <fstream>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include <boost/assign.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <gnuradio/io_signature.h>
+#include <gnuradio/blocks/deinterleave.h>
+#include <gnuradio/blocks/float_to_complex.h>
+
+#include "xtrx_source_c.h"
+
+#include "arg_helpers.h"
+
+using namespace boost::assign;
+
+
+xtrx_source_c_sptr make_xtrx_source_c(const std::string &args)
+{
+ return gnuradio::get_initial_sptr(new xtrx_source_c(args));
+}
+
+static size_t parse_nchan(const std::string &args)
+{
+ size_t nchan = 1;
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("nchan"))
+ nchan = boost::lexical_cast< size_t >( dict["nchan"] );
+
+ if (nchan < 1)
+ nchan = 1;
+
+ return nchan;
+}
+
+xtrx_source_c::xtrx_source_c(const std::string &args) :
+ gr::sync_block("xtrx_source_c",
+ gr::io_signature::make(0, 0, 0),
+ gr::io_signature::make(parse_nchan(args),
+ parse_nchan(args),
+ sizeof(gr_complex))),
+ _sample_flags(0),
+ _rate(0),
+ _master(0),
+ _freq(0),
+ _corr(0),
+ _bandwidth(0),
+ _auto_gain(false),
+ _otw(XTRX_WF_16),
+ _mimo_mode(false),
+ _gain_lna(0),
+ _gain_tia(0),
+ _gain_pga(0),
+ _channels(parse_nchan(args)),
+ _swap_ab(false),
+ _swap_iq(false),
+ _loopback(false),
+ _tdd(false),
+ _fbctrl(false),
+ _timekey(false),
+ _dsp(0)
+{
+ _id = pmt::string_to_symbol(args);
+
+ dict_t dict = params_to_dict(args);
+
+ if (dict.count("otw_format")) {
+ const std::string& otw = dict["otw_format"];
+ if (otw == "sc16" || otw == "16") {
+ _otw = XTRX_WF_16;
+ } else if (otw == "sc12" || otw == "12") {
+ _otw = XTRX_WF_12;
+ } else if (otw == "sc8" || otw == "8") {
+ _otw = XTRX_WF_8;
+ } else {
+ throw std::runtime_error("Parameter `otw_format` should be {sc16,sc12,sc8}");
+ }
+ }
+
+ if (dict.count("master")) {
+ _master = boost::lexical_cast< double >( dict["master"]);
+ }
+
+ std::cerr << args.c_str() << std::endl;
+
+ int loglevel = 2;
+ if (dict.count("loglevel")) {
+ loglevel = boost::lexical_cast< int >( dict["loglevel"] );
+ }
+
+ if (dict.count("fbctrl")) {
+ _fbctrl = boost::lexical_cast< bool >( dict["fbctrl"] );
+ }
+
+ if (dict.count("swap_ab")) {
+ _swap_ab = true;
+ std::cerr << "xtrx_source_c: swap AB channels" << std::endl;
+ }
+
+ if (dict.count("swap_iq")) {
+ _swap_iq = true;
+ std::cerr << "xtrx_source_c: swap IQ" << std::endl;
+ }
+
+ if (dict.count("sfl")) {
+ _sample_flags = boost::lexical_cast< unsigned >( dict["sfl"] );
+ }
+
+ if (dict.count("loopback")) {
+ _loopback = true;
+ std::cerr << "xtrx_source_c: loopback" << std::endl;
+ }
+
+ if (dict.count("tdd")) {
+ _tdd = true;
+ std::cerr << "xtrx_source_c: TDD mode" << std::endl;
+ }
+
+ if (dict.count("dsp")) {
+ _dsp = boost::lexical_cast< double >( dict["dsp"] );
+ std::cerr << "xtrx_source_c: DSP:" << _dsp << std::endl;
+ }
+
+ if (dict.count("dev")) {
+ _dev = dict["dev"];
+ std::cerr << "xtrx_source_c: XTRX device string `" << _dev.c_str() << "`" << std::endl;
+ }
+
+ xtrx_log_setlevel(loglevel, NULL);
+ _xtrx = xtrx_obj::get(_dev.c_str());
+ if (_xtrx->dev_count() * 2 == _channels) {
+ _mimo_mode = true;
+ } else if (_xtrx->dev_count() != _channels) {
+ throw std::runtime_error("Number of requested channels != number of devices");
+ }
+
+ if (dict.count("refclk")) {
+ xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
+ }
+ if (dict.count("extclk")) {
+ xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
+ }
+
+ if (dict.count("vio")) {
+ unsigned vio = boost::lexical_cast< unsigned >( dict["vio"] );
+ _xtrx->set_vio(vio);
+ }
+
+ if (dict.count("dac")) {
+ unsigned dac = boost::lexical_cast< unsigned >( dict["dac"] );
+ xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_VCTCXO_DAC_VAL, dac);
+ }
+
+ if (dict.count("pmode")) {
+ unsigned pmode = boost::lexical_cast< unsigned >( dict["pmode"] );
+ xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_LMS7_PWR_MODE, pmode);
+ }
+
+ if (dict.count("timekey")) {
+ _timekey = boost::lexical_cast< bool >( dict["timekey"] );
+ }
+
+ std::cerr << "xtrx_source_c::xtrx_source_c()" << std::endl;
+ set_alignment(32);
+ if (_otw == XTRX_WF_16) {
+ if (_mimo_mode)
+ set_output_multiple(4096);
+ else
+ set_output_multiple(8192);
+ } else if (_otw == XTRX_WF_8) {
+ if (_mimo_mode)
+ set_output_multiple(8192);
+ else
+ set_output_multiple(16384);
+ }
+}
+
+xtrx_source_c::~xtrx_source_c()
+{
+ std::cerr << "xtrx_source_c::~xtrx_source_c()" << std::endl;
+}
+
+std::string xtrx_source_c::name()
+{
+ return "GrLibXTRX";
+}
+
+size_t xtrx_source_c::get_num_channels( void )
+{
+ return output_signature()->max_streams();
+}
+
+osmosdr::meta_range_t xtrx_source_c::get_sample_rates( void )
+{
+ osmosdr::meta_range_t range;
+ range += osmosdr::range_t( 200000, 160000000, 1 );
+ return range;
+}
+
+double xtrx_source_c::set_sample_rate( double rate )
+{
+ std::cerr << "Set sample rate " << rate << std::endl;
+ _rate = _xtrx->set_smaplerate(rate, _master, false, _sample_flags);
+ return get_sample_rate();
+}
+
+double xtrx_source_c::get_sample_rate( void )
+{
+ return _rate;
+}
+
+osmosdr::freq_range_t xtrx_source_c::get_freq_range( size_t chan )
+{
+ osmosdr::freq_range_t range;
+ range += osmosdr::range_t( double(0.03e9), double(3.8e9), 1); // as far as we know
+ return range;
+}
+
+double xtrx_source_c::set_center_freq( double freq, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ _freq = freq;
+ double corr_freq = (freq)*(1.0 + (_corr) * 0.000001);
+
+ if (_tdd)
+ return get_center_freq(chan);
+
+ xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
+
+ std::cerr << "Set RX freq: " << freq << " chan: " << xchan << std::endl;
+
+ int res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_RX_FDD, xchan, corr_freq - _dsp, &_freq);
+ if (res) {
+ std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
+ }
+
+ res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, xchan, _dsp, NULL);
+
+ return get_center_freq(chan);
+}
+
+double xtrx_source_c::get_center_freq( size_t chan )
+{
+ return _freq;
+}
+
+double xtrx_source_c::set_freq_corr( double ppm, size_t chan )
+{
+ _corr = ppm;
+
+ set_center_freq(_freq, chan);
+
+ return get_freq_corr( chan );
+}
+
+double xtrx_source_c::get_freq_corr( size_t chan )
+{
+ return _corr;
+}
+
+static const std::map<std::string, xtrx_gain_type_t> s_lna_map = boost::assign::map_list_of
+ ("LNA", XTRX_RX_LNA_GAIN)
+ ("TIA", XTRX_RX_TIA_GAIN)
+ ("PGA", XTRX_RX_PGA_GAIN)
+ ("LB", XTRX_RX_LB_GAIN)
+ ;
+
+static xtrx_gain_type_t get_gain_type(const std::string& name)
+{
+ std::map<std::string, xtrx_gain_type_t>::const_iterator it;
+
+ it = s_lna_map.find(name);
+ if (it != s_lna_map.end()) {
+ return it->second;
+ }
+
+ return XTRX_RX_LNA_GAIN;
+}
+
+static const std::vector<std::string> s_lna_list = boost::assign::list_of
+ ("LNA")("TIA")("PGA")("LB")
+ ;
+
+std::vector<std::string> xtrx_source_c::get_gain_names( size_t chan )
+{
+ return s_lna_list;
+}
+
+osmosdr::gain_range_t xtrx_source_c::get_gain_range( size_t chan )
+{
+ return get_gain_range("LNA", chan);
+}
+
+osmosdr::gain_range_t xtrx_source_c::get_gain_range( const std::string & name, size_t chan )
+{
+ osmosdr::gain_range_t range;
+
+ if (name == "LNA") {
+ range += osmosdr::range_t( 0, 24, 3 );
+ range += osmosdr::range_t( 25, 30, 1 );
+ } else if (name == "TIA") {
+ range += osmosdr::range_t( 0 );
+ range += osmosdr::range_t( 9 );
+ range += osmosdr::range_t( 12 );
+ } else if (name == "PGA") {
+ range += osmosdr::range_t( -12.5, 12.5, 1 );
+ } else if (name == "LB") {
+ range += osmosdr::range_t( -40, 0, 1 );
+ }
+
+ return range;
+}
+
+bool xtrx_source_c::set_gain_mode( bool automatic, size_t chan )
+{
+ _auto_gain = automatic;
+ return get_gain_mode(chan);
+}
+
+bool xtrx_source_c::get_gain_mode( size_t chan )
+{
+ return _auto_gain;
+}
+
+double xtrx_source_c::set_gain( double gain, size_t chan )
+{
+ return set_gain(gain, "LNA", chan);
+}
+
+double xtrx_source_c::set_gain( double igain, const std::string & name, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ osmosdr::gain_range_t gains = xtrx_source_c::get_gain_range( name, chan );
+ double gain = gains.clip(igain);
+ double actual_gain;
+ xtrx_gain_type_t gt = get_gain_type(name);
+
+ std::cerr << "Set gain " << name << " chan: " << chan << " (" << gt << "): " << igain << std::endl;
+
+ int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+ gt, gain, &actual_gain);
+ if (res) {
+ std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
+ }
+
+ switch (gt) {
+ case XTRX_RX_LNA_GAIN: _gain_lna = actual_gain; break;
+ case XTRX_RX_TIA_GAIN: _gain_tia = actual_gain; break;
+ case XTRX_RX_PGA_GAIN: _gain_pga = actual_gain; break;
+ default: break;
+ }
+
+ return actual_gain;
+}
+
+double xtrx_source_c::get_gain( size_t chan )
+{
+ return get_gain("LNA");
+}
+
+double xtrx_source_c::get_gain( const std::string & name, size_t chan )
+{
+ xtrx_gain_type_t gt = get_gain_type(name);
+ switch (gt) {
+ case XTRX_RX_LNA_GAIN: return _gain_lna;
+ case XTRX_RX_TIA_GAIN: return _gain_tia;
+ case XTRX_RX_PGA_GAIN: return _gain_pga;
+ default: return 0;
+ }
+}
+
+double xtrx_source_c::set_if_gain(double gain, size_t chan)
+{
+ return set_gain(gain, "PGA", chan);
+}
+
+double xtrx_source_c::set_bandwidth( double bandwidth, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+ std::cerr << "Set bandwidth " << bandwidth << " chan " << chan << std::endl;
+
+ if (bandwidth <= 0.0) {
+ bandwidth = get_sample_rate() * 0.75;
+ if (bandwidth < 0.5e6) {
+ bandwidth = 0.5e6;
+ }
+ }
+
+ int res = xtrx_tune_rx_bandwidth(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+ bandwidth, &_bandwidth);
+ if (res) {
+ std::cerr << "Can't set bandwidth: " << res << std::endl;
+ }
+ return get_bandwidth(chan);
+}
+
+double xtrx_source_c::get_bandwidth( size_t chan )
+{
+ return _bandwidth;
+}
+
+osmosdr::freq_range_t xtrx_source_c::get_bandwidth_range( size_t chan )
+{
+ return osmosdr::freq_range_t(500e3, 140e6, 0);
+}
+
+
+static const std::map<std::string, xtrx_antenna_t> s_ant_map = boost::assign::map_list_of
+ ("AUTO", XTRX_RX_AUTO)
+ ("RXL", XTRX_RX_L)
+ ("RXH", XTRX_RX_H)
+ ("RXW", XTRX_RX_W)
+ ("RXL_LB", XTRX_RX_L_LB)
+ ("RXW_LB", XTRX_RX_W_LB)
+ ("ADC", XTRX_RX_ADC_EXT)
+ ;
+static const std::map<xtrx_antenna_t, std::string> s_ant_map_r = boost::assign::map_list_of
+ (XTRX_RX_AUTO, "AUTO")
+ (XTRX_RX_L, "RXL")
+ (XTRX_RX_H, "RXH")
+ (XTRX_RX_W, "RXW")
+ (XTRX_RX_L_LB, "RXL_LB")
+ (XTRX_RX_W_LB, "RXW_LB")
+ (XTRX_RX_ADC_EXT, "ADC")
+ ;
+
+static xtrx_antenna_t get_ant_type(const std::string& name)
+{
+ std::map<std::string, xtrx_antenna_t>::const_iterator it;
+
+ it = s_ant_map.find(name);
+ if (it != s_ant_map.end()) {
+ return it->second;
+ }
+
+ return XTRX_RX_AUTO;
+}
+
+static const std::vector<std::string> s_ant_list = boost::assign::list_of
+ ("AUTO")("RXL")("RXH")("RXW")("ADC")
+ ;
+
+
+std::vector< std::string > xtrx_source_c::get_antennas( size_t chan )
+{
+ return s_ant_list;
+}
+
+std::string xtrx_source_c::set_antenna( const std::string & antenna, size_t chan )
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+ _ant = get_ant_type(antenna);
+
+ std::cerr << "Set antenna " << antenna << " type:" << _ant << std::endl;
+
+ int res = xtrx_set_antenna_ex(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+ _ant);
+ if (res) {
+ std::cerr << "Can't set antenna: " << antenna << std::endl;
+ }
+ return get_antenna( chan );
+}
+
+std::string xtrx_source_c::get_antenna( size_t chan )
+{
+ return s_ant_map_r.find(_ant)->second;
+}
+
+int xtrx_source_c::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ xtrx_recv_ex_info_t ri;
+ ri.samples = noutput_items;
+ ri.buffer_count = output_items.size();
+ ri.buffers = &output_items[0];
+ ri.flags = RCVEX_DONT_INSER_ZEROS | RCVEX_DROP_OLD_ON_OVERFLOW;
+ ri.timeout = 1000;
+
+ int res = xtrx_recv_sync_ex(_xtrx->dev(), &ri);
+ if (res) {
+ std::stringstream message;
+ message << "xtrx_recv_sync error: " << -res;
+ throw std::runtime_error( message.str() );
+ return 0;
+ }
+
+ if (_timekey) {
+ uint64_t seconds = (ri.out_first_sample / _rate);
+ double fractional = (ri.out_first_sample - (uint64_t)(_rate * seconds)) / _rate;
+
+ //std::cerr << "Time " << seconds << ":" << fractional << std::endl;
+ const pmt::pmt_t val = pmt::make_tuple
+ (pmt::from_uint64(seconds),
+ pmt::from_double(fractional));
+ for(size_t i = 0; i < output_items.size(); i++) {
+ this->add_item_tag(i, nitems_written(0), TIME_KEY,
+ val, _id);
+ this->add_item_tag(i, nitems_written(0), RATE_KEY,
+ pmt::from_double(_rate), _id);
+ this->add_item_tag(i, nitems_written(0), FREQ_KEY,
+ pmt::from_double(this->get_center_freq(i)), _id);
+ }
+ }
+ return ri.out_samples;
+}
+
+bool xtrx_source_c::start()
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+
+ xtrx_run_params_t params;
+ xtrx_run_params_init(¶ms);
+
+ params.dir = XTRX_RX;
+ if (!_mimo_mode)
+ params.rx.flags |= XTRX_RSP_SISO_MODE;
+
+ if (_swap_ab)
+ params.rx.flags |= XTRX_RSP_SWAP_AB;
+
+ if (_swap_iq)
+ params.rx.flags |= XTRX_RSP_SWAP_IQ;
+
+ params.rx.hfmt = XTRX_IQ_FLOAT32;
+ params.rx.wfmt = _otw;
+ params.rx.chs = XTRX_CH_ALL;
+ params.rx.paketsize = 0;
+ params.rx_stream_start = 256*1024;
+
+ params.nflags = (_loopback) ? XTRX_RUN_DIGLOOPBACK : 0;
+
+ int res = xtrx_run_ex(_xtrx->dev(), ¶ms);
+ if (res) {
+ std::cerr << "Got error: " << res << std::endl;
+ }
+
+ res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, XTRX_CH_ALL, _dsp, NULL);
+
+ return res == 0;
+}
+
+bool xtrx_source_c::stop()
+{
+ boost::mutex::scoped_lock lock(_xtrx->mtx);
+ //TODO:
+ std::cerr << "xtrx_source_c::stop()" << std::endl;
+ int res = xtrx_stop(_xtrx->dev(), XTRX_RX);
+ if (res) {
+ std::cerr << "Got error: " << res << std::endl;
+ }
+
+ return res == 0;
+}
+
diff --git a/lib/xtrx/xtrx_source_c.h b/lib/xtrx/xtrx_source_c.h
new file mode 100644
index 0000000..3189f88
--- /dev/null
+++ b/lib/xtrx/xtrx_source_c.h
@@ -0,0 +1,128 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016,2017 Sergey Kostanbaev <sergey.kostanbaev(a)fairwaves.co>
+ *
+ * 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 XTRX_SOURCE_C_H
+#define XTRX_SOURCE_C_H
+
+#include <gnuradio/block.h>
+#include <gnuradio/sync_block.h>
+
+#include "source_iface.h"
+#include "xtrx_obj.h"
+
+static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("rx_time");
+static const pmt::pmt_t RATE_KEY = pmt::string_to_symbol("rx_rate");
+static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("rx_freq");
+
+class xtrx_source_c;
+
+typedef boost::shared_ptr< xtrx_source_c > xtrx_source_c_sptr;
+
+xtrx_source_c_sptr make_xtrx_source_c( const std::string & args = "" );
+
+class xtrx_source_c :
+ public gr::sync_block,
+ public source_iface
+{
+private:
+ friend xtrx_source_c_sptr make_xtrx_source_c(const std::string &args);
+
+ xtrx_source_c(const std::string &args);
+
+public:
+ ~xtrx_source_c();
+
+ std::string name();
+
+ static std::vector< std::string > get_devices( bool fake = false ) { return xtrx_obj::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_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);
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ bool start();
+ bool stop();
+
+private:
+ xtrx_obj_sptr _xtrx;
+ pmt::pmt_t _id;
+
+ unsigned _sample_flags;
+ double _rate;
+ double _master;
+ double _freq;
+ double _corr;
+ double _bandwidth;
+ bool _auto_gain;
+
+ xtrx_wire_format_t _otw;
+ bool _mimo_mode;
+
+ int _gain_lna;
+ int _gain_tia;
+ int _gain_pga;
+
+ unsigned _channels;
+ xtrx_antenna_t _ant;
+
+ bool _swap_ab;
+ bool _swap_iq;
+ bool _loopback;
+ bool _tdd;
+ bool _fbctrl;
+ bool _timekey;
+
+ double _dsp;
+ std::string _dev;
+};
+
+#endif // XTRX_SOURCE_C_H
+
--
2.23.0.rc1
1
0