summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Modules/FindQwt.cmake17
-rw-r--r--cmake/Modules/GrMiscUtils.cmake2
-rw-r--r--config.guess22
-rw-r--r--config.sub13
-rw-r--r--docs/doxygen/other/group_defs.dox1
-rw-r--r--gnuradio-core/src/lib/filter/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc7
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h1
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i1
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc8
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.h1
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.i1
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t6
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t1
-rw-r--r--gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc21
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h3
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc1
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc13
-rw-r--r--gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t3
-rw-r--r--gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t3
-rw-r--r--gnuradio-core/src/lib/hier/gr_channel_model.cc25
-rw-r--r--gnuradio-core/src/lib/hier/gr_channel_model.h5
-rw-r--r--gnuradio-core/src/lib/hier/gr_channel_model.i5
-rw-r--r--gnuradio-core/src/lib/io/gr_oscope_guts.cc5
-rw-r--r--gnuradio-core/src/lib/io/gr_udp_sink.cc2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc11
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.h3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler.cc2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler.h2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc8
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler_sts.h4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc17
-rw-r--r--gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.cc20
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.h19
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.i5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block_impl.cc27
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block_impl.h9
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h2
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py24
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_noise.py12
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/top_block.py8
-rw-r--r--gr-atsc/src/lib/qa_atsci_single_viterbi.cc4
-rw-r--r--gr-audio/lib/alsa/audio_alsa_source.cc6
-rw-r--r--gr-digital/examples/CMakeLists.txt1
-rw-r--r--gr-digital/examples/Makefile.am3
-rwxr-xr-xgr-digital/examples/narrowband/digital_bert_rx.py2
-rwxr-xr-xgr-digital/examples/narrowband/digital_bert_tx.py7
-rwxr-xr-xgr-digital/examples/snr_estimators.py174
-rw-r--r--gr-digital/grc/digital_dxpsk_demod.xml7
-rw-r--r--gr-digital/include/CMakeLists.txt3
-rw-r--r--gr-digital/include/Makefile.am3
-rw-r--r--gr-digital/include/digital_impl_mpsk_snr_est.h279
-rw-r--r--gr-digital/include/digital_mpsk_snr_est_cc.h115
-rw-r--r--gr-digital/include/digital_probe_mpsk_snr_est_c.h113
-rw-r--r--gr-digital/lib/CMakeLists.txt3
-rw-r--r--gr-digital/lib/Makefile.am3
-rw-r--r--gr-digital/lib/digital_constellation.cc2
-rw-r--r--gr-digital/lib/digital_impl_mpsk_snr_est.cc256
-rw-r--r--gr-digital/lib/digital_mpsk_snr_est_cc.cc186
-rw-r--r--gr-digital/lib/digital_probe_mpsk_snr_est_c.cc152
-rw-r--r--gr-digital/python/Makefile.am1
-rwxr-xr-xgr-digital/python/qa_fll_band_edge.py1
-rwxr-xr-xgr-digital/python/qa_mpsk_snr_est.py126
-rw-r--r--gr-digital/swig/CMakeLists.txt2
-rw-r--r--gr-digital/swig/Makefile.am2
-rw-r--r--gr-digital/swig/digital_mpsk_snr_est_cc.i45
-rw-r--r--gr-digital/swig/digital_probe_mpsk_snr_est_c.i45
-rw-r--r--gr-digital/swig/digital_swig.i21
-rwxr-xr-xgr-howto-write-a-block/config.guess22
-rwxr-xr-xgr-howto-write-a-block/config.sub13
-rw-r--r--gr-howto-write-a-block/version.sh2
-rw-r--r--gr-noaa/CMakeLists.txt14
-rw-r--r--gr-noaa/Makefile.am2
-rw-r--r--gr-noaa/gnuradio-noaa.pc.in11
-rwxr-xr-xgr-uhd/apps/uhd_fft.py109
-rwxr-xr-xgr-uhd/apps/uhd_rx_cfile.py11
-rw-r--r--gr-uhd/include/gr_uhd_usrp_source.h9
-rw-r--r--gr-uhd/lib/gr_uhd_usrp_source.cc19
-rw-r--r--gr-wxgui/src/python/stdgui2.py20
-rw-r--r--gruel/src/include/gruel/high_res_timer.h2
-rw-r--r--version.sh2
-rw-r--r--volk/include/volk/volk_16i_max_star_16i_a.h4
-rw-r--r--volk/include/volk/volk_32f_s32f_stddev_32f_a.h6
-rw-r--r--volk/include/volk/volk_32f_stddev_and_mean_32f_x2_a.h6
-rw-r--r--volk/lib/CMakeLists.txt14
-rw-r--r--volk/orc/volk_16ic_magnitude_16i_a_orc_impl.orc2
-rw-r--r--volk/orc/volk_16sc_magnitude_32f_aligned16_orc_impl.orc2
-rw-r--r--volk/orc/volk_32f_sqrt_32f_a_orc_impl.orc2
-rw-r--r--volk/orc/volk_32fc_magnitude_32f_a_orc_impl.orc2
-rw-r--r--volk/orc/volk_32fc_s32f_magnitude_16i_a_orc_impl.orc2
-rw-r--r--volk/orc/volk_8i_convert_16i_a_orc_impl.orc5
94 files changed, 2006 insertions, 188 deletions
diff --git a/cmake/Modules/FindQwt.cmake b/cmake/Modules/FindQwt.cmake
index bc8683f7d..857020796 100644
--- a/cmake/Modules/FindQwt.cmake
+++ b/cmake/Modules/FindQwt.cmake
@@ -3,11 +3,22 @@
# QWT_LIBRARIES libraries to link against
# QWT_FOUND If false, do not try to use Qwt
-find_path ( QWT_INCLUDE_DIRS qwt_plot.h /usr/include/qwt-qt4 /usr/include/qwt /opt/local/include/qwt )
-
-find_library ( QWT_LIBRARIES NAMES qwt-qt4 qwt)
+find_path (QWT_INCLUDE_DIRS
+ NAMES qwt_plot.h
+ PATHS
+ /usr/local/include/qwt-qt4
+ /usr/local/include/qwt
+ /usr/include/qwt-qt4
+ /usr/include/qwt
+)
+
+find_library (QWT_LIBRARIES
+ NAMES qwt-qt4 qwt
+ PATHS /usr/local/lib /usr/lib
+)
# handle the QUIETLY and REQUIRED arguments and set QWT_FOUND to TRUE if
# all listed variables are TRUE
include ( FindPackageHandleStandardArgs )
find_package_handle_standard_args( Qwt DEFAULT_MSG QWT_LIBRARIES QWT_INCLUDE_DIRS )
+MARK_AS_ADVANCED(QWT_LIBRARIES QWT_INCLUDE_DIRS)
diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake
index 0e1f40027..27003cf59 100644
--- a/cmake/Modules/GrMiscUtils.cmake
+++ b/cmake/Modules/GrMiscUtils.cmake
@@ -155,7 +155,7 @@ function(GR_LIBRARY_FOO target)
GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR})
#give the library a special name with ultra-zero soversion
- set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0")
+ set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0")
set(target_name lib${target}-${LIBVER}.so.0.0.0)
#custom command to generate symlinks
diff --git a/config.guess b/config.guess
index 8152efd67..49ba16f15 100644
--- a/config.guess
+++ b/config.guess
@@ -2,9 +2,9 @@
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2011-11-11'
+timestamp='2012-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -57,8 +57,8 @@ GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -145,7 +145,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -897,16 +897,16 @@ EOF
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
- echo cris-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
frv:Linux:*:*)
- echo frv-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
hexagon:Linux:*:*)
- echo hexagon-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
LIBC=gnu
@@ -948,7 +948,7 @@ EOF
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
- echo or32-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
@@ -989,7 +989,7 @@ EOF
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
diff --git a/config.sub b/config.sub
index e76eaf472..d6b6b3c76 100644
--- a/config.sub
+++ b/config.sub
@@ -2,9 +2,9 @@
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2011-11-11'
+timestamp='2012-01-01'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -76,8 +76,8 @@ version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -320,7 +320,6 @@ case $basic_machine in
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | picochip)
- # Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -719,7 +718,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -1559,9 +1557,6 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
diff --git a/docs/doxygen/other/group_defs.dox b/docs/doxygen/other/group_defs.dox
index 6288d1f0a..facdc2338 100644
--- a/docs/doxygen/other/group_defs.dox
+++ b/docs/doxygen/other/group_defs.dox
@@ -32,6 +32,7 @@
/*! \defgroup uhd_blk UHD Interface */
/*! \defgroup audio_blk Audio Interface */
/*! \defgroup pfb_blk Polyphase Filterbank */
+/*! \defgroup snr_blk SNR estimators */
/*!
* \defgroup base_blk Base classes for GR Blocks
diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt
index ce7e387c2..d26e55fb8 100644
--- a/gnuradio-core/src/lib/filter/CMakeLists.txt
+++ b/gnuradio-core/src/lib/filter/CMakeLists.txt
@@ -28,7 +28,7 @@ foreach(gr_core_filter_asm ${gr_core_filter_asms})
endforeach(gr_core_filter_asm)
#detect 32 or 64 bit compiler
-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86|x86_64)$")
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86|x86_64|amd64)$")
include(CheckTypeSize)
check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY)
if (${SIZEOF_VOID_P} EQUAL 8)
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc
index 02bfaf105..9fa98cc69 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc
@@ -62,6 +62,7 @@ gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_compl
#else
d_filter = new gri_fft_filter_ccc_sse(decimation, taps);
#endif
+ d_new_taps = taps;
d_nsamples = d_filter->set_taps(taps);
set_output_multiple(d_nsamples);
}
@@ -78,6 +79,12 @@ gr_fft_filter_ccc::set_taps (const std::vector<gr_complex> &taps)
d_updated = true;
}
+std::vector<gr_complex>
+gr_fft_filter_ccc::taps () const
+{
+ return d_new_taps;
+}
+
int
gr_fft_filter_ccc::work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h
index 721a44a83..1b72a1c00 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h
@@ -62,6 +62,7 @@ class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator
~gr_fft_filter_ccc ();
void set_taps (const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps () const;
int work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i
index aa7564f54..812920d8b 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i
@@ -36,4 +36,5 @@ class gr_fft_filter_ccc : public gr_sync_decimator
~gr_fft_filter_ccc ();
void set_taps (const std::vector<gr_complex> &taps);
+ std::vector<gr_complex> taps () const;
};
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc
index e5b218f20..c0a9b3483 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc
@@ -55,7 +55,7 @@ gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> &
#else
d_filter = new gri_fft_filter_fff_sse(decimation, taps);
#endif
-
+ d_new_taps = taps;
d_nsamples = d_filter->set_taps(taps);
set_output_multiple(d_nsamples);
}
@@ -72,6 +72,12 @@ gr_fft_filter_fff::set_taps (const std::vector<float> &taps)
d_updated = true;
}
+std::vector<float>
+gr_fft_filter_fff::taps () const
+{
+ return d_new_taps;
+}
+
int
gr_fft_filter_fff::work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h
index b0dc74883..ddd8dcac2 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h
@@ -62,6 +62,7 @@ class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator
~gr_fft_filter_fff ();
void set_taps (const std::vector<float> &taps);
+ std::vector<float> taps () const;
int work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i
index bbe84f99f..7e2cde977 100644
--- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i
+++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i
@@ -36,4 +36,5 @@ class gr_fft_filter_fff : public gr_sync_decimator
~gr_fft_filter_fff ();
void set_taps (const std::vector<float> &taps);
+ std::vector<float> taps () const;
};
diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t
index 29e351925..f7458e743 100644
--- a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t
+++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t
@@ -63,6 +63,12 @@ void
d_updated = true;
}
+std::vector<@TAP_TYPE@>
+@NAME@::taps () const
+{
+ return d_new_taps;
+}
+
int
@NAME@::work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t
index db0625504..f638e7bb5 100644
--- a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t
+++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t
@@ -59,6 +59,7 @@ class GR_CORE_API @NAME@ : public gr_sync_decimator
~@NAME@ ();
void set_taps (const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps () const;
int work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t
index 0cbe8cbcc..fb4ff95af 100644
--- a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t
+++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t
@@ -38,4 +38,5 @@ class @NAME@ : public gr_sync_decimator
~@NAME@ ();
void set_taps (const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps () const;
};
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
index 398956ddd..9297b6587 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
@@ -60,7 +60,7 @@ gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float loop_bw,
gr_make_io_signaturev (1, 4, iosig)),
d_updated (false), d_nfilters(filter_size),
d_max_dev(max_rate_deviation),
- d_osps(osps), d_error(0)
+ d_osps(osps), d_error(0), d_out_idx(0)
{
d_nfilters = filter_size;
d_sps = floor(sps);
@@ -380,7 +380,7 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
// produce output as long as we can and there are enough input samples
while((i < noutput_items) && (count < nrequired)) {
- for(int k = 0; k < d_osps; k++) {
+ while(d_out_idx < d_osps) {
d_filtnum = (int)floor(d_k);
// Keep the current filter number in [0, d_nfilters]
@@ -397,16 +397,27 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
count -= 1;
}
- out[i+k] = d_filters[d_filtnum]->filter(&in[count+k]);
+ out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]);
d_k = d_k + d_rate_i + d_rate_f; // update phase
-
+ d_out_idx++;
+
if(output_items.size() == 4) {
err[i] = d_error;
outrate[i] = d_rate_f;
outk[i] = d_k;
}
+
+ // We've run out of output items we can create; return now.
+ if(i+d_out_idx >= noutput_items) {
+ consume_each(count);
+ return i;
+ }
}
+ // reset here; if we didn't complete a full osps samples last time,
+ // the early return would take care of it.
+ d_out_idx = 0;
+
// Update the phase and rate estimates for this symbol
gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]);
error_r = out[i].real() * diff.real();
@@ -424,7 +435,7 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
i+=d_osps;
count += (int)floor(d_sps);
}
- consume_each(count);
+ consume_each(count);
return i;
}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
index f4f589cd9..1e1bbca10 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
@@ -197,7 +197,8 @@ class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block
int d_filtnum;
int d_osps;
float d_error;
-
+ int d_out_idx;
+
/*!
* Build the polyphase filterbank timing synchronizer.
*/
diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc
index 2fc97a78a..d0ed04238 100644
--- a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc
+++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <cmath>
#include <stdexcept>
+#include <unistd.h>
#define NELEM(x) (sizeof (x) / sizeof (x[0]))
diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc
index 3293e3ab8..c66015c11 100644
--- a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc
+++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc
@@ -67,8 +67,17 @@ gr_fft_vcc_fftw::work (int noutput_items,
if (d_window.size()){
gr_complex *dst = d_fft->get_inbuf();
- for (unsigned int i = 0; i < d_fft_size; i++) // apply window
- dst[i] = in[i] * d_window[i];
+ if(!d_forward && d_shift){
+ int offset = (!d_forward && d_shift)?floor(d_fft_size/2):0;
+ int fft_m_offset = d_fft_size - offset;
+ for (unsigned int i = 0; i < offset; i++) // apply window
+ dst[i+fft_m_offset] = in[i] * d_window[i];
+ for (unsigned int i = offset; i < d_fft_size; i++) // apply window
+ dst[i-offset] = in[i] * d_window[i];
+ } else {
+ for (unsigned int i = 0; i < d_fft_size; i++) // apply window
+ dst[i] = in[i] * d_window[i];
+ }
}
else {
if(!d_forward && d_shift) { // apply an ifft shift on the data
diff --git a/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t
index 9dd92c8f5..ab5992257 100644
--- a/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t
+++ b/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t
@@ -55,6 +55,9 @@ class GR_CORE_API @NAME@ : public gr_sync_block {
void set_type (gr_noise_type_t type) { d_type = type; }
void set_amplitude (float ampl) { d_ampl = ampl; }
+ gr_noise_type_t type () const { return d_type; }
+ float amplitude () const { return d_ampl; }
+
virtual int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
diff --git a/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t
index 27261502d..179dc0343 100644
--- a/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t
+++ b/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t
@@ -34,4 +34,7 @@ class @NAME@ : public gr_block {
public:
void set_type (gr_noise_type_t type) { d_type = type; }
void set_amplitude (float ampl) { d_ampl = ampl; }
+
+ gr_noise_type_t type () const { return d_type; }
+ float amplitude () const { return d_ampl; }
};
diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.cc b/gnuradio-core/src/lib/hier/gr_channel_model.cc
index fb57e808a..5f190e972 100644
--- a/gnuradio-core/src/lib/hier/gr_channel_model.cc
+++ b/gnuradio-core/src/lib/hier/gr_channel_model.cc
@@ -99,3 +99,28 @@ gr_channel_model::set_timing_offset(double epsilon)
{
d_timing_offset->set_interp_ratio(epsilon);
}
+
+
+double
+gr_channel_model::noise_voltage() const
+{
+ return d_noise->amplitude();
+}
+
+double
+gr_channel_model::frequency_offset() const
+{
+ return d_freq_offset->frequency();
+}
+
+std::vector<gr_complex>
+gr_channel_model::taps() const
+{
+ return d_multipath->taps();
+}
+
+double
+gr_channel_model::timing_offset() const
+{
+ return d_timing_offset->interp_ratio();
+}
diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.h b/gnuradio-core/src/lib/hier/gr_channel_model.h
index 07c0c76b6..c5d06ce11 100644
--- a/gnuradio-core/src/lib/hier/gr_channel_model.h
+++ b/gnuradio-core/src/lib/hier/gr_channel_model.h
@@ -71,4 +71,9 @@ class GR_CORE_API gr_channel_model : public gr_hier_block2
void set_frequency_offset(double frequency_offset);
void set_taps(const std::vector<gr_complex> &taps);
void set_timing_offset(double epsilon);
+
+ double noise_voltage() const;
+ double frequency_offset() const;
+ std::vector<gr_complex> taps() const;
+ double timing_offset() const;
};
diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.i b/gnuradio-core/src/lib/hier/gr_channel_model.i
index ff9ab466d..2e0cb7bdf 100644
--- a/gnuradio-core/src/lib/hier/gr_channel_model.i
+++ b/gnuradio-core/src/lib/hier/gr_channel_model.i
@@ -42,4 +42,9 @@ class gr_channel_model : public gr_hier_block2
void set_frequency_offset(double frequency_offset);
void set_taps(const std::vector<gr_complex> &taps);
void set_timing_offset(double epsilon);
+
+ double noise_voltage() const;
+ double frequency_offset() const;
+ std::vector<gr_complex> taps() const;
+ double timing_offset() const;
};
diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.cc b/gnuradio-core/src/lib/io/gr_oscope_guts.cc
index ce7feca13..f1bdeb9c1 100644
--- a/gnuradio-core/src/lib/io/gr_oscope_guts.cc
+++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc
@@ -31,8 +31,7 @@
#include <math.h>
#include <assert.h>
-static const int OUTPUT_RECORD_SIZE = 2048; // must be power of 2
-
+static const int OUTPUT_RECORD_SIZE = 16384; // Must be power of 2
static inline int
wrap_bi (int buffer_index) // wrap buffer index
{
@@ -139,7 +138,7 @@ gr_oscope_guts::process_sample (const float *channel_data)
{
for (int i = 0; i < d_nchannels; i++)
{
- for (int j = OUTPUT_RECORD_SIZE-1; j >= 0; j--)
+ for (int j = OUTPUT_RECORD_SIZE-1; j > 0; j--)
{
d_buffer[i][j] = d_buffer[i][j-1];
}
diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.cc b/gnuradio-core/src/lib/io/gr_udp_sink.cc
index 36b4cbe36..9fc4da0ae 100644
--- a/gnuradio-core/src/lib/io/gr_udp_sink.cc
+++ b/gnuradio-core/src/lib/io/gr_udp_sink.cc
@@ -20,6 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
+#include <boost/asio.hpp>
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 737b26f67..ef53baf78 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -155,8 +155,8 @@ propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d,
return true;
}
-gr_block_executor::gr_block_executor (gr_block_sptr block)
- : d_block(block), d_log(0)
+gr_block_executor::gr_block_executor (gr_block_sptr block, int max_noutput_items)
+ : d_block(block), d_log(0), d_max_noutput_items(max_noutput_items)
{
if (ENABLE_LOGGING){
std::string name = str(boost::format("sst-%03d.log") % which_scheduler++);
@@ -182,6 +182,7 @@ gr_block_executor::run_one_iteration()
{
int noutput_items;
int max_items_avail;
+ int max_noutput_items = d_max_noutput_items;
gr_block *m = d_block.get();
gr_block_detail *d = m->detail().get();
@@ -203,6 +204,7 @@ gr_block_executor::run_one_iteration()
// determine the minimum available output space
noutput_items = min_available_space (d, m->output_multiple ());
+ noutput_items = std::min(noutput_items, d_max_noutput_items);
LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
if (noutput_items == -1) // we're done
goto were_done;
@@ -247,6 +249,7 @@ gr_block_executor::run_one_iteration()
// take a swag at how much output we can sink
noutput_items = (int) (max_items_avail * m->relative_rate ());
noutput_items = round_down (noutput_items, m->output_multiple ());
+ noutput_items = std::min(noutput_items, d_max_noutput_items);
LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl);
LOG(*d_log << " noutput_items = " << noutput_items << std::endl);
@@ -307,7 +310,11 @@ gr_block_executor::run_one_iteration()
reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple());
if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items)
noutput_items = reqd_noutput_items;
+
+ // if we need this many outputs, overrule the max_noutput_items setting
+ max_noutput_items = std::max(m->output_multiple(), max_noutput_items);
}
+ noutput_items = std::min(noutput_items, max_noutput_items);
// ask the block how much input they need to produce noutput_items
m->forecast (noutput_items, d_ninput_items_required);
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.h b/gnuradio-core/src/lib/runtime/gr_block_executor.h
index 15279f273..e022d8273 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.h
@@ -51,9 +51,10 @@ protected:
gr_vector_void_star d_output_items;
std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work
std::vector<gr_tag_t> d_returned_tags;
+ int d_max_noutput_items;
public:
- gr_block_executor(gr_block_sptr block);
+ gr_block_executor(gr_block_sptr block, int max_noutput_items=100000);
~gr_block_executor ();
enum state {
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler.cc b/gnuradio-core/src/lib/runtime/gr_scheduler.cc
index e4d8b3dd9..3ae08a7a3 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler.cc
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler.cc
@@ -24,7 +24,7 @@
#endif
#include <gr_scheduler.h>
-gr_scheduler::gr_scheduler(gr_flat_flowgraph_sptr ffg)
+gr_scheduler::gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
{
}
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler.h b/gnuradio-core/src/lib/runtime/gr_scheduler.h
index 4e97b5881..92af8d1cb 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler.h
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler.h
@@ -47,7 +47,7 @@ public:
* The scheduler will continue running until all blocks until they
* report that they are done or the stop method is called.
*/
- gr_scheduler(gr_flat_flowgraph_sptr ffg);
+ gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
virtual ~gr_scheduler();
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc
index fefc0dc70..3cc1d4d45 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc
@@ -43,13 +43,13 @@ public:
gr_scheduler_sptr
-gr_scheduler_sts::make(gr_flat_flowgraph_sptr ffg)
+gr_scheduler_sts::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
{
- return gr_scheduler_sptr(new gr_scheduler_sts(ffg));
+ return gr_scheduler_sptr(new gr_scheduler_sts(ffg, max_noutput_items));
}
-gr_scheduler_sts::gr_scheduler_sts(gr_flat_flowgraph_sptr ffg)
- : gr_scheduler(ffg)
+gr_scheduler_sts::gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+ : gr_scheduler(ffg, max_noutput_items)
{
// Split the flattened flow graph into discrete partitions, each
// of which is topologically sorted.
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h
index 9b73b68c1..08c68d88a 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h
@@ -39,10 +39,10 @@ protected:
* The scheduler will continue running until all blocks until they
* report that they are done or the stop method is called.
*/
- gr_scheduler_sts(gr_flat_flowgraph_sptr ffg);
+ gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
public:
- static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg);
+ static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
~gr_scheduler_sts();
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
index af0338570..0a7ff4556 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc
@@ -33,25 +33,27 @@
class tpb_container
{
gr_block_sptr d_block;
+ int d_max_noutput_items;
public:
- tpb_container(gr_block_sptr block) : d_block(block) {}
+ tpb_container(gr_block_sptr block, int max_noutput_items)
+ : d_block(block), d_max_noutput_items(max_noutput_items) {}
void operator()()
{
- gr_tpb_thread_body body(d_block);
+ gr_tpb_thread_body body(d_block, d_max_noutput_items);
}
};
gr_scheduler_sptr
-gr_scheduler_tpb::make(gr_flat_flowgraph_sptr ffg)
+gr_scheduler_tpb::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
{
- return gr_scheduler_sptr(new gr_scheduler_tpb(ffg));
+ return gr_scheduler_sptr(new gr_scheduler_tpb(ffg, max_noutput_items));
}
-gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg)
- : gr_scheduler(ffg)
+gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+ : gr_scheduler(ffg, max_noutput_items)
{
// Get a topologically sorted vector of all the blocks in use.
// Being topologically sorted probably isn't going to matter, but
@@ -73,7 +75,8 @@ gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg)
std::stringstream name;
name << "thread-per-block[" << i << "]: " << blocks[i];
d_threads.create_thread(
- gruel::thread_body_wrapper<tpb_container>(tpb_container(blocks[i]), name.str()));
+ gruel::thread_body_wrapper<tpb_container>(tpb_container(blocks[i], max_noutput_items),
+ name.str()));
}
}
diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h
index f97ab2e7f..ab74fa84d 100644
--- a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h
+++ b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h
@@ -39,10 +39,10 @@ protected:
* The scheduler will continue running until all blocks until they
* report that they are done or the stop method is called.
*/
- gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg);
+ gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
public:
- static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg);
+ static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items=100000);
~gr_scheduler_tpb();
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc
index f341525c0..56d1352cd 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc
@@ -54,9 +54,9 @@ gr_top_block::~gr_top_block()
}
void
-gr_top_block::start()
+gr_top_block::start(int max_noutput_items)
{
- d_impl->start();
+ d_impl->start(max_noutput_items);
}
void
@@ -72,9 +72,9 @@ gr_top_block::wait()
}
void
-gr_top_block::run()
+gr_top_block::run(int max_noutput_items)
{
- start();
+ start(max_noutput_items);
wait();
}
@@ -96,6 +96,18 @@ gr_top_block::dump()
d_impl->dump();
}
+int
+gr_top_block::max_noutput_items()
+{
+ return d_impl->max_noutput_items();
+}
+
+void
+gr_top_block::set_max_noutput_items(int nmax)
+{
+ d_impl->set_max_noutput_items(nmax);
+}
+
gr_top_block_sptr
gr_top_block::to_top_block()
{
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h
index fca68ae71..9d01ba3ef 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.h
@@ -53,16 +53,25 @@ public:
*
* Calls start() then wait(). Used to run a flowgraph that will stop
* on its own, or when another thread will call stop().
+ *
+ * \param max_noutput_items the maximum number of output items
+ * allowed for any block in the flowgraph. This passes through to
+ * the start function; see that function for more details.
*/
- void run();
+ void run(int max_noutput_items=100000);
/*!
* Start the contained flowgraph. Creates one or more threads to
* execute the flow graph. Returns to the caller once the threads
* are created. Calling start() on a top_block that is already
* started IS an error.
+ *
+ * \param max_noutput_items the maximum number of output items
+ * allowed for any block in the flowgraph; the noutput_items can
+ * always be less than this, but this will cap it as a maximum. Use
+ * this to adjust the maximum latency a flowgraph can exhibit.
*/
- void start();
+ void start(int max_noutput_items=100000);
/*!
* Stop the running flowgraph. Notifies each thread created by the
@@ -107,6 +116,12 @@ public:
*/
void dump();
+ //! Get the number of max noutput_items in the flowgraph
+ int max_noutput_items();
+
+ //! Set the maximum number of noutput_items in the flowgraph
+ void set_max_noutput_items(int nmax);
+
gr_top_block_sptr to_top_block(); // Needed for Python/Guile type coercion
};
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i
index 90fa18b94..70c627ffd 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.i
@@ -40,7 +40,7 @@ private:
public:
~gr_top_block();
- void start() throw (std::runtime_error);
+ void start(int max_noutput_items=100000) throw (std::runtime_error);
void stop();
//void wait();
//void run() throw (std::runtime_error);
@@ -48,6 +48,9 @@ public:
void unlock() throw (std::runtime_error);
void dump();
+ int max_noutput_items();
+ void set_max_noutput_items(int nmax);
+
gr_top_block_sptr to_top_block(); // Needed for Python/Guile type coercion
};
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
index 9cad687fb..0227d789c 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
@@ -39,7 +39,8 @@
#define GR_TOP_BLOCK_IMPL_DEBUG 0
-typedef gr_scheduler_sptr (*scheduler_maker)(gr_flat_flowgraph_sptr ffg);
+typedef gr_scheduler_sptr (*scheduler_maker)(gr_flat_flowgraph_sptr ffg,
+ int max_noutput_items);
static struct scheduler_table {
const char *name;
@@ -50,7 +51,7 @@ static struct scheduler_table {
};
static gr_scheduler_sptr
-make_scheduler(gr_flat_flowgraph_sptr ffg)
+make_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
{
static scheduler_maker factory = 0;
@@ -72,7 +73,7 @@ make_scheduler(gr_flat_flowgraph_sptr ffg)
}
}
}
- return factory(ffg);
+ return factory(ffg, max_noutput_items);
}
@@ -88,10 +89,12 @@ gr_top_block_impl::~gr_top_block_impl()
}
void
-gr_top_block_impl::start()
+gr_top_block_impl::start(int max_noutput_items)
{
gruel::scoped_lock l(d_mutex);
+ d_max_noutput_items = max_noutput_items;
+
if (d_state != IDLE)
throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()");
@@ -105,7 +108,7 @@ gr_top_block_impl::start()
d_ffg->validate();
d_ffg->setup_connections();
- d_scheduler = make_scheduler(d_ffg);
+ d_scheduler = make_scheduler(d_ffg, d_max_noutput_items);
d_state = RUNNING;
}
@@ -168,7 +171,7 @@ gr_top_block_impl::restart()
d_ffg = new_ffg;
// Create a new scheduler to execute it
- d_scheduler = make_scheduler(d_ffg);
+ d_scheduler = make_scheduler(d_ffg, d_max_noutput_items);
d_state = RUNNING;
}
@@ -178,3 +181,15 @@ gr_top_block_impl::dump()
if (d_ffg)
d_ffg->dump();
}
+
+int
+gr_top_block_impl::max_noutput_items()
+{
+ return d_max_noutput_items;
+}
+
+void
+gr_top_block_impl::set_max_noutput_items(int nmax)
+{
+ d_max_noutput_items = nmax;
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h
index 904443be5..d804e3f30 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h
+++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h
@@ -42,7 +42,7 @@ public:
~gr_top_block_impl();
// Create and start scheduler threads
- void start();
+ void start(int max_noutput_items=100000);
// Signal scheduler threads to stop
void stop();
@@ -58,6 +58,12 @@ public:
// Dump the flowgraph to stdout
void dump();
+
+ // Get the number of max noutput_items in the flowgraph
+ int max_noutput_items();
+
+ // Set the maximum number of noutput_items in the flowgraph
+ void set_max_noutput_items(int nmax);
protected:
@@ -70,6 +76,7 @@ protected:
gruel::mutex d_mutex; // protects d_state and d_lock_count
tb_state d_state;
int d_lock_count;
+ int d_max_noutput_items;
private:
void restart();
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
index faa888697..d44c09aa6 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
@@ -28,8 +28,8 @@
using namespace pmt;
-gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block)
- : d_exec(block)
+gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items)
+ : d_exec(block, max_noutput_items)
{
// std::cerr << "gr_tpb_thread_body: " << block << std::endl;
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h
index 548cfedfb..3170b402e 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h
@@ -38,7 +38,7 @@ class GR_CORE_API gr_tpb_thread_body {
gr_block_executor d_exec;
public:
- gr_tpb_thread_body(gr_block_sptr block);
+ gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items=100000);
~gr_tpb_thread_body();
};
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py
index b3124ad29..325495c1d 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py
@@ -273,6 +273,30 @@ class test_fft_filter(gr_unittest.TestCase):
self.assert_fft_float_ok2(expected_result, result_data)
+ def test_fff_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+
+ op = gr.fft_filter_fff(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertEqual(taps, result_data)
+
+ def test_ccc_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+
+ op = gr.fft_filter_ccc(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertComplexTuplesAlmostEqual(taps, result_data, 4)
+
if __name__ == '__main__':
gr_unittest.run(test_fft_filter, "test_fft_filter.xml")
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_noise.py b/gnuradio-core/src/python/gnuradio/gr/qa_noise.py
index 4a575f5d6..d7750cfe2 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_noise.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_noise.py
@@ -34,6 +34,18 @@ class test_noise_source(gr_unittest.TestCase):
# Just confirm that we can instantiate a noise source
op = gr.noise_source_f(gr.GR_GAUSSIAN, 10, 10)
+ def test_002(self):
+ # Test get methods
+ set_type = gr.GR_GAUSSIAN
+ set_ampl = 10
+ op = gr.noise_source_f(set_type, set_ampl, 10)
+ get_type = op.type()
+ get_ampl = op.amplitude()
+
+ self.assertEqual(get_type, set_type)
+ self.assertEqual(get_ampl, set_ampl)
+
+
if __name__ == '__main__':
gr_unittest.run(test_noise_source, "test_noise_source.xml")
diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py
index 1e36d3b48..f2d83893c 100644
--- a/gnuradio-core/src/python/gnuradio/gr/top_block.py
+++ b/gnuradio-core/src/python/gnuradio/gr/top_block.py
@@ -93,14 +93,14 @@ class top_block(object):
raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?")
return getattr(self._tb, name)
- def start(self):
- self._tb.start()
+ def start(self, max_noutput_items=100000):
+ self._tb.start(max_noutput_items)
def stop(self):
self._tb.stop()
- def run(self):
- self.start()
+ def run(self, max_noutput_items=100000):
+ self.start(max_noutput_items)
self.wait()
def wait(self):
diff --git a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
index dac1e94c3..95e595026 100644
--- a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
+++ b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
@@ -238,7 +238,7 @@ qa_atsci_single_viterbi::t1 ()
if (differs) {
const int ERRTOL = 12; /* Or relate to delay? */
int shouldfix = 1;
- int lasti = -ERRTOL;
+ //int lasti = -ERRTOL;
printf ( " Inserted errors: ");
for (int erri = 0; erri < NN; erri++) {
@@ -246,7 +246,7 @@ qa_atsci_single_viterbi::t1 ()
printf (" %d", erri);
// if (erri < lasti+ERRTOL)
// shouldfix = 0;
- lasti = erri;
+ //lasti = erri;
}
}
printf ("\n Erroneous result dibits:");
diff --git a/gr-audio/lib/alsa/audio_alsa_source.cc b/gr-audio/lib/alsa/audio_alsa_source.cc
index 08d4996a8..a90552ff5 100644
--- a/gr-audio/lib/alsa/audio_alsa_source.cc
+++ b/gr-audio/lib/alsa/audio_alsa_source.cc
@@ -348,12 +348,11 @@ audio_alsa_source::work_s16_2x1 (int noutput_items,
typedef gr_int16 sample_t; // the type of samples we're creating
static const float scale_factor = 1.0 / std::pow(2.0f, 16-1);
- unsigned int nchan = output_items.size ();
float **out = (float **) &output_items[0];
sample_t *buf = (sample_t *) d_buffer;
int bi;
- assert (nchan == 1);
+ assert (output_items.size () == 1);
unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
@@ -425,12 +424,11 @@ audio_alsa_source::work_s32_2x1 (int noutput_items,
typedef gr_int32 sample_t; // the type of samples we're creating
static const float scale_factor = 1.0 / std::pow(2.0f, 32-1);
- unsigned int nchan = output_items.size ();
float **out = (float **) &output_items[0];
sample_t *buf = (sample_t *) d_buffer;
int bi;
- assert (nchan == 1);
+ assert (output_items.size () == 1);
unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
assert (d_buffer_size_bytes == d_period_size * sizeof_frame);
diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt
index 2645557cc..7b94f745c 100644
--- a/gr-digital/examples/CMakeLists.txt
+++ b/gr-digital/examples/CMakeLists.txt
@@ -25,6 +25,7 @@ GR_PYTHON_INSTALL(PROGRAMS
example_timing.py
run_length.py
gen_whitener.py
+ snr_estimators.py
DESTINATION ${GR_PKG_DATA_DIR}/examples/digital
COMPONENT "digital_python"
)
diff --git a/gr-digital/examples/Makefile.am b/gr-digital/examples/Makefile.am
index 3841bbd0e..3e6b32e85 100644
--- a/gr-digital/examples/Makefile.am
+++ b/gr-digital/examples/Makefile.am
@@ -29,7 +29,8 @@ dist_basicdata_SCRIPTS = \
example_fll.py \
example_timing.py \
run_length.py \
- gen_whitener.py
+ gen_whitener.py \
+ snr_estimators.py
nbdatadir = $(dig_examples_prefix)/narrowband
dist_nbdata_SCRIPTS = \
diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py
index 28331310d..dfed0eee7 100755
--- a/gr-digital/examples/narrowband/digital_bert_rx.py
+++ b/gr-digital/examples/narrowband/digital_bert_rx.py
@@ -113,9 +113,11 @@ class rx_psk_block(gr.top_block):
self._demodulator = self._demodulator_class(**demod_kwargs)
if(options.rx_freq is not None):
+ symbol_rate = options.bitrate / self._demodulator.bits_per_symbol()
self._source = uhd_receiver(options.args, options.bitrate,
options.samples_per_symbol,
options.rx_freq, options.rx_gain,
+ options.spec,
options.antenna, options.verbose)
options.samples_per_symbol = self._source._sps
diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py
index 46f4f9097..f29e997af 100755
--- a/gr-digital/examples/narrowband/digital_bert_tx.py
+++ b/gr-digital/examples/narrowband/digital_bert_tx.py
@@ -67,9 +67,11 @@ class tx_psk_block(gr.top_block):
self._modulator = self._modulator_class(**mod_kwargs)
if(options.tx_freq is not None):
- self._sink = uhd_transmitter(options.args, options.bitrate,
+ symbol_rate = options.bitrate / self._modulator.bits_per_symbol()
+ self._sink = uhd_transmitter(options.args, symbol_rate,
options.samples_per_symbol,
options.tx_freq, options.tx_gain,
+ options.spec,
options.antenna, options.verbose)
options.samples_per_symbol = self._sink._sps
@@ -87,7 +89,8 @@ class tx_psk_block(gr.top_block):
verbose=options.verbose,
log=options.log)
- self.connect(self._transmitter, self._sink)
+ self.amp = gr.multiply_const_cc(options.amplitude)
+ self.connect(self._transmitter, self.amp, self._sink)
def get_options(mods):
diff --git a/gr-digital/examples/snr_estimators.py b/gr-digital/examples/snr_estimators.py
new file mode 100755
index 000000000..432abd455
--- /dev/null
+++ b/gr-digital/examples/snr_estimators.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+
+import sys
+
+try:
+ import scipy
+ from scipy import stats
+except ImportError:
+ print "Error: Program requires scipy (www.scipy.org)."
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: Program requires Matplotlib (matplotlib.sourceforge.net)."
+ sys.exit(1)
+
+from gnuradio import gr, digital
+from optparse import OptionParser
+from gnuradio.eng_option import eng_option
+
+'''
+This example program uses Python and GNU Radio to calculate SNR of a
+noise BPSK signal to compare them.
+
+For an explination of the online algorithms, see:
+http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Higher-order_statistics
+'''
+
+def online_skewness(data, alpha):
+ n = 0
+ mean = 0
+ M2 = 0
+ M3 = 0
+ d_M3 = 0
+
+ for n in xrange(len(data)):
+ delta = data[n] - mean
+ delta_n = delta / (n+1)
+ term1 = delta * delta_n * (n)
+ mean = mean + delta_n
+ M3 = term1 * delta_n * (n - 1) - 3 * delta_n * M2
+ M2 = M2 + term1
+ d_M3 = (0.001)*M3 + (1-0.001)*d_M3;
+
+ return d_M3
+
+def snr_est_simple(signal):
+ y1 = scipy.mean(abs(signal))
+ y2 = scipy.real(scipy.mean(signal**2))
+ y3 = (y1*y1 - y2)
+ snr_rat = y1*y1/y3
+ return 10.0*scipy.log10(snr_rat), snr_rat
+
+def snr_est_skew(signal):
+ y1 = scipy.mean(abs(signal))
+ y2 = scipy.mean(scipy.real(signal**2))
+ y3 = (y1*y1 - y2)
+ y4 = online_skewness(abs(signal.real), 0.001)
+
+ skw = y4*y4 / (y2*y2*y2);
+ snr_rat = y1*y1 / (y3 + skw*y1*y1)
+ return 10.0*scipy.log10(snr_rat), snr_rat
+
+def snr_est_m2m4(signal):
+ M2 = scipy.mean(abs(signal)**2)
+ M4 = scipy.mean(abs(signal)**4)
+ snr_rat = 2*scipy.sqrt(2*M2*M2 - M4) / (M2 - scipy.sqrt(2*M2*M2 - M4))
+ return 10.0*scipy.log10(snr_rat), snr_rat
+
+def snr_est_svr(signal):
+ N = len(signal)
+ ssum = 0
+ msum = 0
+ for i in xrange(1, N):
+ ssum += (abs(signal[i])**2)*(abs(signal[i-1])**2)
+ msum += (abs(signal[i])**4)
+ savg = (1.0/(float(N)-1.0))*ssum
+ mavg = (1.0/(float(N)-1.0))*msum
+ beta = savg / (mavg - savg)
+
+ snr_rat = 2*((beta - 1) + scipy.sqrt(beta*(beta-1)))
+ return 10.0*scipy.log10(snr_rat), snr_rat
+
+
+def main():
+ gr_estimators = {"simple": digital.SNR_EST_SIMPLE,
+ "skew": digital.SNR_EST_SKEW,
+ "m2m4": digital.SNR_EST_M2M4,
+ "svr": digital.SNR_EST_SVR}
+ py_estimators = {"simple": snr_est_simple,
+ "skew": snr_est_skew,
+ "m2m4": snr_est_m2m4,
+ "svr": snr_est_svr}
+
+
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Set the number of samples to process [default=%default]")
+ parser.add_option("", "--snr-min", type="float", default=-5,
+ help="Minimum SNR [default=%default]")
+ parser.add_option("", "--snr-max", type="float", default=20,
+ help="Maximum SNR [default=%default]")
+ parser.add_option("", "--snr-step", type="float", default=0.5,
+ help="SNR step amount [default=%default]")
+ parser.add_option("-t", "--type", type="choice",
+ choices=gr_estimators.keys(), default="simple",
+ help="Estimator type {0} [default=%default]".format(
+ gr_estimators.keys()))
+ (options, args) = parser.parse_args ()
+
+ N = options.nsamples
+ xx = scipy.random.randn(N)
+ xy = scipy.random.randn(N)
+ bits = 2*scipy.complex64(scipy.random.randint(0, 2, N)) - 1
+
+ snr_known = list()
+ snr_python = list()
+ snr_gr = list()
+
+ # when to issue an SNR tag; can be ignored in this example.
+ ntag = 10000
+
+ n_cpx = xx + 1j*xy
+
+ py_est = py_estimators[options.type]
+ gr_est = gr_estimators[options.type]
+
+ SNR_min = options.snr_min
+ SNR_max = options.snr_max
+ SNR_step = options.snr_step
+ SNR_dB = scipy.arange(SNR_min, SNR_max+SNR_step, SNR_step)
+ for snr in SNR_dB:
+ SNR = 10.0**(snr/10.0)
+ scale = scipy.sqrt(SNR)
+ yy = bits + n_cpx/scale
+ print "SNR: ", snr
+
+ Sknown = scipy.mean(yy**2)
+ Nknown = scipy.var(n_cpx/scale)/2
+ snr0 = Sknown/Nknown
+ snr0dB = 10.0*scipy.log10(snr0)
+ snr_known.append(snr0dB)
+
+ snrdB, snr = py_est(yy)
+ snr_python.append(snrdB)
+
+ gr_src = gr.vector_source_c(bits.tolist(), False)
+ gr_snr = digital.mpsk_snr_est_cc(gr_est, ntag, 0.001)
+ gr_chn = gr.channel_model(1.0/scale)
+ gr_snk = gr.null_sink(gr.sizeof_gr_complex)
+ tb = gr.top_block()
+ tb.connect(gr_src, gr_chn, gr_snr, gr_snk)
+ tb.run()
+
+ snr_gr.append(gr_snr.snr())
+
+ f1 = pylab.figure(1)
+ s1 = f1.add_subplot(1,1,1)
+ s1.plot(SNR_dB, snr_known, "k-o", linewidth=2, label="Known")
+ s1.plot(SNR_dB, snr_python, "b-o", linewidth=2, label="Python")
+ s1.plot(SNR_dB, snr_gr, "g-o", linewidth=2, label="GNU Radio")
+ s1.grid(True)
+ s1.set_title('SNR Estimators')
+ s1.set_xlabel('SNR (dB)')
+ s1.set_ylabel('Estimated SNR')
+ s1.legend()
+
+ pylab.show()
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/gr-digital/grc/digital_dxpsk_demod.xml b/gr-digital/grc/digital_dxpsk_demod.xml
index d5e742097..cfd474f68 100644
--- a/gr-digital/grc/digital_dxpsk_demod.xml
+++ b/gr-digital/grc/digital_dxpsk_demod.xml
@@ -33,6 +33,7 @@
<make>digital.$(type)_demod(
samples_per_symbol=$samples_per_symbol,
excess_bw=$excess_bw,
+ freq_bw=$freq_bw,
phase_bw=$phase_bw,
timing_bw=$timing_bw,
gray_coded=$gray_coded,
@@ -67,6 +68,12 @@
<type>real</type>
</param>
<param>
+ <name>FLL Bandwidth</name>
+ <key>freq_bw</key>
+ <value>6.28/100.0</value>
+ <type>real</type>
+ </param>
+ <param>
<name>Phase Loop Bandwidth</name>
<key>phase_bw</key>
<value>6.28/100.0</value>
diff --git a/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt
index cf20bd1e7..81ed8d368 100644
--- a/gr-digital/include/CMakeLists.txt
+++ b/gr-digital/include/CMakeLists.txt
@@ -22,6 +22,7 @@
########################################################################
install(FILES
digital_api.h
+ digital_impl_mpsk_snr_est.h
digital_binary_slicer_fb.h
digital_clock_recovery_mm_cc.h
digital_clock_recovery_mm_ff.h
@@ -37,12 +38,14 @@ install(FILES
digital_kurtotic_equalizer_cc.h
digital_metric_type.h
digital_mpsk_receiver_cc.h
+ digital_mpsk_snr_est_cc.h
digital_ofdm_cyclic_prefixer.h
digital_ofdm_frame_acquisition.h
digital_ofdm_frame_sink.h
digital_ofdm_insert_preamble.h
digital_ofdm_mapper_bcv.h
digital_ofdm_sampler.h
+ digital_probe_mpsk_snr_est_c.h
digital_gmskmod_bc.h
digital_cpmmod_bc.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
diff --git a/gr-digital/include/Makefile.am b/gr-digital/include/Makefile.am
index 8ce3a94e8..3cf186d3d 100644
--- a/gr-digital/include/Makefile.am
+++ b/gr-digital/include/Makefile.am
@@ -24,6 +24,7 @@ include $(top_srcdir)/Makefile.common
# These headers get installed in ${prefix}/include/gnuradio
grinclude_HEADERS = \
digital_api.h \
+ digital_impl_mpsk_snr_est.h \
digital_binary_slicer_fb.h \
digital_clock_recovery_mm_cc.h \
digital_clock_recovery_mm_ff.h \
@@ -39,12 +40,14 @@ grinclude_HEADERS = \
digital_kurtotic_equalizer_cc.h \
digital_metric_type.h \
digital_mpsk_receiver_cc.h \
+ digital_mpsk_snr_est_cc.h \
digital_ofdm_cyclic_prefixer.h \
digital_ofdm_frame_acquisition.h \
digital_ofdm_frame_sink.h \
digital_ofdm_insert_preamble.h \
digital_ofdm_mapper_bcv.h \
digital_ofdm_sampler.h \
+ digital_probe_mpsk_snr_est_c.h \
digital_gmskmod_bc.h \
digital_cpmmod_bc.h
diff --git a/gr-digital/include/digital_impl_mpsk_snr_est.h b/gr-digital/include/digital_impl_mpsk_snr_est.h
new file mode 100644
index 000000000..df7dbadec
--- /dev/null
+++ b/gr-digital/include/digital_impl_mpsk_snr_est.h
@@ -0,0 +1,279 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_DIGITAL_IMPL_MPSK_SNR_EST_H
+#define INCLUDED_DIGITAL_IMPL_MPSK_SNR_EST_H
+
+#include <digital_api.h>
+#include <gr_sync_block.h>
+
+//! Enum for the type of SNR estimator to select
+/*! \ingroup snr_blk
+ * \anchor ref_snr_est_types
+ *
+ * Below are some ROUGH estimates of what values of SNR each of these
+ * types of estimators is good for. In general, these offer a
+ * trade-off between accuracy and performance.
+ *
+ * \li SNR_EST_SIMPLE: Simple estimator (>= 7 dB)
+ * \li SNR_EST_SKEW: Skewness-base est (>= 5 dB)
+ * \li SNR_EST_M2M4: 2nd & 4th moment est (>= 1 dB)
+ * \li SNR_EST_SVR: SVR-based est (>= 0dB)
+*/
+enum snr_est_type_t {
+ SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB)
+ SNR_EST_SKEW, // Skewness-base est (>= 5 dB)
+ SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB)
+ SNR_EST_SVR // SVR-based est (>= 0dB)
+};
+
+/*! \brief A parent class for SNR estimators, specifically for M-PSK
+ * signals in AWGN channels.
+ * \ingroup snr_blk
+ */
+class DIGITAL_API digital_impl_mpsk_snr_est
+{
+ protected:
+ double d_alpha, d_beta;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ digital_impl_mpsk_snr_est(double alpha);
+ virtual ~digital_impl_mpsk_snr_est();
+
+ //! Get the running-average coefficient
+ double alpha() const;
+
+ //! Set the running-average coefficient
+ void set_alpha(double alpha);
+
+ //! Update the current registers
+ virtual int update(int noutput_items,
+ const gr_complex *in);
+
+ //! Use the register values to compute a new estimate
+ virtual double snr();
+};
+
+
+//! \brief SNR Estimator using simple mean/variance estimates.
+/*! \ingroup snr_blk
+ *
+ * A very simple SNR estimator that just uses mean and variance
+ * estimates of an M-PSK constellation. This esimator is quick and
+ * cheap and accurate for high SNR (above 7 dB or so) but quickly
+ * starts to overestimate the SNR at low SNR.
+ */
+class DIGITAL_API digital_impl_mpsk_snr_est_simple :
+ public digital_impl_mpsk_snr_est
+{
+ private:
+ double d_y1, d_y2;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ digital_impl_mpsk_snr_est_simple(double alpha);
+ ~digital_impl_mpsk_snr_est_simple() {}
+
+ int update(int noutput_items,
+ const gr_complex *in);
+ double snr();
+};
+
+
+//! \brief SNR Estimator using skewness correction.
+/*! \ingroup snr_blk
+ *
+ * This is an estimator that came from a discussion between Tom
+ * Rondeau and fred harris with no known paper reference. The idea is
+ * that at low SNR, the variance estimations will be affected because
+ * of fold-over around the decision boundaries, which results in a
+ * skewness to the samples. We estimate the skewness and use this as
+ * a correcting term.
+ */
+class DIGITAL_API digital_impl_mpsk_snr_est_skew :
+ public digital_impl_mpsk_snr_est
+{
+ private:
+ double d_y1, d_y2, d_y3;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ digital_impl_mpsk_snr_est_skew(double alpha);
+ ~digital_impl_mpsk_snr_est_skew() {}
+
+ int update(int noutput_items,
+ const gr_complex *in);
+ double snr();
+};
+
+
+//! \brief SNR Estimator using 2nd and 4th-order moments.
+/*! \ingroup snr_blk
+ *
+ * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th (M4)
+ * order moments. This estimator uses knowledge of the kurtosis of
+ * the signal (k_a) and noise (k_w) to make its estimation. We use
+ * Beaulieu's approximations here to M-PSK signals and AWGN channels
+ * such that k_a=1 and k_w=2. These approximations significantly
+ * reduce the complexity of the calculations (and computations)
+ * required.
+ *
+ * Reference:
+ * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR
+ * estimation techniques for the AWGN channel," IEEE
+ * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000.
+ */
+class DIGITAL_API digital_impl_mpsk_snr_est_m2m4 :
+ public digital_impl_mpsk_snr_est
+{
+ private:
+ double d_y1, d_y2;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ digital_impl_mpsk_snr_est_m2m4(double alpha);
+ ~digital_impl_mpsk_snr_est_m2m4() {}
+
+ int update(int noutput_items,
+ const gr_complex *in);
+ double snr();
+};
+
+
+//! \brief SNR Estimator using 2nd and 4th-order moments.
+/*! \ingroup snr_blk
+ *
+ * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th (M4)
+ * order moments. This estimator uses knowledge of the kurtosis of
+ * the signal (k_a) and noise (k_w) to make its estimation. In this
+ * case, you can set your own estimations for k_a and k_w, the
+ * kurtosis of the signal and noise, to fit this estimation better to
+ * your signal and channel conditions.
+ *
+ * A word of warning: this estimator has not been fully tested or
+ * proved with any amount of rigor. The estimation for M4 in
+ * particular might be ignoring effectf of when k_a and k_w are
+ * different. Use this estimator with caution and a copy of the
+ * reference on hand.
+ *
+ * The digital_mpsk_snr_est_m2m4 assumes k_a and k_w to simplify the
+ * computations for M-PSK and AWGN channels. Use that estimator
+ * unless you have a way to guess or estimate these values here.
+ *
+ * Original paper:
+ * R. Matzner, "An SNR estimation algorithm for complex baseband
+ * signal using higher order statistics," Facta Universitatis
+ * (Nis), no. 6, pp. 41-52, 1993.
+ *
+ * Reference used in derivation:
+ * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR
+ * estimation techniques for the AWGN channel," IEEE
+ * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000.
+ */
+class DIGITAL_API digital_impl_snr_est_m2m4 :
+ public digital_impl_mpsk_snr_est
+{
+ private:
+ double d_y1, d_y2;
+ double d_ka, d_kw;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ * \param ka: estimate of the signal kurtosis (1 for PSK)
+ * \param kw: estimate of the channel noise kurtosis (2 for AWGN)
+ */
+ digital_impl_snr_est_m2m4(double alpha, double ka, double kw);
+ ~digital_impl_snr_est_m2m4() {}
+
+ int update(int noutput_items,
+ const gr_complex *in);
+ double snr();
+};
+
+
+//! \brief Signal-to-Variation Ratio SNR Estimator.
+/*! \ingroup snr_blk
+ *
+ * This estimator actually comes from an SNR estimator for M-PSK
+ * signals in fading channels, but this implementation is
+ * specifically for AWGN channels. The math was simplified to assume
+ * a signal and noise kurtosis (k_a and k_w) for M-PSK signals in
+ * AWGN. These approximations significantly reduce the complexity of
+ * the calculations (and computations) required.
+ *
+ * Original paper:
+ * A. L. Brandao, L. B. Lopes, and D. C. McLernon, "In-service
+ * monitoring of multipath delay and cochannel interference for
+ * indoor mobile communication systems," Proc. IEEE
+ * Int. Conf. Communications, vol. 3, pp. 1458-1462, May 1994.
+ *
+ * Reference:
+ * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR
+ * estimation techniques for the AWGN channel," IEEE
+ * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000.
+ */
+class DIGITAL_API digital_impl_mpsk_snr_est_svr :
+ public digital_impl_mpsk_snr_est
+{
+ private:
+ double d_y1, d_y2;
+
+ public:
+ /*! Constructor
+ *
+ * Parameters:
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ digital_impl_mpsk_snr_est_svr(double alpha);
+ ~digital_impl_mpsk_snr_est_svr() {}
+
+ int update(int noutput_items,
+ const gr_complex *in);
+ double snr();
+};
+
+#endif /* INCLUDED_DIGITAL_IMPL_MPSK_SNR_EST_H */
diff --git a/gr-digital/include/digital_mpsk_snr_est_cc.h b/gr-digital/include/digital_mpsk_snr_est_cc.h
new file mode 100644
index 000000000..2cbd98bab
--- /dev/null
+++ b/gr-digital/include/digital_mpsk_snr_est_cc.h
@@ -0,0 +1,115 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_DIGITAL_MPSK_SNR_EST_CC_H
+#define INCLUDED_DIGITAL_MPSK_SNR_EST_CC_H
+
+#include <digital_api.h>
+#include <gr_sync_block.h>
+#include <digital_impl_mpsk_snr_est.h>
+
+class digital_mpsk_snr_est_cc;
+typedef boost::shared_ptr<digital_mpsk_snr_est_cc> digital_mpsk_snr_est_cc_sptr;
+
+DIGITAL_API digital_mpsk_snr_est_cc_sptr
+digital_make_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples=10000,
+ double alpha=0.001);
+
+//! \brief A block for computing SNR of a signal.
+/*! \ingroup snr_blk
+ *
+ * This block can be used to monitor and retrieve estimations of the
+ * signal SNR. It is designed to work in a flowgraph and passes all
+ * incoming data along to its output.
+ *
+ * The block is designed for use with M-PSK signals especially. The
+ * type of estimator is specified as the \p type parameter in the
+ * constructor. The estimators tend to trade off performance for
+ * accuracy, although experimentation should be done to figure out
+ * the right approach for a given implementation. Further, the
+ * current set of estimators are designed and proven theoretically
+ * under AWGN conditions; some amount of error should be assumed
+ * and/or estimated for real channel conditions.
+ */
+class DIGITAL_API digital_mpsk_snr_est_cc : public gr_sync_block
+{
+ private:
+ snr_est_type_t d_type;
+ int d_nsamples, d_count;
+ double d_alpha;
+ digital_impl_mpsk_snr_est *d_snr_est;
+
+ //d_key is the tag name, 'snr', d_me is the block name + unique ID
+ pmt::pmt_t d_key, d_me;
+
+ /*! Factory function returning shared pointer of this class
+ *
+ * Parameters:
+ *
+ * \param type: the type of estimator to use \ref ref_snr_est_types
+ * "snr_est_type_t" for details about the available types.
+ * \param tag_nsamples: after this many samples, a tag containing
+ * the SNR (key='snr') will be sent
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ friend DIGITAL_API digital_mpsk_snr_est_cc_sptr
+ digital_make_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples,
+ double alpha);
+
+ // Private constructor
+ digital_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples,
+ double alpha);
+
+public:
+
+ ~digital_mpsk_snr_est_cc();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ //! Return the estimated signal-to-noise ratio in decibels
+ double snr();
+
+ //! Return the type of estimator in use
+ snr_est_type_t type() const;
+
+ //! Return how many samples between SNR tags
+ int tag_nsample() const;
+
+ //! Get the running-average coefficient
+ double alpha() const;
+
+ //! Set type of estimator to use
+ void set_type(snr_est_type_t t);
+
+ //! Set the number of samples between SNR tags
+ void set_tag_nsample(int n);
+
+ //! Set the running-average coefficient
+ void set_alpha(double alpha);
+};
+
+#endif /* INCLUDED_DIGITAL_MPSK_SNR_EST_CC_H */
diff --git a/gr-digital/include/digital_probe_mpsk_snr_est_c.h b/gr-digital/include/digital_probe_mpsk_snr_est_c.h
new file mode 100644
index 000000000..a78e90412
--- /dev/null
+++ b/gr-digital/include/digital_probe_mpsk_snr_est_c.h
@@ -0,0 +1,113 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_DIGITAL_PROBE_MPSK_SNR_EST_C_H
+#define INCLUDED_DIGITAL_PROBE_MPSK_SNR_EST_C_H
+
+#include <digital_api.h>
+#include <gr_sync_block.h>
+#include <digital_impl_mpsk_snr_est.h>
+
+class digital_probe_mpsk_snr_est_c;
+typedef boost::shared_ptr<digital_probe_mpsk_snr_est_c> digital_probe_mpsk_snr_est_c_sptr;
+
+DIGITAL_API digital_probe_mpsk_snr_est_c_sptr
+digital_make_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples=10000,
+ double alpha=0.001);
+
+//! \brief A probe for computing SNR of a signal.
+/*! \ingroup snr_blk
+ *
+ * This is a probe block (a sink) that can be used to monitor and
+ * retrieve estimations of the signal SNR. This probe is designed for
+ * use with M-PSK signals especially. The type of estimator is
+ * specified as the \p type parameter in the constructor. The
+ * estimators tend to trade off performance for accuracy, although
+ * experimentation should be done to figure out the right approach
+ * for a given implementation. Further, the current set of estimators
+ * are designed and proven theoretically under AWGN conditions; some
+ * amount of error should be assumed and/or estimated for real
+ * channel conditions.
+ */
+class DIGITAL_API digital_probe_mpsk_snr_est_c : public gr_sync_block
+{
+ private:
+ snr_est_type_t d_type;
+ int d_nsamples, d_count;
+ double d_alpha;
+ digital_impl_mpsk_snr_est *d_snr_est;
+
+ //d_key is the message name, 'snr'
+ pmt::pmt_t d_key;
+
+ /*! Factory function returning shared pointer of this class
+ *
+ * Parameters:
+ *
+ * \param type: the type of estimator to use \ref ref_snr_est_types
+ * "snr_est_type_t" for details about the available types.
+ * \param msg_nsamples: [not implemented yet] after this many
+ * samples, a message containing the SNR (key='snr') will be sent
+ * \param alpha: the update rate of internal running average
+ * calculations.
+ */
+ friend DIGITAL_API digital_probe_mpsk_snr_est_c_sptr
+ digital_make_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples,
+ double alpha);
+
+ //! Private constructor
+ digital_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples,
+ double alpha);
+
+public:
+
+ ~digital_probe_mpsk_snr_est_c();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ //! Return the estimated signal-to-noise ratio in decibels
+ double snr();
+
+ //! Return the type of estimator in use
+ snr_est_type_t type() const;
+
+ //! Return how many samples between SNR messages
+ int msg_nsample() const;
+
+ //! Get the running-average coefficient
+ double alpha() const;
+
+ //! Set type of estimator to use
+ void set_type(snr_est_type_t t);
+
+ //! Set the number of samples between SNR messages
+ void set_msg_nsample(int n);
+
+ //! Set the running-average coefficient
+ void set_alpha(double alpha);
+};
+
+#endif /* INCLUDED_DIGITAL_PROBE_MPSK_SNR_EST_C_H */
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index b90757111..779972ff3 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -32,6 +32,7 @@ link_directories(${Boost_LIBRARY_DIRS})
# Setup library
########################################################################
list(APPEND gr_digital_sources
+ digital_impl_mpsk_snr_est.cc
digital_binary_slicer_fb.cc
digital_clock_recovery_mm_cc.cc
digital_clock_recovery_mm_ff.cc
@@ -46,12 +47,14 @@ list(APPEND gr_digital_sources
digital_lms_dd_equalizer_cc.cc
digital_kurtotic_equalizer_cc.cc
digital_mpsk_receiver_cc.cc
+ digital_mpsk_snr_est_cc.cc
digital_ofdm_cyclic_prefixer.cc
digital_ofdm_frame_acquisition.cc
digital_ofdm_frame_sink.cc
digital_ofdm_insert_preamble.cc
digital_ofdm_mapper_bcv.cc
digital_ofdm_sampler.cc
+ digital_probe_mpsk_snr_est_c.cc
digital_gmskmod_bc.cc
digital_cpmmod_bc.cc
)
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am
index 2860974ca..d5ad199e3 100644
--- a/gr-digital/lib/Makefile.am
+++ b/gr-digital/lib/Makefile.am
@@ -27,6 +27,7 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \
lib_LTLIBRARIES = libgnuradio-digital.la
libgnuradio_digital_la_SOURCES = \
+ digital_impl_mpsk_snr_est.cc \
digital_binary_slicer_fb.cc \
digital_clock_recovery_mm_cc.cc \
digital_clock_recovery_mm_ff.cc \
@@ -41,12 +42,14 @@ libgnuradio_digital_la_SOURCES = \
digital_lms_dd_equalizer_cc.cc \
digital_kurtotic_equalizer_cc.cc \
digital_mpsk_receiver_cc.cc \
+ digital_mpsk_snr_est_cc.cc \
digital_ofdm_cyclic_prefixer.cc \
digital_ofdm_frame_acquisition.cc \
digital_ofdm_frame_sink.cc \
digital_ofdm_insert_preamble.cc \
digital_ofdm_mapper_bcv.cc \
digital_ofdm_sampler.cc \
+ digital_probe_mpsk_snr_est_c.cc \
digital_gmskmod_bc.cc \
digital_cpmmod_bc.cc
diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc
index 0c100f38e..d9a53c493 100644
--- a/gr-digital/lib/digital_constellation.cc
+++ b/gr-digital/lib/digital_constellation.cc
@@ -357,10 +357,8 @@ digital_constellation_psk::get_sector (const gr_complex *sample)
float phase = arg(*sample);
float width = M_TWOPI / n_sectors;
int sector = floor(phase/width + 0.5);
- unsigned int u_sector;
if (sector < 0)
sector += n_sectors;
- u_sector = sector;
return sector;
}
diff --git a/gr-digital/lib/digital_impl_mpsk_snr_est.cc b/gr-digital/lib/digital_impl_mpsk_snr_est.cc
new file mode 100644
index 000000000..38177083f
--- /dev/null
+++ b/gr-digital/lib/digital_impl_mpsk_snr_est.cc
@@ -0,0 +1,256 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <digital_impl_mpsk_snr_est.h>
+#include <cstdio>
+
+digital_impl_mpsk_snr_est::digital_impl_mpsk_snr_est(double alpha)
+{
+ set_alpha(alpha);
+}
+
+digital_impl_mpsk_snr_est::~digital_impl_mpsk_snr_est()
+{}
+
+void
+digital_impl_mpsk_snr_est::set_alpha(double alpha)
+{
+ d_alpha = alpha;
+ d_beta = 1.0-alpha;
+}
+
+double
+digital_impl_mpsk_snr_est::alpha() const
+{
+ return d_alpha;
+}
+
+int
+digital_impl_mpsk_snr_est::update(int noutput_items,
+ const gr_complex *in)
+{
+ throw std::runtime_error("digital_impl_mpsk_snr_est: Unimplemented");
+}
+
+double
+digital_impl_mpsk_snr_est::snr()
+{
+ throw std::runtime_error("digital_impl_mpsk_snr_est: Unimplemented");
+}
+
+
+/********************************************************************/
+
+
+digital_impl_mpsk_snr_est_simple::digital_impl_mpsk_snr_est_simple(
+ double alpha) :
+ digital_impl_mpsk_snr_est(alpha)
+{
+ d_y1 = 0;
+ d_y2 = 0;
+}
+
+int
+digital_impl_mpsk_snr_est_simple::update(
+ int noutput_items,
+ const gr_complex *in)
+{
+ for (int i = 0; i < noutput_items; i++){
+ double y1 = abs(in[i]);
+ d_y1 = d_alpha*y1 + d_beta*d_y1;
+
+ double y2 = real(in[i]*in[i]);
+ d_y2 = d_alpha*y2 + d_beta*d_y2;
+ }
+ return noutput_items;
+}
+
+double
+digital_impl_mpsk_snr_est_simple::snr()
+{
+ double y1_2 = d_y1*d_y1;
+ double y3 = y1_2 - d_y2 + 1e-20;
+ return 10.0*log10(y1_2/y3);
+}
+
+
+/********************************************************************/
+
+
+digital_impl_mpsk_snr_est_skew::digital_impl_mpsk_snr_est_skew(
+ double alpha) :
+ digital_impl_mpsk_snr_est(alpha)
+{
+ d_y1 = 0;
+ d_y2 = 0;
+ d_y3 = 0;
+}
+
+
+int
+digital_impl_mpsk_snr_est_skew::update(
+ int noutput_items,
+ const gr_complex *in)
+{
+ for (int i = 0; i < noutput_items; i++){
+ double y1 = abs(in[i]);
+ d_y1 = d_alpha*y1 + d_beta*d_y1;
+
+ double y2 = real(in[i]*in[i]);
+ d_y2 = d_alpha*y2 + d_beta*d_y2;
+
+ // online algorithm for calculating skewness
+ // See:
+ // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Higher-order_statistics
+ double d = abs(in[i]) - d_y1;
+ double d_i = d / (i+1);
+ double y3 = (d*d_i*i)*d_i*(i-1) - 3.0*d_i*d_y2;
+ d_y3 = d_alpha*y3 + d_beta*d_y3;
+ }
+ return noutput_items;
+}
+
+double
+digital_impl_mpsk_snr_est_skew::snr()
+{
+ double y3 = d_y3*d_y3 / (d_y2*d_y2*d_y2);
+ double y1_2 = d_y1*d_y1;
+ double x = y1_2 - d_y2;
+ return 10.0*log10(y1_2 / (x + y3*y1_2));
+}
+
+
+/********************************************************************/
+
+
+digital_impl_mpsk_snr_est_m2m4::digital_impl_mpsk_snr_est_m2m4(
+ double alpha) :
+ digital_impl_mpsk_snr_est(alpha)
+{
+ d_y1 = 0;
+ d_y2 = 0;
+}
+
+int
+digital_impl_mpsk_snr_est_m2m4::update(
+ int noutput_items,
+ const gr_complex *in)
+{
+ for (int i = 0; i < noutput_items; i++){
+ double y1 = abs(in[i])*abs(in[i]);
+ d_y1 = d_alpha*y1 + d_beta*d_y1;
+
+ double y2 = abs(in[i])*abs(in[i])*abs(in[i])*abs(in[i]);
+ d_y2 = d_alpha*y2 + d_beta*d_y2;
+ }
+ return noutput_items;
+}
+
+double
+digital_impl_mpsk_snr_est_m2m4::snr()
+{
+ double y1_2 = d_y1*d_y1;
+ return 10.0*log10(2.0*sqrt(2*y1_2 - d_y2) /
+ (d_y1 - sqrt(2*y1_2 - d_y2)));
+}
+
+
+/********************************************************************/
+
+
+digital_impl_snr_est_m2m4::digital_impl_snr_est_m2m4(
+ double alpha, double ka, double kw) :
+ digital_impl_mpsk_snr_est(alpha)
+{
+ d_y1 = 0;
+ d_y2 = 0;
+ d_ka = ka;
+ d_kw = kw;
+}
+
+int
+digital_impl_snr_est_m2m4::update(
+ int noutput_items,
+ const gr_complex *in)
+{
+ for (int i = 0; i < noutput_items; i++) {
+ double y1 = abs(in[i])*abs(in[i]);
+ d_y1 = d_alpha*y1 + d_beta*d_y1;
+
+ double y2 = abs(in[i])*abs(in[i])*abs(in[i])*abs(in[i]);
+ d_y2 = d_alpha*y2 + d_beta*d_y2;
+ }
+ return noutput_items;
+}
+
+double
+digital_impl_snr_est_m2m4::snr()
+{
+ double M2 = d_y1;
+ double M4 = d_y2;
+ double s = M2*(d_kw - 2) +
+ sqrt((4.0-d_ka*d_kw)*M2*M2 + M4*(d_ka+d_kw-4.0)) /
+ (d_ka + d_kw - 4.0);
+ double n = M2 - s;
+
+ return 10.0*log10(s / n);
+}
+
+
+/********************************************************************/
+
+
+digital_impl_mpsk_snr_est_svr::digital_impl_mpsk_snr_est_svr(
+ double alpha) :
+ digital_impl_mpsk_snr_est(alpha)
+{
+ d_y1 = 0;
+ d_y2 = 0;
+}
+
+int
+digital_impl_mpsk_snr_est_svr::update(
+ int noutput_items,
+ const gr_complex *in)
+{
+ for (int i = 0; i < noutput_items; i++){
+ double x = abs(in[i]);
+ double x1 = abs(in[i-1]);
+ double y1 = (x*x)*(x1*x1);
+ d_y1 = d_alpha*y1 + d_beta*d_y1;
+
+ double y2 = x*x*x*x;
+ d_y2 = d_alpha*y2 + d_beta*d_y2;
+ }
+ return noutput_items;
+}
+
+double
+digital_impl_mpsk_snr_est_svr::snr()
+{
+ double x = d_y1 / (d_y2 - d_y1);
+ return 10.0*log10(2.*((x-1) + sqrt(x*(x-1))));
+}
diff --git a/gr-digital/lib/digital_mpsk_snr_est_cc.cc b/gr-digital/lib/digital_mpsk_snr_est_cc.cc
new file mode 100644
index 000000000..b5a60f0d3
--- /dev/null
+++ b/gr-digital/lib/digital_mpsk_snr_est_cc.cc
@@ -0,0 +1,186 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <digital_mpsk_snr_est_cc.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+
+digital_mpsk_snr_est_cc_sptr
+digital_make_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples,
+ double alpha)
+{
+ return gnuradio::get_initial_sptr(new digital_mpsk_snr_est_cc(
+ type, tag_nsamples, alpha));
+}
+
+digital_mpsk_snr_est_cc::digital_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples,
+ double alpha)
+ : gr_sync_block ("mpsk_snr_est_cc",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex)))
+{
+ d_snr_est = NULL;
+
+ d_type = type;
+ d_nsamples = tag_nsamples;
+ d_count = 0;
+ set_alpha(alpha);
+
+ set_type(type);
+
+ // at least 1 estimator has to look back
+ set_history(2);
+
+ std::stringstream str;
+ str << name() << unique_id();
+ d_me = pmt::pmt_string_to_symbol(str.str());
+ d_key = pmt::pmt_string_to_symbol("snr");
+}
+
+digital_mpsk_snr_est_cc::~digital_mpsk_snr_est_cc()
+{
+ if(d_snr_est)
+ delete d_snr_est;
+}
+
+int
+digital_mpsk_snr_est_cc::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ // This is a pass-through block; copy input to output
+ memcpy(output_items[0], input_items[0],
+ noutput_items * sizeof(gr_complex));
+
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // Update, calculate, and issue an SNR tag every d_nsamples
+ int index = 0, x = 0;
+ int64_t nwritten = nitems_written(0);
+ while(index + (d_nsamples-d_count) <= noutput_items) {
+ x = d_nsamples - d_count;
+ nwritten += x;
+
+ // Update the SNR estimate registers from the current input
+ d_snr_est->update(x, &in[index]);
+
+ // Issue a tag with the SNR data
+ pmt::pmt_t pmt_snr = pmt::pmt_from_double(d_snr_est->snr());
+ add_item_tag(0, // stream ID
+ nwritten, // tag's sample number
+ d_key, // snr key
+ pmt_snr, // SNR
+ d_me); // block src id
+
+ index += x;
+ d_count = 0;
+ }
+
+ // Keep track of remaining items and update estimators
+ x = noutput_items - index;
+ d_count += x;
+ d_snr_est->update(x, &in[index]);
+
+ return noutput_items;
+}
+
+double
+digital_mpsk_snr_est_cc::snr()
+{
+ if(d_snr_est)
+ return d_snr_est->snr();
+ else
+ throw std::runtime_error("digital_mpsk_snr_est_cc:: No SNR estimator defined.\n");
+}
+
+snr_est_type_t
+digital_mpsk_snr_est_cc::type() const
+{
+ return d_type;
+}
+
+int
+digital_mpsk_snr_est_cc::tag_nsample() const
+{
+ return d_nsamples;
+}
+
+double
+digital_mpsk_snr_est_cc::alpha() const
+{
+ return d_alpha;
+}
+
+void
+digital_mpsk_snr_est_cc::set_type(snr_est_type_t t)
+{
+ d_type = t;
+
+ if(d_snr_est)
+ delete d_snr_est;
+
+ switch (d_type) {
+ case(SNR_EST_SIMPLE):
+ d_snr_est = new digital_impl_mpsk_snr_est_simple(d_alpha);
+ break;
+ case(SNR_EST_SKEW):
+ d_snr_est = new digital_impl_mpsk_snr_est_skew(d_alpha);
+ break;
+ case(SNR_EST_M2M4):
+ d_snr_est = new digital_impl_mpsk_snr_est_m2m4(d_alpha);
+ break;
+ case(SNR_EST_SVR):
+ d_snr_est = new digital_impl_mpsk_snr_est_svr(d_alpha);
+ break;
+ default:
+ throw std::invalid_argument("digital_mpsk_snr_est_cc: unknown type specified.\n");
+ }
+}
+
+void
+digital_mpsk_snr_est_cc::set_tag_nsample(int n)
+{
+ if(n > 0) {
+ d_nsamples = n;
+ d_count = 0; // reset state
+ }
+ else
+ throw std::invalid_argument("digital_mpsk_snr_est_cc: tag_nsamples can't be <= 0\n");
+}
+
+void
+digital_mpsk_snr_est_cc::set_alpha(double alpha)
+{
+ if((alpha >= 0) && (alpha <= 1.0)) {
+ d_alpha = alpha;
+ if(d_snr_est)
+ d_snr_est->set_alpha(d_alpha);
+ }
+ else
+ throw std::invalid_argument("digital_mpsk_snr_est_cc: alpha must be in [0,1]\n");
+}
diff --git a/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc b/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc
new file mode 100644
index 000000000..5cdfea96d
--- /dev/null
+++ b/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc
@@ -0,0 +1,152 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <digital_probe_mpsk_snr_est_c.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+
+digital_probe_mpsk_snr_est_c_sptr
+digital_make_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples,
+ double alpha)
+{
+ return gnuradio::get_initial_sptr(
+ new digital_probe_mpsk_snr_est_c(type, msg_nsamples, alpha));
+}
+
+digital_probe_mpsk_snr_est_c::digital_probe_mpsk_snr_est_c(
+ snr_est_type_t type,
+ int msg_nsamples,
+ double alpha)
+ : gr_sync_block ("probe_mpsk_snr_est_c",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0))
+{
+ d_snr_est = NULL;
+
+ d_type = type;
+ d_nsamples = msg_nsamples;
+ d_count = 0;
+ set_alpha(alpha);
+
+ set_type(type);
+
+ // at least 1 estimator has to look back
+ set_history(2);
+
+ d_key = pmt::pmt_string_to_symbol("snr");
+}
+
+digital_probe_mpsk_snr_est_c::~digital_probe_mpsk_snr_est_c()
+{
+ if(d_snr_est)
+ delete d_snr_est;
+}
+
+int
+digital_probe_mpsk_snr_est_c::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex*)input_items[0];
+ return d_snr_est->update(noutput_items, in);
+}
+
+double
+digital_probe_mpsk_snr_est_c::snr()
+{
+ if(d_snr_est)
+ return d_snr_est->snr();
+ else
+ throw std::runtime_error("digital_probe_mpsk_snr_est_c:: No SNR estimator defined.\n");
+}
+
+snr_est_type_t
+digital_probe_mpsk_snr_est_c::type() const
+{
+ return d_type;
+}
+
+int
+digital_probe_mpsk_snr_est_c::msg_nsample() const
+{
+ return d_nsamples;
+}
+
+double
+digital_probe_mpsk_snr_est_c::alpha() const
+{
+ return d_alpha;
+}
+
+void
+digital_probe_mpsk_snr_est_c::set_type(snr_est_type_t t)
+{
+ d_type = t;
+
+ if(d_snr_est)
+ delete d_snr_est;
+
+ switch (d_type) {
+ case(SNR_EST_SIMPLE):
+ d_snr_est = new digital_impl_mpsk_snr_est_simple(d_alpha);
+ break;
+ case(SNR_EST_SKEW):
+ d_snr_est = new digital_impl_mpsk_snr_est_skew(d_alpha);
+ break;
+ case(SNR_EST_M2M4):
+ d_snr_est = new digital_impl_mpsk_snr_est_m2m4(d_alpha);
+ break;
+ case(SNR_EST_SVR):
+ d_snr_est = new digital_impl_mpsk_snr_est_svr(d_alpha);
+ break;
+ default:
+ throw std::invalid_argument("digital_probe_mpsk_snr_est_c: unknown type specified.\n");
+ }
+}
+
+void
+digital_probe_mpsk_snr_est_c::set_msg_nsample(int n)
+{
+ if(n > 0) {
+ d_nsamples = n;
+ d_count = 0; // reset state
+ }
+ else
+ throw std::invalid_argument("digital_probe_mpsk_snr_est_c: msg_nsamples can't be <= 0\n");
+}
+
+void
+digital_probe_mpsk_snr_est_c::set_alpha(double alpha)
+{
+ if((alpha >= 0) && (alpha <= 1.0)) {
+ d_alpha = alpha;
+ if(d_snr_est)
+ d_snr_est->set_alpha(d_alpha);
+ }
+ else
+ throw std::invalid_argument("digital_probe_mpsk_snr_est_c: alpha must be in [0,1]\n");
+}
diff --git a/gr-digital/python/Makefile.am b/gr-digital/python/Makefile.am
index ead6f7dfd..42bcc4dd2 100644
--- a/gr-digital/python/Makefile.am
+++ b/gr-digital/python/Makefile.am
@@ -45,6 +45,7 @@ noinst_PYTHON = \
qa_fll_band_edge.py \
qa_lms_equalizer.py \
qa_mpsk_receiver.py \
+ qa_mpsk_snr_est.py \
qa_ofdm_insert_preamble.py
digital_PYTHON = \
diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py
index 088eb2b68..7d89bc9ea 100755
--- a/gr-digital/python/qa_fll_band_edge.py
+++ b/gr-digital/python/qa_fll_band_edge.py
@@ -46,6 +46,7 @@ class test_fll_band_edge_cc(gr_unittest.TestCase):
foffset = 0.2 / (2.0*math.pi)
# Create a set of 1's and -1's, pulse shape and interpolate to sps
+ random.seed(0)
data = [2.0*random.randint(0, 2) - 1.0 for i in xrange(200)]
self.src = gr.vector_source_c(data, False)
self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps)
diff --git a/gr-digital/python/qa_mpsk_snr_est.py b/gr-digital/python/qa_mpsk_snr_est.py
new file mode 100755
index 000000000..d392567bf
--- /dev/null
+++ b/gr-digital/python/qa_mpsk_snr_est.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import digital_swig as digital
+import math, random
+
+def get_cplx():
+ return complex(2*random.randint(0,1) - 1, 0)
+def get_n_cplx():
+ return complex(random.random()-0.5, random.random()-0.5)
+
+class test_mpsk_snr_est (gr_unittest.TestCase):
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ random.seed(0) # make repeatable
+ N = 10000
+ self._noise = [get_n_cplx() for i in xrange(N)]
+ self._bits = [get_cplx() for i in xrange(N)]
+
+ def tearDown (self):
+ self.tb = None
+
+ def mpsk_snr_est_setup (self, op):
+ result = []
+ for i in xrange(1,6):
+ src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)]
+
+ src = gr.vector_source_c (src_data)
+ dst = gr.null_sink (gr.sizeof_gr_complex)
+
+ tb = gr.top_block ()
+ tb.connect (src, op)
+ tb.connect (op, dst)
+ tb.run () # run the graph and wait for it to finish
+
+ result.append(op.snr())
+ return result
+
+ def test_mpsk_snr_est_simple (self):
+ expected_result = [11.48, 5.91, 3.30, 2.08, 1.46]
+
+ N = 10000
+ alpha = 0.001
+ op = digital.mpsk_snr_est_cc (digital.SNR_EST_SIMPLE, N, alpha)
+
+ actual_result = self.mpsk_snr_est_setup(op)
+ self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 2)
+
+ def test_mpsk_snr_est_skew (self):
+ expected_result = [11.48, 5.91, 3.30, 2.08, 1.46]
+
+ N = 10000
+ alpha = 0.001
+ op = digital.mpsk_snr_est_cc (digital.SNR_EST_SKEW, N, alpha)
+
+ actual_result = self.mpsk_snr_est_setup(op)
+ self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 2)
+
+ def test_mpsk_snr_est_m2m4 (self):
+ expected_result = [11.02, 6.20, 4.98, 5.16, 5.66]
+
+ N = 10000
+ alpha = 0.001
+ op = digital.mpsk_snr_est_cc (digital.SNR_EST_M2M4, N, alpha)
+
+ actual_result = self.mpsk_snr_est_setup(op)
+ self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 2)
+
+ def test_mpsk_snr_est_svn (self):
+ expected_result = [10.90, 6.00, 4.76, 4.97, 5.49]
+
+ N = 10000
+ alpha = 0.001
+ op = digital.mpsk_snr_est_cc (digital.SNR_EST_SVR, N, alpha)
+
+ actual_result = self.mpsk_snr_est_setup(op)
+ self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 2)
+
+ def test_probe_mpsk_snr_est_m2m4 (self):
+ expected_result = [11.02, 6.20, 4.98, 5.16, 5.66]
+
+ actual_result = []
+ for i in xrange(1,6):
+ src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)]
+
+ src = gr.vector_source_c (src_data)
+
+ N = 10000
+ alpha = 0.001
+ op = digital.probe_mpsk_snr_est_c (digital.SNR_EST_M2M4, N, alpha)
+
+ tb = gr.top_block ()
+ tb.connect (src, op)
+ tb.run () # run the graph and wait for it to finish
+
+ actual_result.append(op.snr())
+ self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 2)
+
+
+if __name__ == '__main__':
+ # Test various SNR estimators; we're not using a Gaussian
+ # noise source, so these estimates have no real meaning;
+ # just a sanity check.
+ gr_unittest.run(test_mpsk_snr_est, "test_mpsk_snr_est.xml")
+
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index dd6097286..6f2c2251a 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -59,12 +59,14 @@ install(
digital_lms_dd_equalizer_cc.i
digital_kurtotic_equalizer_cc.i
digital_mpsk_receiver_cc.i
+ digital_mpsk_snr_est_cc.i
digital_ofdm_cyclic_prefixer.i
digital_ofdm_frame_acquisition.i
digital_ofdm_frame_sink.i
digital_ofdm_insert_preamble.i
digital_ofdm_mapper_bcv.i
digital_ofdm_sampler.i
+ digital_probe_mpsk_snr_est_c.i
digital_gmskmod_bc.i
digital_cpmmod_bc.i
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
diff --git a/gr-digital/swig/Makefile.am b/gr-digital/swig/Makefile.am
index 8591c8d74..97b47fafa 100644
--- a/gr-digital/swig/Makefile.am
+++ b/gr-digital/swig/Makefile.am
@@ -84,12 +84,14 @@ digital_swig_swiginclude_headers = \
digital_lms_dd_equalizer_cc.i \
digital_kurtotic_equalizer_cc.i \
digital_mpsk_receiver_cc.i \
+ digital_mpsk_snr_est_cc.i \
digital_ofdm_cyclic_prefixer.i \
digital_ofdm_frame_acquisition.i \
digital_ofdm_frame_sink.i \
digital_ofdm_insert_preamble.i \
digital_ofdm_mapper_bcv.i \
digital_ofdm_sampler.i \
+ digital_probe_mpsk_snr_est_c.i \
digital_gmskmod_bc.i \
digital_cpmmod_bc.i \
$(TOP_SWIG_DOC_IFILES)
diff --git a/gr-digital/swig/digital_mpsk_snr_est_cc.i b/gr-digital/swig/digital_mpsk_snr_est_cc.i
new file mode 100644
index 000000000..f0ca13f87
--- /dev/null
+++ b/gr-digital/swig/digital_mpsk_snr_est_cc.i
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital,mpsk_snr_est_cc);
+
+digital_mpsk_snr_est_cc_sptr
+digital_make_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples=10000,
+ double alpha=0.001);
+
+class digital_mpsk_snr_est_cc : public gr_sync_block
+{
+private:
+ void digital_mpsk_snr_est_cc(snr_est_type_t type,
+ int tag_nsamples,
+ double alpha);
+
+public:
+ double snr();
+ snr_est_type_t type() const;
+ int tag_nsample() const;
+ double alpha() const;
+ void set_type(snr_est_type_t t);
+ void set_tag_nsample(int n);
+ void set_alpha(double alpha);
+};
diff --git a/gr-digital/swig/digital_probe_mpsk_snr_est_c.i b/gr-digital/swig/digital_probe_mpsk_snr_est_c.i
new file mode 100644
index 000000000..93db4127a
--- /dev/null
+++ b/gr-digital/swig/digital_probe_mpsk_snr_est_c.i
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital,probe_mpsk_snr_est_c);
+
+digital_probe_mpsk_snr_est_c_sptr
+digital_make_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples=10000,
+ double alpha=0.001);
+
+class digital_probe_mpsk_snr_est_c : public gr_sync_block
+{
+private:
+ void digital_probe_mpsk_snr_est_c(snr_est_type_t type,
+ int msg_nsamples,
+ double alpha);
+
+public:
+ double snr();
+ snr_est_type_t type() const;
+ int msg_nsample() const;
+ double alpha() const;
+ void set_type(snr_est_type_t t);
+ void set_msg_nsample(int n);
+ void set_alpha(double alpha);
+};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 86b5cab13..a39ef9ab7 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -24,6 +24,15 @@
//load generated python docstrings
%include "digital_swig_doc.i"
+#if SWIGPYTHON
+enum snr_est_type_t {
+ SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB)
+ SNR_EST_SKEW, // Skewness-base est (>= 5 dB)
+ SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB)
+ SNR_EST_SVR // SVR-based est (>= 0dB)
+};
+#endif
+
%include <gri_control_loop.i>
%{
@@ -41,12 +50,14 @@
#include "digital_kurtotic_equalizer_cc.h"
#include "digital_lms_dd_equalizer_cc.h"
#include "digital_mpsk_receiver_cc.h"
+#include "digital_mpsk_snr_est_cc.h"
#include "digital_ofdm_cyclic_prefixer.h"
#include "digital_ofdm_frame_acquisition.h"
#include "digital_ofdm_frame_sink.h"
#include "digital_ofdm_insert_preamble.h"
#include "digital_ofdm_mapper_bcv.h"
#include "digital_ofdm_sampler.h"
+#include "digital_probe_mpsk_snr_est_c.h"
#include "digital_cpmmod_bc.h"
#include "digital_gmskmod_bc.h"
%}
@@ -65,16 +76,26 @@
%include "digital_kurtotic_equalizer_cc.i"
%include "digital_lms_dd_equalizer_cc.i"
%include "digital_mpsk_receiver_cc.i"
+%include "digital_mpsk_snr_est_cc.i"
%include "digital_ofdm_cyclic_prefixer.i"
%include "digital_ofdm_frame_acquisition.i"
%include "digital_ofdm_frame_sink.i"
%include "digital_ofdm_insert_preamble.i"
%include "digital_ofdm_mapper_bcv.i"
%include "digital_ofdm_sampler.i"
+%include "digital_probe_mpsk_snr_est_c.i"
%include "digital_cpmmod_bc.i"
%include "digital_gmskmod_bc.i"
#if SWIGGUILE
+
+enum snr_est_type_t {
+ SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB)
+ SNR_EST_SKEW, // Skewness-base est (>= 5 dB)
+ SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB)
+ SNR_EST_SVR // SVR-based est (>= 0dB)
+};
+
%scheme %{
(load-extension-global "libguile-gnuradio-digital_swig" "scm_init_gnuradio_digital_swig_module")
%}
diff --git a/gr-howto-write-a-block/config.guess b/gr-howto-write-a-block/config.guess
index 8152efd67..49ba16f15 100755
--- a/gr-howto-write-a-block/config.guess
+++ b/gr-howto-write-a-block/config.guess
@@ -2,9 +2,9 @@
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2011-11-11'
+timestamp='2012-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -57,8 +57,8 @@ GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -145,7 +145,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -897,16 +897,16 @@ EOF
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
- echo cris-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
frv:Linux:*:*)
- echo frv-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
hexagon:Linux:*:*)
- echo hexagon-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
LIBC=gnu
@@ -948,7 +948,7 @@ EOF
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
- echo or32-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
@@ -989,7 +989,7 @@ EOF
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
diff --git a/gr-howto-write-a-block/config.sub b/gr-howto-write-a-block/config.sub
index e76eaf472..d6b6b3c76 100755
--- a/gr-howto-write-a-block/config.sub
+++ b/gr-howto-write-a-block/config.sub
@@ -2,9 +2,9 @@
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2011-11-11'
+timestamp='2012-01-01'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -76,8 +76,8 @@ version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -320,7 +320,6 @@ case $basic_machine in
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | picochip)
- # Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -719,7 +718,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -1559,9 +1557,6 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
diff --git a/gr-howto-write-a-block/version.sh b/gr-howto-write-a-block/version.sh
index 4e4c7cc31..58ec712f6 100644
--- a/gr-howto-write-a-block/version.sh
+++ b/gr-howto-write-a-block/version.sh
@@ -1,4 +1,4 @@
MAJOR_VERSION=3
API_COMPAT=5
MINOR_VERSION=1
-MAINT_VERSION=git
+MAINT_VERSION=0
diff --git a/gr-noaa/CMakeLists.txt b/gr-noaa/CMakeLists.txt
index 621dd5d6e..a3a5d56db 100644
--- a/gr-noaa/CMakeLists.txt
+++ b/gr-noaa/CMakeLists.txt
@@ -84,4 +84,18 @@ if(ENABLE_PYTHON)
add_subdirectory(apps)
endif(ENABLE_PYTHON)
+########################################################################
+# Create Pkg Config File
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-noaa.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-noaa.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-noaa.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "noaa_devel"
+)
+
endif(ENABLE_GR_NOAA)
diff --git a/gr-noaa/Makefile.am b/gr-noaa/Makefile.am
index 854ce1476..ce5f66109 100644
--- a/gr-noaa/Makefile.am
+++ b/gr-noaa/Makefile.am
@@ -27,3 +27,5 @@ if PYTHON
SUBDIRS += swig python apps
endif
+pkgconfigdir = $(libdir)/pkgconfig
+dist_pkgconfig_DATA = gnuradio-noaa.pc
diff --git a/gr-noaa/gnuradio-noaa.pc.in b/gr-noaa/gnuradio-noaa.pc.in
new file mode 100644
index 000000000..cacfeecca
--- /dev/null
+++ b/gr-noaa/gnuradio-noaa.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnuradio-noaa
+Description: GNU Radio blocks implementing a NOAA satellite protocols
+Requires: gnuradio-core
+Version: @LIBVER@
+Libs: -L${libdir} -lgnuradio-noaa
+Cflags: -I${includedir}
diff --git a/gr-uhd/apps/uhd_fft.py b/gr-uhd/apps/uhd_fft.py
index a9bb1435e..f311a903b 100755
--- a/gr-uhd/apps/uhd_fft.py
+++ b/gr-uhd/apps/uhd_fft.py
@@ -48,7 +48,7 @@ class app_top_block(stdgui2.std_top_block):
parser.add_option("-a", "--args", type="string", default="",
help="UHD device address args , [default=%default]")
parser.add_option("", "--spec", type="string", default=None,
- help="Subdevice of UHD device where appropriate")
+ help="Subdevice of UHD device where appropriate")
parser.add_option("-A", "--antenna", type="string", default=None,
help="select Rx Antenna where appropriate")
parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6,
@@ -61,25 +61,31 @@ class app_top_block(stdgui2.std_top_block):
help="Enable waterfall display")
parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
help="Enable oscilloscope display")
- parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
- help="Set fftsink averaging factor, default=[%default]")
- parser.add_option ("", "--averaging", action="store_true", default=False,
+ parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1,
+ help="Set fftsink averaging factor, default=[%default]")
+ parser.add_option ("", "--averaging", action="store_true", default=False,
help="Enable fftsink averaging, default=[%default]")
- parser.add_option("", "--ref-scale", type="eng_float", default=1.0,
- help="Set dBFS=0dB input value, default=[%default]")
- parser.add_option("--fft-size", type="int", default=1024,
+ parser.add_option("", "--ref-scale", type="eng_float", default=1.0,
+ help="Set dBFS=0dB input value, default=[%default]")
+ parser.add_option("", "--fft-size", type="int", default=1024,
help="Set number of FFT bins [default=%default]")
- parser.add_option("--fft-rate", type="int", default=30,
+ parser.add_option("", "--fft-rate", type="int", default=30,
help="Set FFT update rate, [default=%default]")
+ parser.add_option("", "--wire-format", type="string", default="sc16",
+ help="Set wire format from USRP [default=%default]")
+ parser.add_option("", "--scalar", type="int", default=1024,
+ help="Set scalar multiplier value sc8 wire format [default=%default]")
(options, args) = parser.parse_args()
if len(args) != 0:
parser.print_help()
sys.exit(1)
- self.options = options
+ self.options = options
self.show_debug_info = True
+ scalar="scalar="+str(options.scalar)
self.u = uhd.usrp_source(device_addr=options.args,
- stream_args=uhd.stream_args('fc32'))
+ stream_args=uhd.stream_args(cpu_format='fc32',
+ otw_format=options.wire_format, args=scalar))
# Set the subdevice spec
if(options.spec):
@@ -104,20 +110,20 @@ class app_top_block(stdgui2.std_top_block):
self.scope = fftsink2.fft_sink_c (panel,
fft_size=options.fft_size,
sample_rate=input_rate,
- ref_scale=options.ref_scale,
+ ref_scale=options.ref_scale,
ref_level=20.0,
y_divs = 12,
average=options.averaging,
- avg_alpha=options.avg_alpha,
+ avg_alpha=options.avg_alpha,
fft_rate=options.fft_rate)
self.frame.SetMinSize((800, 420))
self.connect(self.u, self.scope)
self._build_gui(vbox)
- self._setup_events()
+ self._setup_events()
-
+
# set initial values
if options.gain is None:
@@ -162,18 +168,18 @@ class app_top_block(stdgui2.std_top_block):
hbox.Add((5,0), 0, 0)
g = self.u.get_gain_range()
- # some configurations don't have gain control
- if g.stop() > g.start():
- myform['gain'] = form.slider_field(parent=self.panel,
- sizer=hbox, label="Gain",
- weight=3,
- min=int(g.start()), max=int(g.stop()),
- callback=self.set_gain)
+ # some configurations don't have gain control
+ if g.stop() > g.start():
+ myform['gain'] = form.slider_field(parent=self.panel,
+ sizer=hbox, label="Gain",
+ weight=3,
+ min=int(g.start()), max=int(g.stop()),
+ callback=self.set_gain)
- hbox.Add((5,0), 0, 0)
- vbox.Add(hbox, 0, wx.EXPAND)
+ hbox.Add((5,0), 0, 0)
+ vbox.Add(hbox, 0, wx.EXPAND)
- self._build_subpanel(vbox)
+ self._build_subpanel(vbox)
def _build_subpanel(self, vbox_arg):
# build a secondary information panel (sometimes hidden)
@@ -223,15 +229,15 @@ class app_top_block(stdgui2.std_top_block):
self.myform['freq'].set_value(self.u.get_center_freq())
self.myform['rffreq'].set_value(r.actual_rf_freq)
self.myform['dspfreq'].set_value(r.actual_dsp_freq)
- if not self.options.oscilloscope:
- self.scope.set_baseband_freq(target_freq)
- return True
+ if not self.options.oscilloscope:
+ self.scope.set_baseband_freq(target_freq)
+ return True
return False
def set_gain(self, gain):
- if self.myform.has_key('gain'):
- self.myform['gain'].set_value(gain) # update displayed value
+ if self.myform.has_key('gain'):
+ self.myform['gain'].set_value(gain) # update displayed value
self.u.set_gain(gain, 0)
def set_samp_rate(self, samp_rate):
@@ -245,31 +251,32 @@ class app_top_block(stdgui2.std_top_block):
return True
def _setup_events(self):
- if not self.options.waterfall and not self.options.oscilloscope:
- self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick)
-
+ if not self.options.waterfall and not self.options.oscilloscope:
+ self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick)
+
def evt_left_dclick(self, event):
- (ux, uy) = self.scope.win.GetXY(event)
- if event.CmdDown():
- # Re-center on maximum power
- points = self.scope.win._points
- if self.scope.win.peak_hold:
- if self.scope.win.peak_vals is not None:
- ind = numpy.argmax(self.scope.win.peak_vals)
- else:
- ind = int(points.shape()[0]/2)
- else:
- ind = numpy.argmax(points[:,1])
+ (ux, uy) = self.scope.win.GetXY(event)
+ if event.CmdDown():
+ # Re-center on maximum power
+ points = self.scope.win._points
+ if self.scope.win.peak_hold:
+ if self.scope.win.peak_vals is not None:
+ ind = numpy.argmax(self.scope.win.peak_vals)
+ else:
+ ind = int(points.shape()[0]/2)
+ else:
+ ind = numpy.argmax(points[:,1])
+
(freq, pwr) = points[ind]
- target_freq = freq/self.scope.win._scale_factor
- print ind, freq, pwr
+ target_freq = freq/self.scope.win._scale_factor
+ print ind, freq, pwr
self.set_freq(target_freq)
- else:
- # Re-center on clicked frequency
- target_freq = ux/self.scope.win._scale_factor
- self.set_freq(target_freq)
-
-
+ else:
+ # Re-center on clicked frequency
+ target_freq = ux/self.scope.win._scale_factor
+ self.set_freq(target_freq)
+
+
def main ():
app = stdgui2.stdapp(app_top_block, "UHD FFT", nstatus=1)
app.MainLoop()
diff --git a/gr-uhd/apps/uhd_rx_cfile.py b/gr-uhd/apps/uhd_rx_cfile.py
index ea2aad8fe..de44d4f56 100755
--- a/gr-uhd/apps/uhd_rx_cfile.py
+++ b/gr-uhd/apps/uhd_rx_cfile.py
@@ -39,12 +39,15 @@ class rx_cfile_block(gr.top_block):
def __init__(self, options, filename):
gr.top_block.__init__(self)
+ scalar="scalar="+str(options.scalar)
# Create a UHD device source
if options.output_shorts:
- self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('sc16'))
+ self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('sc16',
+ options.wire_format, args=scalar))
self._sink = gr.file_sink(gr.sizeof_short*2, filename)
else:
- self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32'))
+ self._u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32',
+ options.wire_format, args=scalar))
self._sink = gr.file_sink(gr.sizeof_gr_complex, filename)
# Set the subdevice spec
@@ -127,6 +130,10 @@ def get_options():
help="verbose output")
parser.add_option("", "--lo-offset", type="eng_float", default=None,
help="set daughterboard LO offset to OFFSET [default=hw default]")
+ parser.add_option("", "--wire-format", type="string", default="sc16",
+ help="set wire format from USRP [default=%default")
+ parser.add_option("", "--scalar", type="int", default=1024,
+ help="set scalar multiplier value for sc8 wire format [default=%default]")
(options, args) = parser.parse_args ()
if len(args) != 1:
diff --git a/gr-uhd/include/gr_uhd_usrp_source.h b/gr-uhd/include/gr_uhd_usrp_source.h
index e9fc41b93..8a799b397 100644
--- a/gr-uhd/include/gr_uhd_usrp_source.h
+++ b/gr-uhd/include/gr_uhd_usrp_source.h
@@ -455,6 +455,15 @@ public:
* \return the multi usrp device object
*/
virtual uhd::usrp::multi_usrp::sptr get_device(void) = 0;
+
+ /*!
+ * Convenience function for finite data acquisition.
+ * This is not to be used with the scheduler; rather,
+ * one can request samples from the USRP in python.
+ * //TODO multi-channel
+ * //TODO assumes fc32
+ */
+ virtual std::vector<std::complex<float> > finite_acquisition(const size_t nsamps) = 0;
};
#endif /* INCLUDED_GR_UHD_USRP_SOURCE_H */
diff --git a/gr-uhd/lib/gr_uhd_usrp_source.cc b/gr-uhd/lib/gr_uhd_usrp_source.cc
index 51a756908..2244238bd 100644
--- a/gr-uhd/lib/gr_uhd_usrp_source.cc
+++ b/gr-uhd/lib/gr_uhd_usrp_source.cc
@@ -409,6 +409,25 @@ public:
return true;
}
+ std::vector<std::complex<float> > finite_acquisition(const size_t nsamps){
+ #ifdef GR_UHD_USE_STREAM_API
+ uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
+ cmd.num_samps = nsamps;
+ cmd.stream_now = true;
+ _dev->issue_stream_cmd(cmd);
+
+ std::vector<std::complex<float> > samps(nsamps);
+ const size_t actual_num_samps = _rx_stream->recv(
+ &samps.front(), nsamps, _metadata, 0.1
+ );
+ samps.resize(actual_num_samps);
+
+ return samps;
+ #else
+ throw std::runtime_error("not implemented in this version");
+ #endif
+ }
+
private:
uhd::usrp::multi_usrp::sptr _dev;
const uhd::stream_args_t _stream_args;
diff --git a/gr-wxgui/src/python/stdgui2.py b/gr-wxgui/src/python/stdgui2.py
index e510f174c..f397fd01e 100644
--- a/gr-wxgui/src/python/stdgui2.py
+++ b/gr-wxgui/src/python/stdgui2.py
@@ -27,23 +27,27 @@ from gnuradio import gr
class stdapp (wx.App):
- def __init__ (self, top_block_maker, title="GNU Radio", nstatus=2):
+ def __init__ (self, top_block_maker, title="GNU Radio", nstatus=2,
+ max_noutput_items=None):
self.top_block_maker = top_block_maker
self.title = title
self._nstatus = nstatus
+ self._max_noutput_items = max_noutput_items
# All our initialization must come before calling wx.App.__init__.
# OnInit is called from somewhere in the guts of __init__.
wx.App.__init__ (self, redirect=False)
def OnInit (self):
- frame = stdframe (self.top_block_maker, self.title, self._nstatus)
+ frame = stdframe (self.top_block_maker, self.title, self._nstatus,
+ self._max_noutput_items)
frame.Show (True)
self.SetTopWindow (frame)
return True
class stdframe (wx.Frame):
- def __init__ (self, top_block_maker, title="GNU Radio", nstatus=2):
+ def __init__ (self, top_block_maker, title="GNU Radio", nstatus=2,
+ max_nouts=None):
# print "stdframe.__init__"
wx.Frame.__init__(self, None, -1, title)
@@ -57,7 +61,7 @@ class stdframe (wx.Frame):
self.SetMenuBar (mainmenu)
self.Bind (wx.EVT_CLOSE, self.OnCloseWindow)
- self.panel = stdpanel (self, self, top_block_maker)
+ self.panel = stdpanel (self, self, top_block_maker, max_nouts)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel, 1, wx.EXPAND)
self.SetSizer(vbox)
@@ -72,7 +76,8 @@ class stdframe (wx.Frame):
return self.panel.top_block
class stdpanel (wx.Panel):
- def __init__ (self, parent, frame, top_block_maker):
+ def __init__ (self, parent, frame, top_block_maker,
+ max_nouts=None):
# print "stdpanel.__init__"
wx.Panel.__init__ (self, parent, -1)
self.frame = frame
@@ -83,7 +88,10 @@ class stdpanel (wx.Panel):
self.SetAutoLayout (True)
vbox.Fit (self)
- self.top_block.start ()
+ if(max_nouts is not None):
+ self.top_block.start (max_nouts)
+ else:
+ self.top_block.start ()
class std_top_block (gr.top_block):
def __init__ (self, parent, panel, vbox, argv):
diff --git a/gruel/src/include/gruel/high_res_timer.h b/gruel/src/include/gruel/high_res_timer.h
index 9be524624..63841f612 100644
--- a/gruel/src/include/gruel/high_res_timer.h
+++ b/gruel/src/include/gruel/high_res_timer.h
@@ -46,7 +46,7 @@ namespace gruel {
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#define GRUEL_HRT_USE_MACH_ABSOLUTE_TIME
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
- #define GRUEL_HRT_USE_MACH_ABSOLUTE_TIME
+ #define GRUEL_HRT_USE_CLOCK_GETTIME
#else
#define GRUEL_HRT_USE_MICROSEC_CLOCK
#endif
diff --git a/version.sh b/version.sh
index 4e4c7cc31..58ec712f6 100644
--- a/version.sh
+++ b/version.sh
@@ -1,4 +1,4 @@
MAJOR_VERSION=3
API_COMPAT=5
MINOR_VERSION=1
-MAINT_VERSION=git
+MAINT_VERSION=0
diff --git a/volk/include/volk/volk_16i_max_star_16i_a.h b/volk/include/volk/volk_16i_max_star_16i_a.h
index 6a4f63708..28197ddef 100644
--- a/volk/include/volk/volk_16i_max_star_16i_a.h
+++ b/volk/include/volk/volk_16i_max_star_16i_a.h
@@ -18,7 +18,7 @@ static inline void volk_16i_max_star_16i_a_ssse3(short* target, short* src0, un
short candidate = src0[0];
short cands[8];
- __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6;
+ __m128i xmm0, xmm1, xmm3, xmm4, xmm5, xmm6;
__m128i *p_src0;
@@ -41,7 +41,7 @@ static inline void volk_16i_max_star_16i_a_ssse3(short* target, short* src0, un
for(i = 0; i < bound; ++i) {
xmm1 = _mm_load_si128(p_src0);
p_src0 += 1;
- xmm2 = _mm_sub_epi16(xmm1, xmm0);
+ //xmm2 = _mm_sub_epi16(xmm1, xmm0);
diff --git a/volk/include/volk/volk_32f_s32f_stddev_32f_a.h b/volk/include/volk/volk_32f_s32f_stddev_32f_a.h
index 881067bdc..75fe0cb2e 100644
--- a/volk/include/volk/volk_32f_s32f_stddev_32f_a.h
+++ b/volk/include/volk/volk_32f_s32f_stddev_32f_a.h
@@ -60,7 +60,7 @@ static inline void volk_32f_s32f_stddev_32f_a_sse4_1(float* stddev, const float*
}
returnValue /= num_points;
returnValue -= (mean * mean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
}
@@ -106,7 +106,7 @@ static inline void volk_32f_s32f_stddev_32f_a_sse(float* stddev, const float* in
}
returnValue /= num_points;
returnValue -= (mean * mean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
}
@@ -133,7 +133,7 @@ static inline void volk_32f_s32f_stddev_32f_a_generic(float* stddev, const float
returnValue /= num_points;
returnValue -= (mean * mean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
}
diff --git a/volk/include/volk/volk_32f_stddev_and_mean_32f_x2_a.h b/volk/include/volk/volk_32f_stddev_and_mean_32f_x2_a.h
index 3a82e3d2f..20ff676d8 100644
--- a/volk/include/volk/volk_32f_stddev_and_mean_32f_x2_a.h
+++ b/volk/include/volk/volk_32f_stddev_and_mean_32f_x2_a.h
@@ -72,7 +72,7 @@ static inline void volk_32f_stddev_and_mean_32f_x2_a_sse4_1(float* stddev, float
newMean /= num_points;
returnValue /= num_points;
returnValue -= (newMean * newMean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
*mean = newMean;
@@ -128,7 +128,7 @@ static inline void volk_32f_stddev_and_mean_32f_x2_a_sse(float* stddev, float* m
newMean /= num_points;
returnValue /= num_points;
returnValue -= (newMean * newMean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
*mean = newMean;
@@ -157,7 +157,7 @@ static inline void volk_32f_stddev_and_mean_32f_x2_a_generic(float* stddev, floa
newMean /= num_points;
returnValue /= num_points;
returnValue -= (newMean * newMean);
- returnValue = sqrt(returnValue);
+ returnValue = sqrtf(returnValue);
}
*stddev = returnValue;
*mean = newMean;
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt
index 092c3ba0d..00d8660ab 100644
--- a/volk/lib/CMakeLists.txt
+++ b/volk/lib/CMakeLists.txt
@@ -85,7 +85,17 @@ execute_process(
#set the various overrule values (see archs.xml)
#a lot of this is translating between automake and cmake
if(NOT "${CROSSCOMPILE_MULTILIB}" STREQUAL "true")
- set(MD_SUBCPU ${CMAKE_HOST_SYSTEM_PROCESSOR})
+ set(MD_SUBCPU ${CMAKE_SYSTEM_PROCESSOR})
+ #detect 32 or 64 bit compiler
+ if(MD_SUBCPU MATCHES "^(i.86|x86|x86_64|amd64)$")
+ include(CheckTypeSize)
+ check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY)
+ if (${SIZEOF_VOID_P} EQUAL 8)
+ set(MD_SUBCPU x86_64)
+ else()
+ set(MD_SUBCPU x86)
+ endif()
+ endif()
endif()
if(NOT "${ORC_FOUND}" STREQUAL "TRUE")
set(LV_HAVE_ORC "no")
@@ -267,7 +277,7 @@ if(ORC_FOUND)
#create a rule to generate the source and add to the list of sources
add_custom_command(
- COMMAND ${ORCC_EXECUTABLE} --implementation -o ${orcc_gen} ${orc_file}
+ COMMAND ${ORCC_EXECUTABLE} --include math.h --implementation -o ${orcc_gen} ${orc_file}
DEPENDS ${orc_file} OUTPUT ${orcc_gen}
)
list(APPEND volk_sources ${orcc_gen})
diff --git a/volk/orc/volk_16ic_magnitude_16i_a_orc_impl.orc b/volk/orc/volk_16ic_magnitude_16i_a_orc_impl.orc
index 3966526ed..fbaebc46d 100644
--- a/volk/orc/volk_16ic_magnitude_16i_a_orc_impl.orc
+++ b/volk/orc/volk_16ic_magnitude_16i_a_orc_impl.orc
@@ -17,7 +17,7 @@ x2 divf iqf, iqf, scalar
x2 mulf prodiqf, iqf, iqf
splitql qf, if, prodiqf
addf sumf, if, qf
-sqrt, sqrtf rootf, sumf
+sqrtf rootf, sumf
mulf rootf, rootf, scalar
convfl rootl, rootf
convlw dst, rootl
diff --git a/volk/orc/volk_16sc_magnitude_32f_aligned16_orc_impl.orc b/volk/orc/volk_16sc_magnitude_32f_aligned16_orc_impl.orc
index d5c8212c3..66fef7d2e 100644
--- a/volk/orc/volk_16sc_magnitude_32f_aligned16_orc_impl.orc
+++ b/volk/orc/volk_16sc_magnitude_32f_aligned16_orc_impl.orc
@@ -22,4 +22,4 @@ divf imagf, imagf, scalar
mulf realf, realf, realf
mulf imagf, imagf, imagf
addf sumf, realf, imagf
-sqrt, sqrtf dst, sumf
+sqrtf dst, sumf
diff --git a/volk/orc/volk_32f_sqrt_32f_a_orc_impl.orc b/volk/orc/volk_32f_sqrt_32f_a_orc_impl.orc
index 719cca037..f339b1122 100644
--- a/volk/orc/volk_32f_sqrt_32f_a_orc_impl.orc
+++ b/volk/orc/volk_32f_sqrt_32f_a_orc_impl.orc
@@ -1,4 +1,4 @@
.function volk_32f_sqrt_32f_a_orc_impl
.source 4 src
.dest 4 dst
-sqrt, sqrtf dst, src
+sqrtf dst, src
diff --git a/volk/orc/volk_32fc_magnitude_32f_a_orc_impl.orc b/volk/orc/volk_32fc_magnitude_32f_a_orc_impl.orc
index 4fc0642fc..032ab2b1b 100644
--- a/volk/orc/volk_32fc_magnitude_32f_a_orc_impl.orc
+++ b/volk/orc/volk_32fc_magnitude_32f_a_orc_impl.orc
@@ -10,4 +10,4 @@
x2 mulf prodiqf, src, src
splitql qf, if, prodiqf
addf sumf, if, qf
-sqrt, sqrtf dst, sumf
+sqrtf dst, sumf
diff --git a/volk/orc/volk_32fc_s32f_magnitude_16i_a_orc_impl.orc b/volk/orc/volk_32fc_s32f_magnitude_16i_a_orc_impl.orc
index ed89c3d18..d3bf78935 100644
--- a/volk/orc/volk_32fc_s32f_magnitude_16i_a_orc_impl.orc
+++ b/volk/orc/volk_32fc_s32f_magnitude_16i_a_orc_impl.orc
@@ -14,7 +14,7 @@
x2 mulf prodiqf, src, src
splitql qf, if, prodiqf
addf sumf, if, qf
-sqrt, sqrtf rootf, sumf
+sqrtf rootf, sumf
mulf rootf, rootf, scalar
#cmpltf maskl, 32768.0, rootf
#andl maskl, maskl, 0x80000000
diff --git a/volk/orc/volk_8i_convert_16i_a_orc_impl.orc b/volk/orc/volk_8i_convert_16i_a_orc_impl.orc
index d813c6cfa..17198bf1e 100644
--- a/volk/orc/volk_8i_convert_16i_a_orc_impl.orc
+++ b/volk/orc/volk_8i_convert_16i_a_orc_impl.orc
@@ -1,5 +1,6 @@
.function volk_8i_convert_16i_a_orc_impl
.source 1 src
.dest 2 dst
-convsbw dst, src
-shlw dst, dst, 8
+.temp 2 tmp
+convsbw tmp, src
+shlw dst, tmp, 8