diff options
45 files changed, 810 insertions, 285 deletions
diff --git a/config/ax_boost_base.m4 b/config/ax_boost_base.m4 index e9790227e..e9d42ee9a 100644 --- a/config/ax_boost_base.m4 +++ b/config/ax_boost_base.m4 @@ -276,7 +276,7 @@ AC_DEFUN([_AX_BOOST_CHECK_LIB_],[ dnl $1 is unit name. E.g., boost_thread AC_DEFUN([_AX_BOOST_WITH],[ - _AX_BOOST_WITH_($1,m4_bpatsubst($1,_,-)) + _AX_BOOST_WITH_([$1], [m4_bpatsubst($1,_,-)]) ]) dnl $1 is unit name. E.g., boost_thread @@ -315,9 +315,9 @@ AC_DEFUN([_AX_BOOST_CHECK_],[ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" AC_CACHE_CHECK([whether the boost::m4_substr([$1],6) includes are available], [$4], [AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE(AC_LANG_PROGRAM([$2],[$3]),[$4]=yes,[$4]=no) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$2],[$3])], [[$4]=yes], [[$4]=no]) AC_LANG_POP([C++]) - ]) + ]) if test "$[$4]" = "yes"; then _AX_BOOST_CHECK_LIB([$1]) fi @@ -330,5 +330,5 @@ dnl $1 is unit name. E.g., boost_thread dnl $2 is AC_LANG_PROGRAM argument 1 dnl $3 is AC_LANG_PROGRAM argument 2 AC_DEFUN([_AX_BOOST_CHECK],[ - _AX_BOOST_CHECK_($1,$2,$3,ax_cv_$1) + _AX_BOOST_CHECK_([$1], [$2], [$3], [ax_cv_$1]) ]) diff --git a/config/ax_boost_python.m4 b/config/ax_boost_python.m4 index 3c6c666f7..59c86ad0e 100644 --- a/config/ax_boost_python.m4 +++ b/config/ax_boost_python.m4 @@ -65,14 +65,14 @@ ac_cv_boost_python, if test x$PYTHON_INCLUDE_DIR != x; then CPPFLAGS=-I$PYTHON_INCLUDE_DIR $CPPFLAGS fi - AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <boost/python/module.hpp> using namespace boost::python; BOOST_PYTHON_MODULE(test) { throw "Boost::Python test."; }]], - [[return 0;]]), - ac_cv_boost_python=yes, ac_cv_boost_python=no) + [[return 0;]])], + [ac_cv_boost_python=yes, ac_cv_boost_python=no) AC_LANG_RESTORE - CPPFLAGS=$CPPFLAGS_SAVE + CPPFLAGS=$CPPFLAGS_SAVE] ]) if test "$ac_cv_boost_python" = "yes"; then AC_LANG_PUSH([C++]) diff --git a/config/ax_boost_thread.m4 b/config/ax_boost_thread.m4 index 4df23224a..8e42510ea 100644 --- a/config/ax_boost_thread.m4 +++ b/config/ax_boost_thread.m4 @@ -46,19 +46,19 @@ AC_DEFUN([AX_BOOST_THREAD], LDFLAGS="$LDFLAGS $BOOST_LDFLAGS $PTHREAD_LIBS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" - AC_CACHE_CHECK(whether the boost::thread includes are available, - ax_cv_boost_thread, + AC_CACHE_CHECK([whether the boost::thread includes are available], + [ax_cv_boost_thread], [AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]], [[boost::thread_group thrds; - return 0;]]), - ax_cv_boost_thread=yes, ax_cv_boost_thread=no) + return 0;]])], + [ax_cv_boost_thread=yes], [ax_cv_boost_thread=no]) AC_LANG_POP([C++]) ]) if test "$ax_cv_boost_thread" = "yes"; then BOOST_CXXFLAGS="$PTHREAD_CFLAGS" - AC_SUBST(BOOST_CXXFLAGS) + AC_SUBST([BOOST_CXXFLAGS]) _AX_BOOST_CHECK_LIB([boost_thread]) if test "$link_ok" = "yes" && test -n "$PTHREAD_LIBS"; then BOOST_THREAD_LIB="$BOOST_THREAD_LIB $PTHREAD_LIBS" diff --git a/config/gr_check_createfilemapping.m4 b/config/gr_check_createfilemapping.m4 index 5f9b4a49a..a7e290dd3 100644 --- a/config/gr_check_createfilemapping.m4 +++ b/config/gr_check_createfilemapping.m4 @@ -25,7 +25,7 @@ dnl ]) AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],[ AC_MSG_CHECKING([for CreateFileMapping function]) - AC_COMPILE_IFELSE([ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include <windows.h> int main (int argc, char **argv) { @@ -41,12 +41,13 @@ int main (int argc, char **argv) seg_name); // name of mapping object return 0; } -],[HAVE_CREATEFILEMAPPING=yes - AC_DEFINE(HAVE_CREATEFILEMAPPING,[1],[Define if you have the CreateFilemapping function(win32).])], +])],[HAVE_CREATEFILEMAPPING=yes + AC_DEFINE([HAVE_CREATEFILEMAPPING],[1], + [Define if you have the CreateFilemapping function(win32).])], [HAVE_CREATEFILEMAPPING=no]) - AC_MSG_RESULT($HAVE_CREATEFILEMAPPING) - AM_CONDITIONAL(HAVE_CREATEFILEMAPPING, test x$HAVE_CREATEFILEMAPPING = xyes) + AC_MSG_RESULT([$HAVE_CREATEFILEMAPPING]) + AM_CONDITIONAL([HAVE_CREATEFILEMAPPING], [test x$HAVE_CREATEFILEMAPPING = xyes]) ]) diff --git a/config/gr_lib64.m4 b/config/gr_lib64.m4 index 751f774b4..92f1bd917 100644 --- a/config/gr_lib64.m4 +++ b/config/gr_lib64.m4 @@ -40,7 +40,7 @@ AC_DEFUN([GR_LIB64],[ AC_MSG_CHECKING([gr_libdir_suffix]) gr_libdir_suffix="" - AC_SUBST(gr_libdir_suffix) + AC_SUBST([gr_libdir_suffix]) case "$host_os" in linux*) is_linux=yes ;; diff --git a/config/gr_qwt.m4 b/config/gr_qwt.m4 index 537348ac6..035e94091 100644 --- a/config/gr_qwt.m4 +++ b/config/gr_qwt.m4 @@ -61,7 +61,7 @@ AC_DEFUN([GR_QWT], if test "$qwt_incdir" = "" ; then dnl check qwt-qt4/qwt.h (as in Ubuntu) AC_CHECK_HEADER( - [qwt-qt4/qwt_double_interval.h], + [qwt-qt4/qwt_math.h], [qwt_qt4_qwt_h=yes], [qwt_qt4_qwt_h=no] ) @@ -71,7 +71,7 @@ AC_DEFUN([GR_QWT], else dnl check qwt/qwt.h (as in Fedora) AC_CHECK_HEADER( - [qwt/qwt_double_interval.h], + [qwt/qwt_math.h], [qwt_qwt_h=yes], [qwt_qwt_h=no] ) diff --git a/configure.ac b/configure.ac index 6a40fa2a8..531f9adb6 100644 --- a/configure.ac +++ b/configure.ac @@ -55,7 +55,6 @@ LF_CONFIGURE_CC LF_CONFIGURE_CXX GR_LIB64 dnl check for lib64 suffix after choosing compilers - dnl The three macros above are known to override CFLAGS if the user dnl didn't specify them. Though I'm sure somebody thought this was dnl a good idea, it makes it hard to use other than -g -O2 when compiling @@ -67,7 +66,7 @@ if test "$user_set_cflags" != yes; then autoconf_default_CFLAGS="$CFLAGS" CFLAGS="" fi -AC_SUBST(autoconf_default_CFLAGS) +AC_SUBST([autoconf_default_CFLAGS]) dnl The three macros above are known to override CXXFLAGS if the user diff --git a/docs/doxygen/other/group_defs.dox b/docs/doxygen/other/group_defs.dox index 646df6855..6288d1f0a 100644 --- a/docs/doxygen/other/group_defs.dox +++ b/docs/doxygen/other/group_defs.dox @@ -31,6 +31,7 @@ /*! \defgroup qtgui_blk QT Graphical Interfaces */ /*! \defgroup uhd_blk UHD Interface */ /*! \defgroup audio_blk Audio Interface */ +/*! \defgroup pfb_blk Polyphase Filterbank */ /*! * \defgroup base_blk Base classes for GR Blocks diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox index f8d0dcf73..7d78bbbbb 100644 --- a/docs/doxygen/other/main_page.dox +++ b/docs/doxygen/other/main_page.dox @@ -15,5 +15,5 @@ More details on packages in GNU Radio: \li \ref page_qtgui \li \ref page_uhd \li \ref page_vocoder - +\li \ref page_pfb */ diff --git a/docs/doxygen/other/pfb_intro.dox b/docs/doxygen/other/pfb_intro.dox new file mode 100644 index 000000000..8b82d96d7 --- /dev/null +++ b/docs/doxygen/other/pfb_intro.dox @@ -0,0 +1,82 @@ +/*! \page page_pfb Polyphase Filterbanks + +\section Introduction + +Polyphase filterbanks (PFB) are a very powerful set of filtering tools +that can efficiently perform many multi-rate signal processing +tasks. GNU Radio has a set of polyphase filterbank blocks to be used +in all sorts of applications. These blocks and their documentation can +be found in \ref pfb_blk. + +\section Usage + +See the documentation for the individual blocks for details about what +they can do and how they should be used. Furthermore, there are +examples for these blocks in <b>gnuradio-examples/python/pfb</b>. + +The main issue when using the PFB blocks is defining the prototype +filter, which is passed to all of the blocks as a vector of \p +taps. The taps from the prototype filter which get partitioned among +the \p N channels of the channelizer. + +An example of creating a set of filter taps for a PFB channelizer is +found on line 49 of <b>gnuradio-examples/python/pfb/channelizer.py</b> +and reproduced below. Notice that the sample rate is the sample rate +at the input to the channelizer while the bandwidth and transition +width are defined for the channel bandwidths. This makes a fairly long +filter that is then split up between the \p N channels of the PFB. + +\code + self._fs = 9000 # input sample rate + self._M = 9 # Number of channels to channelize + + self._taps = gr.firdes.low_pass_2(1, self._fs, 475.50, 50, + attenuation_dB=100, + window=gr.firdes.WIN_BLACKMAN_hARRIS) +\endcode + +In this example, the signal into the channelizer is sampled at 9 ksps +(complex, so 9 kHz of bandwidth). The filter uses 9 channels, so each +output channel will have a bandwidth and sample rate of 1 kHz. We want +to pass most of the channel, so we define the channel bandwidth to be +a low pass filter with a bandwidth of 475.5 Hz and a transition +bandwidth of 50 Hz, but we have defined this using a sample rate of +the original 9 kHz. The prototype filter has 819 taps to be divided up +between the 9 channels, so each channel uses 91 taps. This is probably +over-kill for a channelizer, and we could reduce the amount of taps +per channel to a couple of dozen with no ill effects. + +The basic rule when defining a set of taps for a PFB block is to think +about the filter running at the highest rate it will see while the +bandwidth is defined for the size of the channels. In the channelizer +case, the highest rate is defined as the rate of the incoming signal, +but in other PFB blocks, this is not so obvious. + +Two very useful blocks to use are the arbitrary resampler and the +clock synchronizer (for PAM signals). These PFBs are defined with a +set number of filters based on the fidelity required from them, not +the rate changes. By default, the \p filter_size is set to 32 for +these blocks, which is a reasonable default for most tasks. Because +the PFB uses this number of filters in the filterbank, the maximum +rate of the bank is defined from this (see the theory of a polyphase +interpolator for a justification of this). So the prototype filter is +defined to use a sample rate of \p filter_size times the signal's +sampling rate. + +A helpful wrapper for the arbitrary resampler is found in +<b>gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py</b>, +which is exposed in Python as <b>blks2.pfb_arb_resampler_ccf</b> and +<b>blks2.pfb_arb_resampler_fff</b>. This block is set up so that the +user only needs to pass it the real number \p rate as the resampling +rate. With just this information, this hierarchical block +automatically creates a filter that fully passes the signal bandwidth +being resampled but does not pass any out-of-band noise. See the code +for this block for details of how the filter is constructed. + +Of course, a user can create his or her own taps and use them in the +arbitrary resampler for more specific requirements. Some of the UHD +examples (<b>gr-uhd/examples</b>) use this ability to create a +received matched filter or channel filter that also resamples the +signal. + +*/ diff --git a/gnuradio-core/src/lib/Makefile.am b/gnuradio-core/src/lib/Makefile.am index 979ac7f91..fc1b7917b 100644 --- a/gnuradio-core/src/lib/Makefile.am +++ b/gnuradio-core/src/lib/Makefile.am @@ -1,4 +1,3 @@ -# # Copyright 2001,2004,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio @@ -54,7 +53,8 @@ libgnuradio_core_la_LIBADD = \ $(GRUEL_LA) \ $(FFTW3F_LIBS) \ $(GSL_LIBS) \ - $(CBLAS_LIBS) + $(CBLAS_LIBS) \ + $(BOOST_FILESYSTEM_LIB) libgnuradio_core_qa_la_LIBADD = \ filter/libfilter-qa.la \ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h index 2c36c95f9..806c33d92 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h @@ -41,6 +41,7 @@ class gr_fir_ccf; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs arbitrary * resampling. The resampling rate can be any real diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h index 541df8aa4..69331a2c6 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h @@ -41,6 +41,7 @@ class gr_fir_fff; * float input, float output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs arbitrary * resampling. The resampling rate can be any real diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h index 751673bc7..68476ed3c 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h @@ -43,6 +43,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in complex inputs and channelizes it to <EM>M</EM> * channels of equal bandwidth. Each of the resulting channels is 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 1ef5fb6ff..674dee181 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 @@ -43,6 +43,7 @@ class gr_fir_ccf; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * * This block performs timing synchronization for PAM signals by * minimizing the derivative of the filtered signal, which in turn diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h index fa1279a7c..d7c646801 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h @@ -42,71 +42,85 @@ class gr_fir_fff; * \brief Timing synchronizer using polyphase filterbanks * * \ingroup filter_blk + * \ingroup pfb_blk * - * This block performs timing synchronization for PAM signals by minimizing the - * derivative of the filtered signal, which in turn maximizes the SNR and - * minimizes ISI. + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. * - * This approach works by setting up two filterbanks; one filterbanke contains the - * signal's pulse shaping matched filter (such as a root raised cosine filter), - * where each branch of the filterbank contains a different phase of the filter. - * The second filterbank contains the derivatives of the filters in the first - * filterbank. Thinking of this in the time domain, the first filterbank contains - * filters that have a sinc shape to them. We want to align the output signal to - * be sampled at exactly the peak of the sinc shape. The derivative of the sinc - * contains a zero at the maximum point of the sinc (sinc(0) = 1, sinc(0)' = 0). - * Furthermore, the region around the zero point is relatively linear. We make - * use of this fact to generate the error signal. + * This approach works by setting up two filterbanks; one filterbanke + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. * - * If the signal out of the derivative filters is d_i[n] for the ith filter, and - * the output of the matched filter is x_i[n], we calculate the error as: - * e[n] = (Re{x_i[n]} * Re{d_i[n]} + Im{x_i[n]} * Im{d_i[n]}) / 2.0 - * This equation averages the error in the real and imaginary parts. There are two - * reasons we multiply by the signal itself. First, if the symbol could be positive - * or negative going, but we want the error term to always tell us to go in the - * same direction depending on which side of the zero point we are on. The sign of - * x_i[n] adjusts the error term to do this. Second, the magnitude of x_i[n] scales - * the error term depending on the symbol's amplitude, so larger signals give us - * a stronger error term because we have more confidence in that symbol's value. - * Using the magnitude of x_i[n] instead of just the sign is especially good for - * signals with low SNR. + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. * - * The error signal, e[n], gives us a value proportional to how far away from the zero - * point we are in the derivative signal. We want to drive this value to zero, so we - * set up a second order loop. We have two variables for this loop; d_k is the filter - * number in the filterbank we are on and d_rate is the rate which we travel through - * the filters in the steady state. That is, due to the natural clock differences between - * the transmitter and receiver, d_rate represents that difference and would traverse - * the filter phase paths to keep the receiver locked. Thinking of this as a second-order - * PLL, the d_rate is the frequency and d_k is the phase. So we update d_rate and d_k - * using the standard loop equations based on two error signals, d_alpha and d_beta. - * We have these two values set based on each other for a critically damped system, so in - * the block constructor, we just ask for "gain," which is d_alpha while d_beta is - * equal to (gain^2)/4. + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. * - * The clock sync block needs to know the number of samples per second (sps), because it - * only returns a single point representing the sample. The sps can be any positive real - * number and does not need to be an integer. The filter taps must also be specified. The - * taps are generated by first conceiving of the prototype filter that would be the signal's - * matched filter. Then interpolate this by the number of filters in the filterbank. These - * are then distributed among all of the filters. So if the prototype filter was to have - * 45 taps in it, then each path of the filterbank will also have 45 taps. This is easily - * done by building the filter with the sample rate multiplied by the number of filters - * to use. + * The clock sync block needs to know the number of samples per second + * (sps), because it only returns a single point representing the + * sample. The sps can be any positive real number and does not need + * to be an integer. The filter taps must also be specified. The taps + * are generated by first conceiving of the prototype filter that + * would be the signal's matched filter. Then interpolate this by the + * number of filters in the filterbank. These are then distributed + * among all of the filters. So if the prototype filter was to have 45 + * taps in it, then each path of the filterbank will also have 45 + * taps. This is easily done by building the filter with the sample + * rate multiplied by the number of filters to use. * - * The number of filters can also be set and defaults to 32. With 32 filters, you get a - * good enough resolution in the phase to produce very small, almost unnoticeable, ISI. - * Going to 64 filters can reduce this more, but after that there is very little gained - * for the extra complexity. + * The number of filters can also be set and defaults to 32. With 32 + * filters, you get a good enough resolution in the phase to produce + * very small, almost unnoticeable, ISI. Going to 64 filters can + * reduce this more, but after that there is very little gained for + * the extra complexity. * - * The initial phase is another settable parameter and refers to the filter path the - * algorithm initially looks at (i.e., d_k starts at init_phase). This value defaults - * to zero, but it might be useful to start at a different phase offset, such as the mid- - * point of the filters. + * The initial phase is another settable parameter and refers to the + * filter path the algorithm initially looks at (i.e., d_k starts at + * init_phase). This value defaults to zero, but it might be useful to + * start at a different phase offset, such as the mid- point of the + * filters. * - * The final parameter is the max_rate_devitation, which defaults to 1.5. This is how far - * we allow d_rate to swing, positive or negative, from 0. Constraining the rate can help - * keep the algorithm from walking too far away to lock during times when there is no signal. + * The final parameter is the max_rate_devitation, which defaults to + * 1.5. This is how far we allow d_rate to swing, positive or + * negative, from 0. Constraining the rate can help keep the algorithm + * from walking too far away to lock during times when there is no + * signal. * */ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h index 200adee3d..6b75c5859 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h @@ -41,6 +41,7 @@ class gri_fft_complex; * input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger down- * sampling (decimation) with a polyphase filterbank. The first input diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h index d2efc591a..3dc52938e 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h @@ -39,6 +39,7 @@ class gr_fir_ccf; * gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk * * This block takes in a signal stream and performs interger up- * sampling (interpolation) with a polyphase filterbank. The first diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h index f5b1cbb94..7e3700921 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -42,6 +42,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk */ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator diff --git a/gr-audio/examples/c++/Makefile.am b/gr-audio/examples/c++/Makefile.am index 88bd7c1fd..d3283354f 100644 --- a/gr-audio/examples/c++/Makefile.am +++ b/gr-audio/examples/c++/Makefile.am @@ -35,4 +35,6 @@ GR_AUDIO_LA=$(top_builddir)/gr-audio/lib/libgnuradio-audio.la noinst_PROGRAMS = dial_tone dial_tone_SOURCES = dial_tone.cc -dial_tone_LDADD = $(GNURADIO_CORE_LA) $(GR_AUDIO_LA) +dial_tone_LDADD = \ + $(GNURADIO_CORE_LA) $(GR_AUDIO_LA) \ + $(BOOST_FILESYSTEM_LIB) diff --git a/gr-qtgui/include/qtgui_sink_f.h b/gr-qtgui/include/qtgui_sink_f.h index bc14147c2..2d79b5eef 100644 --- a/gr-qtgui/include/qtgui_sink_f.h +++ b/gr-qtgui/include/qtgui_sink_f.h @@ -29,7 +29,6 @@ #include <gr_firdes.h> #include <gri_fft.h> #include <qapplication.h> -//#include <qtgui.h> #include "SpectrumGUIClass.h" class qtgui_sink_f; diff --git a/gr-qtgui/include/qtgui_util.h b/gr-qtgui/include/qtgui_util.h index 5b129c7b5..7b3692e75 100644 --- a/gr-qtgui/include/qtgui_util.h +++ b/gr-qtgui/include/qtgui_util.h @@ -44,7 +44,14 @@ public: QwtPickerDblClickPointMachine(); ~QwtPickerDblClickPointMachine(); - virtual CommandList transition( const QwtEventPattern &eventPattern, const QEvent *e); +#if QWT_VERSION < 0x060000 + virtual CommandList transition( const QwtEventPattern &eventPattern, + const QEvent *e); +#else + virtual QList<QwtPickerMachine::Command> + transition( const QwtEventPattern &eventPattern, + const QEvent *e); +#endif }; #endif /* INCLUDED_QTGUI_UTIL_H */ diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc index dda7cfea2..ca7eede36 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.cc +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -68,11 +68,17 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) _imagDataPoints = new double[_numPoints]; // Disable polygon clipping +#if QWT_VERSION < 0x060000 QwtPainter::setDeviceClipping(false); +#else + QwtPainter::setPolylineSplitting(false); +#endif +#if QWT_VERSION < 0x060000 // We don't need the cache here canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); +#endif QPalette palette; palette.setColor(canvas()->backgroundRole(), QColor("white")); @@ -91,13 +97,22 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) _plot_curve->attach(this); _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); _plot_curve->setStyle(QwtPlotCurve::Dots); + +#if QWT_VERSION < 0x060000 _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints); +#else + _plot_curve->setRawSamples(_realDataPoints, _imagDataPoints, _numPoints); +#endif memset(_realDataPoints, 0x0, _numPoints*sizeof(double)); memset(_imagDataPoints, 0x0, _numPoints*sizeof(double)); _zoomer = new ConstellationDisplayZoomer(canvas()); + +#if QWT_VERSION < 0x060000 _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); +#endif + _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, @@ -120,8 +135,14 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) // emit the position of clicks on widget _picker = new QwtDblClickPlotPicker(canvas()); + +#if QWT_VERSION < 0x060000 connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), - this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); +#else + connect(_picker, SIGNAL(selected(const QPointF &)), + this, SLOT(OnPickerPointSelected(const QPointF &))); +#endif connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool ) ), this, SLOT(LegendEntryChecked(QwtPlotItem *, bool ) )); @@ -193,12 +214,18 @@ void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, _realDataPoints = new double[_numPoints]; _imagDataPoints = new double[_numPoints]; +#if QWT_VERSION < 0x060000 _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints); +#else + _plot_curve->setRawSamples(_realDataPoints, _imagDataPoints, _numPoints); +#endif } memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); + replot(); + _lastReplot = gruel::high_res_timer_now(); } } @@ -209,6 +236,7 @@ ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) plotItem->setVisible(!on); } +#if QWT_VERSION < 0x060000 void ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) { @@ -216,5 +244,14 @@ ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); emit plotPointSelected(point); } +#else +void +ConstellationDisplayPlot::OnPickerPointSelected(const QPointF & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} +#endif #endif /* CONSTELLATION_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h index 23004f86c..d252a8c87 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.h +++ b/gr-qtgui/lib/ConstellationDisplayPlot.h @@ -38,6 +38,11 @@ #include <qwt_symbol.h> #include <qtgui_util.h> +#if QWT_VERSION >= 0x060000 +#include <qwt_point_3d.h> // doesn't seem necessary, but is... +#include <qwt_compat.h> +#endif + class ConstellationDisplayPlot : public QwtPlot { Q_OBJECT @@ -62,7 +67,11 @@ public: public slots: void resizeSlot( QSize *s ); +#if QWT_VERSION < 0x060000 void OnPickerPointSelected(const QwtDoublePoint & p); +#else + void OnPickerPointSelected(const QPointF & p); +#endif signals: void plotPointSelected(const QPointF p); diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index f57edd8f6..2e62f2b96 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -133,11 +133,17 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _xAxisPoints = new double[_numPoints]; // Disable polygon clipping +#if QWT_VERSION < 0x060000 QwtPainter::setDeviceClipping(false); +#else + QwtPainter::setPolylineSplitting(false); +#endif +#if QWT_VERSION < 0x060000 // We don't need the cache here canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); +#endif QPalette palette; palette.setColor(canvas()->backgroundRole(), QColor("white")); @@ -156,18 +162,35 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _fft_plot_curve = new QwtPlotCurve("Power Spectrum"); _fft_plot_curve->attach(this); _fft_plot_curve->setPen(QPen(Qt::blue)); + +#if QWT_VERSION < 0x060000 _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints); +#else + _fft_plot_curve->setRawSamples(_xAxisPoints, _dataPoints, _numPoints); +#endif _min_fft_plot_curve = new QwtPlotCurve("Minimum Power"); _min_fft_plot_curve->attach(this); _min_fft_plot_curve->setPen(QPen(Qt::magenta)); + +#if QWT_VERSION < 0x060000 _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); +#else + _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints); +#endif + _min_fft_plot_curve->setVisible(false); _max_fft_plot_curve = new QwtPlotCurve("Maximum Power"); _max_fft_plot_curve->attach(this); _max_fft_plot_curve->setPen(QPen(Qt::darkYellow)); + +#if QWT_VERSION < 0x060000 _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); +#else + _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints); +#endif + _max_fft_plot_curve->setVisible(false); _lower_intensity_marker= new QwtPlotMarker(); @@ -197,9 +220,16 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) symbol.setSize(8); symbol.setPen(QPen(Qt::yellow)); symbol.setBrush(QBrush(Qt::yellow)); + +#if QWT_VERSION < 0x060000 _markerPeakAmplitude->setSymbol(symbol); - _markerPeakAmplitude->attach(this); +#else + _markerPeakAmplitude->setSymbol(&symbol); +#endif + /// THIS CAUSES A PROBLEM! + //_markerPeakAmplitude->attach(this); + _markerNoiseFloorAmplitude = new QwtPlotMarker(); _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine); _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine)); @@ -220,15 +250,25 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) // emit the position of clicks on widget _picker = new QwtDblClickPlotPicker(canvas()); + +#if QWT_VERSION < 0x060000 connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); +#else + connect(_picker, SIGNAL(selected(const QPointF &)), + this, SLOT(OnPickerPointSelected(const QPointF &))); +#endif // Configure magnify on mouse wheel _magnifier = new QwtPlotMagnifier(canvas()); _magnifier->setAxisEnabled(QwtPlot::xBottom, false); _zoomer = new FreqDisplayZoomer(canvas(), 0); + +#if QWT_VERSION < 0x060000 _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); +#endif + _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, @@ -362,7 +402,7 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat { // Only update plot if there is data and if the time interval has elapsed if((numDataPoints > 0) && - (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) { + (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) { if(numDataPoints != _numPoints) { _numPoints = numDataPoints; @@ -375,16 +415,22 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat _xAxisPoints = new double[_numPoints]; _minFFTPoints = new double[_numPoints]; _maxFFTPoints = new double[_numPoints]; - + +#if QWT_VERSION < 0x060000 _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints); _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); +#else + _fft_plot_curve->setRawSamples(_xAxisPoints, _dataPoints, _numPoints); + _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints); + _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints); +#endif _resetXAxisPoints(); ClearMaxData(); ClearMinData(); } - + memcpy(_dataPoints, dataPoints, numDataPoints*sizeof(double)); for(int64_t point = 0; point < numDataPoints; point++){ if(dataPoints[point] < _minFFTPoints[point]){ @@ -401,6 +447,8 @@ FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDat SetUpperIntensityLevel(_peakAmplitude); + replot(); + _lastReplot = gruel::high_res_timer_now(); } } @@ -478,7 +526,7 @@ FrequencyDisplayPlot::SetBGColour (QColor c) { QPalette palette; palette.setColor(canvas()->backgroundRole(), c); - canvas()->setPalette(palette); + canvas()->setPalette(palette); } void @@ -490,6 +538,7 @@ FrequencyDisplayPlot::ShowCFMarker (const bool show) _markerCF->hide(); } +#if QWT_VERSION < 0x060000 void FrequencyDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) { @@ -498,5 +547,15 @@ FrequencyDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) point.setX(point.x() * _xAxisMultiplier); emit plotPointSelected(point); } +#else +void +FrequencyDisplayPlot::OnPickerPointSelected(const QPointF & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); + point.setX(point.x() * _xAxisMultiplier); + emit plotPointSelected(point); +} +#endif #endif /* FREQUENCY_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h index a263fec2f..961f30168 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.h +++ b/gr-qtgui/lib/FrequencyDisplayPlot.h @@ -39,6 +39,10 @@ #include <qwt_symbol.h> #include <qtgui_util.h> +#if QWT_VERSION >= 0x060000 +#include <qwt_compat.h> +#endif + class FrequencyDisplayPlot:public QwtPlot{ Q_OBJECT @@ -76,7 +80,11 @@ public slots: void SetLowerIntensityLevel(const double); void SetUpperIntensityLevel(const double); +#if QWT_VERSION < 0x060000 void OnPickerPointSelected(const QwtDoublePoint & p); +#else + void OnPickerPointSelected(const QPointF & p); +#endif signals: void plotPointSelected(const QPointF p); @@ -107,6 +115,7 @@ private: QwtPlotMarker *_markerCF; QwtDblClickPlotPicker *_picker; + QwtPlotMagnifier *_magnifier; double* _dataPoints; diff --git a/gr-qtgui/lib/Makefile.am b/gr-qtgui/lib/Makefile.am index b87230b23..aba311297 100644 --- a/gr-qtgui/lib/Makefile.am +++ b/gr-qtgui/lib/Makefile.am @@ -70,10 +70,10 @@ grinclude_HEADERS = \ WaterfallDisplayPlot.h \ waterfallGlobalData.h \ ConstellationDisplayPlot.h \ - plot_waterfall.h \ spectrumdisplayform.h \ timedisplayform.h \ SpectrumGUIClass.h \ + plot_waterfall.h \ spectrumUpdateEvents.h #QT_MOC_FLAGS=-DQT_SHARED -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index f635a2b0c..eca6076b6 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -103,14 +103,23 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); _zoomer = new TimeDomainDisplayZoomer(canvas(), 0); + +#if QWT_VERSION < 0x060000 _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); +#endif // Disable polygon clipping +#if QWT_VERSION < 0x060000 QwtPainter::setDeviceClipping(false); +#else + QwtPainter::setPolylineSplitting(false); +#endif +#if QWT_VERSION < 0x060000 // We don't need the cache here canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false); +#endif QPalette palette; palette.setColor(canvas()->backgroundRole(), QColor("white")); @@ -130,8 +139,6 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed) << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray); - int ncolors = colors.size(); - // Setup dataPoints and plot vectors // Automatically deleted when parent is deleted for(int i = 0; i < _nplots; i++) { @@ -141,8 +148,13 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); _plot_curve[i]->attach(this); _plot_curve[i]->setPen(QPen(colors[i])); + +#if QWT_VERSION < 0x060000 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); - } +#else + _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); +#endif +} _sampleRate = 1; _resetXAxisPoints(); @@ -158,8 +170,14 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) // emit the position of clicks on widget _picker = new QwtDblClickPlotPicker(canvas()); + +#if QWT_VERSION < 0x060000 connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); +#else + connect(_picker, SIGNAL(selected(const QPointF &)), + this, SLOT(OnPickerPointSelected(const QPointF &))); +#endif // Configure magnify on mouse wheel _magnifier = new QwtPlotMagnifier(canvas()); @@ -245,7 +263,12 @@ void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, for(int i = 0; i < _nplots; i++) { delete[] _dataPoints[i]; _dataPoints[i] = new double[_numPoints]; + +#if QWT_VERSION < 0x060000 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); +#else + _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); +#endif } setXaxis(0, numDataPoints); @@ -255,6 +278,8 @@ void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, for(int i = 0; i < _nplots; i++) { memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); } + + replot(); } } @@ -300,6 +325,8 @@ TimeDomainDisplayPlot::SetSampleRate(double sr, double units, } } + +#if QWT_VERSION < 0x060000 void TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) { @@ -307,5 +334,14 @@ TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); emit plotPointSelected(point); } +#else +void +TimeDomainDisplayPlot::OnPickerPointSelected(const QPointF & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} +#endif #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h index af87e1b14..6c7fc4330 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.h +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -39,6 +39,10 @@ #include <qwt_symbol.h> #include <qtgui_util.h> +#if QWT_VERSION >= 0x060000 +#include <qwt_compat.h> +#endif + class TimeDomainDisplayPlot:public QwtPlot{ Q_OBJECT @@ -61,7 +65,11 @@ public slots: void SetSampleRate(double sr, double units, const std::string &strunits); +#if QWT_VERSION < 0x060000 void OnPickerPointSelected(const QwtDoublePoint & p); +#else + void OnPickerPointSelected(const QPointF & p); +#endif signals: void plotPointSelected(const QPointF p); diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index 1476be2bd..7abd9aeef 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -230,6 +230,58 @@ private: std::string _unitType; }; +class ColorMap_MultiColor: public QwtLinearColorMap +{ +public: + ColorMap_MultiColor(): + QwtLinearColorMap(Qt::darkCyan, Qt::white) + { + addColorStop(0.25, Qt::cyan); + addColorStop(0.5, Qt::yellow); + addColorStop(0.75, Qt::red); + } +}; + +class ColorMap_WhiteHot: public QwtLinearColorMap +{ +public: + ColorMap_WhiteHot(): + QwtLinearColorMap(Qt::black, Qt::white) + { + } +}; + +class ColorMap_BlackHot: public QwtLinearColorMap +{ +public: + ColorMap_BlackHot(): + QwtLinearColorMap(Qt::white, Qt::black) + { + } +}; + +class ColorMap_Incandescent: public QwtLinearColorMap +{ +public: + ColorMap_Incandescent(): + QwtLinearColorMap(Qt::black, Qt::white) + { + addColorStop(0.5, Qt::darkRed); + } +}; + +class ColorMap_UserDefined: public QwtLinearColorMap +{ +public: + ColorMap_UserDefined(QColor low, QColor high): + QwtLinearColorMap(low, high) + { + } +}; + +/********************************************************************* +MAIN WATERFALL PLOT WIDGET +*********************************************************************/ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) : QwtPlot(parent) @@ -241,8 +293,6 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) resize(parent->width(), parent->height()); _numPoints = 1024; - _waterfallData = new WaterfallData(_startFrequency, _stopFrequency, _numPoints, 200); - QPalette palette; palette.setColor(canvas()->backgroundRole(), QColor("white")); canvas()->setPalette(palette); @@ -255,26 +305,34 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) _lastReplot = 0; - d_spectrogram = new PlotWaterfall(_waterfallData, "Waterfall Display"); - _intensityColorMapType = INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR; - QwtLinearColorMap colorMap(Qt::darkCyan, Qt::white); - colorMap.addColorStop(0.25, Qt::cyan); - colorMap.addColorStop(0.5, Qt::yellow); - colorMap.addColorStop(0.75, Qt::red); + d_data = new WaterfallData(_startFrequency, _stopFrequency, + _numPoints, 200); + +#if QWT_VERSION < 0x060000 + d_spectrogram = new PlotWaterfall(d_data, "Waterfall Display"); + ColorMap_MultiColor colorMap; d_spectrogram->setColorMap(colorMap); - + +#else + d_spectrogram = new QwtPlotSpectrogram("Spectrogram"); + d_spectrogram->setData(*d_data); + d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ImageMode, true); + d_spectrogram->setColorMap(new ColorMap_MultiColor()); +#endif + d_spectrogram->attach(this); // LeftButton for the zooming // MidButton for the panning // RightButton: zoom out by 1 // Ctrl+RighButton: zoom out to full size - _zoomer = new WaterfallZoomer(canvas(), 0); +#if QWT_VERSION < 0x060000 _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); +#endif _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, @@ -286,9 +344,14 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) // emit the position of clicks on widget _picker = new QwtDblClickPlotPicker(canvas()); +#if QWT_VERSION < 0x060000 connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); - +#else + connect(_picker, SIGNAL(selected(const QPointF &)), + this, SLOT(OnPickerPointSelected(const QPointF &))); +#endif + // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically @@ -296,7 +359,7 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); sd->setMinimumExtent( fm.width("100.00") ); - const QColor c(Qt::white); + const QColor c(Qt::black); _zoomer->setRubberBandPen(c); _zoomer->setTrackerPen(c); @@ -307,15 +370,15 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) WaterfallDisplayPlot::~WaterfallDisplayPlot() { - delete _waterfallData; + delete d_data; delete d_spectrogram; } void WaterfallDisplayPlot::Reset() { - _waterfallData->ResizeData(_startFrequency, _stopFrequency, _numPoints); - _waterfallData->Reset(); + d_data->ResizeData(_startFrequency, _stopFrequency, _numPoints); + d_data->Reset(); setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency); @@ -408,9 +471,8 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, } if(gruel::high_res_timer_now() - _lastReplot > timePerFFT*gruel::high_res_timer_tps()) { - //FIXME: We may want to average the data between these updates to smooth display - _waterfallData->addFFTData(dataPoints, numDataPoints, droppedFrames); - _waterfallData->IncrementNumLinesToUpdate(); + d_data->addFFTData(dataPoints, numDataPoints, droppedFrames); + d_data->IncrementNumLinesToUpdate(); QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); timeScale->SetSecondsPerLine(timePerFFT); @@ -421,7 +483,7 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, d_spectrogram->invalidateCache(); d_spectrogram->itemChanged(); - + replot(); _lastReplot = gruel::high_res_timer_now(); @@ -431,9 +493,13 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, void WaterfallDisplayPlot::SetIntensityRange(const double minIntensity, - const double maxIntensity) + const double maxIntensity) { - _waterfallData->setRange(QwtDoubleInterval(minIntensity, maxIntensity)); +#if QWT_VERSION < 0x060000 + d_data->setRange(QwtDoubleInterval(minIntensity, maxIntensity)); +#else + d_data->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity)); +#endif emit UpdatedLowerIntensityLevel(minIntensity); emit UpdatedUpperIntensityLevel(maxIntensity); @@ -447,7 +513,8 @@ WaterfallDisplayPlot::replot() QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); timeScale->initiateUpdate(); - WaterfallFreqDisplayScaleDraw* freqScale = (WaterfallFreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom); + WaterfallFreqDisplayScaleDraw* freqScale = \ + (WaterfallFreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom); freqScale->initiateUpdate(); // Update the time axis display @@ -490,38 +557,54 @@ WaterfallDisplayPlot::SetIntensityColorMapType(const int newType, switch(newType){ case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:{ _intensityColorMapType = newType; - QwtLinearColorMap colorMap(Qt::darkCyan, Qt::white); - colorMap.addColorStop(0.25, Qt::cyan); - colorMap.addColorStop(0.5, Qt::yellow); - colorMap.addColorStop(0.75, Qt::red); +#if QWT_VERSION < 0x060000 + ColorMap_MultiColor colorMap; d_spectrogram->setColorMap(colorMap); +#else + d_spectrogram->setColorMap(new ColorMap_MultiColor()); +#endif break; } case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:{ _intensityColorMapType = newType; - QwtLinearColorMap colorMap(Qt::black, Qt::white); +#if QWT_VERSION < 0x060000 + ColorMap_WhiteHot colorMap; d_spectrogram->setColorMap(colorMap); +#else + d_spectrogram->setColorMap(new ColorMap_WhiteHot()); +#endif break; } case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:{ _intensityColorMapType = newType; - QwtLinearColorMap colorMap(Qt::white, Qt::black); +#if QWT_VERSION < 0x060000 + ColorMap_BlackHot colorMap; d_spectrogram->setColorMap(colorMap); +#else + d_spectrogram->setColorMap(new ColorMap_BlackHot()); +#endif break; } case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:{ _intensityColorMapType = newType; - QwtLinearColorMap colorMap(Qt::black, Qt::white); - colorMap.addColorStop(0.5, Qt::darkRed); +#if QWT_VERSION < 0x060000 + ColorMap_Incandescent colorMap; d_spectrogram->setColorMap(colorMap); +#else + d_spectrogram->setColorMap(new ColorMap_Incandescent()); +#endif break; } case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:{ _userDefinedLowIntensityColor = lowColor; _userDefinedHighIntensityColor = highColor; _intensityColorMapType = newType; - QwtLinearColorMap colorMap(_userDefinedLowIntensityColor, _userDefinedHighIntensityColor); +#if QWT_VERSION < 0x060000 + ColorMap_UserDefined colorMap(lowColor, highColor); d_spectrogram->setColorMap(colorMap); +#else + d_spectrogram->setColorMap(new ColorMap_UserDefined(lowColor, highColor)); +#endif break; } default: break; @@ -549,12 +632,33 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() QwtScaleWidget *rightAxis = axisWidget(QwtPlot::yRight); rightAxis->setTitle("Intensity (dB)"); rightAxis->setColorBarEnabled(true); + +#if QWT_VERSION < 0x060000 rightAxis->setColorMap(d_spectrogram->data()->range(), d_spectrogram->colorMap()); - setAxisScale(QwtPlot::yRight, d_spectrogram->data()->range().minValue(), - d_spectrogram->data()->range().maxValue() ); + d_spectrogram->data()->range().maxValue()); +#else + QwtInterval intv = d_spectrogram->interval(Qt::ZAxis); + switch(_intensityColorMapType) { + case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR: + rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break; + case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT: + rightAxis->setColorMap(intv, new ColorMap_WhiteHot()); break; + case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT: + rightAxis->setColorMap(intv, new ColorMap_BlackHot()); break; + case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT: + rightAxis->setColorMap(intv, new ColorMap_Incandescent()); break; + case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED: + rightAxis->setColorMap(intv, new ColorMap_UserDefined(_userDefinedLowIntensityColor, + _userDefinedHighIntensityColor)); break; + default: + rightAxis->setColorMap(intv, new ColorMap_MultiColor()); break; + } + setAxisScale(QwtPlot::yRight, intv.minValue(), intv.maxValue()); +#endif + enableAxis(QwtPlot::yRight); plotLayout()->setAlignCanvasToScales(true); @@ -570,13 +674,24 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() _lastReplot = gruel::high_res_timer_now(); } +#if QWT_VERSION < 0x060000 void WaterfallDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) { QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + point.setX(point.x() * _xAxisMultiplier); + emit plotPointSelected(point); +} +#else +void +WaterfallDisplayPlot::OnPickerPointSelected(const QPointF & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); point.setX(point.x() * _xAxisMultiplier); emit plotPointSelected(point); } +#endif #endif /* WATERFALL_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h index 0c6a521b1..0458597b0 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.h +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -26,14 +26,20 @@ #include <stdint.h> #include <cstdio> #include <qwt_plot.h> +#include <qwt_plot_spectrogram.h> #include <qwt_plot_zoomer.h> #include <qwt_plot_panner.h> - #include <qtgui_util.h> -#include <plot_waterfall.h> +#include <waterfallGlobalData.h> #include <gruel/high_res_timer.h> +#if QWT_VERSION < 0x060000 +#include <plot_waterfall.h> +#else +#include <qwt_compat.h> +#endif + class WaterfallDisplayPlot:public QwtPlot{ Q_OBJECT @@ -73,7 +79,12 @@ public: public slots: void resizeSlot( QSize *s ); + +#if QWT_VERSION < 0x060000 void OnPickerPointSelected(const QwtDoublePoint & p); +#else + void OnPickerPointSelected(const QPointF & p); +#endif signals: void UpdatedLowerIntensityLevel(const double); @@ -89,14 +100,18 @@ private: double _stopFrequency; int _xAxisMultiplier; - PlotWaterfall *d_spectrogram; - QwtPlotPanner* _panner; QwtPlotZoomer* _zoomer; QwtDblClickPlotPicker *_picker; - WaterfallData* _waterfallData; + WaterfallData *d_data; + +#if QWT_VERSION < 0x060000 + PlotWaterfall *d_spectrogram; +#else + QwtPlotSpectrogram *d_spectrogram; +#endif gruel::high_res_timer_type _lastReplot; diff --git a/gr-qtgui/lib/plot_waterfall.cc b/gr-qtgui/lib/plot_waterfall.cc index 2b1447e03..527eea22e 100644 --- a/gr-qtgui/lib/plot_waterfall.cc +++ b/gr-qtgui/lib/plot_waterfall.cc @@ -2,85 +2,52 @@ #include <qpen.h> #include <qpainter.h> #include "qwt_painter.h" -#include "qwt_double_interval.h" #include "qwt_scale_map.h" #include "qwt_color_map.h" #include "plot_waterfall.h" -#if QT_VERSION < 0x040000 -typedef Q3ValueVector<QRgb> QwtColorTable; -#else -typedef QVector<QRgb> QwtColorTable; +#if QWT_VERSION < 0x060000 +#include "qwt_double_interval.h" #endif +typedef QVector<QRgb> QwtColorTable; class PlotWaterfallImage: public QImage { // This class hides some Qt3/Qt4 API differences public: PlotWaterfallImage(const QSize &size, QwtColorMap::Format format): -#if QT_VERSION < 0x040000 - QImage(size, format == QwtColorMap::RGB ? 32 : 8) -#else - QImage(size, format == QwtColorMap::RGB - ? QImage::Format_ARGB32 : QImage::Format_Indexed8 ) -#endif - { - } - - PlotWaterfallImage(const QImage &other): - QImage(other) - { - } - - void initColorTable(const QImage& other) - { -#if QT_VERSION < 0x040000 - const unsigned int numColors = other.numColors(); - - setNumColors(numColors); - for ( unsigned int i = 0; i < numColors; i++ ) - setColor(i, other.color(i)); -#else - setColorTable(other.colorTable()); -#endif - } - -#if QT_VERSION < 0x040000 - - void setColorTable(const QwtColorTable &colorTable) - { - setNumColors(colorTable.size()); - for ( unsigned int i = 0; i < colorTable.size(); i++ ) - setColor(i, colorTable[i]); - } - - QwtColorTable colorTable() const - { - QwtColorTable table(numColors()); - for ( int i = 0; i < numColors(); i++ ) - table[i] = color(i); - - return table; - } -#endif + QImage(size, format == QwtColorMap::RGB + ? QImage::Format_ARGB32 : QImage::Format_Indexed8 ) + { + } + + PlotWaterfallImage(const QImage &other): + QImage(other) + { + } + + void initColorTable(const QImage& other) + { + setColorTable(other.colorTable()); + } }; class PlotWaterfall::PrivateData { public: - PrivateData() - { - data = NULL; - colorMap = new QwtLinearColorMap(); - } - ~PrivateData() - { - delete colorMap; - } - - WaterfallData *data; - QwtColorMap *colorMap; + PrivateData() + { + data = NULL; + colorMap = new QwtLinearColorMap(); + } + ~PrivateData() + { + delete colorMap; + } + + WaterfallData *data; + QwtColorMap *colorMap; }; /*! @@ -138,7 +105,9 @@ int PlotWaterfall::rtti() const void PlotWaterfall::setColorMap(const QwtColorMap &colorMap) { delete d_data->colorMap; +#if QWT_VERSION < 0x060000 d_data->colorMap = colorMap.copy(); +#endif invalidateCache(); itemChanged(); @@ -150,16 +119,19 @@ void PlotWaterfall::setColorMap(const QwtColorMap &colorMap) */ const QwtColorMap &PlotWaterfall::colorMap() const { - return *d_data->colorMap; + return *d_data->colorMap; } + /*! \return Bounding rect of the data \sa QwtRasterData::boundingRect */ +#if QWT_VERSION < 0x060000 QwtDoubleRect PlotWaterfall::boundingRect() const { - return d_data->data->boundingRect(); + return d_data->data->boundingRect(); } +#endif /*! \brief Returns the recommended raster for a given rect. @@ -170,10 +142,12 @@ QwtDoubleRect PlotWaterfall::boundingRect() const \param rect Rect for the raster hint \return data().rasterHint(rect) */ +#if QWT_VERSION < 0x060000 QSize PlotWaterfall::rasterHint(const QwtDoubleRect &rect) const { - return d_data->data->rasterHint(rect); + return d_data->data->rasterHint(rect); } +#endif /*! \brief Render an image from the data and color map. @@ -192,9 +166,16 @@ QSize PlotWaterfall::rasterHint(const QwtDoubleRect &rect) const \sa QwtRasterData::intensity(), QwtColorMap::rgb(), QwtColorMap::colorIndex() */ -QImage PlotWaterfall::renderImage( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtDoubleRect &area) const +#if QWT_VERSION < 0x060000 +QImage PlotWaterfall::renderImage(const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QwtDoubleRect &area) const +#else +QImage PlotWaterfall::renderImage(const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QRectF &area, + const QSize &size) const +#endif { if ( area.isEmpty() ) return QImage(); @@ -243,7 +224,11 @@ QImage PlotWaterfall::renderImage( PlotWaterfallImage image(rect.size(), d_data->colorMap->format()); +#if QWT_VERSION < 0x060000 const QwtDoubleInterval intensityRange = d_data->data->range(); +#else + const QwtInterval intensityRange = d_data->data->interval(Qt::ZAxis); +#endif if ( !intensityRange.isValid() ) return image; @@ -292,13 +277,7 @@ QImage PlotWaterfall::renderImage( const bool vInvert = yyMap.p1() < yyMap.p2(); if ( hInvert || vInvert ) { -#ifdef __GNUC__ -#endif -#if QT_VERSION < 0x040000 - image = image.mirror(hInvert, vInvert); -#else - image = image.mirrored(hInvert, vInvert); -#endif + image = image.mirrored(hInvert, vInvert); } return image; @@ -317,7 +296,8 @@ QImage PlotWaterfall::renderImage( */ void PlotWaterfall::draw(QPainter *painter, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QwtScaleMap &xMap, + const QwtScaleMap &yMap, const QRect &canvasRect) const { QwtPlotRasterItem::draw(painter, xMap, yMap, canvasRect); diff --git a/gr-qtgui/lib/plot_waterfall.h b/gr-qtgui/lib/plot_waterfall.h index a11461611..d4cb8d6da 100644 --- a/gr-qtgui/lib/plot_waterfall.h +++ b/gr-qtgui/lib/plot_waterfall.h @@ -3,9 +3,12 @@ #include <qglobal.h> #include <waterfallGlobalData.h> +#include <qwt_plot_rasteritem.h> -#include "qwt_valuelist.h" -#include "qwt_plot_rasteritem.h" +#if QWT_VERSION >= 0x060000 +#include <qwt_point_3d.h> // doesn't seem necessary, but is... +#include <qwt_compat.h> +#endif class QwtColorMap; @@ -22,27 +25,40 @@ class QwtColorMap; class PlotWaterfall: public QwtPlotRasterItem { public: - explicit PlotWaterfall(WaterfallData* data, const QString &title = QString::null); + explicit PlotWaterfall(WaterfallData* data, + const QString &title = QString::null); virtual ~PlotWaterfall(); const WaterfallData* data()const; void setColorMap(const QwtColorMap &); + const QwtColorMap &colorMap() const; +#if QWT_VERSION < 0x060000 virtual QwtDoubleRect boundingRect() const; +#endif + virtual QSize rasterHint(const QwtDoubleRect &) const; virtual int rtti() const; virtual void draw(QPainter *p, - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QRect &rect) const; + const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QRect &rect) const; protected: - virtual QImage renderImage( - const QwtScaleMap &xMap, const QwtScaleMap &yMap, - const QwtDoubleRect &rect) const; +#if QWT_VERSION < 0x060000 + QImage renderImage(const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QwtDoubleRect &rect) const; +#else + QImage renderImage(const QwtScaleMap &xMap, + const QwtScaleMap &yMap, + const QRectF &rect, + const QSize &size=QSize(0,0)) const; +#endif private: class PrivateData; diff --git a/gr-qtgui/lib/qtgui_util.cc b/gr-qtgui/lib/qtgui_util.cc index 87b90997a..543ce1b1c 100644 --- a/gr-qtgui/lib/qtgui_util.cc +++ b/gr-qtgui/lib/qtgui_util.cc @@ -22,17 +22,24 @@ #include <qtgui_util.h> +#if QWT_VERSION < 0x060000 QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine() : QwtPickerMachine () { - } +#else +QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine() + : QwtPickerMachine (PointSelection) +{ +} +#endif QwtPickerDblClickPointMachine::~QwtPickerDblClickPointMachine() { } +#if QWT_VERSION < 0x060000 QwtPickerMachine::CommandList QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, const QEvent *e) @@ -53,10 +60,35 @@ QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, return cmdList; } +#else + +QList<QwtPickerMachine::Command> +QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, + const QEvent *e) +{ + QList<QwtPickerMachine::Command> cmdList; + switch(e->type()) { + case QEvent::MouseButtonDblClick: + if ( eventPattern.mouseMatch(QwtEventPattern::MouseSelect1, + (const QMouseEvent *)e) ) { + cmdList += QwtPickerMachine::Begin; + cmdList += QwtPickerMachine::Append; + cmdList += QwtPickerMachine::End; + } + break; + default: + break; + } + return cmdList; +} +#endif + QwtDblClickPlotPicker::QwtDblClickPlotPicker(QwtPlotCanvas* canvas) : QwtPlotPicker(canvas) { +#if QWT_VERSION < 0x060000 setSelectionFlags(QwtPicker::PointSelection); +#endif } QwtDblClickPlotPicker::~QwtDblClickPlotPicker() diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index 0e8594029..9fe553557 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -35,7 +35,6 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) _intValidator->setBottom(0); _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame); _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame); - _timeDomainDisplayPlot = new TimeDomainDisplayPlot(2, TimeDomainDisplayFrame); _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame); _numRealDataPoints = 1024; @@ -62,9 +61,9 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) _noiseFloorAmplitude = -HUGE_VAL; connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), - _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double))); + _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double))); connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), - _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double))); + _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double))); _frequencyDisplayPlot->SetLowerIntensityLevel(-200); _frequencyDisplayPlot->SetUpperIntensityLevel(-200); @@ -90,16 +89,16 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) // Connect double click signals up connect(_frequencyDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), - this, SLOT(onFFTPlotPointSelected(const QPointF))); + this, SLOT(onFFTPlotPointSelected(const QPointF))); connect(_waterfallDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), - this, SLOT(onWFallPlotPointSelected(const QPointF))); + this, SLOT(onWFallPlotPointSelected(const QPointF))); connect(_timeDomainDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), - this, SLOT(onTimePlotPointSelected(const QPointF))); + this, SLOT(onTimePlotPointSelected(const QPointF))); connect(_constellationDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), - this, SLOT(onConstPlotPointSelected(const QPointF))); + this, SLOT(onConstPlotPointSelected(const QPointF))); } SpectrumDisplayForm::~SpectrumDisplayForm() @@ -242,7 +241,7 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints, numTimeDomainDataPoints, d_update_time); - } + } if(tabindex == d_plot_constellation) { _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, imagTimeDomainDataPoints, @@ -258,7 +257,6 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate spectrumUpdateEvent->getDroppedFFTFrames()); } } - // Tell the system the GUI has been updated if(_systemSpecifiedFlag){ @@ -296,7 +294,6 @@ SpectrumDisplayForm::customEvent( QEvent * e) if(_systemSpecifiedFlag){ WindowComboBox->setCurrentIndex(_system->GetWindowType()); FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex()); - //FFTSizeComboBox->setCurrentIndex(1); } waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value()); @@ -466,7 +463,8 @@ SpectrumDisplayForm::_AverageHistory(const double* newBuffer) if(_historyEntryCount > static_cast<int>(_historyVector->size())){ _historyEntryCount = _historyVector->size(); } - _historyEntry = (++_historyEntry)%_historyVector->size(); + _historyEntry += 1; + _historyEntry = _historyEntry % _historyVector->size(); // Total up and then average the values double sum; diff --git a/gr-qtgui/lib/waterfallGlobalData.cc b/gr-qtgui/lib/waterfallGlobalData.cc index 1ba153f0d..04366a297 100644 --- a/gr-qtgui/lib/waterfallGlobalData.cc +++ b/gr-qtgui/lib/waterfallGlobalData.cc @@ -2,14 +2,19 @@ #define WATERFALL_GLOBAL_DATA_CPP #include <waterfallGlobalData.h> +#include <cstdio> WaterfallData::WaterfallData(const double minimumFrequency, const double maximumFrequency, const uint64_t fftPoints, const unsigned int historyExtent) +#if QWT_VERSION < 0x060000 : QwtRasterData(QwtDoubleRect(minimumFrequency /* X START */, 0 /* Y START */, maximumFrequency - minimumFrequency /* WIDTH */, static_cast<double>(historyExtent)/* HEIGHT */)) +#else + : QwtRasterData() +#endif { _intensityRange = QwtDoubleInterval(-200.0, 0.0); @@ -18,6 +23,12 @@ WaterfallData::WaterfallData(const double minimumFrequency, _spectrumData = new double[_fftPoints * _historyLength]; +#if QWT_VERSION >= 0x060000 + setInterval(Qt::XAxis, QwtInterval(minimumFrequency, maximumFrequency)); + setInterval(Qt::YAxis, QwtInterval(0, historyExtent)); + setInterval(Qt::ZAxis, QwtInterval(-200, 0.0)); +#endif + Reset(); } @@ -35,6 +46,7 @@ void WaterfallData::Reset() void WaterfallData::Copy(const WaterfallData* rhs) { +#if QWT_VERSION < 0x060000 if((_fftPoints != rhs->GetNumFFTPoints()) || (boundingRect() != rhs->boundingRect()) ){ _fftPoints = rhs->GetNumFFTPoints(); @@ -42,38 +54,78 @@ void WaterfallData::Copy(const WaterfallData* rhs) delete[] _spectrumData; _spectrumData = new double[_fftPoints * _historyLength]; } +#else + if(_fftPoints != rhs->GetNumFFTPoints()) { + _fftPoints = rhs->GetNumFFTPoints(); + delete[] _spectrumData; + _spectrumData = new double[_fftPoints * _historyLength]; + } +#endif + Reset(); SetSpectrumDataBuffer(rhs->GetSpectrumDataBuffer()); SetNumLinesToUpdate(rhs->GetNumLinesToUpdate()); + +#if QWT_VERSION < 0x060000 setRange(rhs->range()); +#else + setInterval(Qt::XAxis, rhs->interval(Qt::XAxis)); + setInterval(Qt::YAxis, rhs->interval(Qt::YAxis)); + setInterval(Qt::ZAxis, rhs->interval(Qt::ZAxis)); +#endif } void WaterfallData::ResizeData(const double startFreq, const double stopFreq, const uint64_t fftPoints) { +#if QWT_VERSION < 0x060000 if((fftPoints != GetNumFFTPoints()) || (boundingRect().width() != (stopFreq - startFreq)) || (boundingRect().left() != startFreq)){ + + setBoundingRect(QwtDoubleRect(startFreq, 0, + stopFreq-startFreq, + boundingRect().height())); + _fftPoints = fftPoints; + delete[] _spectrumData; + _spectrumData = new double[_fftPoints * _historyLength]; + } + +#else + if((fftPoints != GetNumFFTPoints()) || + (interval(Qt::XAxis).width() != (stopFreq - startFreq)) || + (interval(Qt::XAxis).minValue() != startFreq)){ + + setInterval(Qt::XAxis, QwtInterval(startFreq, stopFreq)); - setBoundingRect(QwtDoubleRect(startFreq, 0, stopFreq-startFreq, boundingRect().height())); _fftPoints = fftPoints; delete[] _spectrumData; _spectrumData = new double[_fftPoints * _historyLength]; } - +#endif + Reset(); } QwtRasterData *WaterfallData::copy() const { +#if QWT_VERSION < 0x060000 WaterfallData* returnData = new WaterfallData(boundingRect().left(), boundingRect().right(), _fftPoints, _historyLength); +#else + WaterfallData* returnData = new WaterfallData(interval(Qt::XAxis).minValue(), + interval(Qt::XAxis).maxValue(), + _fftPoints, _historyLength); +#endif + returnData->Copy(this); return returnData; } + +#if QWT_VERSION < 0x060000 QwtDoubleInterval WaterfallData::range() const { return _intensityRange; @@ -84,14 +136,27 @@ void WaterfallData::setRange(const QwtDoubleInterval& newRange) _intensityRange = newRange; } +#endif + + double WaterfallData::value(double x, double y) const { double returnValue = 0.0; - + +#if QWT_VERSION < 0x060000 const unsigned int intY = static_cast<unsigned int>((1.0 - (y/boundingRect().height())) * - static_cast<double>(_historyLength - 1)); + static_cast<double>(_historyLength-1)); const unsigned int intX = static_cast<unsigned int>((((x - boundingRect().left()) / boundingRect().width()) * static_cast<double>(_fftPoints-1)) + 0.5); +#else + double height = interval(Qt::YAxis).maxValue(); + double left = interval(Qt::XAxis).minValue(); + double right = interval(Qt::XAxis).maxValue(); + double ylen = static_cast<double>(_historyLength-1); + double xlen = static_cast<double>(_fftPoints-1); + const unsigned int intY = static_cast<unsigned int>((1.0 - y/height) * ylen); + const unsigned int intX = static_cast<unsigned int>((((x - left) / (right-left)) * xlen) + 0.5); +#endif const int location = (intY * _fftPoints) + intX; if((location > -1) && (location < static_cast<int64_t>(_fftPoints * _historyLength))){ @@ -132,7 +197,8 @@ void WaterfallData::addFFTData(const double* fftData, } // add the new buffer - memcpy(&_spectrumData[(_historyLength - 1) * _fftPoints], fftData, _fftPoints*sizeof(double)); + memcpy(&_spectrumData[(_historyLength - 1) * _fftPoints], fftData, + _fftPoints*sizeof(double)); } } diff --git a/gr-qtgui/lib/waterfallGlobalData.h b/gr-qtgui/lib/waterfallGlobalData.h index 51f65064c..89e48da5f 100644 --- a/gr-qtgui/lib/waterfallGlobalData.h +++ b/gr-qtgui/lib/waterfallGlobalData.h @@ -4,6 +4,10 @@ #include <qwt_raster_data.h> #include <inttypes.h> +#if QWT_VERSION >= 0x060000 +#include <qwt_point_3d.h> // doesn't seem necessary, but is... +#include <qwt_compat.h> +#endif class WaterfallData: public QwtRasterData { @@ -17,8 +21,11 @@ public: virtual void ResizeData(const double, const double, const uint64_t); virtual QwtRasterData *copy() const; + +#if QWT_VERSION < 0x060000 virtual QwtDoubleInterval range() const; virtual void setRange(const QwtDoubleInterval&); +#endif virtual double value(double x, double y) const; @@ -38,7 +45,12 @@ protected: uint64_t _fftPoints; uint64_t _historyLength; int _numLinesToUpdate; + +#if QWT_VERSION < 0x060000 QwtDoubleInterval _intensityRange; +#else + QwtInterval _intensityRange; +#endif private: diff --git a/gr-usrp/apps/Makefile.am b/gr-usrp/apps/Makefile.am index d014b7c75..b45f3f79c 100644 --- a/gr-usrp/apps/Makefile.am +++ b/gr-usrp/apps/Makefile.am @@ -37,7 +37,8 @@ LDADD = \ $(USRP_LA) \ $(GR_USRP_LA) \ $(BOOST_LDFLAGS) \ - $(BOOST_PROGRAM_OPTIONS_LIB) + $(BOOST_PROGRAM_OPTIONS_LIB) \ + $(BOOST_FILESYSTEM_LIB) noinst_PROGRAMS = \ usrp_rx_cfile \ diff --git a/grc/blocks/gr_complex_to_float.xml b/grc/blocks/gr_complex_to_float.xml index 5b02c3d34..05681b0b9 100644 --- a/grc/blocks/gr_complex_to_float.xml +++ b/grc/blocks/gr_complex_to_float.xml @@ -23,12 +23,12 @@ <vlen>$vlen</vlen> </sink> <source> - <name>out</name> + <name>re</name> <type>float</type> <vlen>$vlen</vlen> </source> <source> - <name>out</name> + <name>im</name> <type>float</type> <vlen>$vlen</vlen> <optional>1</optional> diff --git a/grc/blocks/gr_float_to_complex.xml b/grc/blocks/gr_float_to_complex.xml index a1644efd7..a42cff358 100644 --- a/grc/blocks/gr_float_to_complex.xml +++ b/grc/blocks/gr_float_to_complex.xml @@ -18,12 +18,12 @@ </param> <check>$vlen > 0</check> <sink> - <name>in</name> + <name>re</name> <type>float</type> <vlen>$vlen</vlen> </sink> <sink> - <name>in</name> + <name>im</name> <type>float</type> <vlen>$vlen</vlen> <optional>1</optional> diff --git a/grc/python/Block.py b/grc/python/Block.py index 424706d68..4baf36dc6 100644 --- a/grc/python/Block.py +++ b/grc/python/Block.py @@ -75,22 +75,28 @@ class Block(_Block, _GUIBlock): """ _Block.rewrite(self) + def rectify(ports): + #restore integer contiguity after insertion + #rectify the port names with the index + for i, port in enumerate(ports): + port._key = str(i) + port._name = port._n['name'] + if len(ports) > 1: port._name += str(i) + def insert_port(get_ports, get_port, key): prev_port = get_port(str(int(key)-1)) get_ports().insert( get_ports().index(prev_port)+1, prev_port.copy(new_key=key), ) - #restore integer contiguity after insertion - for i, port in enumerate(get_ports()): port._key = str(i) + rectify(get_ports()) def remove_port(get_ports, get_port, key): port = get_port(key) for connection in port.get_connections(): self.get_parent().remove_element(connection) get_ports().remove(port) - #restore integer contiguity after insertion - for i, port in enumerate(get_ports()): port._key = str(i) + rectify(get_ports()) #adjust nports for get_ports, get_port in ( diff --git a/grc/python/Connection.py b/grc/python/Connection.py index 39f915740..218baf074 100644 --- a/grc/python/Connection.py +++ b/grc/python/Connection.py @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +import Constants +from .. base.Element import Element from .. base.Connection import Connection as _Connection from .. gui.Connection import Connection as _GUIConnection @@ -32,11 +34,10 @@ class Connection(_Connection, _GUIConnection): def validate(self): """ Validate the connections. - The ports must match in type and vector length. + The ports must match in io size. """ - _Connection.validate(self) #checks type - #check vector length - source_vlen = self.get_source().get_vlen() - sink_vlen = self.get_sink().get_vlen() - if source_vlen != sink_vlen: - self.add_error_message('Source vector length "%s" does not match sink vector length "%s".'%(source_vlen, sink_vlen)) + Element.validate(self) + source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen() + sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen() + if source_size != sink_size: + self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size)) diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 868c822aa..4a234f080 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -45,6 +45,38 @@ FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc') +CORE_TYPES = ( #name, key, sizeof, color + ('Complex Float 64', 'fc64', 16, '#72f313'), + ('Complex Float 32', 'fc32', 8, '#3399FF'), + ('Complex Integer 32', 'sc32', 8, '#00b789'), + ('Complex Integer 16', 'sc16', 4, '#f37913'), + ('Complex Integer 8', 'sc8', 2, '#ff0e7f'), + ('Float 64', 'f64', 8, '#86a8fa'), + ('Float 32', 'f32', 4, '#FF8C69'), + ('Integer 32', 's32', 4, '#00FF99'), + ('Integer 16', 's16', 2, '#FFFF66'), + ('Integer 8', 's8', 1, '#FF66FF'), + ('Message Queue', 'msg', 0, '#777777'), + ('Wildcard', '', 0, '#FFFFFF'), +) + +ALIAS_TYPES = { + 'complex' : (8, '#3399FF'), + 'float' : (4, '#FF8C69'), + 'int' : (4, '#00FF99'), + 'short' : (2, '#FFFF66'), + 'byte' : (1, '#FF66FF'), +} + +TYPE_TO_COLOR = dict() +TYPE_TO_SIZEOF = dict() +for name, key, sizeof, color in CORE_TYPES: + TYPE_TO_COLOR[key] = color + TYPE_TO_SIZEOF[key] = sizeof +for key, (sizeof, color) in ALIAS_TYPES.iteritems(): + TYPE_TO_COLOR[key] = color + TYPE_TO_SIZEOF[key] = sizeof + #coloring COMPLEX_COLOR_SPEC = '#3399FF' FLOAT_COLOR_SPEC = '#FF8C69' diff --git a/grc/python/Platform.py b/grc/python/Platform.py index a9c2b18ad..e036361ff 100644 --- a/grc/python/Platform.py +++ b/grc/python/Platform.py @@ -32,20 +32,7 @@ from Constants import \ DEFAULT_FLOW_GRAPH, BLOCKS_DIRS import Constants -COLORS = (#title, #color spec - ('Complex', Constants.COMPLEX_COLOR_SPEC), - ('Float', Constants.FLOAT_COLOR_SPEC), - ('Integer', Constants.INT_COLOR_SPEC), - ('Short', Constants.SHORT_COLOR_SPEC), - ('Byte', Constants.BYTE_COLOR_SPEC), - ('Complex Vector', Constants.COMPLEX_VECTOR_COLOR_SPEC), - ('Float Vector', Constants.FLOAT_VECTOR_COLOR_SPEC), - ('Integer Vector', Constants.INT_VECTOR_COLOR_SPEC), - ('Short Vector', Constants.SHORT_VECTOR_COLOR_SPEC), - ('Byte Vector', Constants.BYTE_VECTOR_COLOR_SPEC), - ('Wildcard', Constants.WILDCARD_COLOR_SPEC), - ('Message', Constants.MSG_COLOR_SPEC), -) +COLORS = [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES] class Platform(_Platform, _GUIPlatform): diff --git a/grc/python/Port.py b/grc/python/Port.py index 3846b0f4e..9baa81110 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -79,7 +79,7 @@ class Port(_Port, _GUIPort): self._vlen = n.find('vlen') or '' self._optional = bool(n.find('optional')) - def get_types(self): return ('complex', 'float', 'int', 'short', 'byte', 'msg', '') + def get_types(self): return Constants.TYPE_TO_SIZEOF.keys() def validate(self): _Port.validate(self) @@ -146,22 +146,16 @@ class Port(_Port, _GUIPort): @return a hex color code. """ try: - if self.get_vlen() == 1: - return {#vlen is 1 - 'complex': Constants.COMPLEX_COLOR_SPEC, - 'float': Constants.FLOAT_COLOR_SPEC, - 'int': Constants.INT_COLOR_SPEC, - 'short': Constants.SHORT_COLOR_SPEC, - 'byte': Constants.BYTE_COLOR_SPEC, - 'msg': Constants.MSG_COLOR_SPEC, - }[self.get_type()] - return {#vlen is non 1 - 'complex': Constants.COMPLEX_VECTOR_COLOR_SPEC, - 'float': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'int': Constants.INT_VECTOR_COLOR_SPEC, - 'short': Constants.SHORT_VECTOR_COLOR_SPEC, - 'byte': Constants.BYTE_VECTOR_COLOR_SPEC, - }[self.get_type()] + color = Constants.TYPE_TO_COLOR[self.get_type()] + if self.get_vlen() == 1: return color + color_val = int(color[1:], 16) + r = (color_val >> 16) & 0xff + g = (color_val >> 8) & 0xff + b = (color_val >> 0) & 0xff + r = max(r-50, 0) + g = max(g-50, 0) + b = max(b-50, 0) + return '#%.2x%.2x%.2x'%(r, g, b) except: return _Port.get_color(self) def copy(self, new_key=None): |