summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml78
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac41
-rw-r--r--doc/example.ini102
-rw-r--r--lib/UdpSocket.cpp2
-rw-r--r--m4/ax_boost_base.m4241
-rw-r--r--m4/ax_boost_system.m4121
-rw-r--r--m4/ax_boost_thread.m4163
-rw-r--r--src/Buffer.cpp88
-rw-r--r--src/Buffer.h44
-rw-r--r--src/ConfigParser.cpp6
-rw-r--r--src/ConfigParser.h3
-rw-r--r--src/ConvEncoder.cpp1
-rw-r--r--src/DabMod.cpp31
-rw-r--r--src/DabModulator.cpp7
-rw-r--r--src/EtiReader.cpp11
-rw-r--r--src/EtiReader.h1
-rw-r--r--src/FIRFilter.cpp5
-rw-r--r--src/FicSource.cpp1
-rw-r--r--src/Flowgraph.cpp7
-rw-r--r--src/FormatConverter.cpp1
-rw-r--r--src/FrameMultiplexer.cpp5
-rw-r--r--src/FrameMultiplexer.h10
-rw-r--r--src/FrequencyInterleaver.cpp9
-rw-r--r--src/GainControl.cpp12
-rw-r--r--src/GainControl.h2
-rw-r--r--src/GuardIntervalInserter.cpp263
-rw-r--r--src/GuardIntervalInserter.h64
-rw-r--r--src/MemlessPoly.cpp5
-rw-r--r--src/NullSymbol.cpp2
-rw-r--r--src/OfdmGenerator.cpp14
-rw-r--r--src/PrbsGenerator.cpp7
-rw-r--r--src/PrbsGenerator.h2
-rw-r--r--src/PuncturingEncoder.cpp1
-rw-r--r--src/RemoteControl.cpp18
-rw-r--r--src/Resampler.cpp10
-rw-r--r--src/Socket.h1
-rw-r--r--src/SubchannelSource.cpp1
-rw-r--r--src/TII.cpp23
-rw-r--r--src/TII.h3
-rw-r--r--src/TimeInterleaver.cpp1
-rw-r--r--src/TimestampDecoder.cpp6
-rw-r--r--src/Utils.cpp6
-rw-r--r--src/Utils.h1
-rw-r--r--src/porting.c13
-rw-r--r--src/porting.h20
46 files changed, 1027 insertions, 432 deletions
diff --git a/.travis.yml b/.travis.yml
index 2bd4ad6..e664812 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,36 +1,56 @@
language: c++
-sudo: required
-dist: trusty
-
-addons: &addons
- apt:
- sources: &sources
- - ubuntu-toolchain-r-test
- packages: &packages
- - libzmq3-dev
- - libzmq3
- - automake
- - libtool
- - libboost1.55-all-dev
- - libcurl4-openssl-dev
- - libfftw3-dev
- # libuhd-dev is not allowed
- - g++-6
-
-compiler:
- - gcc
+
+matrix:
+ include:
+ # Clang on OSX
+ # Sadly, OutputUHD still needs clock_gettime() even if UHD is available
+ # in homebrew
+ - env: MATRIX_EVAL="" CONF="--disable-output-uhd"
+ os: osx
+ osx_image: xcode9.1
+ compiler: clang
+
+ # GCC and clang builds on Linux
+ - env: MATRIX_EVAL="CC=gcc-6 CXX=g++-6" CONF="--disable-zeromq --disable-output-uhd"
+ os: linux
+ dist: trusty
+ sudo: required
+ compiler: gcc
+ addons: &linuxaddons
+ apt:
+ sources: &sources
+ - ubuntu-toolchain-r-test
+ packages: &packages
+ - libzmq3-dev
+ - libzmq3
+ - automake
+ - libtool
+ - libboost1.55-all-dev
+ - libcurl4-openssl-dev
+ - libfftw3-dev
+ # libuhd-dev is not allowed
+ - g++-6
+
+ - env: MATRIX_EVAL="CC=gcc-6 CXX=g++-6" CONF="--disable-output-uhd --enable-output-raw"
+ compiler: gcc
+ addons: *linuxaddons
+
+ - env: MATRIX_EVAL="CC=gcc-6 CXX=g++-6" CONF="--disable-output-uhd --disable-native"
+ compiler: gcc
+ addons: *linuxaddons
+
+ - env: MATRIX_EVAL="CC=gcc-6 CXX=g++-6" CONF="--disable-output-uhd --enable-trace"
+ compiler: gcc
+ addons: *linuxaddons
+
+before_install:
+ - eval "${MATRIX_EVAL}"
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then (brew install fftw boost zeromq automake || true); fi
script:
- |
./bootstrap.sh
- CC=gcc-6 CXX=g++-6 ./configure --disable-zeromq --disable-output-uhd
- make
- - |
- ./bootstrap.sh
- CC=gcc-6 CXX=g++-6 ./configure --disable-output-uhd
- make
- - |
- ./bootstrap.sh
- CC=gcc-6 CXX=g++-6 ./configure --disable-output-uhd --disable-native
+ ./configure $CONF
make
diff --git a/Makefile.am b/Makefile.am
index 2d56842..8b7d5f4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,11 +37,11 @@ bin_PROGRAMS = odr-dabmod
FFT_LDADD=
-odr_dabmod_CXXFLAGS = -Wall -Isrc -Ilib -std=c++11 \
- $(GITVERSION_FLAGS)
odr_dabmod_CFLAGS = -Wall -Isrc -Ilib \
$(GITVERSION_FLAGS)
-odr_dabmod_LDADD = $(FFT_LDADD)
+odr_dabmod_CXXFLAGS = -Wall -Isrc -Ilib -std=c++11 \
+ $(BOOST_CPPFLAGS) $(GITVERSION_FLAGS)
+odr_dabmod_LDADD = $(FFT_LDADD) $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) $(BOOST_SYSTEM_LIB)
odr_dabmod_SOURCES = src/DabMod.cpp \
src/PcDebug.h \
src/Socket.h \
diff --git a/configure.ac b/configure.ac
index 6b58d3f..261d444 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,13 +80,13 @@ AC_ARG_ENABLE([output_uhd],
[], [enable_output_uhd=yes])
AC_LANG_PUSH([C++])
-AX_CHECK_COMPILE_FLAG([-Wduplicated-cond], [CFLAGS="$CFLAGS -Wduplicated-cond"])
-AX_CHECK_COMPILE_FLAG([-Wduplicated-branches], [CFLAGS="$CFLAGS -Wduplicated-branches"])
-AX_CHECK_COMPILE_FLAG([-Wlogical-op], [CFLAGS="$CFLAGS -Wlogical-op"])
-AX_CHECK_COMPILE_FLAG([-Wrestrict], [CFLAGS="$CFLAGS -Wrestrict"])
-AX_CHECK_COMPILE_FLAG([-Wshadow], [CFLAGS="$CFLAGS -Wshadow"])
-AX_CHECK_COMPILE_FLAG([-Wdouble-promotion], [CXXFLAGS="$CXXFLAGS -Wdouble-promotion"])
-AX_CHECK_COMPILE_FLAG(["-Wformat=2"], [CFLAGS="$CFLAGS -Wformat=2"])
+AX_CHECK_COMPILE_FLAG([-Wduplicated-cond], [CXXFLAGS="$CXXFLAGS -Wduplicated-cond"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG([-Wduplicated-branches], [CXXFLAGS="$CXXFLAGS -Wduplicated-branches"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG([-Wlogical-op], [CXXFLAGS="$CXXFLAGS -Wlogical-op"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG([-Wrestrict], [CXXFLAGS="$CXXFLAGS -Wrestrict"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG([-Wshadow], [CXXFLAGS="$CXXFLAGS -Wshadow"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG([-Wdouble-promotion], [CXXFLAGS="$CXXFLAGS -Wdouble-promotion"], [], ["-Werror"])
+AX_CHECK_COMPILE_FLAG(["-Wformat=2"], [CXXFLAGS="$CXXFLAGS -Wformat=2"], [], ["-Werror"])
AC_LANG_POP([C++])
@@ -128,8 +128,9 @@ AC_SUBST([LIBS], ["$FFTW_LIBS $SOAPYSDR_LIBS $PTHREAD_LIBS $ZMQ_LIBS"])
# Checks for UHD.
AS_IF([test "x$enable_output_uhd" = "xyes"],
- [AC_CHECK_LIB([uhd], [main], [],
- [AC_MSG_ERROR([library uhd is missing])] )])
+ [ AC_CHECK_LIB([uhd], [main], [], [AC_MSG_ERROR([library uhd is missing])])
+ AC_CHECK_LIB([rt], [clock_gettime], [], [AC_MSG_ERROR([library rt is missing])])
+ ])
AS_IF([test "x$enable_output_uhd" = "xyes"],
[AC_DEFINE(HAVE_OUTPUT_UHD, [1], [Define if UHD output is enabled])])
@@ -138,10 +139,8 @@ AS_IF([test "x$enable_soapysdr" = "xyes"],
[AC_DEFINE(HAVE_SOAPYSDR, [1], [Define if SoapySDR output is enabled])])
AX_BOOST_BASE([1.54.0], [], AC_MSG_ERROR([BOOST 1.54 or later is required]))
-AC_CHECK_LIB([boost_system], [main], [], [AC_MSG_ERROR([library boost_system is missing])])
-AC_CHECK_LIB([boost_thread], [main], [], [AC_MSG_ERROR([library boost_thread is missing])])
-
-AC_CHECK_LIB([rt], [clock_gettime], [], [AC_MSG_ERROR([library rt is missing])])
+AX_BOOST_SYSTEM
+AX_BOOST_THREAD
# Tests for different memory allocation debuggers.
# Valgrind doesn't need any.
@@ -154,8 +153,7 @@ AS_IF([test "x$enable_debug" != "xno"],
)])
# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h limits.h malloc.h memory.h netinet/in.h stdint.h stdlib.h string.h sys/time.h sys/timeb.h unistd.h])
-AC_CHECK_DECLS([_mm_malloc], [], [], [#include <mm_malloc.h>])
+AC_CHECK_HEADERS([fcntl.h limits.h memory.h netinet/in.h stdint.h stdlib.h string.h sys/time.h sys/timeb.h unistd.h])
AC_HEADER_STDC
# Checks for typedefs, structures, and compiler characteristics.
@@ -175,6 +173,17 @@ AC_COMPILE_IFELSE(
[AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE([M_PIl], [M_PI], [Replacing define])])
AC_LANG_POP([C++])
+# Linux has prctl to set thread names
+AC_MSG_CHECKING(for prctl and PR_SET_NAME)
+AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[
+ #include <sys/prctl.h>
+ void set_thread_name() {
+ prctl(PR_SET_NAME,"test",0,0,0);
+ }
+ ]])],
+ [ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PRCTL, 1, [Define this symbol if you have prctl and PR_SET_NAME]) ],
+ [ AC_MSG_RESULT(no) ])
# Check for march
AS_IF([test "x$enable_native" = "xyes"],
@@ -194,7 +203,7 @@ AS_IF([test "x$enable_native" = "xyes"],
])
AC_TYPE_SIGNAL
-AC_CHECK_FUNCS([bzero floor ftime gettimeofday memset sqrt strchr strerror strtol])
+AC_CHECK_FUNCS([floor memset sqrt strchr strerror strtol])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/doc/example.ini b/doc/example.ini
index e0a1fc8..ec0525c 100644
--- a/doc/example.ini
+++ b/doc/example.ini
@@ -10,15 +10,15 @@ telnetport=2121
; Enable zmq remote control.
; The zmq remote control is intended for machine-to-machine
-; integration and requires that ODR-DabMod is built with zmq support.
-; The zmq remote control may run in parallel with Telnet.
+; integration. It may run in parallel with Telnet.
;
; Protocol:
; ODR-DabMod binds a zmq rep socket so clients must connect
; using either req or dealer socket.
; [] denotes message part as zmq multi-part message are used for delimitation.
; All message parts are utf-8 encoded strings and match the Telnet command set.
-; Explicit codes are denoted with "".
+; Messages to be sent as literal strings are denoted with "" below.
+;
; The following commands are supported:
; REQ: ["ping"]
; REP: ["ok"]
@@ -34,7 +34,7 @@ telnetport=2121
;
; REQ: ["set"][module name][parameter][value]
; REP: ["ok"] _OR_ ["fail"][error description]
-zmqctrl=0
+zmqctrl=1
zmqctrlendpoint=tcp://127.0.0.1:9400
[log]
@@ -53,6 +53,17 @@ source=/dev/stdin
; When the end of file is reached, it is possible to rewind it
loop=0
+; ETI-over-TCP example:
+;transport=tcp
+;source=localhost:9200
+
+; When recieving data using ZeroMQ, the source is the URI to be used
+;transport=zeromq
+;source=tcp://localhost:8080
+; The option max_frames_queued defines the maximum number of ETI frames
+; that can be in the input queue
+;max_frames_queued=100
+
; EDI input.
; Listen for EDI data on a given UDP port
;transport=edi
@@ -63,16 +74,6 @@ loop=0
; No support yet for multicast, should work with and without PFT
; This EDI implementation does not support EDI Packet Resend
-; When recieving data using ZeroMQ, the source is the URI to be used
-;transport=zeromq
-;source=tcp://localhost:8080
-; The option max_frames_queued defines the maximum number of ETI frames
-; that can be in the input queue
-;max_frames_queued=100
-
-; ETI-over-TCP example:
-;transport=tcp
-;source=localhost:9200
[modulator]
; Mode 'fix' uses a fixed factor and is really not recommended. It is more
@@ -99,7 +100,7 @@ gainmode=var
; Transmission mode
; If not defined, take the mode from ETI
-;mode=2
+;mode=1
; The digital gain is a value that is multiplied to each sample. It is used
; to tune the chain to make sure that no non-linearities appear up to the
@@ -116,17 +117,24 @@ digital_gain=0.8
; is enabled or not !
rate=2048000
-; CIC equaliser for USRP1 and USRP2
+; (DEPRECATED) CIC equaliser for USRP1 and USRP2
; Set to 0 to disable CicEqualiser
; when set to 400000000, an additional USRP2 check is enabled.
; See DabModulator.cpp line 186
-dac_clk_rate=0
+;dac_clk_rate=0
; The USRP1 does not have flexible clocking, you will need
;rate=3200000
; and
;dac_clk_rate=128000000
+; When nonzero, overlap ofdmwindowing samples from each OFDM symbol
+; onto the previous and next symbol, using a raised cosine window function.
+; This has the effect of smoothing the transition from one symbol to the next,
+; which improves spectrum shape.
+; In Transmission Mode I, every data symbol is composed of 2552 samples.
+;ofdmwindowing=10
+
; Settings for crest factor reduction. Statistics for ratio of
; samples that were clipped are available through the RC.
[cfr]
@@ -149,19 +157,9 @@ enabled=1
;filtertapsfile=simple_taps.txt
[poly]
-;Predistortion using memoryless polynom
-enabled=1
+;Predistortion using memoryless polynom, see dpd/ folder for more info
+enabled=0
polycoeffile=polyCoefs
-;eg:
-;echo "8
-;0.1
-;0
-;0
-;0
-;0
-;0
-;0
-;0" > polyCoefs
[output]
; choose output: possible values: uhd, file, zmq, soapysdr
@@ -191,7 +189,7 @@ output=uhd
;format=s8
; The output file:
-filename=/dev/stdout
+filename=ofdm.iq
[uhdoutput]
; The UHD output can be directly used with the Ettus USRP devices
@@ -201,30 +199,30 @@ filename=/dev/stdout
; master_clock_rate = 4 * sample_rate
; or even a higher factor.
;
-; Settings for a USRP B100:
+; Settings for the B200:
device=
-; you can put additional UHD device settings here
master_clock_rate=32768000
-type=b100
-txgain=2.0
-; Try first with small gain values
-; Also set rate to 2048000
-
-; For the B200
-; More information and measurements available on:
-; http://wiki.opendigitalradio.org/index.php/USRP_B200_Measurements
-;
-; Settings:
-;device=
-;master_clock_rate=32768000
-;type=b200
-;txgain=40
+type=b200
+txgain=40
; The B200 needs larger gains (up to 89dB) but,
; "Gain settings are application specific, but it is recommended that users
; consider using at least half of the available gain to get reasonable dynamic
; range."
; From the B200 User Manual
; http://files.ettus.com/uhd_docs/manual/html/usrp_b200.html
+;
+; More information and measurements available on:
+; http://wiki.opendigitalradio.org/index.php/USRP_B200_Measurements
+
+
+; Settings for a USRP B100:
+;device=
+; you can put additional UHD device settings here
+;master_clock_rate=32768000
+;type=b100
+;txgain=2.0
+; Try first with small gain values
+; Also set rate to 2048000
; For the USRP1
@@ -233,7 +231,7 @@ txgain=2.0
; the usrp1 can have two daughterboards, the subdevice parameter allows you
; to choose which one to use
;subdevice=A:0
-; The USRP1 doesn't support master_clock_rate, you need to enable resamping
+; The USRP1 doesn't support master_clock_rate, you need to enable resampling
; You must specify either frequency or channel, but not both.
@@ -275,7 +273,7 @@ max_gps_holdover_time=600
; Enable the TCP server to communicate TX and RX feedback for
; digital predistortion.
; Set to 0 to disable
-dpd_port=50055
+;dpd_port=50055
; section defining ZeroMQ output properties
[zmqoutput]
@@ -320,8 +318,12 @@ offset=0.002
; DAB modes I and II are supported, and must be set explicitly in
; this file. Reading DAB mode from ETI is not supported.
enable=0
-comb=16
-pattern=3
+; comb is also known as sub-identifier.
+comb=1
+; pattern is also known as main-identifier. If you run several transmitters
+; in SFN, it is better to use the same pattern for all, and vary the comb.
+; Otherwise identification of the transmitters may be more difficult.
+pattern=11
; There are two variants of TII being used. The old variant that uses the wrong
; phase on the second carrier in each carrier pairs and is therefore not
; conforming to the specification. Modern analysers can decode both variants,
diff --git a/lib/UdpSocket.cpp b/lib/UdpSocket.cpp
index 570da5f..e711577 100644
--- a/lib/UdpSocket.cpp
+++ b/lib/UdpSocket.cpp
@@ -88,7 +88,7 @@ int UdpSocket::reinit(int port, const std::string& name)
address.setAddress(name);
address.setPort(port);
- if (bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) {
+ if (::bind(listenSocket, address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) {
setInetError("Can't bind socket");
::close(listenSocket);
listenSocket = INVALID_SOCKET;
diff --git a/m4/ax_boost_base.m4 b/m4/ax_boost_base.m4
index 54a2a1b..2bce519 100644
--- a/m4/ax_boost_base.m4
+++ b/m4/ax_boost_base.m4
@@ -1,5 +1,5 @@
# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html
+# https://www.gnu.org/software/autoconf-archive/ax_boost_base.html
# ===========================================================================
#
# SYNOPSIS
@@ -33,7 +33,15 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 20
+#serial 43
+
+# example boost program (need to pass version)
+m4_define([_AX_BOOST_BASE_PROGRAM],
+ [AC_LANG_PROGRAM([[
+#include <boost/version.hpp>
+]],[[
+(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))]));
+]])])
AC_DEFUN([AX_BOOST_BASE],
[
@@ -44,87 +52,121 @@ AC_ARG_WITH([boost],
or disable it (ARG=no)
@<:@ARG=yes@:>@ ])],
[
- if test "$withval" = "no"; then
- want_boost="no"
- elif test "$withval" = "yes"; then
- want_boost="yes"
- ac_boost_path=""
- else
- want_boost="yes"
- ac_boost_path="$withval"
- fi
+ AS_CASE([$withval],
+ [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""],
+ [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""],
+ [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"])
],
[want_boost="yes"])
AC_ARG_WITH([boost-libdir],
- AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
- [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
- [
- if test -d "$withval"
- then
- ac_boost_lib_path="$withval"
- else
- AC_MSG_ERROR(--with-boost-libdir expected directory name)
- fi
- ],
- [ac_boost_lib_path=""]
-)
+ [AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
+ [Force given directory for boost libraries.
+ Note that this will override library path detection,
+ so use this parameter only if default library detection fails
+ and you know exactly where your boost libraries are located.])],
+ [
+ AS_IF([test -d "$withval"],
+ [_AX_BOOST_BASE_boost_lib_path="$withval"],
+ [AC_MSG_ERROR([--with-boost-libdir expected directory name])])
+ ],
+ [_AX_BOOST_BASE_boost_lib_path=""])
-if test "x$want_boost" = "xyes"; then
- boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
- boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
- boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
- boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
- boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
- if test "x$boost_lib_version_req_sub_minor" = "x" ; then
- boost_lib_version_req_sub_minor="0"
- fi
- WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
- AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
+BOOST_LDFLAGS=""
+BOOST_CPPFLAGS=""
+AS_IF([test "x$want_boost" = "xyes"],
+ [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])])
+AC_SUBST(BOOST_CPPFLAGS)
+AC_SUBST(BOOST_LDFLAGS)
+])
+
+
+# convert a version string in $2 to numeric and affect to polymorphic var $1
+AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[
+ AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"])
+ _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'`
+ _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'`
+ AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"],
+ [AC_MSG_ERROR([You should at least specify libboost major version])])
+ _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'`
+ AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"],
+ [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"])
+ _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"],
+ [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"])
+ _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor`
+ AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET)
+])
+
+dnl Run the detection of boost should be run only if $want_boost
+AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
+ _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1])
succeeded=no
+
+ AC_REQUIRE([AC_CANONICAL_HOST])
dnl On 64-bit systems check for system libraries in both lib64 and lib.
dnl The former is specified by FHS, but e.g. Debian does not adhere to
dnl this (as it rises problems for generic multi-arch support).
dnl The last entry in the list is chosen by default when no libraries
dnl are found, e.g. when only header-only libraries are installed!
- libsubdirs="lib"
- ax_arch=`uname -m`
- if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = s390x -o $ax_arch = sparc64; then
- libsubdirs="lib64 lib lib64"
- fi
+ AS_CASE([${host_cpu}],
+ [x86_64],[libsubdirs="lib64 libx32 lib lib64"],
+ [ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
+ [libsubdirs="lib"]
+ )
+
+ dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
+ dnl them priority over the other paths since, if libs are found there, they
+ dnl are almost assuredly the ones desired.
+ AS_CASE([${host_cpu}],
+ [i?86],[multiarch_libsubdir="lib/i386-${host_os}"],
+ [multiarch_libsubdir="lib/${host_cpu}-${host_os}"]
+ )
dnl first we check the system location for boost libraries
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
- if test "$ac_boost_path" != ""; then
- BOOST_CPPFLAGS="-I$ac_boost_path/include"
- for ac_boost_path_tmp in $libsubdirs; do
- if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
- BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
- break
- fi
- done
- elif test "$cross_compiling" != yes; then
- for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
- if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
- for libsubdir in $libsubdirs ; do
- if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[
+ AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"])
+ AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[
+ AC_MSG_RESULT([yes])
+ BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include"
+ for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do
+ AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"])
+ AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[
+ AC_MSG_RESULT([yes])
+ BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp";
+ break;
+ ],
+ [AC_MSG_RESULT([no])])
+ done],[
+ AC_MSG_RESULT([no])])
+ ],[
+ if test X"$cross_compiling" = Xyes; then
+ search_libsubdirs=$multiarch_libsubdir
+ else
+ search_libsubdirs="$multiarch_libsubdir $libsubdirs"
+ fi
+ for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
+ if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
+ for libsubdir in $search_libsubdirs ; do
+ if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
- BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
- BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+ BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir"
+ BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include"
break;
fi
done
- fi
+ ])
dnl overwrite ld flags if we have required special directory with
dnl --with-boost-libdir parameter
- if test "$ac_boost_lib_path" != ""; then
- BOOST_LDFLAGS="-L$ac_boost_lib_path"
- fi
+ AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"],
+ [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"])
+ AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
@@ -135,15 +177,7 @@ if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CXX])
AC_LANG_PUSH(C++)
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- @%:@include <boost/version.hpp>
- ]], [[
- #if BOOST_VERSION >= $WANT_BOOST_VERSION
- // Everything is okay
- #else
- # error Boost version is too old
- #endif
- ]])],[
+ AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
@@ -155,30 +189,50 @@ if test "x$want_boost" = "xyes"; then
dnl if we found no boost with system layout we search for boost libraries
dnl built and installed without the --layout=system option or for a staged(not installed) version
- if test "x$succeeded" != "xyes"; then
+ if test "x$succeeded" != "xyes" ; then
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ BOOST_CPPFLAGS=
+ if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
+ BOOST_LDFLAGS=
+ fi
_version=0
- if test "$ac_boost_path" != ""; then
- if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
- for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
- _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ if test -n "$_AX_BOOST_BASE_boost_path" ; then
+ if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then
+ for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
- if test "$V_CHECK" = "1" ; then
+ if test "x$V_CHECK" = "x1" ; then
_version=$_version_tmp
fi
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
- BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+ BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE"
done
+ dnl if nothing found search for layout used in Windows distributions
+ if test -z "$BOOST_CPPFLAGS"; then
+ if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then
+ BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path"
+ fi
+ fi
+ dnl if we found something and BOOST_LDFLAGS was unset before
+ dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here.
+ if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir"
+ fi
fi
else
- if test "$cross_compiling" != yes; then
- for ac_boost_path in /usr /usr/local /opt /opt/local ; do
- if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
- for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
- _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ if test "x$cross_compiling" != "xyes" ; then
+ for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do
+ if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then
+ for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
- if test "$V_CHECK" = "1" ; then
+ if test "x$V_CHECK" = "x1" ; then
_version=$_version_tmp
- best_path=$ac_boost_path
+ best_path=$_AX_BOOST_BASE_boost_path
fi
done
fi
@@ -186,7 +240,7 @@ if test "x$want_boost" = "xyes"; then
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
- if test "$ac_boost_lib_path" = ""; then
+ if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
for libsubdir in $libsubdirs ; do
if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
@@ -194,7 +248,7 @@ if test "x$want_boost" = "xyes"; then
fi
fi
- if test "x$BOOST_ROOT" != "x"; then
+ if test -n "$BOOST_ROOT" ; then
for libsubdir in $libsubdirs ; do
if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
@@ -203,7 +257,7 @@ if test "x$want_boost" = "xyes"; then
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
V_CHECK=`expr $stage_version_shorten \>\= $_version`
- if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
+ if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
BOOST_CPPFLAGS="-I$BOOST_ROOT"
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
@@ -218,15 +272,7 @@ if test "x$want_boost" = "xyes"; then
export LDFLAGS
AC_LANG_PUSH(C++)
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- @%:@include <boost/version.hpp>
- ]], [[
- #if BOOST_VERSION >= $WANT_BOOST_VERSION
- // Everything is okay
- #else
- # error Boost version is too old
- #endif
- ]])],[
+ AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
@@ -235,17 +281,15 @@ if test "x$want_boost" = "xyes"; then
AC_LANG_POP([C++])
fi
- if test "$succeeded" != "yes" ; then
- if test "$_version" = "0" ; then
- AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
+ if test "x$succeeded" != "xyes" ; then
+ if test "x$_version" = "x0" ; then
+ AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
else
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
fi
# execute ACTION-IF-NOT-FOUND (if present):
ifelse([$3], , :, [$3])
else
- AC_SUBST(BOOST_CPPFLAGS)
- AC_SUBST(BOOST_LDFLAGS)
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
# execute ACTION-IF-FOUND (if present):
ifelse([$2], , :, [$2])
@@ -253,6 +297,5 @@ if test "x$want_boost" = "xyes"; then
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
-fi
])
diff --git a/m4/ax_boost_system.m4 b/m4/ax_boost_system.m4
new file mode 100644
index 0000000..207d7be
--- /dev/null
+++ b/m4/ax_boost_system.m4
@@ -0,0 +1,121 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_boost_system.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_SYSTEM
+#
+# DESCRIPTION
+#
+# Test for System library from the Boost C++ libraries. The macro requires
+# a preceding call to AX_BOOST_BASE. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_SYSTEM_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_SYSTEM
+#
+# LICENSE
+#
+# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2008 Michael Tindal
+# Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 19
+
+AC_DEFUN([AX_BOOST_SYSTEM],
+[
+ AC_ARG_WITH([boost-system],
+ AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@],
+ [use the System library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-system=boost_system-gcc-mt ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_system_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_system_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_BUILD])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::System library is available,
+ ax_cv_boost_system,
+ [AC_LANG_PUSH([C++])
+ CXXFLAGS_SAVE=$CXXFLAGS
+ CXXFLAGS=
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
+ [[boost::system::error_category *a = 0;]])],
+ ax_cv_boost_system=yes, ax_cv_boost_system=no)
+ CXXFLAGS=$CXXFLAGS_SAVE
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_system" = "xyes"; then
+ AC_SUBST(BOOST_CPPFLAGS)
+
+ AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ LDFLAGS_SAVE=$LDFLAGS
+ if test "x$ax_boost_user_system_lib" = "x"; then
+ for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+ if test "x$link_system" != "xyes"; then
+ for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+ fi
+
+ else
+ for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_system" = "xno"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/m4/ax_boost_thread.m4 b/m4/ax_boost_thread.m4
new file mode 100644
index 0000000..87f03e3
--- /dev/null
+++ b/m4/ax_boost_thread.m4
@@ -0,0 +1,163 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_THREAD
+#
+# DESCRIPTION
+#
+# Test for Thread library from the Boost C++ libraries. The macro requires
+# a preceding call to AX_BOOST_BASE. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_THREAD_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_THREAD
+#
+# LICENSE
+#
+# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2009 Michael Tindal
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 30
+
+AC_DEFUN([AX_BOOST_THREAD],
+[
+ AC_ARG_WITH([boost-thread],
+ AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
+ [use the Thread library from boost -
+ it is possible to specify a certain library for the linker
+ e.g. --with-boost-thread=boost_thread-gcc-mt ]),
+ [
+ if test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_thread_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_thread_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_BUILD])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::Thread library is available,
+ ax_cv_boost_thread,
+ [AC_LANG_PUSH([C++])
+ CXXFLAGS_SAVE=$CXXFLAGS
+
+ if test "x$host_os" = "xsolaris" ; then
+ CXXFLAGS="-pthreads $CXXFLAGS"
+ elif test "x$host_os" = "xmingw32" ; then
+ CXXFLAGS="-mthreads $CXXFLAGS"
+ else
+ CXXFLAGS="-pthread $CXXFLAGS"
+ fi
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM(
+ [[@%:@include <boost/thread/thread.hpp>]],
+ [[boost::thread_group thrds;
+ return 0;]])],
+ ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
+ CXXFLAGS=$CXXFLAGS_SAVE
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_thread" = "xyes"; then
+ if test "x$host_os" = "xsolaris" ; then
+ BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
+ elif test "x$host_os" = "xmingw32" ; then
+ BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
+ else
+ BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
+ fi
+
+ AC_SUBST(BOOST_CPPFLAGS)
+
+ AC_DEFINE(HAVE_BOOST_THREAD,,
+ [define if the Boost::Thread library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ LDFLAGS_SAVE=$LDFLAGS
+ case "x$host_os" in
+ *bsd* )
+ LDFLAGS="-pthread $LDFLAGS"
+ break;
+ ;;
+ esac
+ if test "x$ax_boost_user_thread_lib" = "x"; then
+ for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [link_thread="yes"; break],
+ [link_thread="no"])
+ done
+ if test "x$link_thread" != "xyes"; then
+ for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [link_thread="yes"; break],
+ [link_thread="no"])
+ done
+ fi
+
+ else
+ for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [link_thread="yes"; break],
+ [link_thread="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_thread" = "xno"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ else
+ BOOST_THREAD_LIB="-l$ax_lib"
+ case "x$host_os" in
+ *bsd* )
+ BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
+ break;
+ ;;
+ solaris )
+ BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread"
+ break;
+ ;;
+ mingw32 )
+ break;
+ ;;
+ * )
+ BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread"
+ break;
+ ;;
+ esac
+ AC_SUBST(BOOST_THREAD_LIB)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 8631c42..3f6f296 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -3,7 +3,7 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyright (C) 2016
+ Copyright (C) 2017
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -28,48 +28,72 @@
#include "Buffer.h"
#include "PcDebug.h"
+#include <string>
#include <stdlib.h>
#include <string.h>
-#include <malloc.h>
-#if HAVE_DECL__MM_MALLOC
-# include <mm_malloc.h>
-#else
-# define memalign(a, b) malloc(b)
-#endif
-
-
Buffer::Buffer(size_t len, const void *data)
{
PDEBUG("Buffer::Buffer(%zu, %p)\n", len, data);
- this->len = 0;
- this->size = 0;
- this->data = NULL;
+ m_len = 0;
+ m_capacity = 0;
+ m_data = nullptr;
setData(data, len);
}
+Buffer::Buffer(const Buffer& other)
+{
+ setData(other.m_data, other.m_len);
+}
+
+Buffer::Buffer(Buffer&& other)
+{
+ m_len = other.m_len;
+ m_capacity = other.m_capacity;
+ m_data = other.m_data;
+
+ other.m_len = 0;
+ other.m_capacity = 0;
+ other.m_data = nullptr;
+}
+
Buffer::Buffer(const std::vector<uint8_t> &vec)
{
PDEBUG("Buffer::Buffer(vector [%zu])\n", vec.size());
- this->len = 0;
- this->size = 0;
- this->data = NULL;
+ m_len = 0;
+ m_capacity = 0;
+ m_data = nullptr;
setData(vec.data(), vec.size());
}
Buffer::~Buffer()
{
- PDEBUG("Buffer::~Buffer() len=%zu, data=%p\n", len, data);
- free(data);
+ PDEBUG("Buffer::~Buffer() len=%zu, data=%p\n", m_len, m_data);
+ if (m_data) {
+ free(m_data);
+ }
}
Buffer &Buffer::operator=(const Buffer &copy)
{
- setData(copy.data, copy.len);
+ setData(copy.m_data, copy.m_len);
+ return *this;
+}
+
+Buffer& Buffer::operator=(Buffer&& other)
+{
+ m_len = other.m_len;
+ m_capacity = other.m_capacity;
+ m_data = other.m_data;
+
+ other.m_len = 0;
+ other.m_capacity = 0;
+ other.m_data = nullptr;
+
return *this;
}
@@ -81,26 +105,30 @@ Buffer &Buffer::operator=(const std::vector<uint8_t> &copy)
Buffer &Buffer::operator+=(const Buffer &copy)
{
- appendData(copy.data, copy.len);
+ appendData(copy.m_data, copy.m_len);
return *this;
}
void Buffer::setLength(size_t len)
{
- if (len > size) {
- void *tmp = data;
+ if (len > m_capacity) {
+ void *tmp = m_data;
/* Align to 32-byte boundary for AVX. */
- data = memalign(32, len);
+ const int ret = posix_memalign(&m_data, 32, len);
+ if (ret != 0) {
+ throw std::runtime_error("memory allocation failed: " +
+ std::to_string(ret));
+ }
- if (tmp != NULL) {
- memcpy(data, tmp, this->len);
+ if (tmp != nullptr) {
+ memcpy(m_data, tmp, m_len);
free(tmp);
}
- size = len;
+ m_capacity = len;
}
- this->len = len;
+ m_len = len;
}
@@ -113,10 +141,10 @@ void Buffer::setData(const void *data, size_t len)
void Buffer::appendData(const void *data, size_t len)
{
- size_t offset = this->len;
- setLength(this->len + len);
- if (data != NULL) {
- memcpy((char*)this->data + offset, data, len);
+ size_t offset = m_len;
+ setLength(m_len + len);
+ if (data != nullptr) {
+ memcpy((char*)m_data + offset, data, len);
}
}
diff --git a/src/Buffer.h b/src/Buffer.h
index 8c5c768..88bd442 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -3,7 +3,7 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyright (C) 2016
+ Copyright (C) 2017
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -41,24 +41,13 @@
* The allocation/freeing of the data is handled internally.
*/
class Buffer {
- protected:
- /* Current length of the data in the Buffer */
- size_t len;
-
- /* Allocated size of the Buffer */
- size_t size;
-
- /* Pointer to the data. Memory allocation is entirely
- * handled by setLength.
- */
- void *data;
-
public:
using sptr = std::shared_ptr<Buffer>;
- Buffer(const Buffer& copy) = default;
- Buffer(const std::vector<uint8_t> &vec);
- Buffer(size_t len = 0, const void *data = NULL);
+ Buffer(size_t len = 0, const void *data = nullptr);
+ Buffer(const Buffer& copy);
+ Buffer(Buffer&& other);
+ Buffer(const std::vector<uint8_t>& vec);
~Buffer();
/* Resize the buffer, reallocate memory if needed */
@@ -68,16 +57,29 @@ class Buffer {
* Reallocates memory if needed.
*/
void setData(const void *data, size_t len);
- Buffer &operator=(const Buffer &copy);
- Buffer &operator=(const std::vector<uint8_t> &copy);
+ Buffer& operator=(const Buffer& copy);
+ Buffer& operator=(Buffer&& other);
+ Buffer& operator=(const std::vector<uint8_t>& copy);
/* Concatenate the current data with the new data given.
* Reallocates memory if needed.
*/
void appendData(const void *data, size_t len);
- Buffer &operator+=(const Buffer &copy);
+ Buffer& operator+=(const Buffer& copy);
+
+ size_t getLength() const { return m_len; }
+ void* getData() const { return m_data; }
+
+ private:
+ /* Current length of the data in the Buffer */
+ size_t m_len;
+
+ /* Allocated size of the Buffer */
+ size_t m_capacity;
+
+ /* Pointer to the data. Memory allocation is entirely
+ * handled by setLength. */
+ void *m_data;
- size_t getLength() const { return len; }
- void *getData() const { return data; }
};
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp
index 8facec3..0e641c0 100644
--- a/src/ConfigParser.cpp
+++ b/src/ConfigParser.cpp
@@ -161,8 +161,12 @@ static void parse_configfile(
mod_settings.dabMode = pt.get("modulator.mode", mod_settings.dabMode);
mod_settings.clockRate = pt.get("modulator.dac_clk_rate", (size_t)0);
- mod_settings.digitalgain = pt.get("modulator.digital_gain", mod_settings.digitalgain);
+ mod_settings.digitalgain = pt.get("modulator.digital_gain",
+ mod_settings.digitalgain);
+
mod_settings.outputRate = pt.get("modulator.rate", mod_settings.outputRate);
+ mod_settings.ofdmWindowOverlap = pt.get("modulator.ofdmwindowing",
+ mod_settings.ofdmWindowOverlap);
// FIR Filter parameters:
if (pt.get("firfilter.enabled", 0) == 1) {
diff --git a/src/ConfigParser.h b/src/ConfigParser.h
index dd6c040..3f64883 100644
--- a/src/ConfigParser.h
+++ b/src/ConfigParser.h
@@ -79,6 +79,9 @@ struct mod_settings_t {
float cfrClip = 1.0f;
float cfrErrorClip = 1.0f;
+ // Settings for the OFDM windowing
+ unsigned ofdmWindowOverlap = 0;
+
#if defined(HAVE_OUTPUT_UHD) || defined(HAVE_SOAPYSDR)
Output::SDRDeviceConfig sdr_device_config;
#endif
diff --git a/src/ConvEncoder.cpp b/src/ConvEncoder.cpp
index 06b2e85..074898f 100644
--- a/src/ConvEncoder.cpp
+++ b/src/ConvEncoder.cpp
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdexcept>
+#include <string>
const static uint8_t PARITY[] = {
diff --git a/src/DabMod.cpp b/src/DabMod.cpp
index d29b489..4961910 100644
--- a/src/DabMod.cpp
+++ b/src/DabMod.cpp
@@ -36,6 +36,7 @@
#include "InputMemory.h"
#include "OutputFile.h"
#include "FormatConverter.h"
+#include "FrameMultiplexer.h"
#include "output/SDR.h"
#include "output/UHD.h"
#include "output/Soapy.h"
@@ -61,13 +62,6 @@
# include <netinet/in.h>
#endif
-#if HAVE_DECL__MM_MALLOC
-# include <mm_malloc.h>
-#else
-# define memalign(a, b) malloc(b)
-#endif
-
-
/* UHD requires the input I and Q samples to be in the interval
* [-1.0,1.0], otherwise they get truncated, which creates very
* wide-spectrum spikes. Depending on the Transmission Mode, the
@@ -203,6 +197,10 @@ static shared_ptr<ModOutput> prepare_output(
output = make_shared<OutputFile>(s.outputName);
}
+ else {
+ throw runtime_error("File output format " + s.fileOutputFormat +
+ " not known");
+ }
}
#if defined(HAVE_OUTPUT_UHD)
else if (s.useUHDOutput) {
@@ -451,7 +449,7 @@ int launch_modulator(int argc, char* argv[])
}
}
#if defined(HAVE_ZEROMQ)
- else if (auto in = dynamic_pointer_cast<InputZeroMQReader>(inputReader)) {
+ else if (dynamic_pointer_cast<InputZeroMQReader>(inputReader)) {
run_again = true;
// Create a new input reader
auto inputZeroMQReader = make_shared<InputZeroMQReader>();
@@ -459,7 +457,8 @@ int launch_modulator(int argc, char* argv[])
inputReader = inputZeroMQReader;
}
#endif
- else if (auto in = dynamic_pointer_cast<InputTcpReader>(inputReader)) {
+ else if (dynamic_pointer_cast<InputTcpReader>(inputReader)) {
+ // Create a new input reader
auto inputTcpReader = make_shared<InputTcpReader>();
inputTcpReader->Open(mod_settings.inputName);
inputReader = inputTcpReader;
@@ -535,17 +534,19 @@ run_modulator_state_t run_modulator(modulator_data& m)
running = 0;
ret = run_modulator_state_t::normal_end;
}
- } catch (zmq_input_overflow& e) {
+ }
+ catch (const zmq_input_overflow& e) {
// The ZeroMQ input has overflowed its buffer
etiLog.level(warn) << e.what();
ret = run_modulator_state_t::again;
- } catch (std::out_of_range& e) {
- // One of the DSP blocks has detected an invalid change
- // or value in some settings. This can be due to a multiplex
- // reconfiguration.
+ }
+ catch (const FrameMultiplexerError& e) {
+ // The FrameMultiplexer saw an error or a change in the size of a
+ // subchannel. This can be due to a multiplex reconfiguration.
etiLog.level(warn) << e.what();
ret = run_modulator_state_t::reconfigure;
- } catch (std::exception& e) {
+ }
+ catch (const std::exception& e) {
etiLog.level(error) << "Exception caught: " << e.what();
ret = run_modulator_state_t::failure;
}
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index 2bd33b4..1ea06de 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -62,8 +62,7 @@ DabModulator::DabModulator(EtiSource& etiSource,
myEtiSource(etiSource),
myFlowgraph()
{
- PDEBUG("DabModulator::DabModulator(%u, %u, %u, %zu) @ %p\n",
- outputRate, clockRate, dabMode, (size_t)gainMode, this);
+ PDEBUG("DabModulator::DabModulator() @ %p\n", this);
if (m_settings.dabMode == 0) {
setMode(2);
@@ -205,7 +204,9 @@ int DabModulator::process(Buffer* dataOut)
rcs.enrol(cifGain.get());
auto cifGuard = make_shared<GuardIntervalInserter>(
- myNbSymbols, mySpacing, myNullSize, mySymSize);
+ myNbSymbols, mySpacing, myNullSize, mySymSize,
+ m_settings.ofdmWindowOverlap);
+ rcs.enrol(cifGuard.get());
shared_ptr<FIRFilter> cifFilter;
if (not m_settings.filterTapsFilename.empty()) {
diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp
index 0b27126..d84ed1f 100644
--- a/src/EtiReader.cpp
+++ b/src/EtiReader.cpp
@@ -58,7 +58,6 @@ EtiReader::EtiReader(
unsigned tist_delay_stages) :
state(EtiReaderStateSync),
myTimestampDecoder(tist_offset_s, tist_delay_stages),
- myCurrentFrame(0),
eti_fc_valid(false)
{
rcs.enrol(&myTimestampDecoder);
@@ -208,8 +207,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn)
if (input_size < 128) {
return dataIn.getLength() - input_size;
}
- PDEBUG("Writting 128 bytes of FIC channel data\n");
- Buffer fic = Buffer(128, in);
+ PDEBUG("Writing 128 bytes of FIC channel data\n");
+ Buffer fic(128, in);
myFicSource->loadFicData(fic);
input_size -= 128;
framesize -= 128;
@@ -218,8 +217,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn)
if (input_size < 96) {
return dataIn.getLength() - input_size;
}
- PDEBUG("Writting 96 bytes of FIC channel data\n");
- Buffer fic = Buffer(96, in);
+ PDEBUG("Writing 96 bytes of FIC channel data\n");
+ Buffer fic(96, in);
myFicSource->loadFicData(fic);
input_size -= 96;
framesize -= 96;
@@ -231,7 +230,7 @@ int EtiReader::loadEtiData(const Buffer& dataIn)
for (size_t i = 0; i < eti_stc.size(); ++i) {
unsigned size = mySources[i]->framesize();
PDEBUG("Writting %i bytes of subchannel data\n", size);
- Buffer subch = Buffer(size, in);
+ Buffer subch(size, in);
mySources[i]->loadSubchannelData(subch);
input_size -= size;
framesize -= size;
diff --git a/src/EtiReader.h b/src/EtiReader.h
index 892afb4..f3a9764 100644
--- a/src/EtiReader.h
+++ b/src/EtiReader.h
@@ -107,7 +107,6 @@ private:
eti_TIST eti_tist;
TimestampDecoder myTimestampDecoder;
- size_t myCurrentFrame;
bool eti_fc_valid;
std::vector<std::shared_ptr<SubchannelSource> > mySources;
diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp
index 4296822..bc2314a 100644
--- a/src/FIRFilter.cpp
+++ b/src/FIRFilter.cpp
@@ -119,7 +119,7 @@ void FIRFilter::load_filter_taps(const std::string &tapsFile)
int n;
for (n = 0; n < n_taps; n++) {
taps_fstream >> filter_taps[n];
- PDEBUG("FIRFilter: tap: %f\n", filter_taps[n] );
+ PDEBUG("FIRFilter: tap: %f\n", (double)filter_taps[n] );
if (taps_fstream.eof()) {
fprintf(stderr, "FIRFilter: file %s should contains %d taps, but EOF reached "\
"after %d taps !\n", tapsFile.c_str(), n_taps, n);
@@ -306,9 +306,6 @@ int FIRFilter::internal_process(Buffer* const dataIn, Buffer* dataOut)
void FIRFilter::set_parameter(const string& parameter, const string& value)
{
- stringstream ss(value);
- ss.exceptions ( stringstream::failbit | stringstream::badbit );
-
if (parameter == "ntaps") {
throw ParameterError("Parameter 'ntaps' is read-only");
}
diff --git a/src/FicSource.cpp b/src/FicSource.cpp
index 92932ec..04197db 100644
--- a/src/FicSource.cpp
+++ b/src/FicSource.cpp
@@ -28,6 +28,7 @@
#include "PcDebug.h"
#include <stdexcept>
+#include <string>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp
index 6ee7b81..465ef41 100644
--- a/src/Flowgraph.cpp
+++ b/src/Flowgraph.cpp
@@ -26,15 +26,10 @@
#include "Flowgraph.h"
#include "PcDebug.h"
+#include <string>
#include <memory>
#include <algorithm>
#include <sstream>
-
-#if HAVE_DECL__MM_MALLOC
-# include <mm_malloc.h>
-#else
-# define memalign(a, b) malloc(b)
-#endif
#include <sys/types.h>
#include <stdexcept>
#include <assert.h>
diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp
index 6826972..60c0545 100644
--- a/src/FormatConverter.cpp
+++ b/src/FormatConverter.cpp
@@ -29,7 +29,6 @@
#include "FormatConverter.h"
#include "PcDebug.h"
-#include <malloc.h>
#include <sys/types.h>
#include <string.h>
#include <stdexcept>
diff --git a/src/FrameMultiplexer.cpp b/src/FrameMultiplexer.cpp
index 1cfaadd..5dc6dca 100644
--- a/src/FrameMultiplexer.cpp
+++ b/src/FrameMultiplexer.cpp
@@ -28,6 +28,7 @@
#include "PcDebug.h"
#include <stdio.h>
+#include <string>
#include <stdexcept>
#include <complex>
#include <memory>
@@ -73,7 +74,7 @@ int FrameMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut)
// Write subchannel
const auto subchannels = m_etiSource.getSubchannels();
if (subchannels.size() != dataIn.size() - 1) {
- throw std::out_of_range(
+ throw FrameMultiplexerError(
"FrameMultiplexer detected subchannel size change from " +
std::to_string(dataIn.size() - 1) + " to " +
std::to_string(subchannels.size()));
@@ -81,7 +82,7 @@ int FrameMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut)
auto subchannel = subchannels.begin();
while (in != dataIn.end()) {
if ((*subchannel)->framesizeCu() * 8 != (*in)->getLength()) {
- throw std::out_of_range(
+ throw FrameMultiplexerError(
"FrameMultiplexer detected invalid subchannel size! " +
std::to_string((*subchannel)->framesizeCu() * 8) + " != " +
std::to_string((*in)->getLength()));
diff --git a/src/FrameMultiplexer.h b/src/FrameMultiplexer.h
index 680cdc7..4d68d88 100644
--- a/src/FrameMultiplexer.h
+++ b/src/FrameMultiplexer.h
@@ -38,12 +38,18 @@
#include <sys/types.h>
+class FrameMultiplexerError : public std::runtime_error {
+ public:
+ FrameMultiplexerError(const char* msg) :
+ std::runtime_error(msg) {}
+ FrameMultiplexerError(const std::string& msg) :
+ std::runtime_error(msg) {}
+};
class FrameMultiplexer : public ModMux
{
public:
- FrameMultiplexer(
- const EtiSource& etiSource);
+ FrameMultiplexer(const EtiSource& etiSource);
int process(std::vector<Buffer*> dataIn, Buffer* dataOut);
const char* name() { return "FrameMultiplexer"; }
diff --git a/src/FrequencyInterleaver.cpp b/src/FrequencyInterleaver.cpp
index 29d54bb..e76d525 100644
--- a/src/FrequencyInterleaver.cpp
+++ b/src/FrequencyInterleaver.cpp
@@ -24,7 +24,8 @@
#include <stdio.h>
#include <stdexcept>
-#include <malloc.h>
+#include <string>
+#include <stdlib.h>
#include <complex>
typedef std::complex<float> complexf;
@@ -68,7 +69,11 @@ FrequencyInterleaver::FrequencyInterleaver(size_t mode) :
break;
}
- d_indexes = (size_t*)memalign(16, d_carriers * sizeof(size_t));
+ const int ret = posix_memalign((void**)(&d_indexes), 16, d_carriers * sizeof(size_t));
+ if (ret != 0) {
+ throw std::runtime_error("memory allocation failed: " + std::to_string(ret));
+ }
+
size_t* index = d_indexes;
size_t perm = 0;
PDEBUG("i: %4u, R: %4u\n", 0, 0);
diff --git a/src/GainControl.cpp b/src/GainControl.cpp
index 2a91b12..0411482 100644
--- a/src/GainControl.cpp
+++ b/src/GainControl.cpp
@@ -46,7 +46,7 @@ using namespace std;
static float var_variance;
GainControl::GainControl(size_t framesize,
- GainMode mode,
+ GainMode gainMode,
float digGain,
float normalise,
float varVariance) :
@@ -60,10 +60,10 @@ GainControl::GainControl(size_t framesize,
m_digGain(digGain),
m_normalise(normalise),
m_var_variance_rc(varVariance),
- m_gainmode(mode),
+ m_gainmode(gainMode),
m_mutex()
{
- PDEBUG("GainControl::GainControl(%zu, %zu) @ %p\n", framesize, (size_t)mode, this);
+ PDEBUG("GainControl::GainControl(%zu, %zu) @ %p\n", framesize, (size_t)m_gainmode, this);
/* register the parameters that can be remote controlled */
RC_ADD_PARAMETER(digital, "Digital Gain");
@@ -532,10 +532,10 @@ void GainControl::set_parameter(const string& parameter, const string& value)
}
}
else {
- stringstream ss;
- ss << "Parameter '" << parameter
+ stringstream ss_err;
+ ss_err << "Parameter '" << parameter
<< "' is not exported by controllable " << get_rc_name();
- throw ParameterError(ss.str());
+ throw ParameterError(ss_err.str());
}
}
diff --git a/src/GainControl.h b/src/GainControl.h
index 44c9fa9..e9eaa8c 100644
--- a/src/GainControl.h
+++ b/src/GainControl.h
@@ -51,7 +51,7 @@ class GainControl : public PipelinedModCodec, public RemoteControllable
{
public:
GainControl(size_t framesize,
- GainMode mode,
+ GainMode gainMode,
float digGain,
float normalise,
float varVariance);
diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp
index 80ba900..14027d3 100644
--- a/src/GuardIntervalInserter.cpp
+++ b/src/GuardIntervalInserter.cpp
@@ -1,6 +1,11 @@
/*
Copyright (C) 2005, 2206, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
+
+ Copyright (C) 2017
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -21,57 +26,101 @@
#include "GuardIntervalInserter.h"
#include "PcDebug.h"
-
-
-#include <sys/types.h>
#include <string.h>
#include <stdexcept>
#include <complex>
+#include <mutex>
typedef std::complex<float> complexf;
-
-GuardIntervalInserter::GuardIntervalInserter(size_t nbSymbols,
+GuardIntervalInserter::GuardIntervalInserter(
+ size_t nbSymbols,
size_t spacing,
size_t nullSize,
- size_t symSize) :
+ size_t symSize,
+ size_t windowOverlap) :
ModCodec(),
+ RemoteControllable("guardinterval"),
d_nbSymbols(nbSymbols),
d_spacing(spacing),
d_nullSize(nullSize),
- d_symSize(symSize)
+ d_symSize(symSize),
+ d_windowOverlap(0)
{
- PDEBUG("GuardIntervalInserter::GuardIntervalInserter(%zu, %zu, %zu, %zu)"
- " @ %p\n", nbSymbols, spacing, nullSize, symSize, this);
-
- if (d_nullSize) {
- myHasNull = true;
- } else {
- myHasNull = false;
+ if (d_nullSize == 0) {
+ throw std::logic_error("NULL symbol must be present");
}
-}
+ RC_ADD_PARAMETER(windowlen, "Window length for OFDM windowng [0 to disable]");
+
+ /* We use a raised-cosine window for the OFDM windowing.
+ * Each symbol is extended on both sides by d_windowOverlap samples.
+ *
+ *
+ * Sym n |####################|
+ * Sym n+1 |####################|
+ *
+ * We now extend the symbols by d_windowOverlap (one dash)
+ *
+ * Sym n extended -|####################|-
+ * Sym n+1 extended -|####################|-
+ *
+ * The windows are raised-cosine:
+ * ____________________
+ * Sym n window / \
+ * ... ____/ \___________ ...
+ *
+ * Sym n+1 window ____________________
+ * / \
+ * ... ________________/ \__ ...
+ *
+ * The window length is 2*d_windowOverlap.
+ */
+
+ update_window(windowOverlap);
-GuardIntervalInserter::~GuardIntervalInserter()
+ PDEBUG("GuardIntervalInserter::GuardIntervalInserter"
+ "(%zu, %zu, %zu, %zu, %zu) @ %p\n",
+ nbSymbols, spacing, nullSize, symSize, windowOverlap, this);
+}
+
+void GuardIntervalInserter::update_window(size_t new_window_overlap)
{
- PDEBUG("GuardIntervalInserter::~GuardIntervalInserter() @ %p\n", this);
+ std::lock_guard<std::mutex> lock(d_windowMutex);
+
+ d_windowOverlap = new_window_overlap;
+ // d_window only contains the rising window edge.
+ d_window.resize(2*d_windowOverlap);
+ for (size_t i = 0; i < 2*d_windowOverlap; i++) {
+ d_window[i] = (float)(0.5 * (1.0 - cos(M_PI * i / (2*d_windowOverlap - 1))));
+ }
}
+#pragma GCC optimize ("O0")
int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
{
PDEBUG("GuardIntervalInserter::process(dataIn: %p, dataOut: %p)\n",
dataIn, dataOut);
- dataOut->setLength((d_nullSize + (d_nbSymbols * d_symSize))
- * sizeof(complexf));
+ std::lock_guard<std::mutex> lock(d_windowMutex);
+
+ // Every symbol overlaps over a length of d_windowOverlap with
+ // the previous symbol, and with the next symbol. First symbol
+ // receives no prefix window, because we don't remember the
+ // last symbol from the previous TF (yet). Last symbol also
+ // receives no suffix window, for the same reason.
+ // Overall output buffer length must stay independent of the windowing.
+ dataOut->setLength((d_nullSize + (d_nbSymbols * d_symSize)) * sizeof(complexf));
const complexf* in = reinterpret_cast<const complexf*>(dataIn->getData());
complexf* out = reinterpret_cast<complexf*>(dataOut->getData());
size_t sizeIn = dataIn->getLength() / sizeof(complexf);
- if (sizeIn != (d_nbSymbols + (myHasNull ? 1 : 0)) * d_spacing) {
+ const size_t num_symbols = d_nbSymbols + 1;
+ if (sizeIn != num_symbols * d_spacing)
+ {
PDEBUG("Nb symbols: %zu\n", d_nbSymbols);
PDEBUG("Spacing: %zu\n", d_spacing);
PDEBUG("Null size: %zu\n", d_nullSize);
@@ -81,24 +130,176 @@ int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
"GuardIntervalInserter::process input size not valid!");
}
- // Null symbol
- if (myHasNull) {
+ // TODO remember the end of the last TF so that we can do some
+ // windowing too.
+
+ if (d_windowOverlap) {
+ {
+ // Handle Null symbol separately because it is longer
+ const size_t prefixlength = d_nullSize - d_spacing;
+
+ // end = spacing
+ memcpy(out, &in[d_spacing - prefixlength],
+ prefixlength * sizeof(complexf));
+
+ memcpy(&out[prefixlength], in, (d_spacing - d_windowOverlap) * sizeof(complexf));
+
+ // The remaining part of the symbol must have half of the window applied,
+ // sloping down from 1 to 0.5
+ for (size_t i = 0; i < d_windowOverlap; i++) {
+ const size_t out_ix = prefixlength + d_spacing - d_windowOverlap + i;
+ const size_t in_ix = d_spacing - d_windowOverlap + i;
+ out[out_ix] = in[in_ix] * d_window[2*d_windowOverlap - (i+1)];
+ }
+
+ // Suffix is taken from the beginning of the symbol, and sees the other
+ // half of the window applied.
+ for (size_t i = 0; i < d_windowOverlap; i++) {
+ const size_t out_ix = prefixlength + d_spacing + i;
+ out[out_ix] = in[i] * d_window[d_windowOverlap - (i+1)];
+ }
+
+ in += d_spacing;
+ out += d_nullSize;
+ // out is now pointing to the proper end of symbol. There are
+ // d_windowOverlap samples ahead that were already written.
+ }
+
+ // Data symbols
+ for (size_t sym_ix = 0; sym_ix < d_nbSymbols; sym_ix++) {
+ /* _ix variables are indices into in[], _ox variables are
+ * indices for out[] */
+ const ssize_t start_rise_ox = -d_windowOverlap;
+ const size_t start_rise_ix = 2 * d_spacing - d_symSize - d_windowOverlap;
+ /*
+ const size_t start_real_symbol_ox = 0;
+ const size_t start_real_symbol_ix = 2 * d_spacing - d_symSize;
+ */
+ const ssize_t end_rise_ox = d_windowOverlap;
+ const size_t end_rise_ix = 2 * d_spacing - d_symSize + d_windowOverlap;
+ const ssize_t end_cyclic_prefix_ox = d_symSize - d_spacing;
+ /* end_cyclic_prefix_ix = end of symbol
+ const size_t begin_fall_ox = d_symSize - d_windowOverlap;
+ const size_t begin_fall_ix = d_spacing - d_windowOverlap;
+ const size_t end_real_symbol_ox = d_symSize;
+ end_real_symbol_ix = end of symbol
+ const size_t end_fall_ox = d_symSize + d_windowOverlap;
+ const size_t end_fall_ix = d_spacing + d_windowOverlap;
+ */
+
+ ssize_t ox = start_rise_ox;
+ size_t ix = start_rise_ix;
+
+ for (size_t i = 0; ix < end_rise_ix; i++) {
+ out[ox] += in[ix] * d_window.at(i);
+ ix++;
+ ox++;
+ }
+ assert(ox == end_rise_ox);
+
+ const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox;
+ memcpy( &out[ox], &in[ix],
+ remaining_prefix_length * sizeof(complexf));
+ ox += remaining_prefix_length;
+ assert(ox = end_cyclic_prefix_ox);
+ ix = 0;
+
+ const bool last_symbol = (sym_ix + 1 >= d_nbSymbols);
+ if (last_symbol) {
+ // No windowing at all at end
+ memcpy(&out[ox], &in[ix], d_spacing * sizeof(complexf));
+ ox += d_spacing;
+ }
+ else {
+ // Copy the middle part of the symbol, d_windowOverlap samples
+ // short of the end.
+ memcpy( &out[ox],
+ &in[ix],
+ (d_spacing - d_windowOverlap) * sizeof(complexf));
+ ox += d_spacing - d_windowOverlap;
+ ix += d_spacing - d_windowOverlap;
+ assert(ox == (ssize_t)(d_symSize - d_windowOverlap));
+
+ // Apply window from 1 to 0.5 for the end of the symbol
+ for (size_t i = 0; ox < (ssize_t)d_symSize; i++) {
+ out[ox] = in[ix] * d_window[2*d_windowOverlap - (i+1)];
+ ox++;
+ ix++;
+ }
+ assert(ix == d_spacing);
+
+ ix = 0;
+ // Cyclic suffix, with window from 0.5 to 0
+ for (size_t i = 0; ox < (ssize_t)(d_symSize + d_windowOverlap); i++) {
+ out[ox] = in[ix] * d_window[d_windowOverlap - (i+1)];
+ ox++;
+ ix++;
+ }
+
+ assert(ix == d_windowOverlap);
+ }
+
+ out += d_symSize;
+ in += d_spacing;
+ // out is now pointing to the proper end of symbol. There are
+ // d_windowOverlap samples ahead that were already written.
+ }
+ }
+ else {
+ // Handle Null symbol separately because it is longer
// end - (nullSize - spacing) = 2 * spacing - nullSize
memcpy(out, &in[2 * d_spacing - d_nullSize],
(d_nullSize - d_spacing) * sizeof(complexf));
memcpy(&out[d_nullSize - d_spacing], in, d_spacing * sizeof(complexf));
in += d_spacing;
out += d_nullSize;
- }
- // Data symbols
- for (size_t i = 0; i < d_nbSymbols; ++i) {
- // end - (nullSize - spacing) = 2 * spacing - nullSize
- memcpy(out, &in[2 * d_spacing - d_symSize],
- (d_symSize - d_spacing) * sizeof(complexf));
- memcpy(&out[d_symSize - d_spacing], in, d_spacing * sizeof(complexf));
- in += d_spacing;
- out += d_symSize;
+
+ // Data symbols
+ for (size_t i = 0; i < d_nbSymbols; ++i) {
+ // end - (symSize - spacing) = 2 * spacing - symSize
+ memcpy(out, &in[2 * d_spacing - d_symSize],
+ (d_symSize - d_spacing) * sizeof(complexf));
+ memcpy(&out[d_symSize - d_spacing], in, d_spacing * sizeof(complexf));
+ in += d_spacing;
+ out += d_symSize;
+ }
}
return sizeIn;
}
+
+void GuardIntervalInserter::set_parameter(
+ const std::string& parameter,
+ const std::string& value)
+{
+ using namespace std;
+ stringstream ss(value);
+ ss.exceptions ( stringstream::failbit | stringstream::badbit );
+
+ if (parameter == "windowlen") {
+ size_t new_window_overlap = 0;
+ ss >> new_window_overlap;
+ update_window(new_window_overlap);
+ }
+ else {
+ stringstream ss_err;
+ ss_err << "Parameter '" << parameter <<
+ "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss_err.str());
+ }
+}
+
+const std::string GuardIntervalInserter::get_parameter(const std::string& parameter) const
+{
+ using namespace std;
+ stringstream ss;
+ if (parameter == "windowlen") {
+ ss << d_windowOverlap;
+ }
+ else {
+ ss << "Parameter '" << parameter <<
+ "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+ return ss.str();
+}
diff --git a/src/GuardIntervalInserter.h b/src/GuardIntervalInserter.h
index 70a8fcd..7714c1a 100644
--- a/src/GuardIntervalInserter.h
+++ b/src/GuardIntervalInserter.h
@@ -1,6 +1,11 @@
/*
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
+
+ Copyright (C) 2017
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://opendigitalradio.org
*/
/*
This file is part of ODR-DabMod.
@@ -25,29 +30,48 @@
# include <config.h>
#endif
-
#include "ModPlugin.h"
+#include "RemoteControl.h"
+#include <stdint.h>
+#include <vector>
-#include <sys/types.h>
+/* The GuardIntervalInserter prepends the cyclic prefix to all
+ * symbols in the transmission frame.
+ *
+ * If windowOverlap is non-zero, it will also add a cyclic suffix of
+ * that length, enlarge the cyclic prefix too, and make symbols
+ * overlap using a raised cosine window.
+ * */
+class GuardIntervalInserter : public ModCodec, public RemoteControllable
+{
+ public:
+ GuardIntervalInserter(
+ size_t nbSymbols,
+ size_t spacing,
+ size_t nullSize,
+ size_t symSize,
+ size_t windowOverlap = 0);
+ int process(Buffer* const dataIn, Buffer* dataOut);
+ const char* name() { return "GuardIntervalInserter"; }
-class GuardIntervalInserter : public ModCodec
-{
-public:
- GuardIntervalInserter(size_t nbSymbols, size_t spacing, size_t nullSize, size_t symSize);
- virtual ~GuardIntervalInserter();
- GuardIntervalInserter(const GuardIntervalInserter&);
- GuardIntervalInserter& operator=(const GuardIntervalInserter&);
-
-
- int process(Buffer* const dataIn, Buffer* dataOut);
- const char* name() { return "GuardIntervalInserter"; }
-
-protected:
- size_t d_nbSymbols;
- size_t d_spacing;
- size_t d_nullSize;
- size_t d_symSize;
- bool myHasNull;
+ /******* REMOTE CONTROL ********/
+ virtual void set_parameter(const std::string& parameter,
+ const std::string& value);
+
+ virtual const std::string get_parameter(
+ const std::string& parameter) const;
+
+ protected:
+ void update_window(size_t new_window_overlap);
+
+ size_t d_nbSymbols;
+ size_t d_spacing;
+ size_t d_nullSize;
+ size_t d_symSize;
+
+ mutable std::mutex d_windowMutex;
+ size_t d_windowOverlap;
+ std::vector<float> d_window;
};
diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp
index f223d34..ae097c9 100644
--- a/src/MemlessPoly.cpp
+++ b/src/MemlessPoly.cpp
@@ -38,7 +38,7 @@
#include <stdio.h>
#include <stdexcept>
-
+#include <string>
#include <future>
#include <array>
#include <iostream>
@@ -370,9 +370,6 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut)
void MemlessPoly::set_parameter(const string& parameter, const string& value)
{
- stringstream ss(value);
- ss.exceptions ( stringstream::failbit | stringstream::badbit );
-
if (parameter == "ncoefs") {
throw ParameterError("Parameter 'ncoefs' is read-only");
}
diff --git a/src/NullSymbol.cpp b/src/NullSymbol.cpp
index 015e564..4684dfe 100644
--- a/src/NullSymbol.cpp
+++ b/src/NullSymbol.cpp
@@ -53,7 +53,7 @@ int NullSymbol::process(Buffer* dataOut)
PDEBUG("NullSymbol::process(dataOut: %p)\n", dataOut);
dataOut->setLength(myNbCarriers * 2 * sizeof(float));
- bzero(dataOut->getData(), dataOut->getLength());
+ memset(dataOut->getData(), 0, dataOut->getLength());
return dataOut->getLength();
}
diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp
index bac3db0..915d568 100644
--- a/src/OfdmGenerator.cpp
+++ b/src/OfdmGenerator.cpp
@@ -190,7 +190,7 @@ int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut)
myFftIn[0][0] = 0;
myFftIn[0][1] = 0;
- bzero(&myFftIn[myZeroDst], myZeroSize * sizeof(FFT_TYPE));
+ memset(&myFftIn[myZeroDst], 0, myZeroSize * sizeof(FFT_TYPE));
memcpy(&myFftIn[myPosDst], &in[myPosSrc],
myPosSize * sizeof(FFT_TYPE));
memcpy(&myFftIn[myNegDst], &in[myNegSrc],
@@ -230,9 +230,9 @@ int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut)
*/
double sum_iq = 0;
double sum_delta = 0;
- for (size_t i = 0; i < mySpacing; i++) {
- sum_iq += (double)std::norm(before_cfr[i]);
- sum_delta += (double)std::norm(symbol[i] - before_cfr[i]);
+ for (size_t j = 0; j < mySpacing; j++) {
+ sum_iq += (double)std::norm(before_cfr[j]);
+ sum_delta += (double)std::norm(symbol[j] - before_cfr[j]);
}
// Clamp to 90dB, otherwise the MER average is going to be inf
@@ -362,10 +362,10 @@ void OfdmGenerator::set_parameter(const std::string& parameter,
throw ParameterError("Parameter 'clip_stats' is read-only");
}
else {
- stringstream ss;
- ss << "Parameter '" << parameter
+ stringstream ss_err;
+ ss_err << "Parameter '" << parameter
<< "' is not exported by controllable " << get_rc_name();
- throw ParameterError(ss.str());
+ throw ParameterError(ss_err.str());
}
}
diff --git a/src/PrbsGenerator.cpp b/src/PrbsGenerator.cpp
index 69d6af4..b159bd3 100644
--- a/src/PrbsGenerator.cpp
+++ b/src/PrbsGenerator.cpp
@@ -22,9 +22,10 @@
#include "PrbsGenerator.h"
#include "PcDebug.h"
+#include <stdexcept>
+#include <string>
#include <stdio.h>
#include <stdlib.h>
-#include <stdexcept>
PrbsGenerator::PrbsGenerator(size_t framesize, uint32_t polynomial,
@@ -178,8 +179,8 @@ int PrbsGenerator::process(
throw std::runtime_error("PrbsGenerator::process "
"input size is not equal to output size!\n");
}
- for (size_t i = 0; i < dataOut[0]->getLength(); ++i) {
- out[i] ^= in[i];
+ for (size_t j = 0; j < dataOut[0]->getLength(); ++j) {
+ out[j] ^= in[j];
}
}
diff --git a/src/PrbsGenerator.h b/src/PrbsGenerator.h
index b86bc70..9390179 100644
--- a/src/PrbsGenerator.h
+++ b/src/PrbsGenerator.h
@@ -53,8 +53,6 @@ private:
unsigned char d_weight[256];
// PRBS polynomial generator
uint32_t d_polynomial;
- // PRBS generator polarity mask
- unsigned char d_polarity_mask;
// PRBS accumulator
uint32_t d_accum;
uint32_t d_accum_init;
diff --git a/src/PuncturingEncoder.cpp b/src/PuncturingEncoder.cpp
index 9bd9004..de4319b 100644
--- a/src/PuncturingEncoder.cpp
+++ b/src/PuncturingEncoder.cpp
@@ -27,6 +27,7 @@
#include "PuncturingEncoder.h"
#include "PcDebug.h"
+#include <string>
#include <stdio.h>
#include <stdexcept>
#include <stdint.h>
diff --git a/src/RemoteControl.cpp b/src/RemoteControl.cpp
index ceae942..a050278 100644
--- a/src/RemoteControl.cpp
+++ b/src/RemoteControl.cpp
@@ -422,11 +422,11 @@ void RemoteControllerZmq::process()
std::string msg_s = ss.str();
- zmq::message_t msg(ss.str().size());
- memcpy ((void*) msg.data(), msg_s.data(), msg_s.size());
+ zmq::message_t zmsg(ss.str().size());
+ memcpy ((void*) zmsg.data(), msg_s.data(), msg_s.size());
int flag = (--cohort_size > 0) ? ZMQ_SNDMORE : 0;
- repSocket.send(msg, flag);
+ repSocket.send(zmsg, flag);
}
}
else if (msg.size() == 2 && command == "show") {
@@ -437,11 +437,11 @@ void RemoteControllerZmq::process()
for (auto &param_val : r) {
std::stringstream ss;
ss << param_val[0] << ": " << param_val[1] << endl;
- zmq::message_t msg(ss.str().size());
- memcpy(msg.data(), ss.str().data(), ss.str().size());
+ zmq::message_t zmsg(ss.str().size());
+ memcpy(zmsg.data(), ss.str().data(), ss.str().size());
int flag = (--r_size > 0) ? ZMQ_SNDMORE : 0;
- repSocket.send(msg, flag);
+ repSocket.send(zmsg, flag);
}
}
catch (ParameterError &e) {
@@ -454,9 +454,9 @@ void RemoteControllerZmq::process()
try {
std::string value = rcs.get_param(module, parameter);
- zmq::message_t msg(value.size());
- memcpy ((void*) msg.data(), value.data(), value.size());
- repSocket.send(msg, 0);
+ zmq::message_t zmsg(value.size());
+ memcpy ((void*) zmsg.data(), value.data(), value.size());
+ repSocket.send(zmsg, 0);
}
catch (ParameterError &err) {
send_fail_reply(repSocket, err.what());
diff --git a/src/Resampler.cpp b/src/Resampler.cpp
index 8069a61..42951c5 100644
--- a/src/Resampler.cpp
+++ b/src/Resampler.cpp
@@ -27,10 +27,11 @@
#include "Resampler.h"
#include "PcDebug.h"
-#include <malloc.h>
+#include <string>
+#include <stdexcept>
+#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
-#include <stdexcept>
#include <assert.h>
#define FFT_REAL(x) x[0]
@@ -81,7 +82,10 @@ Resampler::Resampler(size_t inputRate, size_t outputRate, size_t resolution) :
myFactor = 1.0f / myFftSizeOut * outputRate / inputRate;
}
- myWindow = (float*)memalign(16, myFftSizeIn * sizeof(float));
+ const int ret = posix_memalign((void**)(&myWindow), 16, myFftSizeIn * sizeof(float));
+ if (ret != 0) {
+ throw std::runtime_error("memory allocation failed: " + std::to_string(ret));
+ }
for (size_t i = 0; i < myFftSizeIn; ++i) {
myWindow[i] = (float)(0.5 * (1.0 - cos(2.0 * M_PI * i / (myFftSizeIn - 1))));
PDEBUG("Window[%zu] = %f\n", i, myWindow[i]);
diff --git a/src/Socket.h b/src/Socket.h
index f6a023d..39554ca 100644
--- a/src/Socket.h
+++ b/src/Socket.h
@@ -37,6 +37,7 @@ DESCRIPTION:
#include <unistd.h>
#include <cstdint>
#include <stdexcept>
+#include <string>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <errno.h>
diff --git a/src/SubchannelSource.cpp b/src/SubchannelSource.cpp
index 2a8dc37..b4d6750 100644
--- a/src/SubchannelSource.cpp
+++ b/src/SubchannelSource.cpp
@@ -28,6 +28,7 @@
#include "PcDebug.h"
#include "Log.h"
+#include <string>
#include <stdexcept>
#include <sys/types.h>
#include <stdlib.h>
diff --git a/src/TII.cpp b/src/TII.cpp
index 4710ed4..446d9c6 100644
--- a/src/TII.cpp
+++ b/src/TII.cpp
@@ -190,17 +190,13 @@ int TII::process(Buffer* dataIn, Buffer* dataOut)
}
dataOut->setLength(m_carriers * sizeof(complexf));
- bzero(dataOut->getData(), dataOut->getLength());
+ memset(dataOut->getData(), 0, dataOut->getLength());
if (m_conf.enable and m_insert) {
boost::mutex::scoped_lock lock(m_enabled_carriers_mutex);
complexf* in = reinterpret_cast<complexf*>(dataIn->getData());
complexf* out = reinterpret_cast<complexf*>(dataOut->getData());
- if ((m_enabled_carriers.size() % 2) != 0) {
- throw std::logic_error("odd number of enabled carriers");
- }
-
/* Normalise the TII carrier power according to ETSI TR 101 496-3
* Clause 5.4.2.2 Paragraph 7:
*
@@ -213,13 +209,10 @@ int TII::process(Buffer* dataIn, Buffer* dataOut)
*/
const float normalise_factor = 0.14433756729740644112f; // = 1/sqrt(48)
- for (size_t i = 0; i < m_enabled_carriers.size(); i+=2) {
+ for (size_t i = 0; i < m_enabled_carriers.size(); i++) {
// See header file for an explanation of the old variant
if (m_enabled_carriers[i]) {
out[i] = normalise_factor * (m_conf.old_variant ? in[i+1] : in[i]);
- }
-
- if (m_enabled_carriers[i+1]) {
out[i+1] = normalise_factor * in[i+1];
}
}
@@ -239,10 +232,6 @@ void TII::enable_carrier(int k) {
}
m_enabled_carriers[ix] = true;
- // NULL frequency is never enabled.
- if (ix > 1 and (ix-1 != 768)) {
- m_enabled_carriers[ix-1] = true;
- }
}
void TII::prepare_pattern() {
@@ -287,7 +276,7 @@ void TII::prepare_pattern() {
}
}
- for (int k = 384; k <= 768; k++) {
+ for (int k = 385; k <= 768; k++) {
for (int b = 0; b < 8; b++) {
if ( k == 385 + 2 * comb + 48 * b and
pattern_tm1_2_4[m_conf.pattern][b]) {
@@ -350,10 +339,10 @@ void TII::set_parameter(const std::string& parameter, const std::string& value)
ss >> m_conf.old_variant;
}
else {
- stringstream ss;
- ss << "Parameter '" << parameter <<
+ stringstream ss_err;
+ ss_err << "Parameter '" << parameter <<
"' is not exported by controllable " << get_rc_name();
- throw ParameterError(ss.str());
+ throw ParameterError(ss_err.str());
}
}
diff --git a/src/TII.h b/src/TII.h
index fe67978..4c5c605 100644
--- a/src/TII.h
+++ b/src/TII.h
@@ -122,6 +122,9 @@ class TII : public ModCodec, public RemoteControllable
// m_enabled_carriers is read by modulator thread, and written
// to by RC thread.
mutable boost::mutex m_enabled_carriers_mutex;
+
+ // m_enabled_carriers is true only for the first carrier in the
+ // active pair
std::vector<bool> m_enabled_carriers;
};
diff --git a/src/TimeInterleaver.cpp b/src/TimeInterleaver.cpp
index 3bf6339..7e19af8 100644
--- a/src/TimeInterleaver.cpp
+++ b/src/TimeInterleaver.cpp
@@ -23,6 +23,7 @@
#include "PcDebug.h"
#include <vector>
+#include <string>
#include <stdint.h>
diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp
index ddd3fb7..26deb60 100644
--- a/src/TimestampDecoder.cpp
+++ b/src/TimestampDecoder.cpp
@@ -228,10 +228,10 @@ void TimestampDecoder::set_parameter(
throw ParameterError("timestamp is read-only");
}
else {
- stringstream ss;
- ss << "Parameter '" << parameter
+ stringstream ss_err;
+ ss_err << "Parameter '" << parameter
<< "' is not exported by controllable " << get_rc_name();
- throw ParameterError(ss.str());
+ throw ParameterError(ss_err.str());
}
}
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 385253b..f113be3 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -27,7 +27,9 @@
#include "Utils.h"
#include "GainControl.h"
-#include <sys/prctl.h>
+#if defined(HAVE_PRCTL)
+# include <sys/prctl.h>
+#endif
#include <pthread.h>
static void printHeader()
@@ -160,7 +162,9 @@ int set_realtime_prio(int prio)
void set_thread_name(const char *name)
{
+#if defined(HAVE_PRCTL)
prctl(PR_SET_NAME,name,0,0,0);
+#endif
}
double parseChannel(const std::string& chan)
diff --git a/src/Utils.h b/src/Utils.h
index 2bc6cb3..5d5831b 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -62,6 +62,7 @@ inline long timespecdiff_us(struct timespec& oldTime, struct timespec& time)
// Set SCHED_RR with priority prio (0=lowest)
int set_realtime_prio(int prio);
+// Set the name of the thread
void set_thread_name(const char *name);
// Convert a channel like 10A to a frequency
diff --git a/src/porting.c b/src/porting.c
index 79523e5..f7421b0 100644
--- a/src/porting.c
+++ b/src/porting.c
@@ -21,19 +21,6 @@
#include "porting.h"
-
-#ifndef HAVE_GETTIMEOFDAY
-#include <sys/timeb.h>
-int gettimeofday(struct timeval* t, void* timezone)
-{
- struct timeb timebuffer;
- ftime(&timebuffer);
- t->tv_sec=timebuffer.time;
- t->tv_usec=1000*timebuffer.millitm;
- return 0;
-}
-#endif
-
#ifdef _WIN32
unsigned int _CRT_fmode = _O_BINARY;
#endif
diff --git a/src/porting.h b/src/porting.h
index 2ac9b90..1799ba7 100644
--- a/src/porting.h
+++ b/src/porting.h
@@ -19,25 +19,12 @@
along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PORTING_H
-#define PORTING_H
+#pragma once
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#ifndef HAVE_BZERO
-# define bzero(s, n) memset(s, 0, n)
-#endif
-
-#ifndef HAVE_GETTIMEOFDAY
-#include <sys/time.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-int gettimeofday(struct timeval* t, void* timezone);
-#endif
-
#ifdef _WIN32
#include <fcntl.h>
// For setting default opening mode with fopen as binary, for all files
@@ -45,8 +32,3 @@ int gettimeofday(struct timeval* t, void* timezone);
extern unsigned int _CRT_fmode;
#endif
-#ifndef HAVE_KILL
-# define kill(a, b) raise(b)
-#endif
-
-#endif // PORTING_H