diff options
author | Josh Blum | 2011-10-14 21:16:34 -0700 |
---|---|---|
committer | Josh Blum | 2011-10-14 21:16:34 -0700 |
commit | 5805acef268354468b84e856b7144e3aa2435600 (patch) | |
tree | 2c75cb5b76cd8e1a8c507b6310c77a3d5c717940 | |
parent | 1259a01a9479071bd1729a9c9496444f0a72509b (diff) | |
parent | e0fdd93625a6234ba0d9cabf6e6abfc4df9a2ec6 (diff) | |
download | gnuradio-5805acef268354468b84e856b7144e3aa2435600.tar.gz gnuradio-5805acef268354468b84e856b7144e3aa2435600.tar.bz2 gnuradio-5805acef268354468b84e856b7144e3aa2435600.zip |
Merge branch 'next' of http://gnuradio.org/git/gnuradio into next
-rw-r--r-- | docs/doxygen/other/group_defs.dox | 1 | ||||
-rw-r--r-- | docs/doxygen/other/main_page.dox | 2 | ||||
-rw-r--r-- | docs/doxygen/other/pfb_intro.dox | 82 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h | 128 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h | 128 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h | 1 | ||||
-rw-r--r-- | gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h | 1 | ||||
-rw-r--r-- | grc/blocks/gr_complex_to_float.xml | 4 | ||||
-rw-r--r-- | grc/blocks/gr_float_to_complex.xml | 4 | ||||
-rw-r--r-- | grc/python/Block.py | 14 | ||||
-rw-r--r-- | grc/python/Connection.py | 15 | ||||
-rw-r--r-- | grc/python/Constants.py | 32 | ||||
-rw-r--r-- | grc/python/Platform.py | 15 | ||||
-rw-r--r-- | grc/python/Port.py | 28 |
18 files changed, 298 insertions, 161 deletions
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/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h index 5d2ad0941..749db937e 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 @@ -42,6 +42,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 bf55c312b..7fef06143 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 @@ -42,6 +42,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 56cb5ef40..8fd5c4f78 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h @@ -44,6 +44,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 54ae889d7..514f580ba 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 @@ -44,71 +44,85 @@ 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 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 filterbank 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 filterbank + * 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 symbol (sps), because it - * only returns a single point representing the symbol. 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 symbol + * (sps), because it only returns a single point representing the + * symbol. 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_clock_sync_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h index d5984fe2d..447d3e59d 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 @@ -43,71 +43,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 d091fe4bd..0ae054685 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h @@ -42,6 +42,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 5e3ba6815..6885881e9 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h @@ -40,6 +40,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 0f3b7478c..1f772b1dd 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 @@ -43,6 +43,7 @@ class gri_fft_complex; * gr_complex input, gr_complex output and float taps * * \ingroup filter_blk + * \ingroup pfb_blk */ class GR_CORE_API gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator 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): |