diff options
278 files changed, 13288 insertions, 8207 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d4155ff3d8..15d4ec9cc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,9 +40,9 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) -set(VERSION_INFO_API_COMPAT 6) -set(VERSION_INFO_MINOR_VERSION 2) -set(VERSION_INFO_MAINT_VERSION git) +set(VERSION_INFO_API_COMPAT 7) +set(VERSION_INFO_MINOR_VERSION git) +set(VERSION_INFO_MAINT_VERSION 0) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 5c7b0f3745..4c44ba8812 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -85,7 +85,6 @@ list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_int.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_short.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_uchar.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gri_glfsr.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_interleaved_short_to_complex.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_int_to_float.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_short_to_float.cc @@ -105,7 +104,6 @@ list(APPEND test_gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_nco.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_vco.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_math.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_lfsr.cc ) ######################################################################## @@ -144,7 +142,6 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_short.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_uchar.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr.h - ${CMAKE_CURRENT_SOURCE_DIR}/gri_glfsr.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_interleaved_short_to_complex.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr_15_1_0.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr_32k.h @@ -180,14 +177,12 @@ endif(ENABLE_PYTHON) set(gr_core_general_triple_threats complex_vec_test gr_add_ff - gr_additive_scrambler_bb gr_agc_cc gr_agc_ff gr_agc2_cc gr_agc2_ff gr_align_on_samplenumbers_ss gr_bin_statistics_f - gr_bytes_to_syms gr_char_to_float gr_char_to_short gr_check_counting_s @@ -200,9 +195,6 @@ set(gr_core_general_triple_threats gr_cpm gr_ctcss_squelch_ff gr_decode_ccsds_27_fb - gr_diff_decoder_bb - gr_diff_encoder_bb - gr_diff_phasor_cc gr_dpll_bb gr_deinterleave gr_delay @@ -220,9 +212,6 @@ set(gr_core_general_triple_threats gr_float_to_uchar gr_fmdet_cf gr_frequency_modulator_fc - gr_framer_sink_1 - gr_glfsr_source_b - gr_glfsr_source_f gr_head gr_int_to_float gr_interleave @@ -232,7 +221,6 @@ set(gr_core_general_triple_threats gr_keep_m_in_n gr_kludge_copy gr_lfsr_32k_source_s - gr_map_bb gr_multiply_cc gr_multiply_ff gr_multiply_const_cc @@ -243,13 +231,11 @@ set(gr_core_general_triple_threats gr_null_sink gr_null_source gr_pa_2x2_phase_combiner - gr_packet_sink gr_peak_detector2_fb gr_phase_modulator_fc gr_pll_carriertracking_cc gr_pll_freqdet_cf gr_pll_refout_cc - gr_pn_correlator_cc gr_prefs gr_probe_avg_mag_sqrd_c gr_probe_avg_mag_sqrd_cf @@ -266,7 +252,6 @@ set(gr_core_general_triple_threats gr_short_to_float gr_short_to_char gr_simple_correlator - gr_simple_framer gr_simple_squelch_cc gr_skiphead gr_squelch_base_cc @@ -288,14 +273,10 @@ set(gr_core_general_triple_threats gr_vector_to_streams gr_unpack_k_bits_bb gr_pack_k_bits_bb - gr_descrambler_bb - gr_scrambler_bb - gr_probe_density_b gr_annotator_alltoall gr_annotator_1to1 gr_annotator_raw gr_burst_tagger - gr_correlate_access_code_tag_bb gr_tag_debug ) diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index c0ce655276..b4ddee29ce 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -52,9 +52,7 @@ #include <gr_uchar_to_float.h> #include <gr_frequency_modulator_fc.h> #include <gr_phase_modulator_fc.h> -#include <gr_bytes_to_syms.h> #include <gr_simple_correlator.h> -#include <gr_simple_framer.h> #include <gr_align_on_samplenumbers_ss.h> #include <gr_complex_to_xxx.h> #include <gr_complex_to_interleaved_short.h> @@ -83,13 +81,11 @@ #include <gr_conjugate_cc.h> #include <gr_vco_f.h> #include <gr_threshold_ff.h> -#include <gr_packet_sink.h> #include <gr_dpll_bb.h> #include <gr_fmdet_cf.h> #include <gr_pll_freqdet_cf.h> #include <gr_pll_refout_cc.h> #include <gr_pll_carriertracking_cc.h> -#include <gr_pn_correlator_cc.h> #include <gr_probe_avg_mag_sqrd_c.h> #include <gr_probe_avg_mag_sqrd_cf.h> #include <gr_probe_avg_mag_sqrd_f.h> @@ -102,11 +98,6 @@ #include <gr_test.h> #include <gr_unpack_k_bits_bb.h> #include <gr_pack_k_bits_bb.h> -#include <gr_diff_phasor_cc.h> -#include <gr_diff_encoder_bb.h> -#include <gr_diff_decoder_bb.h> -#include <gr_framer_sink_1.h> -#include <gr_map_bb.h> #include <gr_multiply_cc.h> #include <gr_multiply_ff.h> #include <gr_multiply_const_cc.h> @@ -118,29 +109,22 @@ #include <gr_ctcss_squelch_ff.h> #include <gr_feedforward_agc_cc.h> #include <gr_bin_statistics_f.h> -#include <gr_glfsr_source_b.h> -#include <gr_glfsr_source_f.h> #include <gr_peak_detector2_fb.h> #include <gr_repeat.h> #include <gr_cpfsk_bc.h> #include <gr_encode_ccsds_27_bb.h> #include <gr_decode_ccsds_27_fb.h> -#include <gr_descrambler_bb.h> -#include <gr_scrambler_bb.h> -#include <gr_probe_density_b.h> #include <gr_rail_ff.h> #include <gr_stretch_ff.h> #include <gr_copy.h> -#include <gr_additive_scrambler_bb.h> #include <complex_vec_test.h> #include <gr_annotator_alltoall.h> #include <gr_annotator_1to1.h> #include <gr_annotator_raw.h> #include <gr_burst_tagger.h> #include <gr_cpm.h> -#include <gr_correlate_access_code_tag_bb.h> -#include <gr_add_ff.h> #include <gr_vector_map.h> +#include <gr_add_ff.h> #include <gr_tag_debug.h> %} @@ -174,9 +158,7 @@ %include "gr_uchar_to_float.i" %include "gr_frequency_modulator_fc.i" %include "gr_phase_modulator_fc.i" -%include "gr_bytes_to_syms.i" %include "gr_simple_correlator.i" -%include "gr_simple_framer.i" %include "gr_align_on_samplenumbers_ss.i" %include "gr_complex_to_xxx.i" %include "gr_complex_to_interleaved_short.i" @@ -205,13 +187,11 @@ %include "gr_conjugate_cc.i" %include "gr_vco_f.i" %include "gr_threshold_ff.i" -%include "gr_packet_sink.i" %include "gr_dpll_bb.i" %include "gr_fmdet_cf.i" %include "gr_pll_freqdet_cf.i" %include "gr_pll_refout_cc.i" %include "gr_pll_carriertracking_cc.i" -%include "gr_pn_correlator_cc.i" %include "gr_probe_avg_mag_sqrd_c.i" %include "gr_probe_avg_mag_sqrd_cf.i" %include "gr_probe_avg_mag_sqrd_f.i" @@ -224,11 +204,6 @@ %include "gr_test.i" %include "gr_unpack_k_bits_bb.i" %include "gr_pack_k_bits_bb.i" -%include "gr_diff_phasor_cc.i" -%include "gr_diff_encoder_bb.i" -%include "gr_diff_decoder_bb.i" -%include "gr_framer_sink_1.i" -%include "gr_map_bb.i" %include "gr_multiply_cc.i" %include "gr_multiply_ff.i" %include "gr_multiply_const_cc.i" @@ -240,27 +215,20 @@ %include "gr_ctcss_squelch_ff.i" %include "gr_feedforward_agc_cc.i" %include "gr_bin_statistics_f.i" -%include "gr_glfsr_source_b.i" -%include "gr_glfsr_source_f.i" %include "gr_peak_detector2_fb.i" %include "gr_repeat.i" %include "gr_cpfsk_bc.i" %include "gr_encode_ccsds_27_bb.i" %include "gr_decode_ccsds_27_fb.i" -%include "gr_descrambler_bb.i" -%include "gr_scrambler_bb.i" -%include "gr_probe_density_b.i" %include "gr_rail_ff.i" %include "gr_stretch_ff.i" %include "gr_copy.i" -%include "gr_additive_scrambler_bb.i" %include "complex_vec_test.i" %include "gr_annotator_alltoall.i" %include "gr_annotator_1to1.i" %include "gr_annotator_raw.i" %include "gr_burst_tagger.i" %include "gr_cpm.i" -%include "gr_correlate_access_code_tag_bb.i" -%include "gr_add_ff.i" %include "gr_vector_map.i" +%include "gr_add_ff.i" %include "gr_tag_debug.i" diff --git a/gnuradio-core/src/lib/general/general_generated.i b/gnuradio-core/src/lib/general/general_generated.i index 89b7e1776e..43828e7f71 100644 --- a/gnuradio-core/src/lib/general/general_generated.i +++ b/gnuradio-core/src/lib/general/general_generated.i @@ -18,12 +18,6 @@ #include <gr_add_vff.h> #include <gr_add_vii.h> #include <gr_add_vss.h> -#include <gr_chunks_to_symbols_bc.h> -#include <gr_chunks_to_symbols_bf.h> -#include <gr_chunks_to_symbols_ic.h> -#include <gr_chunks_to_symbols_if.h> -#include <gr_chunks_to_symbols_sc.h> -#include <gr_chunks_to_symbols_sf.h> #include <gr_divide_cc.h> #include <gr_divide_ff.h> #include <gr_divide_ii.h> @@ -100,12 +94,6 @@ %include <gr_add_vff.i> %include <gr_add_vii.i> %include <gr_add_vss.i> -%include <gr_chunks_to_symbols_bc.i> -%include <gr_chunks_to_symbols_bf.i> -%include <gr_chunks_to_symbols_ic.i> -%include <gr_chunks_to_symbols_if.i> -%include <gr_chunks_to_symbols_sc.i> -%include <gr_chunks_to_symbols_sf.i> %include <gr_divide_cc.i> %include <gr_divide_ff.i> %include <gr_divide_ii.i> diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc deleted file mode 100644 index 35cbb9572f..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_additive_scrambler_bb.h> -#include <gr_io_signature.h> - -gr_additive_scrambler_bb_sptr -gr_make_additive_scrambler_bb(int mask, int seed, int len, int count) -{ - return gnuradio::get_initial_sptr(new gr_additive_scrambler_bb(mask, seed, len, count)); -} - -gr_additive_scrambler_bb::gr_additive_scrambler_bb(int mask, int seed, int len, int count) - : gr_sync_block("additive_scrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len), - d_count(count), - d_bits(0) -{ -} - -int -gr_additive_scrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) { - out[i] = in[i]^d_lfsr.next_bit(); - if (d_count > 0) { - if (++d_bits == d_count) { - d_lfsr.reset(); - d_bits = 0; - } - } - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h deleted file mode 100644 index 1c336306d6..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H -#define INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_additive_scrambler_bb; -typedef boost::shared_ptr<gr_additive_scrambler_bb> gr_additive_scrambler_bb_sptr; - -GR_CORE_API gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count=0); - -/*! - * Scramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * \param count Number of bits after which shift register is reset, 0=never - * - * The scrambler works by XORing the incoming bit stream by the output of - * the LFSR. Optionally, after 'count' bits have been processed, the shift - * register is reset to the seed value. This allows processing fixed length - * vectors of samples. - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_additive_scrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count); - - gri_lfsr d_lfsr; - int d_count; - int d_bits; - - gr_additive_scrambler_bb(int mask, int seed, int len, int count); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i deleted file mode 100644 index acf9e8c47e..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,additive_scrambler_bb); - -gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count=0); - -class gr_additive_scrambler_bb : public gr_sync_block -{ -private: - gr_additive_scrambler_bb(int mask, int seed, int len, int count); -}; diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc deleted file mode 100644 index 7dafa29f99..0000000000 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_bytes_to_syms.h> -#include <gr_io_signature.h> -#include <assert.h> - -static const int BITS_PER_BYTE = 8; - -gr_bytes_to_syms_sptr -gr_make_bytes_to_syms () -{ - return gnuradio::get_initial_sptr(new gr_bytes_to_syms ()); -} - -gr_bytes_to_syms::gr_bytes_to_syms () - : gr_sync_interpolator ("bytes_to_syms", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (float)), - BITS_PER_BYTE) -{ -} - -int -gr_bytes_to_syms::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (unsigned char *) input_items[0]; - float *out = (float *) output_items[0]; - - assert (noutput_items % BITS_PER_BYTE == 0); - - for (int i = 0; i < noutput_items / BITS_PER_BYTE; i++){ - int x = in[i]; - - *out++ = (((x >> 7) & 0x1) << 1) - 1; - *out++ = (((x >> 6) & 0x1) << 1) - 1; - *out++ = (((x >> 5) & 0x1) << 1) - 1; - *out++ = (((x >> 4) & 0x1) << 1) - 1; - *out++ = (((x >> 3) & 0x1) << 1) - 1; - *out++ = (((x >> 2) & 0x1) << 1) - 1; - *out++ = (((x >> 1) & 0x1) << 1) - 1; - *out++ = (((x >> 0) & 0x1) << 1) - 1; - } - - return noutput_items; -} - - - diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.h b/gnuradio-core/src/lib/general/gr_bytes_to_syms.h deleted file mode 100644 index 23e5c6b91b..0000000000 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_BYTES_TO_SYMS_H -#define INCLUDED_GR_BYTES_TO_SYMS_H - -#include <gr_core_api.h> -#include <gr_sync_interpolator.h> - -class gr_bytes_to_syms; -typedef boost::shared_ptr<gr_bytes_to_syms> gr_bytes_to_syms_sptr; - -GR_CORE_API gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); - -/*! - * \brief Convert stream of bytes to stream of +/- 1 symbols - * \ingroup converter_blk - * - * input: stream of bytes; output: stream of float - * - * This block is deprecated. - * - * The combination of gr_packed_to_unpacked_bb followed by - * gr_chunks_to_symbols_bf or gr_chunks_to_symbols_bc handles the - * general case of mapping from a stream of bytes into arbitrary float - * or complex symbols. - * - * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. - */ -class GR_CORE_API gr_bytes_to_syms : public gr_sync_interpolator -{ - friend GR_CORE_API gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); - - gr_bytes_to_syms (); - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_BYTES_TO_SYMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.i b/gnuradio-core/src/lib/general/gr_bytes_to_syms.i deleted file mode 100644 index 185e7cd290..0000000000 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.i +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,bytes_to_syms); - -gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); - -class gr_bytes_to_syms : public gr_sync_interpolator -{ - gr_bytes_to_syms (); -}; diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc deleted file mode 100644 index 73ded3c8b3..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_correlate_access_code_tag_bb.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <gr_count_bits.h> -#include <cstdio> -#include <iostream> - -#define VERBOSE 0 - - -gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name) -{ - return gnuradio::get_initial_sptr(new gr_correlate_access_code_tag_bb (access_code, threshold, tag_name)); -} - - -gr_correlate_access_code_tag_bb::gr_correlate_access_code_tag_bb ( - const std::string &access_code, int threshold, const std::string &tag_name) - : gr_sync_block ("correlate_access_code_tag_bb", - gr_make_io_signature (1, 1, sizeof(char)), - gr_make_io_signature (1, 1, sizeof(char))), - d_data_reg(0), d_mask(0), - d_threshold(threshold), d_len(0) - -{ - if (!set_access_code(access_code)){ - fprintf(stderr, "gr_correlate_access_code_tag_bb: access_code is > 64 bits\n"); - throw std::out_of_range ("access_code is > 64 bits"); - } - - std::stringstream str; - str << name() << unique_id(); - d_me = pmt::pmt_string_to_symbol(str.str()); - d_key = pmt::pmt_string_to_symbol(tag_name); -} - -gr_correlate_access_code_tag_bb::~gr_correlate_access_code_tag_bb () -{ -} - -bool -gr_correlate_access_code_tag_bb::set_access_code( - const std::string &access_code) -{ - d_len = access_code.length(); // # of bytes in string - if (d_len > 64) - return false; - - // set len top bits to 1. - d_mask = ((~0ULL) >> (64 - d_len)) << (64 - d_len); - - d_access_code = 0; - for (unsigned i=0; i < 64; i++){ - d_access_code <<= 1; - if (i < d_len) - d_access_code |= access_code[i] & 1; // look at LSB only - } - - return true; -} - -int -gr_correlate_access_code_tag_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - uint64_t abs_out_sample_cnt = nitems_written(0); - - for (int i = 0; i < noutput_items; i++){ - - out[i] = in[i]; - - // compute hamming distance between desired access code and current data - unsigned long long wrong_bits = 0; - unsigned int nwrong = d_threshold+1; - int new_flag = 0; - - wrong_bits = (d_data_reg ^ d_access_code) & d_mask; - nwrong = gr_count_bits64(wrong_bits); - - // test for access code with up to threshold errors - new_flag = (nwrong <= d_threshold); - - // shift in new data and new flag - d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); - if (new_flag) { - if(VERBOSE) std::cout << "writing tag at sample " << abs_out_sample_cnt + i << std::endl; - add_item_tag(0, //stream ID - abs_out_sample_cnt + i - 64 + d_len, //sample - d_key, //frame info - pmt::pmt_t(), //data (unused) - d_me //block src id - ); - } - } - - return noutput_items; -} - diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h deleted file mode 100644 index 345d3004a5..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_gr_correlate_access_code_tag_bb_H -#define INCLUDED_gr_correlate_access_code_tag_bb_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <string> - -class gr_correlate_access_code_tag_bb; -typedef boost::shared_ptr<gr_correlate_access_code_tag_bb> gr_correlate_access_code_tag_bb_sptr; - -/*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ -GR_CORE_API gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, - const std::string &tag_name); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup sync_blk - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: unaltered stream of bits (plus tags) - * - * This block annotates the input stream with tags. The tags have key - * name [tag_name], specified in the constructor. Used for searching - * an input data stream for preambles, etc. - */ -class GR_CORE_API gr_correlate_access_code_tag_bb : public gr_sync_block -{ - friend GR_CORE_API gr_correlate_access_code_tag_bb_sptr - gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, - const std::string &tag_name); - private: - unsigned long long d_access_code; // access code to locate start of packet - // access code is left justified in the word - unsigned long long d_data_reg; // used to look for access_code - unsigned long long d_mask; // masks access_code bits (top N bits are set where - // N is the number of bits in the access code) - unsigned int d_threshold; // how many bits may be wrong in sync vector - unsigned int d_len; //the length of the access code - - pmt::pmt_t d_key, d_me; //d_key is the tag name, d_me is the block name + unique ID - - protected: - gr_correlate_access_code_tag_bb(const std::string &access_code, int threshold, - const std::string &tag_name); - - public: - ~gr_correlate_access_code_tag_bb(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; - -#endif /* INCLUDED_gr_correlate_access_code_tag_bb_H */ diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i deleted file mode 100644 index f7ca4bea7b..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,correlate_access_code_tag_bb); - -/*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - */ -gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name) - throw(std::out_of_range); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup block - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) - * - * Each output byte contains two valid bits, the data bit, and the - * flag bit. The LSB (bit 0) is the data bit, and is the original - * input data, delayed 64 bits. Bit 1 is the - * flag bit and is 1 if the corresponding data bit is the first data - * bit following the access code. Otherwise the flag bit is 0. - */ -class gr_correlate_access_code_tag_bb : public gr_sync_block -{ - friend gr_correlate_access_code_tag_bb_sptr - gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name); - protected: - gr_correlate_access_code_tag_bb(const std::string &access_code, int threshold, const std::string &tag_name); - - public: - ~gr_correlate_access_code_tag_bb(); - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.cc b/gnuradio-core/src/lib/general/gr_descrambler_bb.cc deleted file mode 100644 index b5ae28fa97..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_descrambler_bb.h> -#include <gr_io_signature.h> - -gr_descrambler_bb_sptr -gr_make_descrambler_bb(int mask, int seed, int len) -{ - return gnuradio::get_initial_sptr(new gr_descrambler_bb(mask, seed, len)); -} - -gr_descrambler_bb::gr_descrambler_bb(int mask, int seed, int len) - : gr_sync_block("descrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len) -{ -} - -int -gr_descrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_lfsr.next_bit_descramble(in[i]); - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.h b/gnuradio-core/src/lib/general/gr_descrambler_bb.h deleted file mode 100644 index 333593caaf..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_DESCRAMBLER_BB_H -#define INCLUDED_GR_DESCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_descrambler_bb; -typedef boost::shared_ptr<gr_descrambler_bb> gr_descrambler_bb_sptr; - -GR_CORE_API gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - -/*! - * Descramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_descrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - - gri_lfsr d_lfsr; - - gr_descrambler_bb(int mask, int seed, int len); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_DESCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.i b/gnuradio-core/src/lib/general/gr_descrambler_bb.i deleted file mode 100644 index c6cd0a2852..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,descrambler_bb); - -gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - -class gr_descrambler_bb : public gr_sync_block -{ -private: - gr_descrambler_bb(int mask, int seed, int len); -}; diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc deleted file mode 100644 index 74324a62ea..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_decoder_bb.h> -#include <gr_io_signature.h> - -gr_diff_decoder_bb_sptr -gr_make_diff_decoder_bb (unsigned int modulus) -{ - return gnuradio::get_initial_sptr(new gr_diff_decoder_bb(modulus)); -} - -gr_diff_decoder_bb::gr_diff_decoder_bb (unsigned int modulus) - : gr_sync_block ("diff_decoder_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_modulus(modulus) -{ - set_history(2); // need to look at two inputs -} - -int -gr_diff_decoder_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - in += 1; // ensure that in[-1] is valid - - unsigned modulus = d_modulus; - - for (int i = 0; i < noutput_items; i++){ - out[i] = (in[i] - in[i-1]) % modulus; - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h deleted file mode 100644 index c4ebbc4765..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DIFF_DECODER_BB_H -#define INCLUDED_GR_DIFF_DECODER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_diff_decoder_bb; -typedef boost::shared_ptr<gr_diff_decoder_bb> gr_diff_decoder_bb_sptr; - -GR_CORE_API gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); - -/*! - * \brief y[0] = (x[0] - x[-1]) % M - * \ingroup coding_blk - * - * Differential decoder - */ -class GR_CORE_API gr_diff_decoder_bb : public gr_sync_block -{ - friend GR_CORE_API gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); - gr_diff_decoder_bb(unsigned int modulus); - - unsigned int d_modulus; - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i deleted file mode 100644 index 3dddb17c3e..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,diff_decoder_bb) - -gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); - -class gr_diff_decoder_bb : public gr_sync_block -{ - private: - gr_diff_decoder_bb (unsigned int modulus); -}; diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc deleted file mode 100644 index 98492c746e..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_encoder_bb.h> -#include <gr_io_signature.h> - -gr_diff_encoder_bb_sptr -gr_make_diff_encoder_bb (unsigned int modulus) -{ - return gnuradio::get_initial_sptr(new gr_diff_encoder_bb(modulus)); -} - -gr_diff_encoder_bb::gr_diff_encoder_bb (unsigned int modulus) - : gr_sync_block ("diff_encoder_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_last_out(0), d_modulus(modulus) -{ -} - -int -gr_diff_encoder_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - unsigned last_out = d_last_out; - unsigned modulus = d_modulus; - - for (int i = 0; i < noutput_items; i++){ - out[i] = (in[i] + last_out) % modulus; - last_out = out[i]; - } - - d_last_out = last_out; - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h deleted file mode 100644 index e98876b700..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DIFF_ENCODER_BB_H -#define INCLUDED_GR_DIFF_ENCODER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_diff_encoder_bb; -typedef boost::shared_ptr<gr_diff_encoder_bb> gr_diff_encoder_bb_sptr; - -GR_CORE_API gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); - -/*! - * \brief y[0] = (x[0] + y[-1]) % M - * \ingroup coding_blk - * - * Differential encoder - */ -class GR_CORE_API gr_diff_encoder_bb : public gr_sync_block -{ - friend GR_CORE_API gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); - gr_diff_encoder_bb(unsigned int modulus); - - unsigned int d_last_out; - unsigned int d_modulus; - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i deleted file mode 100644 index 96dadaca5b..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,diff_encoder_bb) - -gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); - -class gr_diff_encoder_bb : public gr_sync_block -{ - private: - gr_diff_encoder_bb (unsigned int modulus); -}; diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc deleted file mode 100644 index 89fa2041e7..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_phasor_cc.h> -#include <gr_io_signature.h> - -gr_diff_phasor_cc_sptr -gr_make_diff_phasor_cc () -{ - return gnuradio::get_initial_sptr(new gr_diff_phasor_cc()); -} - -gr_diff_phasor_cc::gr_diff_phasor_cc () - : gr_sync_block ("diff_phasor_cc", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 1, sizeof (gr_complex))) -{ - set_history(2); -} - - -gr_diff_phasor_cc::~gr_diff_phasor_cc(){} - -int -gr_diff_phasor_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - in += 1; // ensure that i - 1 is valid. - - for(int i = 0; i < noutput_items; i++){ - out[i] = in[i] * conj(in[i-1]); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h deleted file mode 100644 index 21c4f616d5..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DIFF_PHASOR_CC_H -#define INCLUDED_GR_DIFF_PHASOR_CC_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -/*! - * \brief Please fix my documentation! - * \ingroup misc - */ -class gr_diff_phasor_cc; -typedef boost::shared_ptr<gr_diff_phasor_cc> gr_diff_phasor_cc_sptr; - -GR_CORE_API gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); - - -class GR_CORE_API gr_diff_phasor_cc : public gr_sync_block -{ - friend GR_CORE_API gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); - - gr_diff_phasor_cc (); //constructor - - public: - ~gr_diff_phasor_cc(); //destructor - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i deleted file mode 100644 index 8aecd5cc77..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,diff_phasor_cc) - -gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); - -class gr_diff_phasor_cc : public gr_sync_block -{ - private: - gr_diff_phasor_cc (); - - public: - ~gr_diff_phasor_cc(); -}; diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc deleted file mode 100644 index 64a0af6a07..0000000000 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_framer_sink_1.h> -#include <gr_io_signature.h> -#include <cstdio> -#include <stdexcept> -#include <string.h> - -#define VERBOSE 0 - -inline void -gr_framer_sink_1::enter_search() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_search\n"); - - d_state = STATE_SYNC_SEARCH; -} - -inline void -gr_framer_sink_1::enter_have_sync() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_sync\n"); - - d_state = STATE_HAVE_SYNC; - d_header = 0; - d_headerbitlen_cnt = 0; -} - -inline void -gr_framer_sink_1::enter_have_header(int payload_len, int whitener_offset) -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", payload_len, whitener_offset); - - d_state = STATE_HAVE_HEADER; - d_packetlen = payload_len; - d_packet_whitener_offset = whitener_offset; - d_packetlen_cnt = 0; - d_packet_byte = 0; - d_packet_byte_index = 0; -} - -gr_framer_sink_1_sptr -gr_make_framer_sink_1(gr_msg_queue_sptr target_queue) -{ - return gnuradio::get_initial_sptr(new gr_framer_sink_1(target_queue)); -} - - -gr_framer_sink_1::gr_framer_sink_1(gr_msg_queue_sptr target_queue) - : gr_sync_block ("framer_sink_1", - gr_make_io_signature (1, 1, sizeof(unsigned char)), - gr_make_io_signature (0, 0, 0)), - d_target_queue(target_queue) -{ - enter_search(); -} - -gr_framer_sink_1::~gr_framer_sink_1 () -{ -} - -int -gr_framer_sink_1::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - int count=0; - - if (VERBOSE) - fprintf(stderr,">>> Entering state machine\n"); - - while (count < noutput_items){ - switch(d_state) { - - case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt - if (VERBOSE) - fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); - - while (count < noutput_items) { - if (in[count] & 0x2){ // Found it, set up for header decode - enter_have_sync(); - break; - } - count++; - } - break; - - case STATE_HAVE_SYNC: - if (VERBOSE) - fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", - d_headerbitlen_cnt, d_header); - - while (count < noutput_items) { // Shift bits one at a time into header - d_header = (d_header << 1) | (in[count++] & 0x1); - if (++d_headerbitlen_cnt == HEADERBITLEN) { - - if (VERBOSE) - fprintf(stderr, "got header: 0x%08x\n", d_header); - - // we have a full header, check to see if it has been received properly - if (header_ok()){ - int payload_len; - int whitener_offset; - header_payload(&payload_len, &whitener_offset); - enter_have_header(payload_len, whitener_offset); - - if (d_packetlen == 0){ // check for zero-length payload - // build a zero-length message - // NOTE: passing header field as arg1 is not scalable - gr_message_sptr msg = - gr_make_message(0, d_packet_whitener_offset, 0, 0); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - } - } - else - enter_search(); // bad header - break; // we're in a new state - } - } - break; - - case STATE_HAVE_HEADER: - if (VERBOSE) - fprintf(stderr,"Packet Build\n"); - - while (count < noutput_items) { // shift bits into bytes of packet one at a time - d_packet_byte = (d_packet_byte << 1) | (in[count++] & 0x1); - if (d_packet_byte_index++ == 7) { // byte is full so move to next byte - d_packet[d_packetlen_cnt++] = d_packet_byte; - d_packet_byte_index = 0; - - if (d_packetlen_cnt == d_packetlen){ // packet is filled - - // build a message - // NOTE: passing header field as arg1 is not scalable - gr_message_sptr msg = - gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt); - memcpy(msg->msg(), d_packet, d_packetlen_cnt); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - break; - } - } - } - break; - - default: - assert(0); - - } // switch - - } // while - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.h b/gnuradio-core/src/lib/general/gr_framer_sink_1.h deleted file mode 100644 index 93e41745f3..0000000000 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_FRAMER_SINK_1_H -#define INCLUDED_GR_FRAMER_SINK_1_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <gr_msg_queue.h> - -class gr_framer_sink_1; -typedef boost::shared_ptr<gr_framer_sink_1> gr_framer_sink_1_sptr; - -GR_CORE_API gr_framer_sink_1_sptr -gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); - -/*! - * \brief Given a stream of bits and access_code flags, assemble packets. - * \ingroup sink_blk - * - * input: stream of bytes from gr_correlate_access_code_bb - * output: none. Pushes assembled packet into target queue - * - * The framer expects a fixed length header of 2 16-bit shorts - * containing the payload length, followed by the payload. If the - * 2 16-bit shorts are not identical, this packet is ignored. Better - * algs are welcome. - * - * The input data consists of bytes that have two bits used. - * Bit 0, the LSB, contains the data bit. - * Bit 1 if set, indicates that the corresponding bit is the - * the first bit of the packet. That is, this bit is the first - * one after the access code. - */ -class GR_CORE_API gr_framer_sink_1 : public gr_sync_block -{ - friend GR_CORE_API gr_framer_sink_1_sptr - gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); - - private: - enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; - - static const int MAX_PKT_LEN = 4096; - static const int HEADERBITLEN = 32; - - gr_msg_queue_sptr d_target_queue; // where to send the packet when received - state_t d_state; - unsigned int d_header; // header bits - int d_headerbitlen_cnt; // how many so far - - unsigned char d_packet[MAX_PKT_LEN]; // assembled payload - unsigned char d_packet_byte; // byte being assembled - int d_packet_byte_index; // which bit of d_packet_byte we're working on - int d_packetlen; // length of packet - int d_packet_whitener_offset; // offset into whitener string to use - int d_packetlen_cnt; // how many so far - - protected: - gr_framer_sink_1(gr_msg_queue_sptr target_queue); - - void enter_search(); - void enter_have_sync(); - void enter_have_header(int payload_len, int whitener_offset); - - bool header_ok() - { - // confirm that two copies of header info are identical - return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; - } - - void header_payload(int *len, int *offset) - { - // header consists of two 16-bit shorts in network byte order - // payload length is lower 12 bits - // whitener offset is upper 4 bits - *len = (d_header >> 16) & 0x0fff; - *offset = (d_header >> 28) & 0x000f; - } - - public: - ~gr_framer_sink_1(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_FRAMER_SINK_1_H */ diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.i b/gnuradio-core/src/lib/general/gr_framer_sink_1.i deleted file mode 100644 index 06281b138d..0000000000 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.i +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,framer_sink_1); - -gr_framer_sink_1_sptr -gr_make_framer_sink_1(gr_msg_queue_sptr target_queue); - -class gr_framer_sink_1 : public gr_sync_block -{ - protected: - gr_framer_sink_1(gr_msg_queue_sptr target_queue); - - public: - ~gr_framer_sink_1(); -}; diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc b/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc deleted file mode 100644 index fcfeb80dcf..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_glfsr_source_b.h> -#include <gri_glfsr.h> -#include <gr_io_signature.h> -#include <stdexcept> - -gr_glfsr_source_b_sptr -gr_make_glfsr_source_b(int degree, bool repeat, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_glfsr_source_b(degree, repeat, mask, seed)); -} - -gr_glfsr_source_b::gr_glfsr_source_b(int degree, bool repeat, int mask, int seed) - : gr_sync_block ("glfsr_source_b", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (1, 1, sizeof(unsigned char))), - d_repeat(repeat), - d_index(0) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gr_glfsr_source_b: degree must be between 1 and 32 inclusive"); - d_length = (unsigned int)((1ULL << degree)-1); - - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); -} - -gr_glfsr_source_b::~gr_glfsr_source_b() -{ - delete d_glfsr; -} - -int -gr_glfsr_source_b::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - char *out = (char *) output_items[0]; - if ((d_index > d_length) && d_repeat == false) - return -1; /* once through the sequence */ - - int i; - for (i = 0; i < noutput_items; i++) { - out[i] = d_glfsr->next_bit(); - d_index++; - if (d_index > d_length && d_repeat == false) - break; - } - - return i; -} - -int -gr_glfsr_source_b::mask() const -{ - return d_glfsr->mask(); -} diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.h b/gnuradio-core/src/lib/general/gr_glfsr_source_b.h deleted file mode 100644 index 7549a76b32..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_GLFSR_SOURCE_B_H -#define INCLUDED_GR_GLFSR_SOURCE_B_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gri_glfsr; - -class gr_glfsr_source_b; -typedef boost::shared_ptr<gr_glfsr_source_b> gr_glfsr_source_b_sptr; - -GR_CORE_API gr_glfsr_source_b_sptr gr_make_glfsr_source_b(int degree, bool repeat=true, int mask=0, int seed=1); - -/*! - * \brief Galois LFSR pseudo-random source - * \ingroup source_blk - */ -class GR_CORE_API gr_glfsr_source_b : public gr_sync_block -{ - private: - friend GR_CORE_API gr_glfsr_source_b_sptr - gr_make_glfsr_source_b(int degree, bool repeat, int mask, int seed); - - gri_glfsr *d_glfsr; - - bool d_repeat; - unsigned int d_index; - unsigned int d_length; - - gr_glfsr_source_b(int degree, bool repeat, int mask, int seed); - - public: - - ~gr_glfsr_source_b(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - unsigned int period() const { return d_length; } - int mask() const; -}; - -#endif /* INCLUDED_GR_GLFSR_SOURCE_B_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.i b/gnuradio-core/src/lib/general/gr_glfsr_source_b.i deleted file mode 100644 index ffdd52ddba..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,glfsr_source_b); - -gr_glfsr_source_b_sptr -gr_make_glfsr_source_b(int degree, bool repeat=true, int mask=0, int seed=1) - throw (std::runtime_error); - -class gr_glfsr_source_b : public gr_sync_block -{ -protected: - gr_glfsr_source_b(int degree, bool repeat, int mask, int seed); - -public: - unsigned int period() const; - int mask() const; -}; diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc b/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc deleted file mode 100644 index a9efc8a706..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_glfsr_source_f.h> -#include <gri_glfsr.h> -#include <gr_io_signature.h> -#include <stdexcept> - -gr_glfsr_source_f_sptr -gr_make_glfsr_source_f(int degree, bool repeat, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_glfsr_source_f(degree, repeat, mask, seed)); -} - -gr_glfsr_source_f::gr_glfsr_source_f(int degree, bool repeat, int mask, int seed) - : gr_sync_block ("glfsr_source_f", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (1, 1, sizeof(float))), - d_repeat(repeat), - d_index(0) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gr_glfsr_source_f: degree must be between 1 and 32 inclusive"); - d_length = (unsigned int)((1ULL << degree)-1); - - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); -} - -gr_glfsr_source_f::~gr_glfsr_source_f() -{ - delete d_glfsr; -} - -int -gr_glfsr_source_f::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - float *out = (float *) output_items[0]; - if ((d_index > d_length) && d_repeat == false) - return -1; /* once through the sequence */ - - int i; - for (i = 0; i < noutput_items; i++) { - out[i] = (float)d_glfsr->next_bit()*2.0-1.0; - d_index++; - if (d_index > d_length && d_repeat == false) - break; - } - - return i; -} - -int -gr_glfsr_source_f::mask() const -{ - return d_glfsr->mask(); -} diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.h b/gnuradio-core/src/lib/general/gr_glfsr_source_f.h deleted file mode 100644 index 3549e3e5df..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_GLFSR_SOURCE_F_H -#define INCLUDED_GR_GLFSR_SOURCE_F_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gri_glfsr; - -class gr_glfsr_source_f; -typedef boost::shared_ptr<gr_glfsr_source_f> gr_glfsr_source_f_sptr; - -GR_CORE_API gr_glfsr_source_f_sptr gr_make_glfsr_source_f(int degree, bool repeat=true, int mask=0, int seed=1); - -/*! - * \brief Galois LFSR pseudo-random source generating float outputs -1.0 - 1.0 - * \ingroup source_blk - */ -class GR_CORE_API gr_glfsr_source_f : public gr_sync_block -{ - private: - friend GR_CORE_API gr_glfsr_source_f_sptr - gr_make_glfsr_source_f(int degree, bool repeat, int mask, int seed); - - gri_glfsr *d_glfsr; - - bool d_repeat; - unsigned int d_index; - unsigned int d_length; - - gr_glfsr_source_f(int degree, bool repeat, int mask, int seed); - - public: - - ~gr_glfsr_source_f(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - unsigned int period() const { return d_length; } - int mask() const; -}; - -#endif /* INCLUDED_GR_GLFSR_SOURCE_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.i b/gnuradio-core/src/lib/general/gr_glfsr_source_f.i deleted file mode 100644 index 2f84387c27..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,glfsr_source_f); - -gr_glfsr_source_f_sptr -gr_make_glfsr_source_f(int degree, bool repeat=true, int mask=0, int seed=1) - throw (std::runtime_error); - -class gr_glfsr_source_f : public gr_sync_block -{ -protected: - gr_glfsr_source_f(int degree, bool repeat, int mask, int seed); - -public: - unsigned int period() const; - int mask() const; -}; diff --git a/gnuradio-core/src/lib/general/gr_head.cc b/gnuradio-core/src/lib/general/gr_head.cc index cb07c84ddc..1726888113 100644 --- a/gnuradio-core/src/lib/general/gr_head.cc +++ b/gnuradio-core/src/lib/general/gr_head.cc @@ -26,6 +26,7 @@ #include <gr_head.h> #include <gr_io_signature.h> #include <string.h> +#include <iostream> gr_head::gr_head (size_t sizeof_stream_item, unsigned long long nitems) : gr_sync_block ("head", diff --git a/gnuradio-core/src/lib/general/gr_map_bb.cc b/gnuradio-core/src/lib/general/gr_map_bb.cc deleted file mode 100644 index 7deb8971a5..0000000000 --- a/gnuradio-core/src/lib/general/gr_map_bb.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_map_bb.h> -#include <gr_io_signature.h> - -gr_map_bb_sptr -gr_make_map_bb (const std::vector<int> &map) -{ - return gnuradio::get_initial_sptr(new gr_map_bb (map)); -} - -gr_map_bb::gr_map_bb (const std::vector<int> &map) - : gr_sync_block ("map_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))) -{ - for (int i = 0; i < 0x100; i++) - d_map[i] = i; - - unsigned int size = std::min((size_t) 0x100, map.size()); - for (unsigned int i = 0; i < size; i++) - d_map[i] = map[i]; -} - -int -gr_map_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_map[in[i]]; - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_map_bb.h b/gnuradio-core/src/lib/general/gr_map_bb.h deleted file mode 100644 index 0a2f5a45f8..0000000000 --- a/gnuradio-core/src/lib/general/gr_map_bb.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_MAP_BB_H -#define INCLUDED_GR_MAP_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_map_bb; -typedef boost::shared_ptr<gr_map_bb> gr_map_bb_sptr; - -GR_CORE_API gr_map_bb_sptr gr_make_map_bb(const std::vector<int> &map); - -/*! - * \brief output[i] = map[input[i]] - * \ingroup coding_blk - */ - -class GR_CORE_API gr_map_bb : public gr_sync_block -{ - friend GR_CORE_API gr_map_bb_sptr gr_make_map_bb(const std::vector<int> &map); - - unsigned char d_map[0x100]; - - gr_map_bb(const std::vector<int> &map); - -public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_MAP_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_map_bb.i b/gnuradio-core/src/lib/general/gr_map_bb.i deleted file mode 100644 index 9c8bff6447..0000000000 --- a/gnuradio-core/src/lib/general/gr_map_bb.i +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,map_bb); - -gr_map_bb_sptr gr_make_map_bb (const std::vector<int> &map); - -class gr_map_bb : public gr_sync_block -{ - private: - gr_map_bb (const std::vector<int> &map); -}; - diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.cc b/gnuradio-core/src/lib/general/gr_packet_sink.cc deleted file mode 100644 index 19a8c5fc20..0000000000 --- a/gnuradio-core/src/lib/general/gr_packet_sink.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_packet_sink.h> -#include <gr_io_signature.h> -#include <cstdio> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdexcept> -#include <gr_count_bits.h> -#include <string.h> - -#define VERBOSE 0 - -static const int DEFAULT_THRESHOLD = 12; // detect access code with up to DEFAULT_THRESHOLD bits wrong - -inline void -gr_packet_sink::enter_search() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_search\n"); - - d_state = STATE_SYNC_SEARCH; - d_shift_reg = 0; -} - -inline void -gr_packet_sink::enter_have_sync() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_sync\n"); - - d_state = STATE_HAVE_SYNC; - d_header = 0; - d_headerbitlen_cnt = 0; -} - -inline void -gr_packet_sink::enter_have_header(int payload_len) -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_header (payload_len = %d)\n", payload_len); - - d_state = STATE_HAVE_HEADER; - d_packetlen = payload_len; - d_packetlen_cnt = 0; - d_packet_byte = 0; - d_packet_byte_index = 0; -} - -gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, int threshold) -{ - return gnuradio::get_initial_sptr(new gr_packet_sink (sync_vector, target_queue, threshold)); -} - - -gr_packet_sink::gr_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, int threshold) - : gr_sync_block ("packet_sink", - gr_make_io_signature (1, 1, sizeof(float)), - gr_make_io_signature (0, 0, 0)), - d_target_queue(target_queue), d_threshold(threshold == -1 ? DEFAULT_THRESHOLD : threshold) -{ - d_sync_vector = 0; - for(int i=0;i<8;i++){ - d_sync_vector <<= 8; - d_sync_vector |= sync_vector[i]; - } - - enter_search(); -} - -gr_packet_sink::~gr_packet_sink () -{ -} - -int -gr_packet_sink::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - float *inbuf = (float *) input_items[0]; - int count=0; - - if (VERBOSE) - fprintf(stderr,">>> Entering state machine\n"),fflush(stderr); - - while (count<noutput_items) { - switch(d_state) { - - case STATE_SYNC_SEARCH: // Look for sync vector - if (VERBOSE) - fprintf(stderr,"SYNC Search, noutput=%d\n",noutput_items),fflush(stderr); - - while (count < noutput_items) { - if(slice(inbuf[count++])) - d_shift_reg = (d_shift_reg << 1) | 1; - else - d_shift_reg = d_shift_reg << 1; - - // Compute popcnt of putative sync vector - if(gr_count_bits64 (d_shift_reg ^ d_sync_vector) <= d_threshold) { - // Found it, set up for header decode - enter_have_sync(); - break; - } - } - break; - - case STATE_HAVE_SYNC: - if (VERBOSE) - fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", d_headerbitlen_cnt, d_header), - fflush(stderr); - - while (count < noutput_items) { // Shift bits one at a time into header - if(slice(inbuf[count++])) - d_header = (d_header << 1) | 1; - else - d_header = d_header << 1; - - if (++d_headerbitlen_cnt == HEADERBITLEN) { - - if (VERBOSE) - fprintf(stderr, "got header: 0x%08x\n", d_header); - - // we have a full header, check to see if it has been received properly - if (header_ok()){ - int payload_len = header_payload_len(); - if (payload_len <= MAX_PKT_LEN) // reasonable? - enter_have_header(payload_len); // yes. - else - enter_search(); // no. - } - else - enter_search(); // no. - break; // we're in a new state - } - } - break; - - case STATE_HAVE_HEADER: - if (VERBOSE) - fprintf(stderr,"Packet Build\n"),fflush(stderr); - - while (count < noutput_items) { // shift bits into bytes of packet one at a time - if(slice(inbuf[count++])) - d_packet_byte = (d_packet_byte << 1) | 1; - else - d_packet_byte = d_packet_byte << 1; - - if (d_packet_byte_index++ == 7) { // byte is full so move to next byte - d_packet[d_packetlen_cnt++] = d_packet_byte; - d_packet_byte_index = 0; - - if (d_packetlen_cnt == d_packetlen){ // packet is filled - - // build a message - gr_message_sptr msg = gr_make_message(0, 0, 0, d_packetlen_cnt); - memcpy(msg->msg(), d_packet, d_packetlen_cnt); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - break; - } - } - } - break; - - default: - assert(0); - - } // switch - - } // while - - return noutput_items; -} - diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.h b/gnuradio-core/src/lib/general/gr_packet_sink.h deleted file mode 100644 index b4cb0b0f6e..0000000000 --- a/gnuradio-core/src/lib/general/gr_packet_sink.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_PACKET_SINK_H -#define INCLUDED_GR_PACKET_SINK_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <gr_msg_queue.h> - -class gr_packet_sink; -typedef boost::shared_ptr<gr_packet_sink> gr_packet_sink_sptr; - -GR_CORE_API gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold = -1 // -1 -> use default - ); -/*! - * \brief process received bits looking for packet sync, header, and process bits into packet - * \ingroup sink_blk - */ -class GR_CORE_API gr_packet_sink : public gr_sync_block -{ - friend GR_CORE_API gr_packet_sink_sptr - gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - - private: - enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; - - static const int MAX_PKT_LEN = 4096; - static const int HEADERBITLEN = 32; - - gr_msg_queue_sptr d_target_queue; // where to send the packet when received - unsigned long long d_sync_vector; // access code to locate start of packet - unsigned int d_threshold; // how many bits may be wrong in sync vector - - state_t d_state; - - unsigned long long d_shift_reg; // used to look for sync_vector - - unsigned int d_header; // header bits - int d_headerbitlen_cnt; // how many so far - - unsigned char d_packet[MAX_PKT_LEN]; // assembled payload - unsigned char d_packet_byte; // byte being assembled - int d_packet_byte_index; // which bit of d_packet_byte we're working on - int d_packetlen; // length of packet - int d_packetlen_cnt; // how many so far - - protected: - gr_packet_sink(const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - - void enter_search(); - void enter_have_sync(); - void enter_have_header(int payload_len); - - int slice(float x) { return x > 0 ? 1 : 0; } - - bool header_ok() - { - // confirm that two copies of header info are identical - return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; - } - - int header_payload_len() - { - // header consists of two 16-bit shorts in network byte order - int t = (d_header >> 16) & 0xffff; - return t; - } - - public: - ~gr_packet_sink(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - //! return true if we detect carrier - bool carrier_sensed() const - { - return d_state != STATE_SYNC_SEARCH; - } - -}; - -#endif /* INCLUDED_GR_PACKET_SINK_H */ diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.i b/gnuradio-core/src/lib/general/gr_packet_sink.i deleted file mode 100644 index d1290f9d39..0000000000 --- a/gnuradio-core/src/lib/general/gr_packet_sink.i +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,packet_sink) - -gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold = -1 // -1 -> use default - ); - -class gr_packet_sink : public gr_sync_block -{ - protected: - gr_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - public: - ~gr_packet_sink (); - - bool carrier_sensed() const; -}; diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc deleted file mode 100644 index 818e48c34b..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_pn_correlator_cc.h> -#include <gr_io_signature.h> - -gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_pn_correlator_cc(degree, mask, seed)); -} - -gr_pn_correlator_cc::gr_pn_correlator_cc(int degree, int mask, int seed) - : gr_sync_decimator ("pn_correlator_cc", - gr_make_io_signature (1, 1, sizeof(gr_complex)), - gr_make_io_signature (1, 1, sizeof(gr_complex)), - (unsigned int)((1ULL << degree)-1)) // PN code length -{ - d_len = (unsigned int)((1ULL << degree)-1); - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_reference = new gri_glfsr(mask, seed); - for (int i = 0; i < d_len; i++) // initialize to last value in sequence - d_pn = 2.0*d_reference->next_bit()-1.0; -} - -gr_pn_correlator_cc::~gr_pn_correlator_cc() -{ - delete d_reference; -} - -int -gr_pn_correlator_cc::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - gr_complex sum; - - for (int i = 0; i < noutput_items; i++) { - sum = 0.0; - - for (int j = 0; j < d_len; j++) { - if (j != 0) // retard PN generator one sample per period - d_pn = 2.0*d_reference->next_bit()-1.0; // no conditionals - sum += *in++ * d_pn; - } - - *out++ = sum*gr_complex(1.0/d_len, 0.0); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h deleted file mode 100644 index 69bd2c502f..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_PN_CORRELATOR_CC_H -#define INCLUDED_GR_PN_CORRELATOR_CC_H - -#include <gr_core_api.h> -#include <gr_sync_decimator.h> -#include <gri_glfsr.h> - -class gr_pn_correlator_cc; -typedef boost::shared_ptr<gr_pn_correlator_cc> gr_pn_correlator_cc_sptr; - -GR_CORE_API gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask=0, int seed=1); -/*! - * \brief PN code sequential search correlator - * - * \ingroup sync_blk - * Receives complex baseband signal, outputs complex correlation against - * reference PN code, one sample per PN code period - */ - -class GR_CORE_API gr_pn_correlator_cc : public gr_sync_decimator -{ - friend GR_CORE_API gr_pn_correlator_cc_sptr gr_make_pn_correlator_cc(int degree, int mask, int seed); - - int d_len; - float d_pn; - gri_glfsr *d_reference; - - protected: - gr_pn_correlator_cc(int degree, int mask, int seed); - - public: - virtual int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - ~gr_pn_correlator_cc(); -}; - -#endif /* INCLUDED_GR_PN_CORRELATOR_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i deleted file mode 100644 index e992f33a7f..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,pn_correlator_cc) - -gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask=0, int seed=1); - -class gr_pn_correlator_cc : public gr_sync_decimator -{ - protected: - gr_pn_correlator_cc(); -}; diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.cc b/gnuradio-core/src/lib/general/gr_probe_density_b.cc deleted file mode 100644 index 31661780af..0000000000 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_probe_density_b.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <iostream> - -gr_probe_density_b_sptr -gr_make_probe_density_b(double alpha) -{ - return gnuradio::get_initial_sptr(new gr_probe_density_b(alpha)); -} - -gr_probe_density_b::gr_probe_density_b(double alpha) - : gr_sync_block("density_b", - gr_make_io_signature(1, 1, sizeof(char)), - gr_make_io_signature(0, 0, 0)) -{ - set_alpha(alpha); - d_density = 1.0; -} - -gr_probe_density_b::~gr_probe_density_b() -{ -} - -int -gr_probe_density_b::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const char *in = (const char *)input_items[0]; - - for (int i = 0; i < noutput_items; i++) - d_density = d_alpha*(double)in[i] + d_beta*d_density; - - return noutput_items; -} - -void -gr_probe_density_b::set_alpha(double alpha) -{ - d_alpha = alpha; - d_beta = 1.0-d_alpha; -} - diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.h b/gnuradio-core/src/lib/general/gr_probe_density_b.h deleted file mode 100644 index ab84a63a96..0000000000 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_PROBE_DENSITY_B_H -#define INCLUDED_GR_PROBE_DENSITY_B_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_probe_density_b; - -typedef boost::shared_ptr<gr_probe_density_b> gr_probe_density_b_sptr; - -GR_CORE_API gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); - -/*! - * This block maintains a running average of the input stream and - * makes it available as an accessor function. The input stream - * is type unsigned char. - * - * If you send this block a stream of unpacked bytes, it will tell - * you what the bit density is. - * - * \param alpha Average filter constant - * - */ - -class GR_CORE_API gr_probe_density_b : public gr_sync_block -{ -private: - friend GR_CORE_API gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); - - double d_alpha; - double d_beta; - double d_density; - - gr_probe_density_b(double alpha); - -public: - ~gr_probe_density_b(); - - /*! - * \brief Returns the current density value - */ - double density() const { return d_density; } - - /*! - * \brief Set the average filter constant - */ - void set_alpha(double alpha); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_PROBE_DENSITY_B_H */ diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_scrambler_bb.cc deleted file mode 100644 index 31eb192077..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_scrambler_bb.h> -#include <gr_io_signature.h> - -gr_scrambler_bb_sptr -gr_make_scrambler_bb(int mask, int seed, int len) -{ - return gnuradio::get_initial_sptr(new gr_scrambler_bb(mask, seed, len)); -} - -gr_scrambler_bb::gr_scrambler_bb(int mask, int seed, int len) - : gr_sync_block("scrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len) -{ -} - -int -gr_scrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_lfsr.next_bit_scramble(in[i]); - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.h b/gnuradio-core/src/lib/general/gr_scrambler_bb.h deleted file mode 100644 index edb429e0a0..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_SCRAMBLER_BB_H -#define INCLUDED_GR_SCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_scrambler_bb; -typedef boost::shared_ptr<gr_scrambler_bb> gr_scrambler_bb_sptr; - -GR_CORE_API gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - -/*! - * Scramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_scrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - - gri_lfsr d_lfsr; - - gr_scrambler_bb(int mask, int seed, int len); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_SCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.i b/gnuradio-core/src/lib/general/gr_scrambler_bb.i deleted file mode 100644 index a7ef7b364f..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,scrambler_bb); - -gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - -class gr_scrambler_bb : public gr_sync_block -{ -private: - gr_scrambler_bb(int mask, int seed, int len); -}; diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.cc b/gnuradio-core/src/lib/general/gr_simple_framer.cc deleted file mode 100644 index 506603bb71..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_simple_framer.h> -#include <gr_simple_framer_sync.h> -#include <gr_io_signature.h> -#include <assert.h> -#include <stdexcept> -#include <string.h> - - -gr_simple_framer_sptr -gr_make_simple_framer (int payload_bytesize) -{ - return gnuradio::get_initial_sptr(new gr_simple_framer (payload_bytesize)); -} - -gr_simple_framer::gr_simple_framer (int payload_bytesize) - : gr_block ("simple_framer", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_seqno (0), d_payload_bytesize (payload_bytesize), - d_input_block_size (payload_bytesize), - d_output_block_size (payload_bytesize + GRSF_OVERHEAD) -{ - set_output_multiple (d_output_block_size); -} - -void -gr_simple_framer::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - assert (noutput_items % d_output_block_size == 0); - - int nblocks = noutput_items / d_output_block_size; - int input_required = nblocks * d_input_block_size; - - unsigned ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) - ninput_items_required[i] = input_required; -} - -int -gr_simple_framer::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - int n = 0; - int nblocks = 0; - - memset (out, 0x55, noutput_items); - - while (n < noutput_items){ - out[0] = (GRSF_SYNC >> 56) & 0xff; - out[1] = (GRSF_SYNC >> 48) & 0xff; - out[2] = (GRSF_SYNC >> 40) & 0xff; - out[3] = (GRSF_SYNC >> 32) & 0xff; - out[4] = (GRSF_SYNC >> 24) & 0xff; - out[5] = (GRSF_SYNC >> 16) & 0xff; - out[6] = (GRSF_SYNC >> 8) & 0xff; - out[7] = (GRSF_SYNC >> 0) & 0xff; - out[8] = d_seqno++; - - memcpy (&out[9], in, d_input_block_size); - in += d_input_block_size; - out += d_output_block_size; - n += d_output_block_size; - nblocks++; - } - - assert (n == noutput_items); - - consume_each (nblocks * d_input_block_size); - return n; -} diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.h b/gnuradio-core/src/lib/general/gr_simple_framer.h deleted file mode 100644 index 76a4b7baba..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SIMPLE_FRAMER_H -#define INCLUDED_GR_SIMPLE_FRAMER_H - -#include <gr_core_api.h> -#include <gr_block.h> - -class gr_simple_framer; -typedef boost::shared_ptr<gr_simple_framer> gr_simple_framer_sptr; - -GR_CORE_API gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - -/*! - * \brief add sync field, seq number and command field to payload - * \ingroup sync_blk - */ -class GR_CORE_API gr_simple_framer : public gr_block -{ - int d_seqno; - int d_payload_bytesize; - int d_input_block_size; // bytes - int d_output_block_size; // bytes - - friend GR_CORE_API gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - gr_simple_framer (int payload_bytesize); - - public: - void forecast (int noutput_items, - gr_vector_int &ninput_items_required); - - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - - -#endif /* INCLUDED_GR_SIMPLE_FRAMER_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.i b/gnuradio-core/src/lib/general/gr_simple_framer.i deleted file mode 100644 index c13ead87bf..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,simple_framer); - -gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - -class gr_simple_framer : public gr_block -{ - private: - gr_simple_framer (int payload_bytesize); -}; diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc index c887376e45..e9dad8fab8 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.cc +++ b/gnuradio-core/src/lib/general/gr_skiphead.cc @@ -41,6 +41,31 @@ gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip) return gnuradio::get_initial_sptr(new gr_skiphead (itemsize, nitems_to_skip)); } +void +gr_skiphead::set_nitems_to_skip(uint64_t nitems_to_skip) +{ + d_nitems_to_skip = nitems_to_skip; + reset(); +} + +uint64_t +gr_skiphead::nitems_to_skip() const +{ + return d_nitems_to_skip; +} + +uint64_t +gr_skiphead::nitems_skiped() const +{ + return d_nitems; +} + +void +gr_skiphead::reset() +{ + d_nitems = 0; +} + int gr_skiphead::general_work(int noutput_items, gr_vector_int &ninput_items_ignored, diff --git a/gnuradio-core/src/lib/general/gr_skiphead.h b/gnuradio-core/src/lib/general/gr_skiphead.h index 899b40f27a..710530ff4c 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.h +++ b/gnuradio-core/src/lib/general/gr_skiphead.h @@ -51,6 +51,26 @@ class GR_CORE_API gr_skiphead : public gr_block public: + /*! + * \brief Sets number of items to skip; resets current skip count to 0. + */ + void set_nitems_to_skip(uint64_t nitems_to_skip); + + /*! + * \brief Gets the number of items to skip. + */ + uint64_t nitems_to_skip() const; + + /*! + * \brief Gets the number of items already skipped. + */ + uint64_t nitems_skiped() const; + + /*! + * \brief Resets number of items skipped to 0. + */ + void reset(); + int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/general/gr_skiphead.i b/gnuradio-core/src/lib/general/gr_skiphead.i index 3246db9702..8ab23a77a6 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.i +++ b/gnuradio-core/src/lib/general/gr_skiphead.i @@ -22,9 +22,14 @@ GR_SWIG_BLOCK_MAGIC(gr,skiphead); -gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip); +gr_skiphead_sptr gr_make_skiphead(size_t itemsize, + uint64_t nitems_to_skip); -class gr_skiphead : public gr_block { - friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip); - gr_skiphead (size_t itemsize, uint64_t nitems_to_skip); +class gr_skiphead : public gr_block +{ +public: + void set_nitems_to_skip(uint64_t nitems_to_skip); + uint64_t nitems_to_skip() const; + uint64_t nitems_skiped() const; + void reset(); }; diff --git a/gnuradio-core/src/lib/general/gri_fft.cc b/gnuradio-core/src/lib/general/gri_fft.cc index 68e7e69519..78446ad39b 100644 --- a/gnuradio-core/src/lib/general/gri_fft.cc +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -59,6 +59,12 @@ gri_fft_malloc_float(int size) return (float*)fftwf_malloc(sizeof(float)*size); } +double * +gri_fft_malloc_double(int size) +{ + return (double*)fftwf_malloc(sizeof(double)*size); +} + void gri_fft_free(void *b) { diff --git a/gnuradio-core/src/lib/general/gri_fft.h b/gnuradio-core/src/lib/general/gri_fft.h index 65e9d046e2..c6fbd4f43f 100644 --- a/gnuradio-core/src/lib/general/gri_fft.h +++ b/gnuradio-core/src/lib/general/gri_fft.h @@ -30,17 +30,21 @@ #include <gr_complex.h> #include <boost/thread.hpp> -/*! \brief Helper function for allocating complex fft buffers +/*! \brief Helper function for allocating complex* buffers */ -gr_complex* gri_fft_malloc_complex(int size); +GR_CORE_API gr_complex* gri_fft_malloc_complex(int size); -/*! \brief Helper function for allocating float fft buffers +/*! \brief Helper function for allocating float* buffers */ -float* gri_fft_malloc_float(int size); +GR_CORE_API float* gri_fft_malloc_float(int size); + +/*! \brief Helper function for allocating double* buffers + */ +GR_CORE_API double* gri_fft_malloc_double(int size); /*! \brief Helper function for freeing fft buffers */ -void gri_fft_free(void *b); +GR_CORE_API void gri_fft_free(void *b); /*! diff --git a/gnuradio-core/src/lib/general/gri_glfsr.cc b/gnuradio-core/src/lib/general/gri_glfsr.cc deleted file mode 100644 index ba6951882b..0000000000 --- a/gnuradio-core/src/lib/general/gri_glfsr.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gri_glfsr.h> -#include <stdexcept> - -static int s_polynomial_masks[] = { - 0x00000000, - 0x00000001, // x^1 + 1 - 0x00000003, // x^2 + x^1 + 1 - 0x00000005, // x^3 + x^1 + 1 - 0x00000009, // x^4 + x^1 + 1 - 0x00000012, // x^5 + x^2 + 1 - 0x00000021, // x^6 + x^1 + 1 - 0x00000041, // x^7 + x^1 + 1 - 0x0000008E, // x^8 + x^4 + x^3 + x^2 + 1 - 0x00000108, // x^9 + x^4 + 1 - 0x00000204, // x^10 + x^4 + 1 - 0x00000402, // x^11 + x^2 + 1 - 0x00000829, // x^12 + x^6 + x^4 + x^1 + 1 - 0x0000100D, // x^13 + x^4 + x^3 + x^1 + 1 - 0x00002015, // x^14 + x^5 + x^3 + x^1 + 1 - 0x00004001, // x^15 + x^1 + 1 - 0x00008016, // x^16 + x^5 + x^3 + x^2 + 1 - 0x00010004, // x^17 + x^3 + 1 - 0x00020013, // x^18 + x^5 + x^2 + x^1 + 1 - 0x00040013, // x^19 + x^5 + x^2 + x^1 + 1 - 0x00080004, // x^20 + x^3 + 1 - 0x00100002, // x^21 + x^2 + 1 - 0x00200001, // x^22 + x^1 + 1 - 0x00400010, // x^23 + x^5 + 1 - 0x0080000D, // x^24 + x^4 + x^3 + x^1 + 1 - 0x01000004, // x^25 + x^3 + 1 - 0x02000023, // x^26 + x^6 + x^2 + x^1 + 1 - 0x04000013, // x^27 + x^5 + x^2 + x^1 + 1 - 0x08000004, // x^28 + x^3 + 1 - 0x10000002, // x^29 + x^2 + 1 - 0x20000029, // x^30 + x^4 + x^1 + 1 - 0x40000004, // x^31 + x^3 + 1 - 0x80000057 // x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + 1 -}; - -int gri_glfsr::glfsr_mask(int degree) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gri_glfsr::glfsr_mask(): degree must be between 1 and 32 inclusive"); - return s_polynomial_masks[degree]; -} diff --git a/gnuradio-core/src/lib/general/gri_glfsr.h b/gnuradio-core/src/lib/general/gri_glfsr.h deleted file mode 100644 index 9aae2d9f17..0000000000 --- a/gnuradio-core/src/lib/general/gri_glfsr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GRI_GLFSR_H -#define INCLUDED_GRI_GLFSR_H - -#include <gr_core_api.h> - -/*! - * \brief Galois Linear Feedback Shift Register using specified polynomial mask - * \ingroup misc - * - * Generates a maximal length pseudo-random sequence of length 2^degree-1 - */ - -class GR_CORE_API gri_glfsr -{ - private: - int d_shift_register; - int d_mask; - - public: - - gri_glfsr(int mask, int seed) { d_shift_register = seed; d_mask = mask; } - static int glfsr_mask(int degree); - - unsigned char next_bit() { - unsigned char bit = d_shift_register & 1; - d_shift_register >>= 1; - if (bit) - d_shift_register ^= d_mask; - return bit; - } - - int mask() const { return d_mask; } -}; - -#endif /* INCLUDED_GRI_GLFSR_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc index 26b21983e6..61e5c159bd 100644 --- a/gnuradio-core/src/lib/general/qa_general.cc +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -33,7 +33,6 @@ #include <qa_gr_fxpt_nco.h> #include <qa_gr_fxpt_vco.h> #include <qa_gr_math.h> -#include <qa_gri_lfsr.h> CppUnit::TestSuite * qa_general::suite () @@ -47,7 +46,6 @@ qa_general::suite () s->addTest (qa_gr_fxpt_nco::suite ()); s->addTest (qa_gr_fxpt_vco::suite ()); s->addTest (qa_gr_math::suite ()); - s->addTest (qa_gri_lfsr::suite ()); return s; } diff --git a/gnuradio-core/src/lib/general/qa_gri_lfsr.cc b/gnuradio-core/src/lib/general/qa_gri_lfsr.cc deleted file mode 100644 index 87d610df68..0000000000 --- a/gnuradio-core/src/lib/general/qa_gri_lfsr.cc +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gri_lfsr.h> -#include <qa_gri_lfsr.h> -#include <cppunit/TestAssert.h> -#include <stdio.h> -#include <string.h> -#include <vector> - -void -qa_gri_lfsr::test_lfsr () -{ - int mask = 0x19; - int seed = 0x01; - int length = 5; - - gri_lfsr lfsr1(mask,seed,length); - gri_lfsr lfsr2(mask,seed,length); - - unsigned char expected[] = {1, 0, 1, 1, 0, 1, 0, 1, 0, 0}; - - for(unsigned int i=0; i<31; i++){ - lfsr1.next_bit(); - } - - // test that after one lfsr cycle we still match out uncycled lfsr - for (unsigned int i = 0; i < 41; i++) { - CPPUNIT_ASSERT_EQUAL((int) lfsr1.next_bit(), (int) lfsr2.next_bit()); - } - - // test the known correct values at the given shift offset - for(unsigned int i=0; i<10; i++){ - CPPUNIT_ASSERT_EQUAL((int) lfsr1.next_bit(), (int) expected[i]); - } - - // test for register length too long - CPPUNIT_ASSERT_THROW(gri_lfsr(mask, seed, 32), std::invalid_argument); -} - -void -qa_gri_lfsr::test_scrambler() -{ - // CCSDS 7-bit scrambler - int mask = 0x8A; - int seed = 0x7F; - int length = 7; - - gri_lfsr scrambler(mask, seed, length); - - // Impulse (1 and 126 more zeroes) - unsigned char src[] = - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 }; // flush bits - - // Impulse response (including leading bits) - unsigned char expected[] = - { 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, - 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, }; - - int len = sizeof(src); - std::vector<unsigned char> actual(len); - - for (int i = 0; i < len; i++) - actual[i] = scrambler.next_bit_scramble(src[i]); - - CPPUNIT_ASSERT(memcmp(expected, &actual[0], len) == 0); -} - -void -qa_gri_lfsr::test_descrambler() -{ - // CCSDS 7-bit scrambler - int mask = 0x8A; - int seed = 0x7F; - int length = 7; - - gri_lfsr descrambler(mask, seed, length); - - // Scrambled sequence (impulse response) - unsigned char src[] = - { 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, - 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; - - // Original (garbage while synchronizing, them impulse) - unsigned char expected[] = - { 0, 1, 0, 0, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - int len = sizeof(src); - std::vector<unsigned char> actual(len); - - for (int i = 0; i < len; i++) - actual[i] = descrambler.next_bit_descramble(src[i]); - - CPPUNIT_ASSERT(memcmp(expected, &actual[0], len) == 0); -} diff --git a/gnuradio-core/src/lib/general/qa_gri_lfsr.h b/gnuradio-core/src/lib/general/qa_gri_lfsr.h deleted file mode 100644 index e91843bbb3..0000000000 --- a/gnuradio-core/src/lib/general/qa_gri_lfsr.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef _QA_GRI_LFSR_H_ -#define _QA_GRI_LFSR_H_ - -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/TestCase.h> - -class qa_gri_lfsr : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE(qa_gri_lfsr); - CPPUNIT_TEST(test_lfsr); - CPPUNIT_TEST(test_scrambler); - CPPUNIT_TEST(test_descrambler); - CPPUNIT_TEST_SUITE_END(); - - private: - void test_lfsr(); - void test_scrambler(); - void test_descrambler(); -}; - -#endif /* _QA_GRI_LFSR_H_ */ diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt index b44a470750..ed49cf07e5 100644 --- a/gnuradio-core/src/lib/gengen/CMakeLists.txt +++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt @@ -101,7 +101,6 @@ expand_h_cc_i(gr_multiply_const_vXX ss ii ff cc) expand_h_cc_i(gr_integrate_XX ss ii ff cc) expand_h_cc_i(gr_moving_average_XX ss ii ff cc) -expand_h_cc_i(gr_chunks_to_symbols_XX bf bc sf sc if ic) expand_h_cc_i(gr_unpacked_to_packed_XX bb ss ii) expand_h_cc_i(gr_packed_to_unpacked_XX bb ss ii) expand_h_cc_i(gr_xor_XX bb ss ii) diff --git a/gnuradio-core/src/lib/gengen/generate_common.py b/gnuradio-core/src/lib/gengen/generate_common.py index 13d01b0f90..37d8944f5b 100755 --- a/gnuradio-core/src/lib/gengen/generate_common.py +++ b/gnuradio-core/src/lib/gengen/generate_common.py @@ -54,7 +54,6 @@ reg_roots = [ # other blocks others = ( - ('gr_chunks_to_symbols_XX', ('bf', 'bc', 'sf', 'sc', 'if', 'ic')), ('gr_unpacked_to_packed_XX', ('bb','ss','ii')), ('gr_packed_to_unpacked_XX', ('bb','ss','ii')), ('gr_xor_XX', ('bb','ss','ii')), diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t deleted file mode 100644 index 4a642c13e2..0000000000 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -// @WARNING@ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <@NAME@.h> -#include <gr_io_signature.h> -#include <assert.h> -#include <iostream> -#include <string.h> - -@SPTR_NAME@ -gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) -{ - return gnuradio::get_initial_sptr (new @NAME@ (symbol_table,D)); -} - -@NAME@::@NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) - : gr_sync_interpolator ("@BASE_NAME@", - gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), - gr_make_io_signature (1, -1, sizeof (@O_TYPE@)), - D), - d_D (D), - d_symbol_table (symbol_table) -{ -} - -int -@NAME@::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - assert (noutput_items % d_D == 0); - assert (input_items.size() == output_items.size()); - int nstreams = input_items.size(); - - for (int m=0;m<nstreams;m++) { - const @I_TYPE@ *in = (@I_TYPE@ *) input_items[m]; - @O_TYPE@ *out = (@O_TYPE@ *) output_items[m]; - - // per stream processing - for (int i = 0; i < noutput_items / d_D; i++){ - assert (((unsigned int)in[i]*d_D+d_D) <= d_symbol_table.size()); - memcpy(out, &d_symbol_table[(unsigned int)in[i]*d_D], d_D*sizeof(@O_TYPE@)); - out+=d_D; - } - // end of per stream processing - - } - return noutput_items; -} diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t deleted file mode 100644 index 17d5688b86..0000000000 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -// @WARNING@ - -#ifndef @GUARD_NAME@ -#define @GUARD_NAME@ - -#include <gr_core_api.h> -#include <gr_sync_interpolator.h> - -class @NAME@; -typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; - -GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - -/*! - * \brief Map a stream of symbol indexes (unpacked bytes or shorts) to stream of float or complex onstellation points.in \p D dimensions (\p D = 1 by default) - * \ingroup converter_blk - * - * input: stream of @I_TYPE@; output: stream of @O_TYPE@ - * - * out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 - * - * The combination of gr_packed_to_unpacked_XX followed by - * gr_chunks_to_symbols_XY handles the general case of mapping - * from a stream of bytes or shorts into arbitrary float - * or complex symbols. - * - * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_packed_to_unpacked_ss, gr_unpacked_to_packed_ss, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. - * \sa gr_chunks_to_symbols_sf, gr_chunks_to_symbols_sc. - */ - -class GR_CORE_API @NAME@ : public gr_sync_interpolator -{ - friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D); - - int d_D; - std::vector<@O_TYPE@> d_symbol_table; - @NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - - public: - int D () const { return d_D; } - std::vector<@O_TYPE@> symbol_table () const { return d_symbol_table; } - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } -}; - -#endif diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t deleted file mode 100644 index 14c8be4863..0000000000 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -// @WARNING@ - -GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); - -@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - -class @NAME@ : public gr_sync_interpolator -{ -private: - @NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - -public: - int D () const { return d_D; } - std::vector<@O_TYPE@> symbol_table () const { return d_symbol_table; } -}; diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc index d698927629..c0da23b4f7 100644 --- a/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc @@ -82,7 +82,7 @@ gr_tagged_file_sink::work (int noutput_items, uint64_t start_N = nitems_read(0); uint64_t end_N = start_N + (uint64_t)(noutput_items); pmt::pmt_t bkey = pmt::pmt_string_to_symbol("burst"); - //pmt::pmt_t tkey = pmt::pmt_string_to_symbol("time"); // use gr_tags::key_time + pmt::pmt_t tkey = pmt::pmt_string_to_symbol("rx_time"); // use gr_tags::key_time std::vector<gr_tag_t> all_tags; get_tags_in_range(all_tags, 0, start_N, end_N); @@ -91,6 +91,20 @@ gr_tagged_file_sink::work (int noutput_items, std::vector<gr_tag_t>::iterator vitr = all_tags.begin(); + // Look for a time tag and initialize d_timeval. + std::vector<gr_tag_t> time_tags_outer; + get_tags_in_range(time_tags_outer, 0, start_N, end_N, tkey); + if (time_tags_outer.size() > 0) { + const gr_tag_t tag = time_tags_outer[0]; + uint64_t offset = tag.offset; + pmt::pmt_t time = tag.value; + uint64_t tsecs = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(time, 0)); + double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1)); + double delta = (double)offset / d_sample_rate; + d_timeval = (double)tsecs + tfrac + delta; + d_last_N = offset; + } + int idx = 0, idx_stop = 0; while(idx < noutput_items) { if(d_state == NOT_IN_BURST) { @@ -108,8 +122,7 @@ gr_tagged_file_sink::work (int noutput_items, // to new time based on sample rate of this block. std::vector<gr_tag_t> time_tags; //get_tags_in_range(time_tags, 0, d_last_N, N, gr_tags::key_time); - get_tags_in_range(time_tags, 0, d_last_N, N, - pmt::pmt_string_to_symbol("time")); + get_tags_in_range(time_tags, 0, d_last_N, N, tkey); if(time_tags.size() > 0) { const gr_tag_t tag = time_tags[time_tags.size()-1]; @@ -117,7 +130,7 @@ gr_tagged_file_sink::work (int noutput_items, // Get time based on last time tag from USRP pmt::pmt_t time = tag.value; - int tsecs = pmt::pmt_to_long(pmt::pmt_tuple_ref(time, 0)); + uint64_t tsecs = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(time, 0)); double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1)); // Get new time from last time tag + difference in time to when @@ -143,7 +156,7 @@ gr_tagged_file_sink::work (int noutput_items, std::stringstream filename; filename.setf(std::ios::fixed, std::ios::floatfield); filename.precision(8); - filename << "file" << d_n << "_" << d_timeval << ".dat"; + filename << "file" << d_unique_id << "_" << d_n << "_" << d_timeval << ".dat"; d_n++; int fd; diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py deleted file mode 100755 index c1fe2a7000..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import math -import random - -def make_random_int_tuple(L, min, max): - result = [] - for x in range(L): - result.append(random.randint(min, max)) - return tuple(result) - - -class test_diff_encoder (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_diff_encdec_000(self): - random.seed(0) - modulus = 2 - src_data = make_random_int_tuple(1000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - - def test_diff_encdec_001(self): - random.seed(0) - modulus = 4 - src_data = make_random_int_tuple(1000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - - def test_diff_encdec_002(self): - random.seed(0) - modulus = 8 - src_data = make_random_int_tuple(40000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - -if __name__ == '__main__': - gr_unittest.run(test_diff_encoder, "test_diff_encoder.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py deleted file mode 100755 index 41f96aa616..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import math - -class test_diff_phasor (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_diff_phasor_cc (self): - src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) - expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) - src = gr.vector_source_c (src_data) - op = gr.diff_phasor_cc () - dst = gr.vector_sink_c () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () # run the graph and wait for it to finish - actual_result = dst.data () # fetch the contents of the sink - self.assertComplexTuplesAlmostEqual (expected_result, actual_result) - - - -if __name__ == '__main__': - gr_unittest.run(test_diff_phasor, "test_diff_phasor.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py deleted file mode 100755 index 95b8c06641..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import math - -def sincos(x): - return math.cos(x) + math.sin(x) * 1j - -class test_bytes_to_syms (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_bytes_to_syms_001 (self): - src_data = (0x01, 0x80, 0x03) - expected_result = (-1, -1, -1, -1, -1, -1, -1, +1, - +1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, +1, +1) - src = gr.vector_source_b (src_data) - op = gr.bytes_to_syms () - dst = gr.vector_sink_f () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () - result_data = dst.data () - self.assertEqual (expected_result, result_data) - - def test_simple_framer (self): - src_data = (0x00, 0x11, 0x22, 0x33, - 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, - 0xcc, 0xdd, 0xee, 0xff) - - expected_result = ( - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x00, 0x00, 0x11, 0x22, 0x33, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x01, 0x44, 0x55, 0x66, 0x77, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) - - src = gr.vector_source_b (src_data) - op = gr.simple_framer (4) - dst = gr.vector_sink_b () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () - result_data = dst.data () - self.assertEqual (expected_result, result_data) - - -if __name__ == '__main__': - gr_unittest.run(test_bytes_to_syms, "test_bytes_to_syms.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py deleted file mode 100755 index 161e4a5cc1..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_glfsr_source(gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_000_make_b(self): - src = gr.glfsr_source_b(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) - - def test_001_degree_b(self): - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(0)) - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(33)) - - def test_002_correlation_b(self): - for degree in range(1,11): # Higher degrees take too long to correlate - src = gr.glfsr_source_b(degree, False) - b2f = gr.chunks_to_symbols_bf((-1.0,1.0), 1) - dst = gr.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() - self.tb.connect(src, b2f, dst) - self.tb.run() - self.tb.disconnect_all() - actual_result = dst.data() - R = auto_correlate(actual_result) - self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin - for i in range(len(R)-1): - self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else - - def test_003_make_f(self): - src = gr.glfsr_source_f(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) - - def test_004_degree_f(self): - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(0)) - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(33)) - def test_005_correlation_f(self): - for degree in range(1,11): # Higher degrees take too long to correlate - src = gr.glfsr_source_f(degree, False) - dst = gr.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() - self.tb.connect(src, dst) - self.tb.run() - - actual_result = dst.data() - R = auto_correlate(actual_result) - self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin - for i in range(len(R)-1): - self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else - -def auto_correlate(data): - l = len(data) - R = [0,]*l - for lag in range(l): - for i in range(l): - R[lag] += data[i]*data[i-lag] - return R - -if __name__ == '__main__': - gr_unittest.run(test_glfsr_source, "test_glfsr_source.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py deleted file mode 100755 index 6a62a6997b..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_pn_correlator_cc(gr_unittest.TestCase): - - def setUp(self): - self.tb = gr.top_block () - - def tearDown(self): - self.tb = None - - def test_000_make(self): - c = gr.pn_correlator_cc(10) - - def test_001_correlate(self): - degree = 10 - length = 2**degree-1 - src = gr.glfsr_source_f(degree) - head = gr.head(gr.sizeof_float, length*length) - f2c = gr.float_to_complex() - corr = gr.pn_correlator_cc(degree) - dst = gr.vector_sink_c() - self.tb.connect(src, head, f2c, corr, dst) - self.tb.run() - data = dst.data() - self.assertEqual(data[-1], (1.0+0j)) - -if __name__ == '__main__': - gr_unittest.run(test_pn_correlator_cc, "test_pn_correlator_cc.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py b/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py deleted file mode 100755 index 5fe89bdc7f..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_scrambler(gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_scrambler_descrambler(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.scrambler_bb(0x8a, 0x7F, 7) # CCSDS 7-bit scrambler - descrambler = gr.descrambler_bb(0x8a, 0x7F, 7) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(tuple(src_data[:-8]), dst.data()[8:]) # skip garbage during synchronization - - def test_additive_scrambler(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7) - descrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(src_data, dst.data()) - - def test_additive_scrambler_reset(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7, 100) - descrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7, 100) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(src_data, dst.data()) - -if __name__ == '__main__': - gr_unittest.run(test_scrambler, "test_scrambler.xml") diff --git a/gr-audio/examples/python/noise.py b/gr-audio/examples/python/noise.py index 12eee1906d..bba9e83eae 100755 --- a/gr-audio/examples/python/noise.py +++ b/gr-audio/examples/python/noise.py @@ -22,6 +22,7 @@ from gnuradio import gr from gnuradio import audio +from gnuradio import digital from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -44,7 +45,7 @@ class my_top_block(gr.top_block): ampl = 0.1 src = gr.glfsr_source_b(32) # Pseudorandom noise source - b2f = gr.chunks_to_symbols_bf([ampl, -ampl], 1) + b2f = digital.chunks_to_symbols_bf([ampl, -ampl], 1) dst = audio.sink(sample_rate, options.audio_output) self.connect(src, b2f, dst) diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py index ab7e988eba..daefc5116d 100755 --- a/gr-digital/examples/narrowband/digital_bert_rx.py +++ b/gr-digital/examples/narrowband/digital_bert_rx.py @@ -78,10 +78,10 @@ class bert_receiver(gr.hier_block2): self.connect(self._demod.time_recov, self._snr_probe) # Descramble BERT sequence. A channel error will create 3 incorrect bits - self._descrambler = gr.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler + self._descrambler = digital.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler # Measure BER by the density of 0s in the stream - self._ber = gr.probe_density_b(1.0/self._symbol_rate) + self._ber = digital.probe_density_b(1.0/self._symbol_rate) self.connect(self, self._demod, self._descrambler, self._ber) diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py index f29e997af6..7caccdf42b 100755 --- a/gr-digital/examples/narrowband/digital_bert_tx.py +++ b/gr-digital/examples/narrowband/digital_bert_tx.py @@ -43,7 +43,7 @@ class bert_transmit(gr.hier_block2): # Create BERT data bit stream self._bits = gr.vector_source_b([1,], True) # Infinite stream of ones - self._scrambler = gr.scrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit scrambler + self._scrambler = digital.scrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit scrambler self._mod = digital.generic_mod(constellation, samples_per_symbol, differential, excess_bw, gray_coded, diff --git a/gr-digital/grc/digital_dxpsk_demod.xml b/gr-digital/grc/digital_dxpsk_demod.xml index f3e9ee6fcc..1c6314d305 100644 --- a/gr-digital/grc/digital_dxpsk_demod.xml +++ b/gr-digital/grc/digital_dxpsk_demod.xml @@ -23,7 +23,7 @@ <!-- ################################################### -##DPSK2 Mod - 2, 4, 8 +##DPSK2 Mod - 2, 4 ################################################### --> <block> @@ -36,7 +36,7 @@ freq_bw=$freq_bw, phase_bw=$phase_bw, timing_bw=$timing_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log )</make> @@ -87,16 +87,15 @@ </param> <param> <name>Gray Code</name> - <key>gray_coded</key> - <value>True</value> + <key>mod_code</key> <type>enum</type> <option> <name>Yes</name> - <key>True</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>False</key> + <key>"none"</key> </option> </param> <param> diff --git a/gr-digital/grc/digital_dxpsk_mod.xml b/gr-digital/grc/digital_dxpsk_mod.xml index 93334d27d5..08a95f1a9c 100644 --- a/gr-digital/grc/digital_dxpsk_mod.xml +++ b/gr-digital/grc/digital_dxpsk_mod.xml @@ -23,7 +23,7 @@ <!-- ################################################### -## DPSK Mod - 2, 4, 8 +## DPSK Mod - 2, 4 ################################################### --> <block> @@ -33,7 +33,7 @@ <make>digital.$(type)_mod( samples_per_symbol=$samples_per_symbol, excess_bw=$excess_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log) </make> @@ -49,10 +49,6 @@ <name>DQPSK</name> <key>dqpsk</key> </option> - <option> - <name>D8PSK</name> - <key>d8psk</key> - </option> </param> <param> <name>Samples/Symbol</name> @@ -68,16 +64,15 @@ </param> <param> <name>Gray Code</name> - <key>gray_coded</key> - <value>True</value> + <key>mod_code</key> <type>enum</type> <option> <name>Yes</name> - <key>True</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>False</key> + <key>"none"</key> </option> </param> <param> diff --git a/gr-digital/grc/digital_simple_framer.xml b/gr-digital/grc/digital_simple_framer.xml index bbeed32d3e..2d57222f3b 100644 --- a/gr-digital/grc/digital_simple_framer.xml +++ b/gr-digital/grc/digital_simple_framer.xml @@ -7,8 +7,8 @@ <block> <name>Simple Framer</name> <key>digital_simple_framer</key> - <import>from gnuradio import gr</import> - <make>gr.simple_framer($payload_bytesize)</make> + <import>from gnuradio import digital</import> + <make>digital.simple_framer($payload_bytesize)</make> <param> <name>Payload Byte Size</name> <key>payload_bytesize</key> diff --git a/gr-digital/include/digital_bytes_to_syms.h b/gr-digital/include/digital_bytes_to_syms.h index 3062366b95..c1857c8cf2 100644 --- a/gr-digital/include/digital_bytes_to_syms.h +++ b/gr-digital/include/digital_bytes_to_syms.h @@ -39,12 +39,12 @@ DIGITAL_API digital_bytes_to_syms_sptr digital_make_bytes_to_syms(); * This block is deprecated. * * The combination of gr_packed_to_unpacked_bb followed by - * gr_chunks_to_symbols_bf or gr_chunks_to_symbols_bc handles the + * digital_chunks_to_symbols_bf or digital_chunks_to_symbols_bc handles the * general case of mapping from a stream of bytes into arbitrary float * or complex symbols. * * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + * \sa digital_chunks_to_symbols_bf, digital_chunks_to_symbols_bc. */ class DIGITAL_API digital_bytes_to_syms : public gr_sync_interpolator { diff --git a/gr-digital/include/digital_chunks_to_symbols_XX.h.t b/gr-digital/include/digital_chunks_to_symbols_XX.h.t index 92b7c94d58..3a82c68070 100644 --- a/gr-digital/include/digital_chunks_to_symbols_XX.h.t +++ b/gr-digital/include/digital_chunks_to_symbols_XX.h.t @@ -43,7 +43,7 @@ digital_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D * out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 * * The combination of gr_packed_to_unpacked_XX followed by - * gr_chunks_to_symbols_XY handles the general case of mapping + * digital_chunks_to_symbols_XY handles the general case of mapping * from a stream of bytes or shorts into arbitrary float * or complex symbols. * diff --git a/gr-digital/include/digital_framer_sink_1.h b/gr-digital/include/digital_framer_sink_1.h index bb82bf5a73..51d872d874 100644 --- a/gr-digital/include/digital_framer_sink_1.h +++ b/gr-digital/include/digital_framer_sink_1.h @@ -37,7 +37,7 @@ digital_make_framer_sink_1(gr_msg_queue_sptr target_queue); * \brief Given a stream of bits and access_code flags, assemble packets. * \ingroup sink_blk * - * input: stream of bytes from gr_correlate_access_code_bb + * input: stream of bytes from digital_correlate_access_code_bb * output: none. Pushes assembled packet into target queue * * The framer expects a fixed length header of 2 16-bit shorts diff --git a/gr-digital/include/digital_glfsr_source_b.h b/gr-digital/include/digital_glfsr_source_b.h index 92e5e81f5c..151e5a296c 100644 --- a/gr-digital/include/digital_glfsr_source_b.h +++ b/gr-digital/include/digital_glfsr_source_b.h @@ -26,7 +26,7 @@ #include <digital_api.h> #include <gr_sync_block.h> -class gri_glfsr; +class digital_impl_glfsr; class digital_glfsr_source_b; typedef boost::shared_ptr<digital_glfsr_source_b> digital_glfsr_source_b_sptr; @@ -54,7 +54,7 @@ class DIGITAL_API digital_glfsr_source_b : public gr_sync_block digital_make_glfsr_source_b(int degree, bool repeat, int mask, int seed); - gri_glfsr *d_glfsr; + digital_impl_glfsr *d_glfsr; bool d_repeat; unsigned int d_index; diff --git a/gr-digital/include/digital_glfsr_source_f.h b/gr-digital/include/digital_glfsr_source_f.h index 77d7b0f741..fb5b064e4f 100644 --- a/gr-digital/include/digital_glfsr_source_f.h +++ b/gr-digital/include/digital_glfsr_source_f.h @@ -26,7 +26,7 @@ #include <digital_api.h> #include <gr_sync_block.h> -class gri_glfsr; +class digital_impl_glfsr; class digital_glfsr_source_f; typedef boost::shared_ptr<digital_glfsr_source_f> digital_glfsr_source_f_sptr; @@ -54,7 +54,7 @@ class DIGITAL_API digital_glfsr_source_f : public gr_sync_block digital_make_glfsr_source_f(int degree, bool repeat, int mask, int seed); - gri_glfsr *d_glfsr; + digital_impl_glfsr *d_glfsr; bool d_repeat; unsigned int d_index; diff --git a/gr-digital/include/digital_pn_correlator_cc.h b/gr-digital/include/digital_pn_correlator_cc.h index 87cc2ff93c..407cc1e67b 100644 --- a/gr-digital/include/digital_pn_correlator_cc.h +++ b/gr-digital/include/digital_pn_correlator_cc.h @@ -25,7 +25,7 @@ #include <digital_api.h> #include <gr_sync_decimator.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> class digital_pn_correlator_cc; typedef boost::shared_ptr<digital_pn_correlator_cc> digital_pn_correlator_cc_sptr; @@ -56,7 +56,7 @@ class DIGITAL_API digital_pn_correlator_cc : public gr_sync_decimator int d_len; float d_pn; - gri_glfsr *d_reference; + digital_impl_glfsr *d_reference; protected: digital_pn_correlator_cc(int degree, int mask, int seed); diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index d9a53c4930..383c73c30d 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -466,8 +466,8 @@ digital_make_constellation_dqpsk() digital_constellation_dqpsk::digital_constellation_dqpsk () { // This constellation is not gray coded, which allows - // us to use differential encodings (through gr_diff_encode and - // gr_diff_decode) on the symbols. + // us to use differential encodings (through digital_diff_encode and + // digital_diff_decode) on the symbols. d_constellation.resize(4); d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO); d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO); diff --git a/gr-digital/lib/digital_glfsr_source_b.cc b/gr-digital/lib/digital_glfsr_source_b.cc index e557e475a8..63a5ffdb0a 100644 --- a/gr-digital/lib/digital_glfsr_source_b.cc +++ b/gr-digital/lib/digital_glfsr_source_b.cc @@ -26,7 +26,7 @@ #endif #include <digital_glfsr_source_b.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> #include <gr_io_signature.h> #include <stdexcept> @@ -50,8 +50,8 @@ digital_glfsr_source_b::digital_glfsr_source_b(int degree, bool repeat, d_length = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_glfsr = new digital_impl_glfsr(mask, seed); } digital_glfsr_source_b::~digital_glfsr_source_b() diff --git a/gr-digital/lib/digital_glfsr_source_f.cc b/gr-digital/lib/digital_glfsr_source_f.cc index 5a7736ef8d..6ae84d5679 100644 --- a/gr-digital/lib/digital_glfsr_source_f.cc +++ b/gr-digital/lib/digital_glfsr_source_f.cc @@ -26,7 +26,7 @@ #endif #include <digital_glfsr_source_f.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> #include <gr_io_signature.h> #include <stdexcept> @@ -50,8 +50,8 @@ digital_glfsr_source_f::digital_glfsr_source_f(int degree, bool repeat, d_length = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_glfsr = new digital_impl_glfsr(mask, seed); } digital_glfsr_source_f::~digital_glfsr_source_f() diff --git a/gr-digital/lib/digital_pn_correlator_cc.cc b/gr-digital/lib/digital_pn_correlator_cc.cc index 43a3ddbd1f..52e06bc2ad 100644 --- a/gr-digital/lib/digital_pn_correlator_cc.cc +++ b/gr-digital/lib/digital_pn_correlator_cc.cc @@ -44,8 +44,8 @@ digital_pn_correlator_cc::digital_pn_correlator_cc(int degree, { d_len = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_reference = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_reference = new digital_impl_glfsr(mask, seed); for (int i = 0; i < d_len; i++) // initialize to last value in sequence d_pn = 2.0*d_reference->next_bit()-1.0; } diff --git a/gr-digital/python/bpsk.py b/gr-digital/python/bpsk.py index 0d8f05c4c1..9f2354003c 100644 --- a/gr-digital/python/bpsk.py +++ b/gr-digital/python/bpsk.py @@ -31,18 +31,11 @@ from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod import digital_swig import modulation_utils -# Default number of points in constellation. -_def_constellation_points = 2 -# Whether differential coding is used. -_def_differential = False - # ///////////////////////////////////////////////////////////////////////////// # BPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def bpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("BPSK can only have 2 constellation points.") +def bpsk_constellation(): return digital_swig.constellation_bpsk() # ///////////////////////////////////////////////////////////////////////////// @@ -51,8 +44,7 @@ def bpsk_constellation(m=_def_constellation_points): class bpsk_mod(generic_mod): - def __init__(self, constellation_points=_def_constellation_points, - differential=False, *args, **kwargs): + def __init__(self, mod_code=None, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -61,12 +53,12 @@ class bpsk_mod(generic_mod): output is the complex modulated signal at baseband. See generic_mod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for BPSK.') super(bpsk_mod, self).__init__(constellation=constellation, differential=differential, *args, **kwargs) @@ -77,8 +69,7 @@ class bpsk_mod(generic_mod): class bpsk_demod(generic_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=False, *args, **kwargs): + def __init__(self, mod_code=None, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -87,12 +78,12 @@ class bpsk_demod(generic_demod): output is the complex modulated signal at baseband. See generic_demod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for BPSK.') super(bpsk_demod, self).__init__(constellation=constellation, differential=differential, *args, **kwargs) @@ -102,19 +93,16 @@ class bpsk_demod(generic_demod): # DBPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def dbpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("DBPSK can only have 2 constellation points.") +def dbpsk_constellation(): return digital_swig.constellation_dbpsk() # ///////////////////////////////////////////////////////////////////////////// # DBPSK modulator # ///////////////////////////////////////////////////////////////////////////// -class dbpsk_mod(generic_mod): +class dbpsk_mod(bpsk_mod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=None, *args, **kwargs): """ Hierarchical block for RRC-filtered DBPSK modulation. @@ -123,14 +111,12 @@ class dbpsk_mod(generic_mod): output is the complex modulated signal at baseband. See generic_mod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for DBPSK.') - super(dbpsk_mod, self).__init__(constellation=constellation, - differential=True, + super(dbpsk_mod, self).__init__(differential=True, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -138,10 +124,9 @@ class dbpsk_mod(generic_mod): # # ///////////////////////////////////////////////////////////////////////////// -class dbpsk_demod(generic_demod): +class dbpsk_demod(bpsk_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=None, *args, **kwargs): """ Hierarchical block for RRC-filtered DBPSK modulation. @@ -150,14 +135,12 @@ class dbpsk_demod(generic_demod): output is the complex modulated signal at baseband. See generic_demod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for DBPSK.') - super(dbpsk_demod, self).__init__(constellation=constellation, - differential=True, + super(dbpsk_demod, self).__init__(differential=True, *args, **kwargs) # diff --git a/gr-digital/python/cpm.py b/gr-digital/python/cpm.py index 05032336d4..f11832b626 100644 --- a/gr-digital/python/cpm.py +++ b/gr-digital/python/cpm.py @@ -131,7 +131,7 @@ class cpm_mod(gr.hier_block2): # Turn it into symmetric PAM data. - self.pam = gr.chunks_to_symbols_bf(self.sym_alphabet,1) + self.pam = digital_swig.chunks_to_symbols_bf(self.sym_alphabet,1) # Generate pulse (sum of taps = samples_per_symbol/2) if cpm_type == 0: # CPFSK diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index a6c4f3445a..105c6fe8ff 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -76,10 +76,10 @@ def add_common_options(parser): class generic_mod(gr.hier_block2): def __init__(self, constellation, - samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, + samples_per_symbol=_def_samples_per_symbol, + pre_diff_code=True, excess_bw=_def_excess_bw, - gray_coded=True, verbose=_def_verbose, log=_def_log): """ @@ -92,10 +92,12 @@ class generic_mod(gr.hier_block2): @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per baud >= 2 @type samples_per_symbol: float + @param differential: whether to use differential encoding + @type differential: boolean + @param pre_diff_code: whether to use apply a pre-differential mapping + @type pre_diff_code: boolean @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float - @param gray_coded: turn gray coding on/off - @type gray_coded: bool @param verbose: Print information about modulator? @type verbose: bool @param log: Log modulation data to files? @@ -110,6 +112,8 @@ class generic_mod(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._differential = differential + # Only apply a predifferential coding if the constellation also supports it. + self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %f" % self._samples_per_symbol) @@ -120,7 +124,7 @@ class generic_mod(gr.hier_block2): self.bytes2chunks = \ gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - if gray_coded == True: + if self.pre_diff_code: self.symbol_mapper = digital.map_bb(self._constellation.pre_diff_code()) if differential: @@ -142,7 +146,7 @@ class generic_mod(gr.hier_block2): # Connect blocks = [self, self.bytes2chunks] - if gray_coded == True: + if self.pre_diff_code: blocks.append(self.symbol_mapper) if differential: blocks.append(self.diffenc) @@ -186,7 +190,7 @@ class generic_mod(gr.hier_block2): print "Modulation logging turned on." self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.8b")) if self._differential: @@ -208,10 +212,10 @@ class generic_mod(gr.hier_block2): class generic_demod(gr.hier_block2): def __init__(self, constellation, - samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, + samples_per_symbol=_def_samples_per_symbol, + pre_diff_code=True, excess_bw=_def_excess_bw, - gray_coded=True, freq_bw=_def_freq_bw, timing_bw=_def_timing_bw, phase_bw=_def_phase_bw, @@ -227,10 +231,12 @@ class generic_demod(gr.hier_block2): @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per symbol >= 2 @type samples_per_symbol: float + @param differential: whether to use differential encoding + @type differential: boolean + @param pre_diff_code: whether to use apply a pre-differential mapping + @type pre_diff_code: boolean @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float - @param gray_coded: turn gray coding on/off - @type gray_coded: bool @param freq_bw: loop filter lock-in bandwidth @type freq_bw: float @param timing_bw: timing recovery loop lock-in bandwidth @@ -259,6 +265,9 @@ class generic_demod(gr.hier_block2): if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) + # Only apply a predifferential coding if the constellation also supports it. + self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() + arity = pow(2,self.bits_per_symbol()) nfilts = 32 @@ -289,7 +298,7 @@ class generic_demod(gr.hier_block2): if differential: self.diffdec = digital.diff_decoder_bb(arity) - if gray_coded: + if self.pre_diff_code: self.symbol_mapper = digital.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) @@ -307,7 +316,7 @@ class generic_demod(gr.hier_block2): self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: blocks.append(self.symbol_mapper) blocks += [self.unpack, self] self.connect(*blocks) @@ -357,7 +366,7 @@ class generic_demod(gr.hier_block2): if self._differential: self.connect(self.diffdec, gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) self.connect(self.unpack, diff --git a/gr-digital/python/pkt.py b/gr-digital/python/pkt.py index 8650bdbb02..09254a7caa 100644 --- a/gr-digital/python/pkt.py +++ b/gr-digital/python/pkt.py @@ -143,7 +143,7 @@ class demod_pkts(gr.hier_block2): self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY self.correlator = digital_swig.correlate_access_code_bb(access_code, threshold) - self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + self.framer_sink = digital.framer_sink_1(self._rcvd_pktq) self.connect(self, self._demodulator, self.correlator, self.framer_sink) self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) diff --git a/gr-digital/python/psk.py b/gr-digital/python/psk.py index 58f6787f0c..4b35447278 100644 --- a/gr-digital/python/psk.py +++ b/gr-digital/python/psk.py @@ -35,17 +35,23 @@ from generic_mod_demod import generic_mod, generic_demod _def_constellation_points = 4 # The default encoding (e.g. gray-code, set-partition) _def_mod_code = mod_codes.GRAY_CODE +# Default use of differential encoding +_def_differential = True -def create_encodings(mod_code, arity): +def create_encodings(mod_code, arity, differential): post_diff_code = None if mod_code not in mod_codes.codes: raise ValueError('That modulation code does not exist.') if mod_code == mod_codes.GRAY_CODE: - pre_diff_code = gray_code.gray_code(arity) - elif mod_code == mod_codes.SET_PARTITION_CODE: - pre_diff_code = set_partition_code.set_partition_code(arity) + if differential: + pre_diff_code = gray_code.gray_code(arity) + post_diff_code = None + else: + pre_diff_code = [] + post_diff_code = gray_code.gray_code(arity) elif mod_code == mod_codes.NO_CODE: pre_diff_code = [] + post_diff_code = None else: raise ValueError('That modulation code is not implemented for this constellation.') return (pre_diff_code, post_diff_code) @@ -54,7 +60,8 @@ def create_encodings(mod_code, arity): # PSK constellation # ///////////////////////////////////////////////////////////////////////////// -def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code): +def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential): """ Creates a PSK constellation object. """ @@ -62,7 +69,7 @@ def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code): if (k != int(k)): raise StandardError('Number of constellation points must be a power of two.') points = [exp(2*pi*(0+1j)*i/m) for i in range(0,m)] - pre_diff_code, post_diff_code = create_encodings(mod_code, m) + pre_diff_code, post_diff_code = create_encodings(mod_code, m, differential) if post_diff_code is not None: inverse_post_diff_code = mod_codes.invert_code(post_diff_code) points = [points[x] for x in inverse_post_diff_code] @@ -77,6 +84,7 @@ class psk_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential, *args, **kwargs): """ @@ -88,8 +96,8 @@ class psk_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = psk_constellation(constellation_points, mod_code) - super(psk_mod, self).__init__(constellation, *args, **kwargs) + constellation = psk_constellation(constellation_points, mod_code, differential) + super(psk_mod, self).__init__(constellation, differential, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// # PSK demodulator @@ -100,6 +108,7 @@ class psk_demod(generic_demod): def __init__(self, constellation_points=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential, *args, **kwargs): """ @@ -111,8 +120,8 @@ class psk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation = psk_constellation(constellation_points, mod_code) - super(psk_demod, self).__init__(constellation, *args, **kwargs) + constellation = psk_constellation(constellation_points, mod_code, differential) + super(psk_demod, self).__init__(constellation, differential, *args, **kwargs) # # Add these to the mod/demod registry diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py index b17d2a0fcb..e0b5b3888e 100755 --- a/gr-digital/python/qa_constellation.py +++ b/gr-digital/python/qa_constellation.py @@ -67,8 +67,24 @@ def threed_constell(): tested_constellation_info = ( (psk.psk_constellation, {'m': (2, 4, 8, 16, 32, 64), - 'mod_code': tested_mod_codes, }, + 'mod_code': tested_mod_codes, + 'differential': (True,)}, True, None), + (psk.psk_constellation, + {'m': (2, 4, 8, 16, 32, 64), + 'mod_code': tested_mod_codes, + 'differential': (False,)}, + False, None), + (qam.qam_constellation, + {'constellation_points': (4, 16, 64), + 'mod_code': tested_mod_codes, + 'differential': (True,)}, + True, None), + (qam.qam_constellation, + {'constellation_points': (4, 16, 64), + 'mod_code': tested_mod_codes, + 'differential': (False,)}, + False, None), (digital_swig.constellation_bpsk, {}, True, None), (digital_swig.constellation_qpsk, {}, False, None), (digital_swig.constellation_dqpsk, {}, True, None), @@ -167,13 +183,13 @@ class mod_demod(gr.hier_block2): # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): - self.blocks.append(gr.map_bb(self.constellation.pre_diff_code())) + self.blocks.append(digital_swig.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: - self.blocks.append(gr.diff_encoder_bb(arity)) + self.blocks.append(digital_swig.diff_encoder_bb(arity)) # Convert to constellation symbols. - self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), - self.constellation.dimensionality())) + self.blocks.append(digital_swig.chunks_to_symbols_bc(self.constellation.points(), + self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: @@ -184,10 +200,10 @@ class mod_demod(gr.hier_block2): self.blocks.append(digital_swig.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: - self.blocks.append(gr.diff_decoder_bb(arity)) + self.blocks.append(digital_swig.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): - self.blocks.append(gr.map_bb( + self.blocks.append(digital_swig.map_bb( mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(gr.unpack_k_bits_bb( diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py index 2d25433b92..8c2d2da0c5 100755 --- a/gr-digital/python/qa_constellation_receiver.py +++ b/gr-digital/python/qa_constellation_receiver.py @@ -85,11 +85,16 @@ class test_constellation_receiver (gr_unittest.TestCase): # That is not implemented since the receiver has no way of # knowing where the beginning of a symbol is. # It also doesn't work for non-differential modulation. - if constellation.dimensionality() != 1 or not differential: + if constellation.dimensionality() != 1: continue data_length = DATA_LENGTH * constellation.bits_per_symbol() + if differential: + freq_offset=True + else: + freq_offset=False tb = rec_test_tb(constellation, differential, - src_data=self.src_data[:data_length]) + src_data=self.src_data[:data_length], + freq_offset=freq_offset) tb.run() data = tb.dst.data() d1 = tb.src_data[:int(len(tb.src_data)*self.ignore_fraction)] @@ -105,12 +110,14 @@ class rec_test_tb (gr.top_block): and generic demodulation. """ def __init__(self, constellation, differential, - data_length=None, src_data=None): + data_length=None, src_data=None, freq_offset=True): """ - constellation -- a constellation object - differential -- whether differential encoding is used - data_length -- the number of bits of data to use - src_data -- a list of the bits to use + Args: + constellation: a constellation object + differential: whether differential encoding is used + data_length: the number of bits of data to use + src_data: a list of the bits to use + freq_offset: whether to use a frequency offset in the channel """ super(rec_test_tb, self).__init__() # Transmission Blocks @@ -122,11 +129,18 @@ class rec_test_tb (gr.top_block): src = gr.vector_source_b(self.src_data) mod = generic_mod(constellation, differential=differential) # Channel - channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) + if freq_offset: + channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) + else: + channel = gr.channel_model(NOISE_VOLTAGE, 0, TIMING_OFFSET) # Receiver Blocks - demod = generic_demod(constellation, differential=differential, - freq_bw=FREQ_BW, - phase_bw=PHASE_BW) + if freq_offset: + demod = generic_demod(constellation, differential=differential, + freq_bw=FREQ_BW, + phase_bw=PHASE_BW) + else: + demod = generic_demod(constellation, differential=differential, + freq_bw=0, phase_bw=0) self.dst = gr.vector_sink_b() self.connect(src, packer, mod, channel, demod, self.dst) diff --git a/gr-digital/python/qa_glfsr_source.py b/gr-digital/python/qa_glfsr_source.py index 157520d7f8..7d02037335 100755 --- a/gr-digital/python/qa_glfsr_source.py +++ b/gr-digital/python/qa_glfsr_source.py @@ -38,9 +38,9 @@ class test_glfsr_source(gr_unittest.TestCase): def test_001_degree_b(self): self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(0)) + lambda: digital.glfsr_source_b(0)) self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(33)) + lambda: digital.glfsr_source_b(33)) def test_002_correlation_b(self): for degree in range(1,11): # Higher degrees take too long to correlate @@ -65,9 +65,9 @@ class test_glfsr_source(gr_unittest.TestCase): def test_004_degree_f(self): self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(0)) + lambda: digital.glfsr_source_f(0)) self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(33)) + lambda: digital.glfsr_source_f(33)) def test_005_correlation_f(self): for degree in range(1,11): # Higher degrees take too long to correlate src = digital.glfsr_source_f(degree, False) diff --git a/gr-digital/python/qam.py b/gr-digital/python/qam.py index 5b1f7683b8..0635fda75e 100644 --- a/gr-digital/python/qam.py +++ b/gr-digital/python/qam.py @@ -157,14 +157,20 @@ def qam_constellation(constellation_points=_def_constellation_points, else: raise ValueError("Mod code is not implemented for QAM") if differential: - points = make_differential_constellation(constellation_points, gray_coded) + points = make_differential_constellation(constellation_points, gray_coded=False) else: points = make_non_differential_constellation(constellation_points, gray_coded) side = int(sqrt(constellation_points)) width = 2.0/(side-1) - # No pre-diff code - # Should add one so that we can gray-code the quadrant bits too. - pre_diff_code = [] + # For differential and gray-coded then gray-code the first two + # bits with a pre_diff_code. + # FIXME: It would be good to have a test to make sure that gray-coded constellations + # are really gray-coded. Perhaps by checking on the correlation between bit-errors. + if differential and gray_coded: + m = constellation_points + pre_diff_code = range(0, m/2) + range(3*m/4, m) + range(m/2, 3*m/4) + else: + pre_diff_code = [] constellation = digital_swig.constellation_rect(points, pre_diff_code, 4, side, side, width, width) return constellation diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py index be21fd76f1..2fdeabd40f 100644 --- a/gr-digital/python/qpsk.py +++ b/gr-digital/python/qpsk.py @@ -27,21 +27,20 @@ Demodulation is not included since the generic_mod_demod from gnuradio import gr from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod +from utils import mod_codes import digital_swig import modulation_utils -# Default number of points in constellation. -_def_constellation_points = 4 -# Whether gray coding is used. -_def_gray_coded = True +# The default encoding (e.g. gray-code, set-partition) +_def_mod_code = mod_codes.GRAY_CODE # ///////////////////////////////////////////////////////////////////////////// # QPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def qpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("QPSK can only have 4 constellation points.") +def qpsk_constellation(mod_code=_def_mod_code): + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") return digital_swig.constellation_qpsk() # ///////////////////////////////////////////////////////////////////////////// @@ -50,9 +49,7 @@ def qpsk_constellation(m=_def_constellation_points): class qpsk_mod(generic_mod): - def __init__(self, constellation_points=_def_constellation_points, - gray_coded=_def_gray_coded, - *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered QPSK modulation. @@ -62,15 +59,21 @@ class qpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() - if constellation_points != 4: - raise ValueError("QPSK can only have 4 constellation points.") - if not gray_coded: - raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + + pre_diff_code = True + if not differential: + constellation = digital_swig.constellation_qpsk() + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + else: + constellation = digital_swig.constellation_dqpsk() + if mod_code not in (mod_codes.GRAY_CODE or mod_codes.NO_CODE): + raise ValueError("That mod_code is not supported for DQPSK mod/demod.") + if mod_code == mod_codes.NO_CODE: + pre_diff_code = False + super(qpsk_mod, self).__init__(constellation=constellation, - gray_coded=gray_coded, + pre_diff_code=pre_diff_code, *args, **kwargs) @@ -81,7 +84,7 @@ class qpsk_mod(generic_mod): class qpsk_demod(generic_demod): - def __init__(self, constellation_points=_def_constellation_points, + def __init__(self, mod_code=_def_mod_code, differential=False, *args, **kwargs): """ @@ -93,11 +96,20 @@ class qpsk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for QPSK.') + pre_diff_code = True + if not differential: + constellation = digital_swig.constellation_qpsk() + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + else: + constellation = digital_swig.constellation_dqpsk() + if mod_code not in (mod_codes.GRAY_CODE or mod_codes.NO_CODE): + raise ValueError("That mod_code is not supported for DQPSK mod/demod.") + if mod_code == mod_codes.NO_CODE: + pre_diff_code = False + super(qpsk_demod, self).__init__(constellation=constellation, + pre_diff_code=pre_diff_code, *args, **kwargs) @@ -106,20 +118,18 @@ class qpsk_demod(generic_demod): # DQPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def dqpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("DQPSK can only have 4 constellation points.") +def dqpsk_constellation(mod_code=_def_mod_code): + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("The DQPSK constellation is only generated for gray_coding. But it can be used for non-grayed coded modulation if one doesn't use the pre-differential code.") return digital_swig.constellation_dqpsk() # ///////////////////////////////////////////////////////////////////////////// # DQPSK modulator # ///////////////////////////////////////////////////////////////////////////// -class dqpsk_mod(generic_mod): +class dqpsk_mod(qpsk_mod): - def __init__(self, constellation_points=_def_constellation_points, - gray_coded=_def_gray_coded, - differential=True, *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, *args, **kwargs): """ Hierarchical block for RRC-filtered DQPSK modulation. @@ -128,14 +138,7 @@ class dqpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_dqpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for DQPSK.') - super(dqpsk_mod, self).__init__(constellation=constellation, - gray_coded=gray_coded, - differential=True, + super(dqpsk_mod, self).__init__(mod_code, differential=True, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -143,10 +146,9 @@ class dqpsk_mod(generic_mod): # # ///////////////////////////////////////////////////////////////////////////// -class dqpsk_demod(generic_demod): +class dqpsk_demod(qpsk_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, *args, **kwargs): """ Hierarchical block for RRC-filtered DQPSK modulation. @@ -156,12 +158,7 @@ class dqpsk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_dqpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for DQPSK.') - super(dqpsk_demod, self).__init__(constellation=constellation, - differential=True, + super(dqpsk_demod, self).__init__(mod_code, differential=True, *args, **kwargs) # diff --git a/gr-fcd/doc/README.fcd b/gr-fcd/doc/README.fcd index 83b4da1ce3..c6ee02fff0 100644 --- a/gr-fcd/doc/README.fcd +++ b/gr-fcd/doc/README.fcd @@ -1,7 +1,7 @@ This is the gr-fcd package. It contains a source block for the FunCube Dongle hardware. -The Python namespace is in gnuradio.qtgui, which would be normally +The Python namespace is in gnuradio.fcd, which would be normally imported as: from gnuradio import fcd diff --git a/gr-fcd/doc/fcd.dox b/gr-fcd/doc/fcd.dox index 6e07c585bc..aca4dadaad 100644 --- a/gr-fcd/doc/fcd.dox +++ b/gr-fcd/doc/fcd.dox @@ -5,7 +5,7 @@ This is the gr-fcd package. It contains a source block for the FunCube Dongle hardware. -The Python namespace is in gnuradio.qtgui, which would be normally +The Python namespace is in gnuradio.fcd, which would be normally imported as: \code diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h index e3fd3f278a..305b1cb711 100644 --- a/gr-fft/include/fft/fft.h +++ b/gr-fft/include/fft/fft.h @@ -35,14 +35,18 @@ namespace gr { namespace fft { - /*! \brief Helper function for allocating complex fft buffers + /*! \brief Helper function for allocating complex* buffers */ FFT_API gr_complex* malloc_complex(int size); - /*! \brief Helper function for allocating float fft buffers + /*! \brief Helper function for allocating float* buffers */ FFT_API float* malloc_float(int size); + /*! \brief Helper function for allocating double* buffers + */ + FFT_API double* malloc_double(int size); + /*! \brief Helper function for freeing fft buffers */ FFT_API void free(void *b); diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc index 6074236e18..60838ee302 100644 --- a/gr-fft/lib/fft.cc +++ b/gr-fft/lib/fft.cc @@ -62,6 +62,12 @@ namespace gr { return (float*)fftwf_malloc(sizeof(float)*size); } + double * + malloc_double(int size) + { + return (double*)fftwf_malloc(sizeof(double)*size); + } + void free(void *b) { diff --git a/gr-filter/include/filter/firdes.h b/gr-filter/include/filter/firdes.h index 172563ea00..0ae5894b38 100644 --- a/gr-filter/include/filter/firdes.h +++ b/gr-filter/include/filter/firdes.h @@ -40,6 +40,7 @@ namespace gr { public: enum win_type { + WIN_NONE = -1, // don't use a window WIN_HAMMING = 0, // max attenuation 53 dB WIN_HANN = 1, // max attenuation 44 dB WIN_BLACKMAN = 2, // max attenuation 74 dB diff --git a/gr-qtgui/CMakeLists.txt b/gr-qtgui/CMakeLists.txt index f6260bc7e9..be35beeec2 100644 --- a/gr-qtgui/CMakeLists.txt +++ b/gr-qtgui/CMakeLists.txt @@ -46,7 +46,11 @@ GR_REGISTER_COMPONENT("gr-qtgui" ENABLE_GR_QTGUI Boost_FOUND QT4_FOUND QWT_FOUND + ENABLE_GRUEL + ENABLE_VOLK ENABLE_GR_CORE + ENABLE_GR_FFT + ENABLE_GR_FILTER PYTHONLIBS_FOUND ${qt_gui_python_deps} ) @@ -103,7 +107,7 @@ CPACK_COMPONENT("qtgui_swig" ######################################################################## # Add subdirectories ######################################################################## -add_subdirectory(include) +add_subdirectory(include/qtgui) add_subdirectory(lib) add_subdirectory(doc) if(ENABLE_PYTHON) @@ -111,6 +115,7 @@ if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python) add_subdirectory(examples) + add_subdirectory(apps) endif(ENABLE_PYTHON) ######################################################################## diff --git a/gr-qtgui/apps/CMakeLists.txt b/gr-qtgui/apps/CMakeLists.txt new file mode 100644 index 0000000000..07a8298701 --- /dev/null +++ b/gr-qtgui/apps/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +include(GrPython) + +GR_PYTHON_INSTALL( + FILES + plot_form.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/qtgui + COMPONENT "qtgui_python" +) + +GR_PYTHON_INSTALL( + PROGRAMS + gr_time_plot_c + gr_time_plot_f + gr_time_plot_i + gr_time_plot_s + gr_time_plot_b + gr_psd_plot_c + gr_psd_plot_f + gr_psd_plot_i + gr_psd_plot_s + gr_psd_plot_b + gr_spectrogram_plot_c + gr_spectrogram_plot_f + gr_spectrogram_plot_i + gr_spectrogram_plot_s + gr_spectrogram_plot_b + gr_constellation_plot + DESTINATION ${GR_RUNTIME_DIR} + COMPONENT "qtgui_python" +) diff --git a/gr-qtgui/apps/gr_constellation_plot b/gr-qtgui/apps/gr_constellation_plot new file mode 100755 index 0000000000..66d227ecc9 --- /dev/null +++ b/gr-qtgui/apps/gr_constellation_plot @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_gr_complex, 0) + data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, start, nsamples, max_nsamples): + gr.top_block.__init__(self) + + self._filelist = filelist + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) + self.gui_snk = qtgui.const_sink_c(self._nsamps, + "GNU Radio Constellation Plot", + self._nsigs) + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_c(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots the constellations of a list of files." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.start, nsamples, max_nsamples); + + main_box = dialog_box(tb, 'GNU Radio Constellation Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_psd_plot_b b/gr-qtgui/apps/gr_psd_plot_b new file mode 100755 index 0000000000..e3e86a271f --- /dev/null +++ b/gr-qtgui/apps/gr_psd_plot_b @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_char, 0) + data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.uint8(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio PSD Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_b(data)) + self.cnvrt.append(gr.char_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the PSDs of a list of files. Files are a binary list of chars/bytes." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, + help="Set a scaling factor for the char->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_char) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average) + + main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_psd_plot_c b/gr-qtgui/apps/gr_psd_plot_c new file mode 100755 index 0000000000..faa0fc60a4 --- /dev/null +++ b/gr-qtgui/apps/gr_psd_plot_c @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_gr_complex, 0) + data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [complex(0,0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) + self.gui_snk = qtgui.freq_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio PSD Plot", self._nsigs) + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_c(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the PSDs of a list of files. Files are a binary list of complex floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.average); + + main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_psd_plot_f b/gr-qtgui/apps/gr_psd_plot_f new file mode 100755 index 0000000000..326618f848 --- /dev/null +++ b/gr-qtgui/apps/gr_psd_plot_f @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_float, 0) + data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.float32(0.0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio PSD Plot", self._nsigs) + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_f(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the PSDs of a list of files. Files are a binary list of floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_float) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.average); + + main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_psd_plot_i b/gr-qtgui/apps/gr_psd_plot_i new file mode 100755 index 0000000000..a0264ac1c9 --- /dev/null +++ b/gr-qtgui/apps/gr_psd_plot_i @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_int, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.int32(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio PSD Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_i(data)) + self.cnvrt.append(gr.int_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the PSDs of a list of files. Files are a binary list of integers." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, + help="Set a scaling factor for the int->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_int) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average) + + main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_psd_plot_s b/gr-qtgui/apps/gr_psd_plot_s new file mode 100755 index 0000000000..6852cf7d0f --- /dev/null +++ b/gr-qtgui/apps/gr_psd_plot_s @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_short, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.int16(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio PSD Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_s(data)) + self.cnvrt.append(gr.short_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the PSDs of a list of files. Files are a binary list of shorts." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, + help="Set a scaling factor for the short->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_short) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average) + + main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_spectrogram_plot_b b/gr-qtgui/apps/gr_spectrogram_plot_b new file mode 100755 index 0000000000..41c1af521a --- /dev/null +++ b/gr-qtgui/apps/gr_spectrogram_plot_b @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_char, 0) + data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.uint8(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.add = gr.add_ff() + self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio Spectrogram Plot") + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_b(data)) + self.cnvrt.append(gr.char_to_float(1, self._scale)) + n += 1 + + self.connect(self.add, self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs): + self.connect(s, self.cnvrt[i], (self.add, i)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of chars/bytes." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, + help="Set a scaling factor for the char->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_char) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average); + + main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_spectrogram_plot_c b/gr-qtgui/apps/gr_spectrogram_plot_c new file mode 100755 index 0000000000..28fa82f298 --- /dev/null +++ b/gr-qtgui/apps/gr_spectrogram_plot_c @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_gr_complex, 0) + data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [complex(0,0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) + self.add = gr.add_cc() + self.gui_snk = qtgui.waterfall_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio Spectrogram Plot") + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_c(data)) + n += 1 + + self.connect(self.add, self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs): + self.connect(s, (self.add, i)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of complex floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.average); + + main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_spectrogram_plot_f b/gr-qtgui/apps/gr_spectrogram_plot_f new file mode 100755 index 0000000000..d1bb73212a --- /dev/null +++ b/gr-qtgui/apps/gr_spectrogram_plot_f @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_float, 0) + data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.float32(0.0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.add = gr.add_ff() + self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio Spectrogram Plot") + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_f(data)) + n += 1 + + self.connect(self.add, self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs): + self.connect(s, (self.add, i)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_float) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.average); + + main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_spectrogram_plot_i b/gr-qtgui/apps/gr_spectrogram_plot_i new file mode 100755 index 0000000000..a617f9087d --- /dev/null +++ b/gr-qtgui/apps/gr_spectrogram_plot_i @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_int, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.int32(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.add = gr.add_ff() + self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio Spectrogram Plot") + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_i(data)) + self.cnvrt.append(gr.int_to_float(1, self._scale)) + n += 1 + + self.connect(self.add, self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs): + self.connect(s, self.cnvrt[i], (self.add, i)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of integers." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, + help="Set a scaling factor for the int->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_int) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average); + + main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_spectrogram_plot_s b/gr-qtgui/apps/gr_spectrogram_plot_s new file mode 100755 index 0000000000..29f3d3df77 --- /dev/null +++ b/gr-qtgui/apps/gr_spectrogram_plot_s @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples_and_pad(filename, start, in_size, min_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_short, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) + data = data.tolist() + fhandle.close() + + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [scipy.int16(0)] + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, scale, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + self._avg = avg + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.add = gr.add_ff() + self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, + self._center_freq, self._samp_rate, + "GNU Radio Spectrogram Plot") + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + self.srcs.append(gr.vector_source_s(data)) + self.cnvrt.append(gr.short_to_float(1, self._scale)) + n += 1 + + self.connect(self.add, self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs): + self.connect(s, self.cnvrt[i], (self.add, i)) + + self.gui_snk.set_update_time(0); + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + self._nsamps = newnsamps + + for s,f in zip(self.srcs, self._filelist): + data = read_samples_and_pad(f, self._start, + self._nsamps, self._psd_size) + s.set_data(data) + + self.start() + +def main(): + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of shorts." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, + help="Set a scaling factor for the short->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_short) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, nsamples, max_nsamples, + options.scale, options.average); + + main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_time_plot_b b/gr-qtgui/apps/gr_time_plot_b new file mode 100755 index 0000000000..90043c91f6 --- /dev/null +++ b/gr-qtgui/apps/gr_time_plot_b @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_char, 0) + data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class gr_time_plot_f(gr.top_block): + def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, + "GNU Radio Time Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_b(data)) + self.cnvrt.append(gr.char_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots a list of files on a scope plot. Files are a binary list of chars/bytes." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, + help="Set a scaling factor for the char->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_char) + max_nsamples = min(filesizes) + + tb = gr_time_plot_f(filelist, options.sample_rate, + options.start, nsamples, max_nsamples, + options.scale); + + main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_time_plot_c b/gr-qtgui/apps/gr_time_plot_c new file mode 100755 index 0000000000..858bbce240 --- /dev/null +++ b/gr-qtgui/apps/gr_time_plot_c @@ -0,0 +1,167 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_gr_complex, 0) + data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class my_top_block(gr.top_block): + def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) + self.gui_snk = qtgui.time_sink_c(self._nsamps, self._samp_rate, + "GNU Radio Time Plot", self._nsigs) + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_c(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "Re{{{0}}}".format(fname)) + self.gui_snk.set_title(n+1, "Im{{{0}}}".format(fname)) + n += 2 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots a list of files on a scope plot. Files are a binary list of complex floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) + max_nsamples = min(filesizes) + + tb = my_top_block(filelist, options.sample_rate, + options.start, nsamples, max_nsamples); + + main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_time_plot_f b/gr-qtgui/apps/gr_time_plot_f new file mode 100755 index 0000000000..30834aca7a --- /dev/null +++ b/gr-qtgui/apps/gr_time_plot_f @@ -0,0 +1,166 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_float, 0) + data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class gr_time_plot_f(gr.top_block): + def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, + "GNU Radio Time Plot", self._nsigs) + n = 0 + self.srcs = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_f(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots a list of files on a scope plot. Files are a binary list of floats." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_float) + max_nsamples = min(filesizes) + + tb = gr_time_plot_f(filelist, options.sample_rate, + options.start, nsamples, max_nsamples); + + main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_time_plot_i b/gr-qtgui/apps/gr_time_plot_i new file mode 100755 index 0000000000..202fc32793 --- /dev/null +++ b/gr-qtgui/apps/gr_time_plot_i @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_int, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class gr_time_plot_f(gr.top_block): + def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, + "GNU Radio Time Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_i(data)) + self.cnvrt.append(gr.int_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots a list of files on a scope plot. Files are a binary list of integers." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, + help="Set a scaling factor for the int->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_int) + max_nsamples = min(filesizes) + + tb = gr_time_plot_f(filelist, options.sample_rate, + options.start, nsamples, max_nsamples, + options.scale); + + main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/gr_time_plot_s b/gr-qtgui/apps/gr_time_plot_s new file mode 100755 index 0000000000..6788284833 --- /dev/null +++ b/gr-qtgui/apps/gr_time_plot_s @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * +except ImportError: + from plot_form import * + +def read_samples(filename, start, in_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_short, 0) + data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) + data = data.tolist() + fhandle.close() + + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + + return data + +class gr_time_plot_f(gr.top_block): + def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._start = start + self._max_nsamps = max_nsamples + self._scale = scale + self._nsigs = len(self._filelist) + + if(nsamples is None): + self._nsamps = max_nsamples + else: + self._nsamps = nsamples + + self.qapp = QtGui.QApplication(sys.argv) + + self.skip = gr.skiphead(gr.sizeof_float, self._start) + self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, + "GNU Radio Time Plot", self._nsigs) + n = 0 + self.srcs = list() + self.cnvrt = list() + for f in filelist: + data = read_samples(f, self._start, self._nsamps) + self.srcs.append(gr.vector_source_s(data)) + self.cnvrt.append(gr.short_to_float(1, self._scale)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_title(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.cnvrt[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + def get_gui(self): + return self.pyWin + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + for s,f in zip(self.srcs, self._filelist): + data = read_samples(f, self._start, newnsamps) + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + +def main(): + description = "Plots a list of files on a scope plot. Files are a binary list of shorts." + parser = OptionParser(option_class=eng_option, description=description, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=None, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, + help="Set a scaling factor for the short->float conversion [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + filelist = list(args) + + nsamples = options.nsamples + + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_short) + max_nsamples = min(filesizes) + + tb = gr_time_plot_f(filelist, options.sample_rate, + options.start, nsamples, max_nsamples, + options.scale); + + main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box.show() + + tb.run() + tb.qapp.exec_() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py new file mode 100644 index 0000000000..2fb19d72b8 --- /dev/null +++ b/gr-qtgui/apps/plot_form.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +try: + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, top_block, title=''): + QtGui.QWidget.__init__(self, None) + + self._start = 0 + self._end = 0 + + self.top_block = top_block + + self.setWindowTitle(title) + + self.size_val = QtGui.QIntValidator(0, top_block._max_nsamps, self) + + self.start_form = QtGui.QFormLayout() + self.start_edit = QtGui.QLineEdit(self) + self.start_edit.setMinimumWidth(100) + self.start_edit.setText(QtCore.QString("%1").arg(top_block._start)) + self.start_edit.setValidator(self.size_val) + self.start_form.addRow("Start:", self.start_edit) + self.connect(self.start_edit, QtCore.SIGNAL("returnPressed()"), + self.update_points) + + end = top_block._start + top_block._nsamps + self.end_form = QtGui.QFormLayout() + self.end_edit = QtGui.QLineEdit(self) + self.end_edit.setMinimumWidth(100) + self.end_edit.setText(QtCore.QString("%1").arg(end)) + self.end_edit.setValidator(self.size_val) + self.end_form.addRow("End:", self.end_edit) + self.connect(self.end_edit, QtCore.SIGNAL("returnPressed()"), + self.update_points) + + self.layout = QtGui.QGridLayout(self) + self.layout.addWidget(top_block.get_gui(), 0,0,1,2) + self.layout.addLayout(self.start_form, 1,0,1,1) + self.layout.addLayout(self.end_form, 1,1,1,1) + + self.resize(800, 500) + + def update_points(self): + newstart = self.start_edit.text().toUInt()[0] + newend = self.end_edit.text().toUInt()[0] + if(newstart != self._start or newend != self._end): + if(newend < newstart): + QtGui.QMessageBox.information( + self, "Warning", + "End sample is less than start sample.", + QtGui.QMessageBox.Ok); + else: + newnsamps = newend - newstart + self.top_block.reset(newstart, newnsamps) + self._start = newstart + self._end = newend diff --git a/gr-qtgui/apps/qt_digital.py b/gr-qtgui/apps/qt_digital.py index 2bc039a31f..d353e0041c 100755 --- a/gr-qtgui/apps/qt_digital.py +++ b/gr-qtgui/apps/qt_digital.py @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blks2 +from gnuradio import gr, digital from gnuradio import eng_notation import sys @@ -60,7 +60,7 @@ class dialog_box(QtGui.QMainWindow): self.set_time_offset(self.fg.timing_offset()) self.set_gain_mu(self.fg.rx_gain_mu()) - self.set_alpha(self.fg.rx_alpha()) + self.set_loop_bw(self.fg.loop_bw()) # Add the qtsnk widgets to the hlayout box self.gui.sinkLayout.addWidget(snkTx) @@ -146,13 +146,13 @@ class dialog_box(QtGui.QMainWindow): def set_gain_mu(self, gain): self.gui.gainMuEdit.setText(QtCore.QString("%1").arg(gain)) - def set_alpha(self, alpha): - self.gui.alphaEdit.setText(QtCore.QString("%1").arg(alpha)) + def set_loop_bw(self, bw): + self.gui.alphaEdit.setText(QtCore.QString("%1").arg(bw)) def alphaEditText(self): try: - alpha = self.gui.alphaEdit.text().toDouble()[0] - self.fg.set_rx_alpha(alpha) + bw = self.gui.alphaEdit.text().toDouble()[0] + self.fg.set_loop_bw(bw) except RuntimeError: pass @@ -174,13 +174,16 @@ class my_top_block(gr.top_block): self.sps = 2 self.excess_bw = 0.35 - self.gray_code = True + self.gray_code = digital.mod_codes.GRAY_CODE fftsize = 2048 self.data = scipy.random.randint(0, 255, 1000) self.src = gr.vector_source_b(self.data.tolist(), True) - self.mod = blks2.dqpsk_mod(self.sps, self.excess_bw, self.gray_code, False, False) + self.mod = digital.dqpsk_mod(self.gray_code, + samples_per_symbol=self.sps, + excess_bw=self.excess_bw, + verbose=False, log=False) self.rrctaps = gr.firdes.root_raised_cosine(1, self.sps, 1, self.excess_bw, 21) self.rx_rrc = gr.fir_filter_ccf(1, self.rrctaps) @@ -194,17 +197,16 @@ class my_top_block(gr.top_block): self.gain_omega = .25 * self.gain_mu * self.gain_mu self.omega_rel_lim = 0.05 - self.alpha = 0.15 - self.beta = 0.25 * self.alpha * self.alpha + self._loop_bw = 2*scipy.pi/100.0 self.fmin = -1000/self.sample_rate() self.fmax = 1000/self.sample_rate() - self.receiver = gr.mpsk_receiver_cc(self.arity, 0, - self.alpha, self.beta, - self.fmin, self.fmax, - self.mu, self.gain_mu, - self.omega, self.gain_omega, - self.omega_rel_lim) + self.receiver = digital.mpsk_receiver_cc(self.arity, 0, + self._loop_bw, + self.fmin, self.fmax, + self.mu, self.gain_mu, + self.omega, self.gain_omega, + self.omega_rel_lim) self.snr_dB = 15 @@ -288,18 +290,12 @@ class my_top_block(gr.top_block): self.receiver.set_gain_mu(self.gain_mu) self.receiver.set_gain_omega(self.gain_omega) - def rx_alpha(self): - return self.alpha - - def rx_beta(self): - return self.beta - - def set_rx_alpha(self, alpha): - self.alpha = alpha - self.beta = .25 * self.alpha * self.alpha - self.receiver.set_alpha(self.alpha) - self.receiver.set_beta(self.beta) + def set_loop_bw(self, loop_bw): + self._loop_bw = bw + self.receiver.set_loop_bw(self._loop_bw) + def loop_bw(self): + return self._loop_bw if __name__ == "__main__": tb = my_top_block(); diff --git a/gr-qtgui/apps/uhd_display.py b/gr-qtgui/apps/uhd_display.py index d02fbad9ee..250d757b6c 100755 --- a/gr-qtgui/apps/uhd_display.py +++ b/gr-qtgui/apps/uhd_display.py @@ -24,12 +24,11 @@ from gnuradio import gr from gnuradio import uhd from gnuradio import eng_notation from gnuradio.eng_option import eng_option -from gnuradio.qtgui import qtgui from optparse import OptionParser import sys try: - from gnuradio.qtgui import qtgui + from gnuradio import qtgui from PyQt4 import QtGui, QtCore import sip except ImportError: diff --git a/gr-qtgui/doc/qtgui.dox b/gr-qtgui/doc/qtgui.dox index 8664af163d..c12fbf0106 100644 --- a/gr-qtgui/doc/qtgui.dox +++ b/gr-qtgui/doc/qtgui.dox @@ -51,7 +51,7 @@ while the GUI is alive. \code from PyQt4 import Qt -from gnuradio.qtgui import qtgui +from gnuradio import qtgui import sys, sip class grclass(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_const_c.py b/gr-qtgui/examples/pyqt_const_c.py new file mode 100755 index 0000000000..e3cc3e527e --- /dev/null +++ b/gr-qtgui/examples/pyqt_const_c.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, display, control): + QtGui.QWidget.__init__(self, None) + self.setWindowTitle('PyQt Test GUI') + + self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self) + self.boxlayout.addWidget(display, 1) + self.boxlayout.addWidget(control) + + self.resize(800, 500) + +class control_box(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Control Panel') + + self.setToolTip('Control the signals') + QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10)) + + self.layout = QtGui.QFormLayout(self) + + # Control the first signal + self.freq1Edit = QtGui.QLineEdit(self) + self.freq1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Frequency:", self.freq1Edit) + self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"), + self.freq1EditText) + + self.amp1Edit = QtGui.QLineEdit(self) + self.amp1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit) + self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"), + self.amp1EditText) + + + # Control the second signal + self.freq2Edit = QtGui.QLineEdit(self) + self.freq2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Frequency:", self.freq2Edit) + self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"), + self.freq2EditText) + + + self.amp2Edit = QtGui.QLineEdit(self) + self.amp2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit) + self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"), + self.amp2EditText) + + self.quit = QtGui.QPushButton('Close', self) + self.quit.setMinimumWidth(100) + self.layout.addWidget(self.quit) + + self.connect(self.quit, QtCore.SIGNAL('clicked()'), + QtGui.qApp, QtCore.SLOT('quit()')) + + def attach_signal1(self, signal): + self.signal1 = signal + self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency())) + self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude())) + + def attach_signal2(self, signal): + self.signal2 = signal + self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency())) + self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude())) + + def freq1EditText(self): + try: + newfreq = float(self.freq1Edit.text()) + self.signal1.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp1EditText(self): + try: + newamp = float(self.amp1Edit.text()) + self.signal1.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + + def freq2EditText(self): + try: + newfreq = float(self.freq2Edit.text()) + self.signal2.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp2EditText(self): + try: + newamp = float(self.amp2Edit.text()) + self.signal2.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + +class my_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + Rs = 8000 + f1 = 100 + f2 = 200 + + npts = 2048 + + self.qapp = QtGui.QApplication(sys.argv) + + src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.5, 0) + src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.5, 0) + src = gr.add_cc() + channel = gr.channel_model(0.001) + thr = gr.throttle(gr.sizeof_gr_complex, 100*npts) + self.snk1 = qtgui.const_sink_c(npts, "Constellation Example", 1) + + self.connect(src1, (src,0)) + self.connect(src2, (src,1)) + self.connect(src, channel, thr, (self.snk1, 0)) + + self.ctrl_win = control_box() + self.ctrl_win.attach_signal1(src1) + self.ctrl_win.attach_signal2(src2) + + # Get the reference pointer to the SpectrumDisplayForm QWidget + pyQt = self.snk1.pyqwidget() + + # Wrap the pointer as a PyQt SIP object + # This can now be manipulated as a PyQt4.QtGui.QWidget + pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + self.main_box = dialog_box(pyWin, self.ctrl_win) + self.main_box.show() + +if __name__ == "__main__": + tb = my_top_block(); + tb.start() + tb.qapp.exec_() + tb.stop() + diff --git a/gr-qtgui/examples/pyqt_freq_c.py b/gr-qtgui/examples/pyqt_freq_c.py new file mode 100755 index 0000000000..0422046204 --- /dev/null +++ b/gr-qtgui/examples/pyqt_freq_c.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, display, control): + QtGui.QWidget.__init__(self, None) + self.setWindowTitle('PyQt Test GUI') + + self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self) + self.boxlayout.addWidget(display, 1) + self.boxlayout.addWidget(control) + + self.resize(800, 500) + +class control_box(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Control Panel') + + self.setToolTip('Control the signals') + QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10)) + + self.layout = QtGui.QFormLayout(self) + + # Control the first signal + self.freq1Edit = QtGui.QLineEdit(self) + self.freq1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Frequency:", self.freq1Edit) + self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"), + self.freq1EditText) + + self.amp1Edit = QtGui.QLineEdit(self) + self.amp1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit) + self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"), + self.amp1EditText) + + + # Control the second signal + self.freq2Edit = QtGui.QLineEdit(self) + self.freq2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Frequency:", self.freq2Edit) + self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"), + self.freq2EditText) + + + self.amp2Edit = QtGui.QLineEdit(self) + self.amp2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit) + self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"), + self.amp2EditText) + + self.quit = QtGui.QPushButton('Close', self) + self.quit.setMinimumWidth(100) + self.layout.addWidget(self.quit) + + self.connect(self.quit, QtCore.SIGNAL('clicked()'), + QtGui.qApp, QtCore.SLOT('quit()')) + + def attach_signal1(self, signal): + self.signal1 = signal + self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency())) + self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude())) + + def attach_signal2(self, signal): + self.signal2 = signal + self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency())) + self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude())) + + def freq1EditText(self): + try: + newfreq = float(self.freq1Edit.text()) + self.signal1.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp1EditText(self): + try: + newamp = float(self.amp1Edit.text()) + self.signal1.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + + def freq2EditText(self): + try: + newfreq = float(self.freq2Edit.text()) + self.signal2.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp2EditText(self): + try: + newamp = float(self.amp2Edit.text()) + self.signal2.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + +class my_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + Rs = 8000 + f1 = 100 + f2 = 200 + + npts = 2048 + + self.qapp = QtGui.QApplication(sys.argv) + + src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0) + src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0) + src = gr.add_cc() + channel = gr.channel_model(0.01) + thr = gr.throttle(gr.sizeof_gr_complex, 100*npts) + self.snk1 = qtgui.freq_sink_c(npts, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, Rs, + "Complex Freq Example", 3) + + self.connect(src1, (src,0)) + self.connect(src2, (src,1)) + self.connect(src, channel, thr, (self.snk1, 0)) + self.connect(src1, (self.snk1, 1)) + self.connect(src2, (self.snk1, 2)) + + self.ctrl_win = control_box() + self.ctrl_win.attach_signal1(src1) + self.ctrl_win.attach_signal2(src2) + + # Get the reference pointer to the SpectrumDisplayForm QWidget + pyQt = self.snk1.pyqwidget() + + # Wrap the pointer as a PyQt SIP object + # This can now be manipulated as a PyQt4.QtGui.QWidget + pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + #pyWin.show() + self.main_box = dialog_box(pyWin, self.ctrl_win) + self.main_box.show() + +if __name__ == "__main__": + tb = my_top_block(); + tb.start() + tb.qapp.exec_() + tb.stop() + diff --git a/gr-qtgui/examples/pyqt_freq_f.py b/gr-qtgui/examples/pyqt_freq_f.py new file mode 100755 index 0000000000..fb7a9f93c6 --- /dev/null +++ b/gr-qtgui/examples/pyqt_freq_f.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, display, control): + QtGui.QWidget.__init__(self, None) + self.setWindowTitle('PyQt Test GUI') + + self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self) + self.boxlayout.addWidget(display, 1) + self.boxlayout.addWidget(control) + + self.resize(800, 500) + +class control_box(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Control Panel') + + self.setToolTip('Control the signals') + QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10)) + + self.layout = QtGui.QFormLayout(self) + + # Control the first signal + self.freq1Edit = QtGui.QLineEdit(self) + self.freq1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Frequency:", self.freq1Edit) + self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"), + self.freq1EditText) + + self.amp1Edit = QtGui.QLineEdit(self) + self.amp1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit) + self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"), + self.amp1EditText) + + + # Control the second signal + self.freq2Edit = QtGui.QLineEdit(self) + self.freq2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Frequency:", self.freq2Edit) + self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"), + self.freq2EditText) + + + self.amp2Edit = QtGui.QLineEdit(self) + self.amp2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit) + self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"), + self.amp2EditText) + + self.quit = QtGui.QPushButton('Close', self) + self.quit.setMinimumWidth(100) + self.layout.addWidget(self.quit) + + self.connect(self.quit, QtCore.SIGNAL('clicked()'), + QtGui.qApp, QtCore.SLOT('quit()')) + + def attach_signal1(self, signal): + self.signal1 = signal + self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency())) + self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude())) + + def attach_signal2(self, signal): + self.signal2 = signal + self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency())) + self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude())) + + def freq1EditText(self): + try: + newfreq = float(self.freq1Edit.text()) + self.signal1.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp1EditText(self): + try: + newamp = float(self.amp1Edit.text()) + self.signal1.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + + def freq2EditText(self): + try: + newfreq = float(self.freq2Edit.text()) + self.signal2.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp2EditText(self): + try: + newamp = float(self.amp2Edit.text()) + self.signal2.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + +class my_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + Rs = 8000 + f1 = 100 + f2 = 200 + + npts = 2048 + + self.qapp = QtGui.QApplication(sys.argv) + + src1 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0) + src2 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0) + src = gr.add_ff() + thr = gr.throttle(gr.sizeof_float, 100*npts) + self.snk1 = qtgui.freq_sink_f(npts, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, Rs, + "Real freq Example", 3) + + self.connect(src1, (src,0)) + self.connect(src2, (src,1)) + self.connect(src, thr, (self.snk1, 0)) + self.connect(src1, (self.snk1, 1)) + self.connect(src2, (self.snk1, 2)) + + self.ctrl_win = control_box() + self.ctrl_win.attach_signal1(src1) + self.ctrl_win.attach_signal2(src2) + + # Get the reference pointer to the SpectrumDisplayForm QWidget + pyQt = self.snk1.pyqwidget() + + # Wrap the pointer as a PyQt SIP object + # This can now be manipulated as a PyQt4.QtGui.QWidget + pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + #pyWin.show() + self.main_box = dialog_box(pyWin, self.ctrl_win) + self.main_box.show() + +if __name__ == "__main__": + tb = my_top_block(); + tb.start() + tb.qapp.exec_() + tb.stop() + diff --git a/gr-qtgui/examples/pyqt_time_c.py b/gr-qtgui/examples/pyqt_time_c.py index 04425e11f1..255cd1c855 100755 --- a/gr-qtgui/examples/pyqt_time_c.py +++ b/gr-qtgui/examples/pyqt_time_c.py @@ -145,13 +145,13 @@ class my_top_block(gr.top_block): channel = gr.channel_model(0.01) thr = gr.throttle(gr.sizeof_gr_complex, 100*npts) self.snk1 = qtgui.time_sink_c(npts, Rs, - "Complex Time Example", 3) + "Complex Time Example", 1) self.connect(src1, (src,0)) self.connect(src2, (src,1)) self.connect(src, channel, thr, (self.snk1, 0)) - self.connect(src1, (self.snk1, 1)) - self.connect(src2, (self.snk1, 2)) + #self.connect(src1, (self.snk1, 1)) + #self.connect(src2, (self.snk1, 2)) self.ctrl_win = control_box() self.ctrl_win.attach_signal1(src1) @@ -169,14 +169,16 @@ class my_top_block(gr.top_block): pyWin, QtCore.SLOT("setTitle(int, QString)")) pyWin.emit(QtCore.SIGNAL("setTitle(int, QString)"), 0, "Re{sum}") self.snk1.set_title(1, "Im{Sum}") - self.snk1.set_title(2, "Re{src1}") - self.snk1.set_title(3, "Im{src1}") - self.snk1.set_title(4, "Re{src2}") - self.snk1.set_title(5, "Im{src2}") + #self.snk1.set_title(2, "Re{src1}") + #self.snk1.set_title(3, "Im{src1}") + #self.snk1.set_title(4, "Re{src2}") + #self.snk1.set_title(5, "Im{src2}") # Can also set the color of a curve #self.snk1.set_color(5, "blue") + self.snk1.set_update_time(0.5) + #pyWin.show() self.main_box = dialog_box(pyWin, self.ctrl_win) self.main_box.show() diff --git a/gr-qtgui/examples/pyqt_waterfall_c.py b/gr-qtgui/examples/pyqt_waterfall_c.py new file mode 100755 index 0000000000..b7f8396ff3 --- /dev/null +++ b/gr-qtgui/examples/pyqt_waterfall_c.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, display, control): + QtGui.QWidget.__init__(self, None) + self.setWindowTitle('PyQt Test GUI') + + self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self) + self.boxlayout.addWidget(display, 1) + self.boxlayout.addWidget(control) + + self.resize(800, 500) + +class control_box(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Control Panel') + + self.setToolTip('Control the signals') + QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10)) + + self.layout = QtGui.QFormLayout(self) + + # Control the first signal + self.freq1Edit = QtGui.QLineEdit(self) + self.freq1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Frequency:", self.freq1Edit) + self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"), + self.freq1EditText) + + self.amp1Edit = QtGui.QLineEdit(self) + self.amp1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit) + self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"), + self.amp1EditText) + + + # Control the second signal + self.freq2Edit = QtGui.QLineEdit(self) + self.freq2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Frequency:", self.freq2Edit) + self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"), + self.freq2EditText) + + + self.amp2Edit = QtGui.QLineEdit(self) + self.amp2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit) + self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"), + self.amp2EditText) + + self.quit = QtGui.QPushButton('Close', self) + self.quit.setMinimumWidth(100) + self.layout.addWidget(self.quit) + + self.connect(self.quit, QtCore.SIGNAL('clicked()'), + QtGui.qApp, QtCore.SLOT('quit()')) + + def attach_signal1(self, signal): + self.signal1 = signal + self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency())) + self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude())) + + def attach_signal2(self, signal): + self.signal2 = signal + self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency())) + self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude())) + + def freq1EditText(self): + try: + newfreq = float(self.freq1Edit.text()) + self.signal1.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp1EditText(self): + try: + newamp = float(self.amp1Edit.text()) + self.signal1.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + + def freq2EditText(self): + try: + newfreq = float(self.freq2Edit.text()) + self.signal2.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp2EditText(self): + try: + newamp = float(self.amp2Edit.text()) + self.signal2.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + +class my_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + Rs = 8000 + f1 = 100 + f2 = 200 + + npts = 2048 + + self.qapp = QtGui.QApplication(sys.argv) + + src1 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0) + src2 = gr.sig_source_c(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0) + src = gr.add_cc() + channel = gr.channel_model(0.01) + thr = gr.throttle(gr.sizeof_gr_complex, 100*npts) + self.snk1 = qtgui.waterfall_sink_c(npts, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, Rs, + "Complex Waterfall Example") + + self.connect(src1, (src,0)) + self.connect(src2, (src,1)) + self.connect(src, channel, thr, (self.snk1, 0)) + + self.ctrl_win = control_box() + self.ctrl_win.attach_signal1(src1) + self.ctrl_win.attach_signal2(src2) + + # Get the reference pointer to the SpectrumDisplayForm QWidget + pyQt = self.snk1.pyqwidget() + + # Wrap the pointer as a PyQt SIP object + # This can now be manipulated as a PyQt4.QtGui.QWidget + pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + #pyWin.show() + self.main_box = dialog_box(pyWin, self.ctrl_win) + self.main_box.show() + +if __name__ == "__main__": + tb = my_top_block(); + tb.start() + tb.qapp.exec_() + tb.stop() + diff --git a/gr-qtgui/examples/pyqt_waterfall_f.py b/gr-qtgui/examples/pyqt_waterfall_f.py new file mode 100755 index 0000000000..29ae259e5f --- /dev/null +++ b/gr-qtgui/examples/pyqt_waterfall_f.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import sys + +try: + from gnuradio import qtgui + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4 and gr-qtgui." + sys.exit(1) + +class dialog_box(QtGui.QWidget): + def __init__(self, display, control): + QtGui.QWidget.__init__(self, None) + self.setWindowTitle('PyQt Test GUI') + + self.boxlayout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self) + self.boxlayout.addWidget(display, 1) + self.boxlayout.addWidget(control) + + self.resize(800, 500) + +class control_box(QtGui.QWidget): + def __init__(self, parent=None): + QtGui.QWidget.__init__(self, parent) + self.setWindowTitle('Control Panel') + + self.setToolTip('Control the signals') + QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10)) + + self.layout = QtGui.QFormLayout(self) + + # Control the first signal + self.freq1Edit = QtGui.QLineEdit(self) + self.freq1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Frequency:", self.freq1Edit) + self.connect(self.freq1Edit, QtCore.SIGNAL("editingFinished()"), + self.freq1EditText) + + self.amp1Edit = QtGui.QLineEdit(self) + self.amp1Edit.setMinimumWidth(100) + self.layout.addRow("Signal 1 Amplitude:", self.amp1Edit) + self.connect(self.amp1Edit, QtCore.SIGNAL("editingFinished()"), + self.amp1EditText) + + + # Control the second signal + self.freq2Edit = QtGui.QLineEdit(self) + self.freq2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Frequency:", self.freq2Edit) + self.connect(self.freq2Edit, QtCore.SIGNAL("editingFinished()"), + self.freq2EditText) + + + self.amp2Edit = QtGui.QLineEdit(self) + self.amp2Edit.setMinimumWidth(100) + self.layout.addRow("Signal 2 Amplitude:", self.amp2Edit) + self.connect(self.amp2Edit, QtCore.SIGNAL("editingFinished()"), + self.amp2EditText) + + self.quit = QtGui.QPushButton('Close', self) + self.quit.setMinimumWidth(100) + self.layout.addWidget(self.quit) + + self.connect(self.quit, QtCore.SIGNAL('clicked()'), + QtGui.qApp, QtCore.SLOT('quit()')) + + def attach_signal1(self, signal): + self.signal1 = signal + self.freq1Edit.setText(QtCore.QString("%1").arg(self.signal1.frequency())) + self.amp1Edit.setText(QtCore.QString("%1").arg(self.signal1.amplitude())) + + def attach_signal2(self, signal): + self.signal2 = signal + self.freq2Edit.setText(QtCore.QString("%1").arg(self.signal2.frequency())) + self.amp2Edit.setText(QtCore.QString("%1").arg(self.signal2.amplitude())) + + def freq1EditText(self): + try: + newfreq = float(self.freq1Edit.text()) + self.signal1.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp1EditText(self): + try: + newamp = float(self.amp1Edit.text()) + self.signal1.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + + def freq2EditText(self): + try: + newfreq = float(self.freq2Edit.text()) + self.signal2.set_frequency(newfreq) + except ValueError: + print "Bad frequency value entered" + + def amp2EditText(self): + try: + newamp = float(self.amp2Edit.text()) + self.signal2.set_amplitude(newamp) + except ValueError: + print "Bad amplitude value entered" + + +class my_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + Rs = 8000 + f1 = 100 + f2 = 200 + + npts = 2048 + + self.qapp = QtGui.QApplication(sys.argv) + + src1 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f1, 0.1, 0) + src2 = gr.sig_source_f(Rs, gr.GR_SIN_WAVE, f2, 0.1, 0) + src = gr.add_ff() + thr = gr.throttle(gr.sizeof_float, 100*npts) + self.snk1 = qtgui.waterfall_sink_f(npts, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, Rs, + "Real Waterfall Example") + + self.connect(src1, (src,0)) + self.connect(src2, (src,1)) + self.connect(src, thr, (self.snk1, 0)) + + self.ctrl_win = control_box() + self.ctrl_win.attach_signal1(src1) + self.ctrl_win.attach_signal2(src2) + + # Get the reference pointer to the SpectrumDisplayForm QWidget + pyQt = self.snk1.pyqwidget() + + # Wrap the pointer as a PyQt SIP object + # This can now be manipulated as a PyQt4.QtGui.QWidget + pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + #pyWin.show() + self.main_box = dialog_box(pyWin, self.ctrl_win) + self.main_box.show() + +if __name__ == "__main__": + tb = my_top_block(); + tb.start() + tb.qapp.exec_() + tb.stop() + diff --git a/gr-qtgui/grc/qtgui_block_tree.xml b/gr-qtgui/grc/qtgui_block_tree.xml new file mode 100644 index 0000000000..898c1c0044 --- /dev/null +++ b/gr-qtgui/grc/qtgui_block_tree.xml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> + +<!-- + Copyright 2012 Free Software Foundation, Inc. + + This file is part of GNU Radio + + GNU Radio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Radio is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Radio; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, + Boston, MA 02110-1301, USA. +--> + +<!-- +################################################### +##Block Tree for GR QTGUI blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>QT GUI Sinks</name> + <block>qtgui_sink_x</block> + <block>qtgui_freq_sink_x</block> + <block>qtgui_time_sink_x</block> + <block>qtgui_const_sink_x</block> + <block>qtgui_waterfall_sink_x</block> + </cat> + <cat> + <name>QT GUI Widgets</name> + <block>qtgui_tab_widget</block> + <block>variable_qtgui_range</block> + <block>variable_qtgui_chooser</block> + <block>variable_qtgui_check_box</block> + <block>variable_qtgui_entry</block> + <block>variable_qtgui_label</block> + </cat> +</cat> diff --git a/gr-qtgui/grc/qtgui_check_box.xml b/gr-qtgui/grc/qtgui_check_box.xml index 95f4f968a6..e3a00d002e 100644 --- a/gr-qtgui/grc/qtgui_check_box.xml +++ b/gr-qtgui/grc/qtgui_check_box.xml @@ -8,7 +8,6 @@ <block> <name>QT GUI Check Box</name> <key>variable_qtgui_check_box</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <var_make>self.$(id) = $(id) = $value</var_make> <make>#set $win = '_%s_check_box'%$id diff --git a/gr-qtgui/grc/qtgui_chooser.xml b/gr-qtgui/grc/qtgui_chooser.xml index cb50902897..6a8760cbe6 100644 --- a/gr-qtgui/grc/qtgui_chooser.xml +++ b/gr-qtgui/grc/qtgui_chooser.xml @@ -8,7 +8,6 @@ <block> <name>QT GUI Chooser</name> <key>variable_qtgui_chooser</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <var_make>self.$(id) = $(id) = $value</var_make> <make>#slurp diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml b/gr-qtgui/grc/qtgui_const_sink_x.xml new file mode 100644 index 0000000000..536237d164 --- /dev/null +++ b/gr-qtgui/grc/qtgui_const_sink_x.xml @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<!-- +################################################### +##QT GUI Sink +################################################### + --> +<block> + <name>QT GUI Constellation Sink</name> + <key>qtgui_const_sink_x</key> + <import>from PyQt4 import Qt</import> + <import>from gnuradio import qtgui</import> + <import>import sip</import> + <make>#set $win = 'self._%s_win'%$id +qtgui.$(type.fcn)( + $size, \#size + $name, \#name + $nconnections \#number of inputs +) +self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) +$(gui_hint()($win))</make> + <callback>set_resize($width, $height)</callback> + <callback>set_update_time($t)</callback> + <callback>set_title($which, $title)</callback> + <callback>set_color($which, $color)</callback> + <param> + <name>Type</name> + <key>type</key> + <value>complex</value> + <type>enum</type> + <option><name>Complex</name><key>complex</key><opt>fcn:const_sink_c</opt></option> +<!-- <option><name>Float</name><key>float</key><opt>fcn:const_sink_f</opt></option> --> + </param> + <param> + <name>Name</name> + <key>name</key> + <value>QT GUI Plot</value> + <type>string</type> + </param> + <param> + <name>Number of Points</name> + <key>size</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Number of Inputs</name> + <key>nconnections</key> + <value>1</value> + <type>int</type> + <hide>part</hide> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <sink> + <name>in</name> + <type>$type</type> + <nports>$nconnections</nports> + </sink> + <doc> +The GUI hint can be used to position the widget within the application. \ +The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \ +Both the tab specification and the grid position are optional. + </doc> +</block> diff --git a/gr-qtgui/grc/qtgui_entry.xml b/gr-qtgui/grc/qtgui_entry.xml index 1a98402a0f..514071afab 100644 --- a/gr-qtgui/grc/qtgui_entry.xml +++ b/gr-qtgui/grc/qtgui_entry.xml @@ -8,7 +8,6 @@ <block> <name>QT GUI Entry</name> <key>variable_qtgui_entry</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <import>from gnuradio import eng_notation</import> <var_make>self.$(id) = $(id) = $value</var_make> diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml new file mode 100644 index 0000000000..69ce5f4e68 --- /dev/null +++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml @@ -0,0 +1,122 @@ +<?xml version="1.0"?> +<!-- +################################################### +##QT GUI Sink +################################################### + --> +<block> + <name>QT GUI Frequency Sink</name> + <key>qtgui_freq_sink_x</key> + <import>from PyQt4 import Qt</import> + <import>from gnuradio import qtgui</import> + <import>from gnuradio.gr import firdes</import> + <import>import sip</import> + <make>#set $win = 'self._%s_win'%$id +qtgui.$(type.fcn)( + $fftsize, \#size + $wintype, \#wintype + $fc, \#fc + $bw, \#bw + $name, \#name + $nconnections \#number of inputs +) +self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) +$(gui_hint()($win))</make> + <callback>set_frequency_range($fc, $bw)</callback> + <callback>set_update_time($t)</callback> + <callback>set_title($which, $title)</callback> + <callback>set_color($which, $color)</callback> + <param> + <name>Type</name> + <key>type</key> + <value>complex</value> + <type>enum</type> + <option><name>Complex</name><key>complex</key><opt>fcn:freq_sink_c</opt></option> + <option><name>Float</name><key>float</key><opt>fcn:freq_sink_f</opt></option> + </param> + <param> + <name>Name</name> + <key>name</key> + <value>QT GUI Plot</value> + <type>string</type> + </param> + <param> + <name>FFT Size</name> + <key>fftsize</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Window Type</name> + <key>wintype</key> + <value>firdes.WIN_BLACKMAN_hARRIS</value> + <type>int</type> + <hide>part</hide> + <option> + <name>Blackman-harris</name> + <key>firdes.WIN_BLACKMAN_hARRIS</key> + </option> + <option> + <name>Hamming</name> + <key>firdes.WIN_HAMMING</key> + </option> + <option> + <name>Hann</name> + <key>firdes.WIN_HANN</key> + </option> + <option> + <name>Blackman</name> + <key>firdes.WIN_BLACKMAN</key> + </option> + <option> + <name>Rectangular</name> + <key>firdes.WIN_RECTANGULAR</key> + </option> + <option> + <name>Kaiser</name> + <key>firdes.WIN_KAISER</key> + </option> + </param> + <param> + <name>Center Frequency (Hz)</name> + <key>fc</key> + <value>0</value> + <type>real</type> + </param> + <param> + <name>Bandwidth (Hz)</name> + <key>bw</key> + <value>samp_rate</value> + <type>real</type> + </param> + <param> + <name>Update Rate</name> + <key>rate</key> + <value>10</value> + <type>real</type> + </param> + <param> + <name>Number of Inputs</name> + <key>nconnections</key> + <value>1</value> + <type>int</type> + <hide>part</hide> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <sink> + <name>in</name> + <type>$type</type> + <nports>$nconnections</nports> + </sink> + <doc> +The GUI hint can be used to position the widget within the application. \ +The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \ +Both the tab specification and the grid position are optional. + </doc> +</block> diff --git a/gr-qtgui/grc/qtgui_label.xml b/gr-qtgui/grc/qtgui_label.xml index 5049118c47..3615574c4c 100644 --- a/gr-qtgui/grc/qtgui_label.xml +++ b/gr-qtgui/grc/qtgui_label.xml @@ -8,7 +8,6 @@ <block> <name>QT GUI Label</name> <key>variable_qtgui_label</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <import>from gnuradio import eng_notation</import> <var_make>self.$(id) = $(id) = $value</var_make> diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml index 6b0555f98e..f2d42f1a5f 100644 --- a/gr-qtgui/grc/qtgui_range.xml +++ b/gr-qtgui/grc/qtgui_range.xml @@ -8,7 +8,6 @@ <block> <name>QT GUI Range</name> <key>variable_qtgui_range</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <import>import PyQt4.Qwt5 as Qwt</import> <var_make>self.$(id) = $(id) = $value</var_make> diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml index 83d6ec2879..9ea9dc583f 100644 --- a/gr-qtgui/grc/qtgui_sink_x.xml +++ b/gr-qtgui/grc/qtgui_sink_x.xml @@ -7,9 +7,8 @@ <block> <name>QT GUI Sink</name> <key>qtgui_sink_x</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> - <import>from gnuradio.qtgui import qtgui</import> + <import>from gnuradio import qtgui</import> <import>from gnuradio.gr import firdes</import> <import>import sip</import> <make>#set $win = 'self._%s_win'%$id @@ -24,8 +23,18 @@ qtgui.$(type.fcn)( $plottime, \#plottime $plotconst, \#plotconst ) +self.$(id).set_update_time(1.0/$rate) self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) -$(gui_hint()($win))</make> +$(gui_hint()($win)) + +#if $freqchangevar() is not None +def $(id)_callback(p, num): + if num == 1 or num == 2: self.set_$(freqchangevar)(p.x()) + +Qt.QObject.connect(self._$(id)_win, Qt.SIGNAL("plotPointSelected(QPointF, int)"), $(id)_callback ) +#end if + +</make> <callback>set_frequency_range($fc, $bw)</callback> <param> <name>Type</name> @@ -91,6 +100,12 @@ $(gui_hint()($win))</make> <type>real</type> </param> <param> + <name>Update Rate</name> + <key>rate</key> + <value>10</value> + <type>real</type> + </param> + <param> <name>Plot Frequency</name> <key>plotfreq</key> <value>True</value> @@ -133,6 +148,13 @@ $(gui_hint()($win))</make> <type>gui_hint</type> <hide>part</hide> </param> + <param> + <name>Clicked freq variable</name> + <key>freqchangevar</key> + <value>None</value> + <type>raw</type> + <hide>part</hide> + </param> <sink> <name>in</name> <type>$type</type> diff --git a/gr-qtgui/grc/qtgui_tab_widget.xml b/gr-qtgui/grc/qtgui_tab_widget.xml index f900541093..c098c9fef5 100644 --- a/gr-qtgui/grc/qtgui_tab_widget.xml +++ b/gr-qtgui/grc/qtgui_tab_widget.xml @@ -7,7 +7,6 @@ <block> <name>QT GUI Tab Widget</name> <key>qtgui_tab_widget</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> <make>#set $win = 'self.%s'%$id Qt.QTabWidget() diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml index 9c8da6fbcf..17b2cfd016 100644 --- a/gr-qtgui/grc/qtgui_time_sink_x.xml +++ b/gr-qtgui/grc/qtgui_time_sink_x.xml @@ -7,9 +7,8 @@ <block> <name>QT GUI Time Sink</name> <key>qtgui_time_sink_x</key> - <category>QT GUI Widgets</category> <import>from PyQt4 import Qt</import> - <import>from gnuradio.qtgui import qtgui</import> + <import>from gnuradio import qtgui</import> <import>from gnuradio.gr import firdes</import> <import>import sip</import> <make>#set $win = 'self._%s_win'%$id diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml new file mode 100644 index 0000000000..47de5b593c --- /dev/null +++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml @@ -0,0 +1,114 @@ +<?xml version="1.0"?> +<!-- +################################################### +##QT GUI Sink +################################################### + --> +<block> + <name>QT GUI Waterfall Sink</name> + <key>qtgui_waterfall_sink_x</key> + <import>from PyQt4 import Qt</import> + <import>from gnuradio import qtgui</import> + <import>from gnuradio.gr import firdes</import> + <import>import sip</import> + <make>#set $win = 'self._%s_win'%$id +qtgui.$(type.fcn)( + $fftsize, \#size + $wintype, \#wintype + $fc, \#fc + $bw, \#bw + $name, \#name +) +self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) +$(gui_hint()($win))</make> + <callback>set_frequency_range($fc, $bw)</callback> + <callback>set_update_time($t)</callback> + <callback>set_title($which, $title)</callback> + <callback>set_color($which, $color)</callback> + <param> + <name>Type</name> + <key>type</key> + <value>complex</value> + <type>enum</type> + <option><name>Complex</name><key>complex</key><opt>fcn:waterfall_sink_c</opt></option> + <option><name>Float</name><key>float</key><opt>fcn:waterfall_sink_f</opt></option> + </param> + <param> + <name>Name</name> + <key>name</key> + <value>QT GUI Plot</value> + <type>string</type> + </param> + <param> + <name>FFT Size</name> + <key>fftsize</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Window Type</name> + <key>wintype</key> + <value>firdes.WIN_BLACKMAN_hARRIS</value> + <type>int</type> + <hide>part</hide> + <option> + <name>Blackman-harris</name> + <key>firdes.WIN_BLACKMAN_hARRIS</key> + </option> + <option> + <name>Hamming</name> + <key>firdes.WIN_HAMMING</key> + </option> + <option> + <name>Hann</name> + <key>firdes.WIN_HANN</key> + </option> + <option> + <name>Blackman</name> + <key>firdes.WIN_BLACKMAN</key> + </option> + <option> + <name>Rectangular</name> + <key>firdes.WIN_RECTANGULAR</key> + </option> + <option> + <name>Kaiser</name> + <key>firdes.WIN_KAISER</key> + </option> + </param> + <param> + <name>Center Frequency (Hz)</name> + <key>fc</key> + <value>0</value> + <type>real</type> + </param> + <param> + <name>Bandwidth (Hz)</name> + <key>bw</key> + <value>samp_rate</value> + <type>real</type> + </param> + <param> + <name>Update Rate</name> + <key>rate</key> + <value>10</value> + <type>real</type> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <sink> + <name>in</name> + <type>$type</type> + <nports>1</nports> + </sink> + <doc> +The GUI hint can be used to position the widget within the application. \ +The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \ +Both the tab specification and the grid position are optional. + </doc> +</block> diff --git a/gr-qtgui/include/CMakeLists.txt b/gr-qtgui/include/qtgui/CMakeLists.txt index ef4cb11752..d0d3d13fb5 100644 --- a/gr-qtgui/include/CMakeLists.txt +++ b/gr-qtgui/include/qtgui/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,12 +21,17 @@ # Install the header files ######################################################################## install(FILES - gr_qtgui_api.h - qtgui_time_sink_c.h - qtgui_time_sink_f.h - qtgui_sink_c.h - qtgui_sink_f.h - qtgui_util.h - DESTINATION ${GR_INCLUDE_DIR}/gnuradio + api.h + time_sink_c.h + time_sink_f.h + freq_sink_c.h + freq_sink_f.h + const_sink_c.h + waterfall_sink_c.h + waterfall_sink_f.h + sink_c.h + sink_f.h + utils.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/qtgui COMPONENT "qtgui_devel" ) diff --git a/gr-qtgui/include/gr_qtgui_api.h b/gr-qtgui/include/qtgui/api.h index c39add1e82..e88948e07b 100644 --- a/gr-qtgui/include/gr_qtgui_api.h +++ b/gr-qtgui/include/qtgui/api.h @@ -19,15 +19,15 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_QTGUI_API_H -#define INCLUDED_GR_QTGUI_API_H +#ifndef INCLUDED_QTGUI_API_H +#define INCLUDED_QTGUI_API_H #include <gruel/attributes.h> #ifdef gnuradio_qtgui_EXPORTS -# define GR_QTGUI_API __GR_ATTR_EXPORT +# define QTGUI_API __GR_ATTR_EXPORT #else -# define GR_QTGUI_API __GR_ATTR_IMPORT +# define QTGUI_API __GR_ATTR_IMPORT #endif -#endif /* INCLUDED_GR_QTGUI_API_H */ +#endif /* INCLUDED_QTGUI_API_H */ diff --git a/gr-qtgui/include/qtgui/const_sink_c.h b/gr-qtgui/include/qtgui/const_sink_c.h new file mode 100644 index 0000000000..48da4b9fa1 --- /dev/null +++ b/gr-qtgui/include/qtgui/const_sink_c.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_CONST_SINK_C_H +#define INCLUDED_QTGUI_CONST_SINK_C_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display the IQ constellation of multiple signals. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a complex + * streams and plots them on an IQ constellation plot. + */ + class QTGUI_API const_sink_c : virtual public gr_sync_block + { + public: + // gr::qtgui::const_sink_c::sptr + typedef boost::shared_ptr<const_sink_c> sptr; + + /*! + * \brief Build a complex PSD sink. + * + * \param size number of points to plot at once + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int size, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_update_time(double t) = 0; + virtual void set_title(int which, const std::string &title) = 0; + virtual void set_color(int which, const std::string &color) = 0; + virtual void set_line_width(int which, int width) = 0; + virtual void set_line_style(int which, Qt::PenStyle style) = 0; + virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_nsamps(const int newsize) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_CONST_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui/freq_sink_c.h b/gr-qtgui/include/qtgui/freq_sink_c.h new file mode 100644 index 0000000000..e1c30080c2 --- /dev/null +++ b/gr-qtgui/include/qtgui/freq_sink_c.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_FREQ_SINK_C_H +#define INCLUDED_QTGUI_FREQ_SINK_C_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals in frequency. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a complex + * streams and plots the PSD. Each signal is plotted with a + * different color, and the \a set_title and \a set_color + * functions can be used to change the lable and color for a given + * input number. + */ + class QTGUI_API freq_sink_c : virtual public gr_sync_block + { + public: + // gr::qtgui::freq_sink_c::sptr + typedef boost::shared_ptr<freq_sink_c> sptr; + + /*! + * \brief Build a complex PSD sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + virtual void set_fft_average(const float fftavg) = 0; + virtual float fft_average() const = 0; + + virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; + virtual void set_fft_power_db(double min, double max) = 0; + + virtual void set_update_time(double t) = 0; + virtual void set_title(int which, const std::string &title) = 0; + virtual void set_color(int which, const std::string &color) = 0; + virtual void set_line_width(int which, int width) = 0; + virtual void set_line_style(int which, Qt::PenStyle style) = 0; + virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_FREQ_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui/freq_sink_f.h b/gr-qtgui/include/qtgui/freq_sink_f.h new file mode 100644 index 0000000000..6b7d1717b5 --- /dev/null +++ b/gr-qtgui/include/qtgui/freq_sink_f.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_FREQ_SINK_F_H +#define INCLUDED_QTGUI_FREQ_SINK_F_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals in frequency. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a floating + * point streams and plots the PSD. Each signal is plotted with a + * different color, and the \a set_title and \a set_color + * functions can be used to change the lable and color for a given + * input number. + */ + class QTGUI_API freq_sink_f : virtual public gr_sync_block + { + public: + // gr::qtgui::freq_sink_f::sptr + typedef boost::shared_ptr<freq_sink_f> sptr; + + /*! + * \brief Build a floating point PSD sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + virtual void set_fft_average(const float fftavg) = 0; + virtual float fft_average() const = 0; + + virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; + virtual void set_fft_power_db(double min, double max) = 0; + + virtual void set_update_time(double t) = 0; + virtual void set_title(int which, const std::string &title) = 0; + virtual void set_color(int which, const std::string &color) = 0; + virtual void set_line_width(int which, int width) = 0; + virtual void set_line_style(int which, Qt::PenStyle style) = 0; + virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_FREQ_SINK_F_H */ diff --git a/gr-qtgui/include/qtgui/sink_c.h b/gr-qtgui/include/qtgui/sink_c.h new file mode 100644 index 0000000000..b844ca7777 --- /dev/null +++ b/gr-qtgui/include/qtgui/sink_c.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_C_H +#define INCLUDED_QTGUI_SINK_C_H + +#include <qtgui/api.h> +#include <gr_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display freq, spec, time, and const plots. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes a complex stream and + * plots it. The default action is to plot the signal as a PSD (FFT), + * spectrogram (waterfall), time domain I&Q, and constellation (I + * vs. Q) plots. The plots may be turned off by setting the + * appropriate boolean value in the constructor to False. + */ + + class QTGUI_API sink_c : virtual public gr_block + { + public: + // gr::qtgui::sink_c::sptr + typedef boost::shared_ptr<sink_c> sptr; + + /*! + * \brief Build a complex qtgui sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + + virtual void set_frequency_range(const double centerfreq, + const double bandwidth) = 0; + virtual void set_fft_power_db(double min, double max) = 0; + + //void set_time_domain_axis(double min, double max); + //void set_constellation_axis(double xmin, double xmax, + // double ymin, double ymax); + //void set_constellation_pen_size(int size); + + virtual void set_update_time(double t) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui/sink_f.h b/gr-qtgui/include/qtgui/sink_f.h new file mode 100644 index 0000000000..961a5d561f --- /dev/null +++ b/gr-qtgui/include/qtgui/sink_f.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_F_H +#define INCLUDED_QTGUI_SINK_F_H + +#include <qtgui/api.h> +#include <gr_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display freq, spec, and time. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes a float stream and + * plots it. The default action is to plot the signal as a PSD (FFT), + * spectrogram (waterfall), and time domain plots. The plots may be + * turned off by setting the appropriate boolean value in the + * constructor to False. + */ + + class QTGUI_API sink_f : virtual public gr_block + { + public: + // gr::qtgui::sink_f::sptr + typedef boost::shared_ptr<sink_f> sptr; + + /*! + * \brief Build a floating point qtgui sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + + virtual void set_frequency_range(const double centerfreq, + const double bandwidth) = 0; + virtual void set_fft_power_db(double min, double max) = 0; + + //void set_time_domain_axis(double min, double max); + //void set_constellation_axis(double xmin, double xmax, + // double ymin, double ymax); + //void set_constellation_pen_size(int size); + + virtual void set_update_time(double t) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_SINK_F_H */ diff --git a/gr-qtgui/include/qtgui/time_sink_c.h b/gr-qtgui/include/qtgui/time_sink_c.h new file mode 100644 index 0000000000..17176e65f9 --- /dev/null +++ b/gr-qtgui/include/qtgui/time_sink_c.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_C_H +#define INCLUDED_QTGUI_TIME_SINK_C_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals in time. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a complex + * streams and plots them in the time domain. For each signal, both + * the signal's I and Q parts are plotted, and they are all plotted + * with a different color, and the \a set_title and \a set_color + * functions can be used to change the lable and color for a given + * input number. + */ + class QTGUI_API time_sink_c : virtual public gr_sync_block + { + public: + // gr::qtgui::time_sink_c::sptr + typedef boost::shared_ptr<time_sink_c> sptr; + + /*! + * \brief Build complex time sink + * + * \param size number of points to plot at once + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_time_domain_axis(double min, double max) = 0; + virtual void set_update_time(double t) = 0; + virtual void set_title(int which, const std::string &title) = 0; + virtual void set_color(int which, const std::string &color) = 0; + virtual void set_line_width(int which, int width) = 0; + virtual void set_line_style(int which, Qt::PenStyle style) = 0; + virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_nsamps(const int newsize) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_TIME_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui/time_sink_f.h b/gr-qtgui/include/qtgui/time_sink_f.h new file mode 100644 index 0000000000..df6ba9f554 --- /dev/null +++ b/gr-qtgui/include/qtgui/time_sink_f.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_F_H +#define INCLUDED_QTGUI_TIME_SINK_F_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals in time. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a float streams + * and plots them in the time domain. Each signal is plotted with a + * different color, and the \a set_title and \a set_color functions + * can be used to change the lable and color for a given input number. + */ + class QTGUI_API time_sink_f : virtual public gr_sync_block + { + public: + // gr::qtgui::time_sink_f::sptr + typedef boost::shared_ptr<time_sink_f> sptr; + + /*! + * \brief Build floating point time sink + * + * \param size number of points to plot at once + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param nconnections number of signals connected to sink + * \param parent a QWidget parent object, if any + */ + static sptr make(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_time_domain_axis(double min, double max) = 0; + virtual void set_update_time(double t) = 0; + virtual void set_title(int which, const std::string &title) = 0; + virtual void set_color(int which, const std::string &color) = 0; + virtual void set_line_width(int which, int width) = 0; + virtual void set_line_style(int which, Qt::PenStyle style) = 0; + virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_nsamps(const int newsize) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_TIME_SINK_F_H */ diff --git a/gr-qtgui/include/qtgui_util.h b/gr-qtgui/include/qtgui/utils.h index 2deaddb947..f490c48567 100644 --- a/gr-qtgui/include/qtgui_util.h +++ b/gr-qtgui/include/qtgui/utils.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,16 +20,15 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_QTGUI_UTIL_H -#define INCLUDED_QTGUI_UTIL_H +#ifndef INCLUDED_QTGUI_UTILS_H +#define INCLUDED_QTGUI_UTILS_H #include <qevent.h> -#include <gr_qtgui_api.h> +#include <qtgui/api.h> #include <qwt_plot_picker.h> #include <qwt_picker_machine.h> - -class GR_QTGUI_API QwtDblClickPlotPicker: public QwtPlotPicker +class QTGUI_API QwtDblClickPlotPicker: public QwtPlotPicker { public: QwtDblClickPlotPicker(QwtPlotCanvas *); @@ -38,20 +37,19 @@ public: virtual QwtPickerMachine * stateMachine(int) const; }; -class GR_QTGUI_API QwtPickerDblClickPointMachine: public QwtPickerMachine +class QTGUI_API QwtPickerDblClickPointMachine: public QwtPickerMachine { public: QwtPickerDblClickPointMachine(); ~QwtPickerDblClickPointMachine(); #if QWT_VERSION < 0x060000 - virtual CommandList transition( const QwtEventPattern &eventPattern, - const QEvent *e); + virtual CommandList #else virtual QList<QwtPickerMachine::Command> - transition( const QwtEventPattern &eventPattern, - const QEvent *e); #endif + transition( const QwtEventPattern &eventPattern, + const QEvent *e); }; -#endif /* INCLUDED_QTGUI_UTIL_H */ +#endif /* INCLUDED_QTGUI_UTILS_H */ diff --git a/gr-qtgui/include/qtgui/waterfall_sink_c.h b/gr-qtgui/include/qtgui/waterfall_sink_c.h new file mode 100644 index 0000000000..838d50f44d --- /dev/null +++ b/gr-qtgui/include/qtgui/waterfall_sink_c.h @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_WATERFALL_SINK_C_H +#define INCLUDED_QTGUI_WATERFALL_SINK_C_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals on a + * waterfall (spectrogram) plot. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a complex + * streams and plots a waterfall (spectrogram) plot. + * + * Note that unlike the other qtgui sinks, this one does not + * support multiple input streams. We have yet to figure out a + * good way to display multiple, independent signals on this kind + * of a plot. If there are any suggestions or examples of this, we + * would love to see them. Otherwise, to display multiple signals + * here, it's probably best to sum the signals together and + * connect that here. + */ + class QTGUI_API waterfall_sink_c : virtual public gr_sync_block + { + public: + // gr::qtgui::waterfall_sink_c::sptr + typedef boost::shared_ptr<waterfall_sink_c> sptr; + + + /*! + * \brief Build a complex waterfall sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param parent a QWidget parent object, if any + */ + static sptr make(int size, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + virtual void set_fft_average(const float fftavg) = 0; + virtual float fft_average() const = 0; + + virtual void set_frequency_range(const double centerfreq, + const double bandwidth) = 0; + + virtual void set_update_time(double t) = 0; + virtual void set_title(const std::string &title) = 0; + virtual void set_color(const std::string &color) = 0; + virtual void set_line_width(int width) = 0; + virtual void set_line_style(Qt::PenStyle style) = 0; + virtual void set_line_marker(QwtSymbol::Style marker) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_WATERFALL_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui/waterfall_sink_f.h b/gr-qtgui/include/qtgui/waterfall_sink_f.h new file mode 100644 index 0000000000..0ee38256c3 --- /dev/null +++ b/gr-qtgui/include/qtgui/waterfall_sink_f.h @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_WATERFALL_SINK_F_H +#define INCLUDED_QTGUI_WATERFALL_SINK_F_H + +#include <qtgui/api.h> +#include <gr_sync_block.h> + +#include <Python.h> +#include <qapplication.h> +#include <qwt_symbol.h> + +namespace gr { + namespace qtgui { + + /*! + * \brief A graphical sink to display multiple signals on a + * waterfall (spectrogram) plot. + * \ingroup qtgui_blk + * + * This is a QT-based graphical sink the takes set of a floating + * point streams and plots a waterfall (spectrogram) plot. + * + * Note that unlike the other qtgui sinks, this one does not + * support multiple input streams. We have yet to figure out a + * good way to display multiple, independent signals on this kind + * of a plot. If there are any suggestions or examples of this, we + * would love to see them. Otherwise, to display multiple signals + * here, it's probably best to sum the signals together and + * connect that here. + */ + class QTGUI_API waterfall_sink_f : virtual public gr_sync_block + { + public: + // gr::qtgui::waterfall_sink_f::sptr + typedef boost::shared_ptr<waterfall_sink_f> sptr; + + /*! + * \brief Build a floating point waterfall sink. + * + * \param size size of the FFT to compute and display + * \param wintype type of window to apply (see filter/firdes.h) + * \param fc center frequency of signal (use for x-axis labels) + * \param bw bandwidth of signal (used to set x-axis labels) + * \param name title for the plot + * \param parent a QWidget parent object, if any + */ + static sptr make(int size, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent=NULL); + + virtual void exec_() = 0; + virtual PyObject* pyqwidget() = 0; + + virtual void set_fft_size(const int fftsize) = 0; + virtual int fft_size() const = 0; + virtual void set_fft_average(const float fftavg) = 0; + virtual float fft_average() const = 0; + + virtual void set_frequency_range(const double centerfreq, + const double bandwidth) = 0; + + virtual void set_update_time(double t) = 0; + virtual void set_title(const std::string &title) = 0; + virtual void set_color(const std::string &color) = 0; + virtual void set_line_width(int width) = 0; + virtual void set_line_style(Qt::PenStyle style) = 0; + virtual void set_line_marker(QwtSymbol::Style marker) = 0; + + virtual void set_size(int width, int height) = 0; + + QApplication *d_qApplication; + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_WATERFALL_SINK_F_H */ diff --git a/gr-qtgui/include/qtgui_sink_c.h b/gr-qtgui/include/qtgui_sink_c.h deleted file mode 100644 index 68fff368a9..0000000000 --- a/gr-qtgui/include/qtgui_sink_c.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_QTGUI_SINK_C_H -#define INCLUDED_QTGUI_SINK_C_H - -#include <Python.h> -#include <gr_qtgui_api.h> -#include <gr_block.h> -#include <gr_firdes.h> -#include <gri_fft.h> -#include <qapplication.h> -#include <gruel/high_res_timer.h> -#include "SpectrumGUIClass.h" - -class qtgui_sink_c; -typedef boost::shared_ptr<qtgui_sink_c> qtgui_sink_c_sptr; - -GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc=0, double bandwidth=1.0, - const std::string &name="Spectrum Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plottime=true, bool plotconst=true, - QWidget *parent=NULL); - -/*! - * \brief A graphical sink to display freq, spec, time, and const plots. - * \ingroup qtgui_blk - * - * This is a QT-based graphical sink the takes a complex stream and - * plots it. The default action is to plot the signal as a PSD (FFT), - * spectrogram (waterfall), time domain I&Q, and constellation (I - * vs. Q) plots. The plots may be turned off by setting the - * appropriate boolean value in the constructor to False. - */ - -class GR_QTGUI_API qtgui_sink_c : public gr_block -{ -private: - friend GR_QTGUI_API qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - qtgui_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - void initialize(); - - int d_fftsize; - gr_firdes::win_type d_wintype; - std::vector<float> d_window; - double d_center_freq; - double d_bandwidth; - std::string d_name; - gruel::high_res_timer_type d_last_update; - bool d_update_active; - - bool d_shift; - gri_fft_complex *d_fft; - - int d_index; - gr_complex *d_residbuf; - - bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; - - gruel::high_res_timer_type d_update_time; - - QWidget *d_parent; - SpectrumGUIClass *d_main_gui; - - void windowreset(); - void buildwindow(); - void fftresize(); - void fft(const gr_complex *data_in, int size); - -public: - ~qtgui_sink_c(); - void exec_(); - QWidget* qwidget(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_constellation_pen_size(int size); - void set_frequency_axis(double min, double max); - - void set_update_time(double t); - - QApplication *d_qApplication; - - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_QTGUI_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui_sink_f.h b/gr-qtgui/include/qtgui_sink_f.h deleted file mode 100644 index 709f02a2f5..0000000000 --- a/gr-qtgui/include/qtgui_sink_f.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_QTGUI_SINK_F_H -#define INCLUDED_QTGUI_SINK_F_H - -#include <Python.h> -#include <gr_qtgui_api.h> -#include <gr_block.h> -#include <gr_firdes.h> -#include <gri_fft.h> -#include <qapplication.h> -#include "SpectrumGUIClass.h" - -class qtgui_sink_f; -typedef boost::shared_ptr<qtgui_sink_f> qtgui_sink_f_sptr; - -GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc=0, double bw=1.0, - const std::string &name="Spectrum Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plottime=true, bool plotconst=false, - QWidget *parent=NULL); - -/*! - * \brief A graphical sink to display freq, spec, and time. - * \ingroup qtgui_blk - * - * This is a QT-based graphical sink the takes a float stream and - * plots it. The default action is to plot the signal as a PSD (FFT), - * spectrogram (waterfall), and time domain plots. The plots may be - * turned off by setting the appropriate boolean value in the - * constructor to False. - */ - -class GR_QTGUI_API qtgui_sink_f : public gr_block -{ -private: - friend GR_QTGUI_API qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - qtgui_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - void initialize(); - - int d_fftsize; - gr_firdes::win_type d_wintype; - std::vector<float> d_window; - double d_center_freq; - double d_bandwidth; - std::string d_name; - - bool d_shift; - gri_fft_complex *d_fft; - - int d_index; - float *d_residbuf; - - bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; - - double d_update_time; - - QWidget *d_parent; - SpectrumGUIClass *d_main_gui; - - void windowreset(); - void buildwindow(); - void fftresize(); - void fft(const float *data_in, int size); - -public: - ~qtgui_sink_f(); - void exec_(); - QWidget* qwidget(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_constellation_pen_size(int size); - void set_frequency_axis(double min, double max); - - void set_update_time(double t); - - QApplication *d_qApplication; - - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_QTGUI_SINK_F_H */ diff --git a/gr-qtgui/include/qtgui_time_sink_c.h b/gr-qtgui/include/qtgui_time_sink_c.h deleted file mode 100644 index 561d796cfa..0000000000 --- a/gr-qtgui/include/qtgui_time_sink_c.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_QTGUI_TIME_SINK_C_H -#define INCLUDED_QTGUI_TIME_SINK_C_H - -#include <Python.h> -#include <gr_qtgui_api.h> -#include <gr_sync_block.h> -#include <gr_firdes.h> -#include <gri_fft.h> -#include <qapplication.h> -#include <timedisplayform.h> - -class qtgui_time_sink_c; -typedef boost::shared_ptr<qtgui_time_sink_c> qtgui_time_sink_c_sptr; - -GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, - const std::string &name, - int nconnectons=1, - QWidget *parent=NULL); - -/*! - * \brief A graphical sink to display multiple signals in time. - * \ingroup qtgui_blk - * - * This is a QT-based graphical sink the takes set of a complex - * streams and plots them in the time domain. For each signal, both - * the signal's I and Q parts are plotted, and they are all plotted - * with a different color, and the \a set_title and \a set_color - * functions can be used to change the lable and color for a given - * input number. - */ -class GR_QTGUI_API qtgui_time_sink_c : public gr_sync_block -{ -private: - friend GR_QTGUI_API qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent); - qtgui_time_sink_c(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent=NULL); - - void initialize(); - - int d_size; - double d_bandwidth; - std::string d_name; - int d_nconnections; - - int d_index; - std::vector<double*> d_residbufs; - - double d_update_time; - - QWidget *d_parent; - TimeDisplayForm *d_main_gui; - - gruel::high_res_timer_type d_current_time; - gruel::high_res_timer_type d_last_time; - -public: - ~qtgui_time_sink_c(); - void exec_(); - QWidget* qwidget(); - PyObject* pyqwidget(); - - void set_time_domain_axis(double min, double max); - void set_update_time(double t); - void set_title(int which, const std::string &title); - void set_color(int which, const std::string &color); - - QApplication *d_qApplication; - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_QTGUI_TIME_SINK_C_H */ diff --git a/gr-qtgui/include/qtgui_time_sink_f.h b/gr-qtgui/include/qtgui_time_sink_f.h deleted file mode 100644 index 993e0556cf..0000000000 --- a/gr-qtgui/include/qtgui_time_sink_f.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_QTGUI_TIME_SINK_F_H -#define INCLUDED_QTGUI_TIME_SINK_F_H - -#include <Python.h> -#include <gr_qtgui_api.h> -#include <gr_sync_block.h> -#include <gr_firdes.h> -#include <gri_fft.h> -#include <qapplication.h> -#include <timedisplayform.h> - -class qtgui_time_sink_f; -typedef boost::shared_ptr<qtgui_time_sink_f> qtgui_time_sink_f_sptr; - -GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, - const std::string &name, - int nconnectons=1, - QWidget *parent=NULL); - -/*! - * \brief A graphical sink to display multiple signals in time. - * \ingroup qtgui_blk - * - * This is a QT-based graphical sink the takes set of a float streams - * and plots them in the time domain. Each signal is plotted with a - * different color, and the \a set_title and \a set_color functions - * can be used to change the lable and color for a given input number. - */ -class GR_QTGUI_API qtgui_time_sink_f : public gr_sync_block -{ -private: - friend GR_QTGUI_API qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent); - qtgui_time_sink_f(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent=NULL); - - void initialize(); - - int d_size; - double d_bandwidth; - std::string d_name; - int d_nconnections; - - int d_index; - std::vector<double*> d_residbufs; - - double d_update_time; - - QWidget *d_parent; - TimeDisplayForm *d_main_gui; - - gruel::high_res_timer_type d_current_time; - gruel::high_res_timer_type d_last_time; - -public: - ~qtgui_time_sink_f(); - void exec_(); - QWidget* qwidget(); - PyObject* pyqwidget(); - - void set_time_domain_axis(double min, double max); - void set_update_time(double t); - void set_title(int which, const std::string &title); - void set_color(int which, const std::string &color); - - QApplication *d_qApplication; - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_QTGUI_TIME_SINK_F_H */ diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt index 2dc35e81cb..beebd98cc5 100644 --- a/gr-qtgui/lib/CMakeLists.txt +++ b/gr-qtgui/lib/CMakeLists.txt @@ -22,7 +22,13 @@ ######################################################################## set(qtgui_moc_hdrs spectrumdisplayform.h + displayform.h timedisplayform.h + freqdisplayform.h + constellationdisplayform.h + waterfalldisplayform.h + form_menus.h + DisplayPlot.h FrequencyDisplayPlot.h TimeDomainDisplayPlot.h WaterfallDisplayPlot.h @@ -41,20 +47,30 @@ endif(NOT EXISTS ${spectrum_ui_hdr}) set(qtgui_srcs ${qtgui_moc_srcs} ${qtgui_ui_hdrs} + DisplayPlot.cc FrequencyDisplayPlot.cc TimeDomainDisplayPlot.cc WaterfallDisplayPlot.cc waterfallGlobalData.cc ConstellationDisplayPlot.cc spectrumdisplayform.cc + displayform.cc timedisplayform.cc + freqdisplayform.cc + constellationdisplayform.cc + waterfalldisplayform.cc SpectrumGUIClass.cc spectrumUpdateEvents.cc plot_waterfall.cc - qtgui_sink_c.cc - qtgui_sink_f.cc - qtgui_time_sink_c.cc - qtgui_time_sink_f.cc + sink_c_impl.cc + sink_f_impl.cc + time_sink_c_impl.cc + time_sink_f_impl.cc + freq_sink_c_impl.cc + freq_sink_f_impl.cc + const_sink_c_impl.cc + waterfall_sink_c_impl.cc + waterfall_sink_f_impl.cc qtgui_util.cc ) @@ -63,12 +79,18 @@ set(qtgui_srcs ######################################################################## include_directories( ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} + ${GR_FILTER_INCLUDE_DIRS} ${GR_QTGUI_INCLUDE_DIRS} + ${VOLK_INCLUDE_DIRS} ) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) +include_directories(${FFTW3F_INCLUDE_DIRS}) +link_directories(${FFTW3F_LIBRARY_DIRS}) + include_directories(${QWT_INCLUDE_DIRS}) link_directories(${QWT_LIBRARY_DIRS}) @@ -80,9 +102,13 @@ include_directories(${PYTHON_INCLUDE_PATH}) #deprecated for dirs (cmake 2.6) ######################################################################## list(APPEND qtgui_libs gnuradio-core + gnuradio-fft + gnuradio-filter + volk ${QT_LIBRARIES} ${QWT_LIBRARIES} ${PYTHON_LIBRARIES} + ${FFTW3F_LIBRARIES} ) add_definitions(-DQWT_DLL) #setup QWT library linkage @@ -94,6 +120,7 @@ GR_LIBRARY_FOO(gnuradio-qtgui RUNTIME_COMPONENT "qtgui_runtime" DEVEL_COMPONENT # Install the header files ######################################################################## install(FILES + DisplayPlot.h FrequencyDisplayPlot.h TimeDomainDisplayPlot.h WaterfallDisplayPlot.h @@ -101,7 +128,12 @@ install(FILES ConstellationDisplayPlot.h plot_waterfall.h spectrumdisplayform.h + displayform.h timedisplayform.h + freqdisplayform.h + constellationdisplayform.h + waterfalldisplayform.h + form_menus.h SpectrumGUIClass.h spectrumUpdateEvents.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.cc b/gr-qtgui/lib/ConstellationDisplayPlot.cc index 7a595fef45..5bc89f83fa 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.cc +++ b/gr-qtgui/lib/ConstellationDisplayPlot.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,6 +27,7 @@ #include <qwt_scale_draw.h> #include <qwt_legend.h> +#include <QColor> #include <iostream> class ConstellationDisplayZoomer: public QwtPlotZoomer @@ -47,42 +48,22 @@ public: protected: using QwtPlotZoomer::trackerText; - virtual QwtText trackerText( const QwtDoublePoint& p ) const + virtual QwtText trackerText( const QPoint& p ) const { - QwtText t(QString("(%1, %2)").arg(p.x(), 0, 'f', 4). - arg(p.y(), 0, 'f', 4)); + QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); + QwtText t(QString("(%1, %2)").arg(dp.x(), 0, 'f', 4). + arg(dp.y(), 0, 'f', 4)); return t; } }; -ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) - : QwtPlot(parent) +ConstellationDisplayPlot::ConstellationDisplayPlot(int nplots, QWidget* parent) + : DisplayPlot(nplots, parent) { - _lastReplot = 0; - resize(parent->width(), parent->height()); _numPoints = 1024; _penSize = 5; - _realDataPoints = new double[_numPoints]; - _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")); - canvas()->setPalette(palette); setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); set_xaxis(-2.0, 2.0); @@ -92,21 +73,6 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) set_yaxis(-2.0, 2.0); setAxisTitle(QwtPlot::yLeft, "Quadrature"); - // Automatically deleted when parent is deleted - _plot_curve = new QwtPlotCurve("Constellation Points"); - _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 @@ -118,56 +84,55 @@ ConstellationDisplayPlot::ConstellationDisplayPlot(QWidget* parent) _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); - _panner = new QwtPlotPanner(canvas()); - _panner->setAxisEnabled(QwtPlot::yRight, false); - _panner->setMouseButton(Qt::MidButton); - - // Avoid jumping when labels with more/less digits - // appear/disappear when scrolling vertically - - const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); - QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); - sd->setMinimumExtent( fm.width("100.00") ); - const QColor c(Qt::darkRed); _zoomer->setRubberBandPen(c); _zoomer->setTrackerPen(c); - // emit the position of clicks on widget - _picker = new QwtDblClickPlotPicker(canvas()); + QList<QColor> colors; + colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green) + << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta) + << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed) + << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray); + + // Setup dataPoints and plot vectors + // Automatically deleted when parent is deleted + for(int i = 0; i < _nplots; i++) { + _realDataPoints.push_back(new double[_numPoints]); + _imagDataPoints.push_back(new double[_numPoints]); + memset(_realDataPoints[i], 0x0, _numPoints*sizeof(double)); + memset(_imagDataPoints[i], 0x0, _numPoints*sizeof(double)); + + _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); + _plot_curve[i]->attach(this); + _plot_curve[i]->setPen(QPen(colors[i])); + + QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7)); #if QWT_VERSION < 0x060000 - connect(_picker, SIGNAL(selected(const QwtDoublePoint &)), - this, SLOT(OnPickerPointSelected(const QwtDoublePoint &))); + _plot_curve[i]->setRawData(_realDataPoints[i], _imagDataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(*symbol); #else - connect(_picker, SIGNAL(selected(const QPointF &)), - this, SLOT(OnPickerPointSelected6(const QPointF &))); + _plot_curve[i]->setRawSamples(_realDataPoints[i], _imagDataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(symbol); #endif - connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool ) ), - this, SLOT(LegendEntryChecked(QwtPlotItem *, bool ) )); + setLineStyle(i, Qt::NoPen); + setLineMarker(i, QwtSymbol::Ellipse); + } } ConstellationDisplayPlot::~ConstellationDisplayPlot() { - delete[] _realDataPoints; - delete[] _imagDataPoints; + for(int i = 0; i < _nplots; i++) { + delete [] _realDataPoints[i]; + delete [] _imagDataPoints[i]; + } // _fft_plot_curves deleted when parent deleted // _zoomer and _panner deleted when parent deleted } void -ConstellationDisplayPlot::set_pen_size(int size) -{ - if(size > 0 && size < 30){ - _penSize = size; - _plot_curve->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - } -} - - -void ConstellationDisplayPlot::set_xaxis(double min, double max) { setAxisScale(QwtPlot::xBottom, min, max); @@ -187,69 +152,72 @@ ConstellationDisplayPlot::set_axis(double xmin, double xmax, set_yaxis(ymin, ymax); } -void ConstellationDisplayPlot::replot() +void +ConstellationDisplayPlot::set_pen_size(int size) { - QwtPlot::replot(); + if(size > 0 && size < 30){ + _penSize = size; + for(int i = 0; i < _nplots; i++) { + _plot_curve[i]->setPen(QPen(Qt::blue, _penSize, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + } + } } void -ConstellationDisplayPlot::resizeSlot( QSize *s ) +ConstellationDisplayPlot::replot() { - resize(s->width(), s->height()); + QwtPlot::replot(); } -void ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, - const double* imagDataPoints, - const int64_t numDataPoints, - const double timeInterval) -{ - if((numDataPoints > 0) && - (gruel::high_res_timer_now() - _lastReplot > timeInterval*gruel::high_res_timer_tps())) { - if(numDataPoints != _numPoints){ - _numPoints = numDataPoints; - - delete[] _realDataPoints; - delete[] _imagDataPoints; - _realDataPoints = new double[_numPoints]; - _imagDataPoints = new double[_numPoints]; +void +ConstellationDisplayPlot::PlotNewData(const std::vector<double*> realDataPoints, + const std::vector<double*> imagDataPoints, + const int64_t numDataPoints, + const double timeInterval) +{ + if(!_stop) { + if((numDataPoints > 0)) { + if(numDataPoints != _numPoints) { + _numPoints = numDataPoints; + + for(int i = 0; i < _nplots; i++) { + delete [] _realDataPoints[i]; + delete [] _imagDataPoints[i]; + _realDataPoints[i] = new double[_numPoints]; + _imagDataPoints[i] = new double[_numPoints]; #if QWT_VERSION < 0x060000 - _plot_curve->setRawData(_realDataPoints, _imagDataPoints, _numPoints); + _plot_curve[i]->setRawData(_realDataPoints[i], _imagDataPoints[i], _numPoints); #else - _plot_curve->setRawSamples(_realDataPoints, _imagDataPoints, _numPoints); + _plot_curve[i]->setRawSamples(_realDataPoints[i], _imagDataPoints[i], _numPoints); #endif - } + } + } - memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double)); - memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double)); + for(int i = 0; i < _nplots; i++) { + memcpy(_realDataPoints[i], realDataPoints[i], numDataPoints*sizeof(double)); + memcpy(_imagDataPoints[i], imagDataPoints[i], numDataPoints*sizeof(double)); + } - replot(); + replot(); - _lastReplot = gruel::high_res_timer_now(); + } } } void -ConstellationDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) -{ - plotItem->setVisible(!on); -} - -void -ConstellationDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) -{ - QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); - emit plotPointSelected(point); -} - -void -ConstellationDisplayPlot::OnPickerPointSelected6(const QPointF & p) +ConstellationDisplayPlot::PlotNewData(const double* realDataPoints, + const double* imagDataPoints, + const int64_t numDataPoints, + const double timeInterval) { - QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); - emit plotPointSelected(point); + std::vector<double*> vecRealDataPoints; + std::vector<double*> vecImagDataPoints; + vecRealDataPoints.push_back((double*)realDataPoints); + vecImagDataPoints.push_back((double*)imagDataPoints); + PlotNewData(vecRealDataPoints, vecImagDataPoints, + numDataPoints, timeInterval); } #endif /* CONSTELLATION_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/ConstellationDisplayPlot.h b/gr-qtgui/lib/ConstellationDisplayPlot.h index 9e0f6f26a8..f3cbeef1cb 100644 --- a/gr-qtgui/lib/ConstellationDisplayPlot.h +++ b/gr-qtgui/lib/ConstellationDisplayPlot.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,43 +20,34 @@ * Boston, MA 02110-1301, USA. */ -#ifndef CONSTELLATION_DISPLAY_PLOT_HPP -#define CONSTELLATION_DISPLAY_PLOT_HPP +#ifndef CONSTELLATION_DISPLAY_PLOT_H +#define CONSTELLATION_DISPLAY_PLOT_H #include <stdint.h> #include <cstdio> -#include <qwt_plot.h> -#include <qwt_painter.h> -#include <qwt_plot_canvas.h> -#include <qwt_plot_curve.h> -#include <qwt_scale_engine.h> -#include <qwt_scale_widget.h> -#include <qwt_plot_zoomer.h> -#include <qwt_plot_panner.h> -#include <qwt_plot_marker.h> -#include <gruel/high_res_timer.h> -#include <qwt_symbol.h> -#include <qtgui_util.h> +#include <vector> +#include "DisplayPlot.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 +class ConstellationDisplayPlot : public DisplayPlot { Q_OBJECT public: - ConstellationDisplayPlot(QWidget*); + ConstellationDisplayPlot(int nplots, QWidget*); virtual ~ConstellationDisplayPlot(); + void PlotNewData(const std::vector<double*> realDataPoints, + const std::vector<double*> imagDataPoints, + const int64_t numDataPoints, + const double timeInterval); + + // Old method to be removed void PlotNewData(const double* realDataPoints, const double* imagDataPoints, const int64_t numDataPoints, const double timeInterval); - virtual void replot(); + void replot(); void set_xaxis(double min, double max); void set_yaxis(double min, double max); @@ -65,37 +56,13 @@ public: void set_pen_size(int size); public slots: - void resizeSlot( QSize *s ); - - // Because of the preprocessing of slots in QT, these are no - // easily separated by the version check. Make one for each - // version until it's worked out. - void OnPickerPointSelected(const QwtDoublePoint & p); - void OnPickerPointSelected6(const QPointF & p); - -signals: - void plotPointSelected(const QPointF p); - -protected slots: - void LegendEntryChecked(QwtPlotItem *plotItem, bool on); - -protected: + // set axis private: - QwtPlotCurve* _plot_curve; - - QwtPlotPanner* _panner; - QwtPlotZoomer* _zoomer; - - QwtDblClickPlotPicker *_picker; - - double* _realDataPoints; - double* _imagDataPoints; - - gruel::high_res_timer_type _lastReplot; + std::vector<double*> _realDataPoints; + std::vector<double*> _imagDataPoints; - int64_t _numPoints; int64_t _penSize; }; -#endif /* CONSTELLATION_DISPLAY_PLOT_HPP */ +#endif /* CONSTELLATION_DISPLAY_PLOT_H */ diff --git a/gr-qtgui/lib/DisplayPlot.cc b/gr-qtgui/lib/DisplayPlot.cc new file mode 100644 index 0000000000..577b4f1483 --- /dev/null +++ b/gr-qtgui/lib/DisplayPlot.cc @@ -0,0 +1,221 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <DisplayPlot.h> + +#include <qwt_scale_draw.h> +#include <qwt_legend.h> +#include <QColor> +#include <cmath> +#include <iostream> + +DisplayPlot::DisplayPlot(int nplots, QWidget* parent) + : QwtPlot(parent), _nplots(nplots), _stop(false) +{ + resize(parent->width(), parent->height()); + + // 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")); + canvas()->setPalette(palette); + + _panner = new QwtPlotPanner(canvas()); + _panner->setAxisEnabled(QwtPlot::yRight, false); + _panner->setMouseButton(Qt::MidButton); + + // 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 + _picker->setStateMachine(new QwtPickerDblClickPointMachine()); + connect(_picker, SIGNAL(selected(const QPointF &)), + this, SLOT(OnPickerPointSelected6(const QPointF &))); +#endif + + // Configure magnify on mouse wheel + _magnifier = new QwtPlotMagnifier(canvas()); + _magnifier->setAxisEnabled(QwtPlot::xBottom, false); + + // Avoid jumping when labels with more/less digits + // appear/disappear when scrolling vertically + + const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); + QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); + sd->setMinimumExtent( fm.width("100.00") ); + + QwtLegend* legendDisplay = new QwtLegend(this); + legendDisplay->setItemMode(QwtLegend::CheckableItem); + insertLegend(legendDisplay); + + connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), + this, SLOT(LegendEntryChecked(QwtPlotItem *, bool))); +} + +DisplayPlot::~DisplayPlot() +{ + // _zoomer and _panner deleted when parent deleted +} + +void +DisplayPlot::setYaxis(double min, double max) +{ + setAxisScale(QwtPlot::yLeft, min, max); + _zoomer->setZoomBase(); +} + +void +DisplayPlot::setXaxis(double min, double max) +{ + setAxisScale(QwtPlot::xBottom, min, max); + _zoomer->setZoomBase(); +} + +void +DisplayPlot::setTitle(int which, QString title) +{ + _plot_curve[which]->setTitle(title); +} + +QString +DisplayPlot::title(int which) +{ + return _plot_curve[which]->title().text(); +} + +void +DisplayPlot::setColor(int which, QString color) +{ + // Set the color of the pen + QPen pen(_plot_curve[which]->pen()); + pen.setColor(color); + _plot_curve[which]->setPen(pen); + + // And set the color of the markers +#if QWT_VERSION < 0x060000 + //_plot_curve[which]->setBrush(QBrush(QColor(color))); + _plot_curve[which]->setPen(pen); + + QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol(); + setLineMarker(which, sym.style()); +#else + QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol(); + sym->setColor(color); + sym->setPen(pen); + _plot_curve[which]->setSymbol(sym); +#endif +} + +void +DisplayPlot::setLineWidth(int which, int width) +{ + // Set the new line width + QPen pen(_plot_curve[which]->pen()); + pen.setWidth(width); + _plot_curve[which]->setPen(pen); + + // Scale the marker size proportionally +#if QWT_VERSION < 0x060000 + QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol(); + sym.setSize(7+10*log10(width), 7+10*log10(width)); + _plot_curve[which]->setSymbol(sym); +#else + QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol(); + sym->setSize(7+10*log10(width), 7+10*log10(width)); + _plot_curve[which]->setSymbol(sym); +#endif +} + +void +DisplayPlot::setLineStyle(int which, Qt::PenStyle style) +{ + QPen pen(_plot_curve[which]->pen()); + pen.setStyle(style); + _plot_curve[which]->setPen(pen); +} + +void +DisplayPlot::setLineMarker(int which, QwtSymbol::Style marker) +{ +#if QWT_VERSION < 0x060000 + QwtSymbol sym = (QwtSymbol)_plot_curve[which]->symbol(); + QPen pen(_plot_curve[which]->pen()); + QBrush brush(pen.color()); + sym.setStyle(marker); + sym.setPen(pen); + sym.setBrush(brush); + _plot_curve[which]->setSymbol(sym); +#else + QwtSymbol *sym = (QwtSymbol*)_plot_curve[which]->symbol(); + sym->setStyle(marker); + _plot_curve[which]->setSymbol(sym); +#endif +} + +void +DisplayPlot::setStop(bool on) +{ + _stop = on; +} + +void +DisplayPlot::resizeSlot( QSize *s ) +{ + // -10 is to spare some room for the legend and x-axis label + resize(s->width()-10, s->height()-10); +} + +void DisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) +{ + plotItem->setVisible(!on); + replot(); +} + +void +DisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} + +void +DisplayPlot::OnPickerPointSelected6(const QPointF & p) +{ + QPointF point = p; + //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); + emit plotPointSelected(point); +} diff --git a/gr-qtgui/lib/DisplayPlot.h b/gr-qtgui/lib/DisplayPlot.h new file mode 100644 index 0000000000..975a92a18d --- /dev/null +++ b/gr-qtgui/lib/DisplayPlot.h @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2010,2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef DOMAIN_DISPLAY_PLOT_H +#define DOMAIN_DISPLAY_PLOT_H + +#include <stdint.h> +#include <cstdio> +#include <vector> +#include <qwt_plot.h> +#include <qwt_painter.h> +#include <qwt_plot_canvas.h> +#include <qwt_plot_curve.h> +#include <qwt_scale_engine.h> +#include <qwt_scale_widget.h> +#include <qwt_plot_zoomer.h> +#include <qwt_plot_panner.h> +#include <qwt_plot_magnifier.h> +#include <qwt_plot_marker.h> +#include <qwt_symbol.h> +#include <qtgui/utils.h> + +#if QWT_VERSION >= 0x060000 +#include <qwt_compat.h> +#endif + +class DisplayPlot:public QwtPlot{ + Q_OBJECT + +public: + DisplayPlot(int nplots, QWidget*); + virtual ~DisplayPlot(); + + virtual void replot() = 0; + + // Make sure to create your won PlotNewData method in the derived + // class: + // void PlotNewData(...); + +public slots: + void setYaxis(double min, double max); + void setXaxis(double min, double max); + void setTitle(int which, QString title); + void setColor(int which, QString color); + void setLineWidth(int which, int width); + void setLineStyle(int which, Qt::PenStyle style); + void setLineMarker(int which, QwtSymbol::Style marker); + + void setStop(bool on); + + QString title(int which); + + void resizeSlot(QSize *s); + + // Because of the preprocessing of slots in QT, these are not + // easily separated by the version check. Make one for each + // version until it's worked out. + void OnPickerPointSelected(const QwtDoublePoint & p); + void OnPickerPointSelected6(const QPointF & p); + +signals: + void plotPointSelected(const QPointF p); + +protected slots: + void LegendEntryChecked(QwtPlotItem *plotItem, bool on); + +protected: + int _nplots; + std::vector<QwtPlotCurve*> _plot_curve; + + QwtPlotPanner* _panner; + QwtPlotZoomer* _zoomer; + + QwtDblClickPlotPicker *_picker; + QwtPlotMagnifier *_magnifier; + + int64_t _numPoints; + + bool _stop; +}; + +#endif /* DOMAIN_DISPLAY_PLOT_H */ diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index b74d460150..c9fb94ad68 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -25,73 +25,28 @@ #include <FrequencyDisplayPlot.h> +#include "qtgui_types.h" #include <qwt_scale_draw.h> - -class FreqPrecisionClass -{ -public: - FreqPrecisionClass(const int freqPrecision) - { - _frequencyPrecision = freqPrecision; - } - - virtual ~FreqPrecisionClass() - { - } - - virtual unsigned int GetFrequencyPrecision() const - { - return _frequencyPrecision; - } - - virtual void SetFrequencyPrecision(const unsigned int newPrecision) - { - _frequencyPrecision = newPrecision; - } -protected: - unsigned int _frequencyPrecision; - -private: - -}; - -class FreqDisplayScaleDraw: public QwtScaleDraw, public FreqPrecisionClass -{ -public: - FreqDisplayScaleDraw(const unsigned int precision) - : QwtScaleDraw(), FreqPrecisionClass(precision) - { - } - - virtual ~FreqDisplayScaleDraw() - { - } - - virtual QwtText label(double value) const - { - return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision()); - } - -protected: - -private: - -}; - -class FreqDisplayZoomer: public QwtPlotZoomer, public FreqPrecisionClass +#include <qwt_legend.h> +#include <qwt_legend_item.h> +#include <QColor> +#include <iostream> + +/*********************************************************************** + * Widget to provide mouse pointer coordinate text + **********************************************************************/ +class FreqDisplayZoomer: public QwtPlotZoomer, public FreqOffsetAndPrecisionClass { public: FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision) - : QwtPlotZoomer(canvas),FreqPrecisionClass(freqPrecision) + : QwtPlotZoomer(canvas), + FreqOffsetAndPrecisionClass(freqPrecision) { setTrackerMode(QwtPicker::AlwaysOn); } - - virtual ~FreqDisplayZoomer(){ - - } - - virtual void updateTrackerText(){ + + virtual void updateTrackerText() + { updateDisplay(); } @@ -102,11 +57,12 @@ public: protected: using QwtPlotZoomer::trackerText; - virtual QwtText trackerText( const QwtDoublePoint& p ) const + virtual QwtText trackerText(QPoint const &p) const { - QwtText t(QString("%1 %2, %3 dB"). - arg(p.x(), 0, 'f', GetFrequencyPrecision()). - arg(_unitType.c_str()).arg(p.y(), 0, 'f', 2)); + QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); + QwtText t(QString("%1 %2, %3 dB") + .arg(dp.x(), 0, 'f', GetFrequencyPrecision()) + .arg(_unitType.c_str()).arg(dp.y(), 0, 'f', 2)); return t; } @@ -114,41 +70,23 @@ private: std::string _unitType; }; -FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) - : QwtPlot(parent) + +/*********************************************************************** + * Main frequency display plotter widget + **********************************************************************/ +FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent) + : DisplayPlot(nplots, parent) { _startFrequency = 0; _stopFrequency = 4000; - _lastReplot = 0; - - resize(parent->width(), parent->height()); - _useCenterFrequencyFlag = false; _numPoints = 1024; - _dataPoints = new double[_numPoints]; _minFFTPoints = new double[_numPoints]; _maxFFTPoints = new double[_numPoints]; _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")); - canvas()->setPalette(palette); - setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); @@ -158,16 +96,31 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis); setAxisTitle(QwtPlot::yLeft, "Power (dB)"); - // Automatically deleted when parent is deleted - _fft_plot_curve = new QwtPlotCurve("Power Spectrum"); - _fft_plot_curve->attach(this); - _fft_plot_curve->setPen(QPen(Qt::blue)); + QList<QColor> colors; + colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green) + << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta) + << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed) + << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray); + // Automatically deleted when parent is deleted + for(int i = 0; i < _nplots; i++) { + _dataPoints.push_back(new double[_numPoints]); + memset(_dataPoints[i], 0x0, _numPoints*sizeof(double)); + + _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); + _plot_curve[i]->attach(this); + _plot_curve[i]->setPen(QPen(colors[i])); + + const QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7)); + #if QWT_VERSION < 0x060000 - _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints); + _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(*symbol); #else - _fft_plot_curve->setRawSamples(_xAxisPoints, _dataPoints, _numPoints); + _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(symbol); #endif + } _min_fft_plot_curve = new QwtPlotCurve("Minimum Power"); _min_fft_plot_curve->attach(this); @@ -203,7 +156,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine)); _upper_intensity_marker->attach(this); - memset(_dataPoints, 0x0, _numPoints*sizeof(double)); memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); for(int64_t number = 0; number < _numPoints; number++){ @@ -248,21 +200,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) replot(); - // 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(OnPickerPointSelected6(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 @@ -274,16 +211,6 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); - _panner = new QwtPlotPanner(canvas()); - _panner->setAxisEnabled(QwtPlot::yRight, false); - _panner->setMouseButton(Qt::MidButton); - - // Avoid jumping when labels with more/less digits - // appear/disappear when scrolling vertically - - const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); - QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); - sd->setMinimumExtent( fm.width("100.00") ); const QColor c(Qt::darkRed); _zoomer->setRubberBandPen(c); @@ -291,17 +218,24 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent) // Do this after the zoomer has been built _resetXAxisPoints(); + + // Turn off min/max hold plots in legend + QWidget *w; + QwtLegend* legendDisplay = legend(); + w = legendDisplay->find(_min_fft_plot_curve); + ((QwtLegendItem*)w)->setChecked(true); + w = legendDisplay->find(_max_fft_plot_curve); + ((QwtLegendItem*)w)->setChecked(true); } FrequencyDisplayPlot::~FrequencyDisplayPlot() { - delete[] _dataPoints; + for(int i = 0; i < _nplots; i++) + delete [] _dataPoints[i]; + delete[] _maxFFTPoints; delete[] _minFFTPoints; delete[] _xAxisPoints; - - // _fft_plot_curves deleted when parent deleted - // _zoomer and _panner deleted when parent deleted } void @@ -390,73 +324,83 @@ FrequencyDisplayPlot::replot() } void -FrequencyDisplayPlot::resizeSlot( QSize *s ) -{ - resize(s->width(), s->height()); -} - -void -FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints, +FrequencyDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, + const int64_t numDataPoints, const double noiseFloorAmplitude, const double peakFrequency, const double peakAmplitude, const double timeInterval) { - // 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())) { - - if(numDataPoints != _numPoints) { - _numPoints = numDataPoints; - - delete[] _dataPoints; - delete[] _minFFTPoints; - delete[] _maxFFTPoints; - delete[] _xAxisPoints; - _dataPoints = new double[_numPoints]; - _xAxisPoints = new double[_numPoints]; - _minFFTPoints = new double[_numPoints]; - _maxFFTPoints = new double[_numPoints]; + if(!_stop) { + if(numDataPoints > 0) { + if(numDataPoints != _numPoints) { + _numPoints = numDataPoints; + + delete[] _minFFTPoints; + delete[] _maxFFTPoints; + delete[] _xAxisPoints; + _xAxisPoints = new double[_numPoints]; + _minFFTPoints = new double[_numPoints]; + _maxFFTPoints = new double[_numPoints]; + + for(int i = 0; i < _nplots; i++) { + delete[] _dataPoints[i]; + _dataPoints[i] = 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); + _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _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); + _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _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]){ - _minFFTPoints[point] = dataPoints[point]; + _resetXAxisPoints(); + ClearMaxData(); + ClearMinData(); } - if(dataPoints[point] > _maxFFTPoints[point]){ - _maxFFTPoints[point] = dataPoints[point]; + + for(int i = 0; i < _nplots; i++) { + memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); } - } - _noiseFloorAmplitude = noiseFloorAmplitude; - _peakFrequency = peakFrequency; - _peakAmplitude = peakAmplitude; + for(int64_t point = 0; point < numDataPoints; point++){ + if(dataPoints[0][point] < _minFFTPoints[point]) { + _minFFTPoints[point] = dataPoints[0][point]; + } + if(dataPoints[0][point] > _maxFFTPoints[point]) { + _maxFFTPoints[point] = dataPoints[0][point]; + } + } - SetUpperIntensityLevel(_peakAmplitude); + _noiseFloorAmplitude = noiseFloorAmplitude; + _peakFrequency = peakFrequency; + _peakAmplitude = peakAmplitude; - replot(); + SetUpperIntensityLevel(_peakAmplitude); - _lastReplot = gruel::high_res_timer_now(); + replot(); + } } } void +FrequencyDisplayPlot::PlotNewData(const double* dataPoints, + const int64_t numDataPoints, + const double noiseFloorAmplitude, const double peakFrequency, + const double peakAmplitude, const double timeInterval) +{ + std::vector<double*> vecDataPoints; + vecDataPoints.push_back((double*)dataPoints); + PlotNewData(vecDataPoints, numDataPoints, noiseFloorAmplitude, + peakFrequency, peakAmplitude, timeInterval); +} + +void FrequencyDisplayPlot::ClearMaxData() { - for(int64_t number = 0; number < _numPoints; number++){ + for(int64_t number = 0; number < _numPoints; number++) { _maxFFTPoints[number] = _minYAxis; } } @@ -464,7 +408,7 @@ FrequencyDisplayPlot::ClearMaxData() void FrequencyDisplayPlot::ClearMinData() { - for(int64_t number = 0; number < _numPoints; number++){ + for(int64_t number = 0; number < _numPoints; number++) { _minFFTPoints[number] = _maxYAxis; } } @@ -484,9 +428,10 @@ FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag) void FrequencyDisplayPlot::_resetXAxisPoints() { - double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(_numPoints); + double fft_bin_size = (_stopFrequency-_startFrequency) + / static_cast<double>(_numPoints); double freqValue = _startFrequency; - for(int64_t loc = 0; loc < _numPoints; loc++){ + for(int64_t loc = 0; loc < _numPoints; loc++) { _xAxisPoints[loc] = freqValue; freqValue += fft_bin_size; } @@ -506,23 +451,23 @@ FrequencyDisplayPlot::_resetXAxisPoints() void FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel) { - _lower_intensity_marker->setYValue( lowerIntensityLevel ); + _lower_intensity_marker->setYValue(lowerIntensityLevel); } void FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel) { - _upper_intensity_marker->setYValue( upperIntensityLevel ); + _upper_intensity_marker->setYValue(upperIntensityLevel); } void -FrequencyDisplayPlot::SetTraceColour (QColor c) +FrequencyDisplayPlot::SetTraceColour(QColor c) { - _fft_plot_curve->setPen(QPen(c)); + _plot_curve[0]->setPen(QPen(c)); } void -FrequencyDisplayPlot::SetBGColour (QColor c) +FrequencyDisplayPlot::SetBGColour(QColor c) { QPalette palette; palette.setColor(canvas()->backgroundRole(), c); @@ -530,7 +475,7 @@ FrequencyDisplayPlot::SetBGColour (QColor c) } void -FrequencyDisplayPlot::ShowCFMarker (const bool show) +FrequencyDisplayPlot::ShowCFMarker(const bool show) { if (show) _markerCF->show(); diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.h b/gr-qtgui/lib/FrequencyDisplayPlot.h index 5c3ea708c3..17bb9d2391 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.h +++ b/gr-qtgui/lib/FrequencyDisplayPlot.h @@ -25,29 +25,15 @@ #include <stdint.h> #include <cstdio> -#include <qwt_plot.h> -#include <qwt_painter.h> -#include <qwt_plot_canvas.h> -#include <qwt_plot_curve.h> -#include <qwt_scale_engine.h> -#include <qwt_scale_widget.h> -#include <qwt_plot_zoomer.h> -#include <qwt_plot_panner.h> -#include <qwt_plot_marker.h> -#include <qwt_plot_magnifier.h> -#include <gruel/high_res_timer.h> -#include <qwt_symbol.h> -#include <qtgui_util.h> - -#if QWT_VERSION >= 0x060000 -#include <qwt_compat.h> -#endif - -class FrequencyDisplayPlot:public QwtPlot{ +#include <vector> +#include "DisplayPlot.h" + +class FrequencyDisplayPlot: public DisplayPlot +{ Q_OBJECT public: - FrequencyDisplayPlot(QWidget*); + FrequencyDisplayPlot(int nplots, QWidget*); virtual ~FrequencyDisplayPlot(); void SetFrequencyRange(const double, const double, @@ -57,7 +43,14 @@ public: double GetStartFrequency()const; double GetStopFrequency()const; - void PlotNewData(const double* dataPoints, const int64_t numDataPoints, + void PlotNewData(const std::vector<double*> dataPoints, + const int64_t numDataPoints, + const double noiseFloorAmplitude, const double peakFrequency, + const double peakAmplitude, const double timeInterval); + + // Old method to be removed + void PlotNewData(const double* dataPoints, + const int64_t numDataPoints, const double noiseFloorAmplitude, const double peakFrequency, const double peakAmplitude, const double timeInterval); @@ -67,7 +60,7 @@ public: void SetMaxFFTVisible(const bool); void SetMinFFTVisible(const bool); - virtual void replot(); + void replot(); void set_yaxis(double min, double max); @@ -76,63 +69,43 @@ public: void ShowCFMarker (const bool); public slots: - void resizeSlot( QSize *e ); void SetLowerIntensityLevel(const double); void SetUpperIntensityLevel(const double); - // Because of the preprocessing of slots in QT, these are no - // easily separated by the version check. Make one for each - // version until it's worked out. void OnPickerPointSelected(const QwtDoublePoint & p); void OnPickerPointSelected6(const QPointF & p); -signals: - void plotPointSelected(const QPointF p); - -protected: - private: - void _resetXAxisPoints(); + std::vector<double*> _dataPoints; + + QwtPlotCurve* _min_fft_plot_curve; + QwtPlotCurve* _max_fft_plot_curve; + double _startFrequency; double _stopFrequency; double _maxYAxis; double _minYAxis; - QwtPlotCurve* _fft_plot_curve; - QwtPlotCurve* _min_fft_plot_curve; - QwtPlotCurve* _max_fft_plot_curve; - QwtPlotMarker* _lower_intensity_marker; QwtPlotMarker* _upper_intensity_marker; - QwtPlotPanner* _panner; - QwtPlotZoomer* _zoomer; - QwtPlotMarker *_markerPeakAmplitude; QwtPlotMarker *_markerNoiseFloorAmplitude; QwtPlotMarker *_markerCF; - QwtDblClickPlotPicker *_picker; - - QwtPlotMagnifier *_magnifier; - - double* _dataPoints; double* _xAxisPoints; int _xAxisMultiplier; double* _minFFTPoints; double* _maxFFTPoints; - int64_t _numPoints; double _peakFrequency; double _peakAmplitude; double _noiseFloorAmplitude; - gruel::high_res_timer_type _lastReplot; - bool _useCenterFrequencyFlag; }; diff --git a/gr-qtgui/lib/SpectrumGUIClass.cc b/gr-qtgui/lib/SpectrumGUIClass.cc index d2dbc77723..e73ee2d50c 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.cc +++ b/gr-qtgui/lib/SpectrumGUIClass.cc @@ -27,6 +27,7 @@ //Added by qt3to4: #include <QEvent> #include <QCustomEvent> +#include <volk/volk.h> const long SpectrumGUIClass::MAX_FFT_SIZE = 32768; const long SpectrumGUIClass::MIN_FFT_SIZE = 256; @@ -88,13 +89,12 @@ SpectrumGUIClass::OpenSpectrumWindow(QWidget* parent, if(!_windowOpennedFlag){ if(!_fftBuffersCreatedFlag){ - _fftPoints = new std::complex<float>[_dataPoints]; + _fftPoints = new float[_dataPoints]; _realTimeDomainPoints = new double[_dataPoints]; _imagTimeDomainPoints = new double[_dataPoints]; _fftBuffersCreatedFlag = true; - - - memset(_fftPoints, 0x0, _dataPoints*sizeof(std::complex<float>)); + + memset(_fftPoints, 0x0, _dataPoints*sizeof(float)); memset(_realTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); memset(_imagTimeDomainPoints, 0x0, _dataPoints*sizeof(double)); } @@ -223,7 +223,7 @@ SpectrumGUIClass::GetCenterFrequency() void SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, - const std::complex<float>* fftBuffer, + const float* fftBuffer, const uint64_t inputBufferSize, const float* realTimeDomainData, const uint64_t realTimeDomainDataSize, @@ -242,9 +242,11 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, if(updateDisplayFlag){ if((fftBuffer != NULL) && (bufferSize > 0)){ - memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(std::complex<float>)); + memcpy(_fftPoints, fftBuffer, bufferSize * sizeof(float)); } + //ALL OF THIS SHIT SHOULD BE COMBINED WITH THE FFTSHIFT + //USE VOLK_32FC_DEINTERLEAVE_64F_X2_A TO GET REAL/IMAG FROM COMPLEX32 // Can't do a memcpy since ths is going from float to double data type if((realTimeDomainData != NULL) && (realTimeDomainDataSize > 0)){ const float* realTimeDomainDataPtr = realTimeDomainData; @@ -252,24 +254,18 @@ SpectrumGUIClass::UpdateWindow(const bool updateDisplayFlag, double* realTimeDomainPointsPtr = _realTimeDomainPoints; timeDomainBufferSize = realTimeDomainDataSize; - memset( _imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double)); - for( uint64_t number = 0; number < realTimeDomainDataSize; number++){ + memset(_imagTimeDomainPoints, 0x0, realTimeDomainDataSize*sizeof(double)); + for(uint64_t number = 0; number < realTimeDomainDataSize; number++){ *realTimeDomainPointsPtr++ = *realTimeDomainDataPtr++; } } - // Can't do a memcpy since ths is going from float to double data type if((complexTimeDomainData != NULL) && (complexTimeDomainDataSize > 0)){ - const float* complexTimeDomainDataPtr = complexTimeDomainData; - - double* realTimeDomainPointsPtr = _realTimeDomainPoints; - double* imagTimeDomainPointsPtr = _imagTimeDomainPoints; - + volk_32fc_deinterleave_64f_x2_a(_realTimeDomainPoints, + _imagTimeDomainPoints, + (const lv_32fc_t *)complexTimeDomainData, + complexTimeDomainDataSize); timeDomainBufferSize = complexTimeDomainDataSize; - for( uint64_t number = 0; number < complexTimeDomainDataSize; number++){ - *realTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; - *imagTimeDomainPointsPtr++ = *complexTimeDomainDataPtr++; - } } } diff --git a/gr-qtgui/lib/SpectrumGUIClass.h b/gr-qtgui/lib/SpectrumGUIClass.h index e0612413b0..a1150199b2 100644 --- a/gr-qtgui/lib/SpectrumGUIClass.h +++ b/gr-qtgui/lib/SpectrumGUIClass.h @@ -62,7 +62,7 @@ public: double GetStopFrequency(); double GetCenterFrequency(); - void UpdateWindow(const bool, const std::complex<float>*, + void UpdateWindow(const bool, const float*, const uint64_t, const float*, const uint64_t, const float*, const uint64_t, @@ -122,7 +122,7 @@ private: SpectrumDisplayForm* _spectrumDisplayForm; - std::complex<float>* _fftPoints; + float* _fftPoints; double* _realTimeDomainPoints; double* _imagTimeDomainPoints; }; diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index 84b09af90f..a10418bddf 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,6 +28,7 @@ #include <qwt_scale_draw.h> #include <qwt_legend.h> #include <QColor> +#include <cmath> #include <iostream> class TimePrecisionClass @@ -80,11 +81,12 @@ public: protected: using QwtPlotZoomer::trackerText; - virtual QwtText trackerText( const QwtDoublePoint& p ) const + virtual QwtText trackerText( const QPoint& p ) const { - QwtText t(QString("%1 %2, %3 V").arg(p.x(), 0, 'f', GetTimePrecision()). + QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); + QwtText t(QString("%1 %2, %3 V").arg(dp.x(), 0, 'f', GetTimePrecision()). arg(_unitType.c_str()). - arg(p.y(), 0, 'f', 4)); + arg(dp.y(), 0, 'f', 4)); return t; } @@ -93,11 +95,13 @@ private: std::string _unitType; }; + +/*********************************************************************** + * Main Time domain plotter widget + **********************************************************************/ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) - : QwtPlot(parent), _nplots(nplots) + : DisplayPlot(nplots, parent) { - resize(parent->width(), parent->height()); - _numPoints = 1024; _xAxisPoints = new double[_numPoints]; memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); @@ -108,22 +112,14 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) _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 + _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, + Qt::RightButton, Qt::ControlModifier); + _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, + Qt::RightButton); - QPalette palette; - palette.setColor(canvas()->backgroundRole(), QColor("white")); - canvas()->setPalette(palette); + const QColor c(Qt::darkRed); + _zoomer->setRubberBandPen(c); + _zoomer->setTrackerPen(c); setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); setXaxis(0, _numPoints); @@ -149,57 +145,19 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(int nplots, QWidget* parent) _plot_curve[i]->attach(this); _plot_curve[i]->setPen(QPen(colors[i])); + QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(colors[i]), QPen(colors[i]), QSize(7,7)); + #if QWT_VERSION < 0x060000 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(*symbol); #else _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(symbol); #endif -} + } _sampleRate = 1; _resetXAxisPoints(); - - _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, - Qt::RightButton, Qt::ControlModifier); - _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, - Qt::RightButton); - - _panner = new QwtPlotPanner(canvas()); - _panner->setAxisEnabled(QwtPlot::yRight, false); - _panner->setMouseButton(Qt::MidButton); - - // 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(OnPickerPointSelected6(const QPointF &))); -#endif - - // Configure magnify on mouse wheel - _magnifier = new QwtPlotMagnifier(canvas()); - _magnifier->setAxisEnabled(QwtPlot::xBottom, false); - - // Avoid jumping when labels with more/less digits - // appear/disappear when scrolling vertically - - const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); - QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); - sd->setMinimumExtent( fm.width("100.00") ); - - const QColor c(Qt::darkRed); - _zoomer->setRubberBandPen(c); - _zoomer->setTrackerPen(c); - - QwtLegend* legendDisplay = new QwtLegend(this); - legendDisplay->setItemMode(QwtLegend::CheckableItem); - insertLegend(legendDisplay); - - connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), - this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) )); } TimeDomainDisplayPlot::~TimeDomainDisplayPlot() @@ -212,74 +170,45 @@ TimeDomainDisplayPlot::~TimeDomainDisplayPlot() } void -TimeDomainDisplayPlot::setYaxis(double min, double max) -{ - setAxisScale(QwtPlot::yLeft, min, max); - _zoomer->setZoomBase(); -} - -void -TimeDomainDisplayPlot::setXaxis(double min, double max) -{ - setAxisScale(QwtPlot::xBottom, min, max); - _zoomer->setZoomBase(); -} - -void -TimeDomainDisplayPlot::setTitle(int which, QString title) -{ - _plot_curve[which]->setTitle(title); -} - -void -TimeDomainDisplayPlot::setColor(int which, QString color) -{ - _plot_curve[which]->setPen(QPen(color)); -} - -void TimeDomainDisplayPlot::replot() +TimeDomainDisplayPlot::replot() { QwtPlot::replot(); } void -TimeDomainDisplayPlot::resizeSlot( QSize *s ) -{ - // -10 is to spare some room for the legend and x-axis label - resize(s->width()-10, s->height()-10); -} - -void TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, - const int64_t numDataPoints, - const double timeInterval) +TimeDomainDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, + const int64_t numDataPoints, + const double timeInterval) { - if((numDataPoints > 0)) { - if(numDataPoints != _numPoints){ - _numPoints = numDataPoints; + if(!_stop) { + if((numDataPoints > 0)) { + if(numDataPoints != _numPoints){ + _numPoints = numDataPoints; - delete[] _xAxisPoints; - _xAxisPoints = new double[_numPoints]; + delete[] _xAxisPoints; + _xAxisPoints = new double[_numPoints]; - for(int i = 0; i < _nplots; i++) { - delete[] _dataPoints[i]; - _dataPoints[i] = new double[_numPoints]; + 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); + _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); #else - _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); #endif + } + + setXaxis(0, numDataPoints); + _resetXAxisPoints(); } - setXaxis(0, numDataPoints); - _resetXAxisPoints(); - } + for(int i = 0; i < _nplots; i++) { + memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); + } - for(int i = 0; i < _nplots; i++) { - memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); + replot(); } - - replot(); } } @@ -301,11 +230,6 @@ void TimeDomainDisplayPlot::_resetXAxisPoints() _zoomer->zoom(0); } -void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on) -{ - plotItem->setVisible(!on); -} - void TimeDomainDisplayPlot::SetSampleRate(double sr, double units, const std::string &strunits) @@ -325,21 +249,4 @@ TimeDomainDisplayPlot::SetSampleRate(double sr, double units, } } - -void -TimeDomainDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) -{ - QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); - emit plotPointSelected(point); -} - -void -TimeDomainDisplayPlot::OnPickerPointSelected6(const QPointF & p) -{ - QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); - emit plotPointSelected(point); -} - #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h index 356da25ad4..9c07e96ba0 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.h +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,30 +20,16 @@ * Boston, MA 02110-1301, USA. */ -#ifndef TIME_DOMAIN_DISPLAY_PLOT_HPP -#define TIME_DOMAIN_DISPLAY_PLOT_HPP +#ifndef TIME_DOMAIN_DISPLAY_PLOT_H +#define TIME_DOMAIN_DISPLAY_PLOT_H #include <stdint.h> #include <cstdio> #include <vector> -#include <qwt_plot.h> -#include <qwt_painter.h> -#include <qwt_plot_canvas.h> -#include <qwt_plot_curve.h> -#include <qwt_scale_engine.h> -#include <qwt_scale_widget.h> -#include <qwt_plot_zoomer.h> -#include <qwt_plot_panner.h> -#include <qwt_plot_magnifier.h> -#include <qwt_plot_marker.h> -#include <qwt_symbol.h> -#include <qtgui_util.h> +#include "DisplayPlot.h" -#if QWT_VERSION >= 0x060000 -#include <qwt_compat.h> -#endif - -class TimeDomainDisplayPlot:public QwtPlot{ +class TimeDomainDisplayPlot: public DisplayPlot +{ Q_OBJECT public: @@ -53,50 +39,19 @@ public: void PlotNewData(const std::vector<double*> dataPoints, const int64_t numDataPoints, const double timeInterval); - virtual void replot(); + void replot(); public slots: - void setYaxis(double min, double max); - void setXaxis(double min, double max); - void setTitle(int which, QString title); - void setColor(int which, QString color); - - void resizeSlot( QSize *s ); void SetSampleRate(double sr, double units, const std::string &strunits); - // Because of the preprocessing of slots in QT, these are no - // easily separated by the version check. Make one for each - // version until it's worked out. - void OnPickerPointSelected(const QwtDoublePoint & p); - void OnPickerPointSelected6(const QPointF & p); - -signals: - void plotPointSelected(const QPointF p); - -protected slots: - void LegendEntryChecked(QwtPlotItem *plotItem, bool on); - -protected: - private: void _resetXAxisPoints(); - int _nplots; - std::vector<QwtPlotCurve*> _plot_curve; - - QwtPlotPanner* _panner; - QwtPlotZoomer* _zoomer; - - QwtDblClickPlotPicker *_picker; - QwtPlotMagnifier *_magnifier; - std::vector<double*> _dataPoints; double* _xAxisPoints; double _sampleRate; - - int64_t _numPoints; }; -#endif /* TIME_DOMAIN_DISPLAY_PLOT_HPP */ +#endif /* TIME_DOMAIN_DISPLAY_PLOT_H */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index 63eb57ffe8..40d16d0072 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,128 +25,23 @@ #include <WaterfallDisplayPlot.h> +#include "qtgui_types.h" #include <qwt_color_map.h> -#include <qwt_scale_widget.h> #include <qwt_scale_draw.h> -#include <qwt_plot_zoomer.h> -#include <qwt_plot_panner.h> +#include <qwt_legend.h> +#include <qwt_legend_item.h> #include <qwt_plot_layout.h> - -#include <qapplication.h> +#include <QColor> +#include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> namespace pt = boost::posix_time; -class FreqOffsetAndPrecisionClass -{ -public: - FreqOffsetAndPrecisionClass(const int freqPrecision) - { - _frequencyPrecision = freqPrecision; - _centerFrequency = 0; - } - - virtual ~FreqOffsetAndPrecisionClass() - { - } - - virtual unsigned int GetFrequencyPrecision() const - { - return _frequencyPrecision; - } - - virtual void SetFrequencyPrecision(const unsigned int newPrecision) - { - _frequencyPrecision = newPrecision; - } - - virtual double GetCenterFrequency() const - { - return _centerFrequency; - } - - virtual void SetCenterFrequency(const double newFreq) - { - _centerFrequency = newFreq; - } - -protected: - unsigned int _frequencyPrecision; - double _centerFrequency; - -private: - -}; - -class WaterfallFreqDisplayScaleDraw: public QwtScaleDraw, public FreqOffsetAndPrecisionClass{ -public: - WaterfallFreqDisplayScaleDraw(const unsigned int precision) - : QwtScaleDraw(), FreqOffsetAndPrecisionClass(precision) - { - } - - virtual ~WaterfallFreqDisplayScaleDraw() - { - } - - QwtText label(double value) const - { - return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision()); - } - - virtual void initiateUpdate() - { - invalidateCache(); - } - -protected: - -private: - -}; - -class TimeScaleData -{ -public: - TimeScaleData() - { - _zeroTime = 0; - _secondsPerLine = 1.0; - } - - virtual ~TimeScaleData() - { - } - - virtual gruel::high_res_timer_type GetZeroTime() const - { - return _zeroTime; - } - - virtual void SetZeroTime(const gruel::high_res_timer_type newTime) - { - _zeroTime = newTime - gruel::high_res_timer_epoch(); - } - - virtual void SetSecondsPerLine(const double newTime) - { - _secondsPerLine = newTime; - } - - virtual double GetSecondsPerLine() const - { - return _secondsPerLine; - } - - -protected: - gruel::high_res_timer_type _zeroTime; - double _secondsPerLine; - -private: - -}; +#include <QDebug> +/*********************************************************************** + * Create a time label HH:MM:SS.SSS from an input time + **********************************************************************/ static QString make_time_label(double secs) { @@ -160,6 +55,9 @@ make_time_label(double secs) return QString("").sprintf("%s.%03ld", time_str.c_str(), long(std::fmod(secs*1000, 1000))); } +/*********************************************************************** + * Text scale widget to provide Y (time) axis text + **********************************************************************/ class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData { public: @@ -173,8 +71,8 @@ public: virtual QwtText label(double value) const { - double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (value * GetSecondsPerLine()); - return QwtText(make_time_label(secs)); + double secs = double(value * GetSecondsPerLine()); + return QwtText(QString("").sprintf("%.1f", secs)); } virtual void initiateUpdate() @@ -190,7 +88,10 @@ private: }; -class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData, +/*********************************************************************** + * Widget to provide mouse pointer coordinate text + **********************************************************************/ +class WaterfallZoomer: public QwtPlotZoomer, public TimeScaleData, public FreqOffsetAndPrecisionClass { public: @@ -217,12 +118,14 @@ public: protected: using QwtPlotZoomer::trackerText; - virtual QwtText trackerText( const QwtDoublePoint& p ) const + virtual QwtText trackerText( QPoint const &p ) const { - double secs = GetZeroTime()/double(gruel::high_res_timer_tps()) - (p.y() * GetSecondsPerLine()); - QwtText t(QString("%1 %2, %3"). - arg(p.x(), 0, 'f', GetFrequencyPrecision()). - arg(_unitType.c_str()).arg(make_time_label(secs))); + QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); + double secs = double(dp.y() * GetSecondsPerLine()); + QwtText t(QString("%1 %2, %3 s") + .arg(dp.x(), 0, 'f', GetFrequencyPrecision()) + .arg(_unitType.c_str()) + .arg(secs, 0, 'f', 2)); return t; } @@ -230,100 +133,59 @@ 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 +* Main waterfall plot widget *********************************************************************/ - -WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) - : QwtPlot(parent) +WaterfallDisplayPlot::WaterfallDisplayPlot(int nplots, QWidget* parent) + : DisplayPlot(nplots, parent) { - _zoomer = NULL; + _zoomer = NULL; // need this for proper init _startFrequency = 0; _stopFrequency = 4000; + _useCenterFrequencyFlag = false; resize(parent->width(), parent->height()); _numPoints = 1024; - QPalette palette; - palette.setColor(canvas()->backgroundRole(), QColor("white")); - canvas()->setPalette(palette); - setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); - setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(0)); + setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); - setAxisTitle(QwtPlot::yLeft, "Time"); + setAxisTitle(QwtPlot::yLeft, "Time (s)"); setAxisScaleDraw(QwtPlot::yLeft, new QwtTimeScaleDraw()); _lastReplot = 0; - _intensityColorMapType = INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR; + QList<int> colormaps; + colormaps << INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR + << INTENSITY_COLOR_MAP_TYPE_WHITE_HOT + << INTENSITY_COLOR_MAP_TYPE_BLACK_HOT + << INTENSITY_COLOR_MAP_TYPE_INCANDESCENT + << INTENSITY_COLOR_MAP_TYPE_USER_DEFINED; - d_data = new WaterfallData(_startFrequency, _stopFrequency, - _numPoints, 200); + for(int i = 0; i < _nplots; i++) { + d_data.push_back(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); + d_spectrogram.push_back(new PlotWaterfall(d_data[i], "Spectrogram")); #else - d_spectrogram = new QwtPlotSpectrogram("Spectrogram"); - d_spectrogram->setData(d_data); - d_spectrogram->setDisplayMode(QwtPlotSpectrogram::ImageMode, true); - d_spectrogram->setColorMap(new ColorMap_MultiColor()); + d_spectrogram.push_back(new QwtPlotSpectrogram("Spectrogram")); + d_spectrogram[i]->setData(d_data[i]); + d_spectrogram[i]->setDisplayMode(QwtPlotSpectrogram::ImageMode, true); + d_spectrogram[i]->setColorMap(new ColorMap_MultiColor()); #endif - d_spectrogram->attach(this); + // a hack around the fact that we aren't using plot curves for the + // spectrogram plots. + _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); + + d_spectrogram[i]->attach(this); + + _intensityColorMapType.push_back(colormaps[i%colormaps.size()]); + SetIntensityColorMapType(i, _intensityColorMapType[i], + QColor("white"), QColor("white")); + } // LeftButton for the zooming // MidButton for the panning @@ -338,27 +200,6 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); - _panner = new QwtPlotPanner(canvas()); - _panner->setAxisEnabled(QwtPlot::yRight, false); - _panner->setMouseButton(Qt::MidButton); - - // 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(OnPickerPointSelected6(const QPointF &))); -#endif - - // Avoid jumping when labels with more/less digits - // appear/disappear when scrolling vertically - - const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); - QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); - sd->setMinimumExtent( fm.width("100.00") ); - const QColor c(Qt::black); _zoomer->setRubberBandPen(c); _zoomer->setTrackerPen(c); @@ -370,15 +211,15 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(QWidget* parent) WaterfallDisplayPlot::~WaterfallDisplayPlot() { - delete d_data; - delete d_spectrogram; } void WaterfallDisplayPlot::Reset() { - d_data->ResizeData(_startFrequency, _stopFrequency, _numPoints); - d_data->Reset(); + for(int i = 0; i < _nplots; i++) { + d_data[i]->ResizeData(_startFrequency, _stopFrequency, _numPoints); + d_data[i]->Reset(); + } setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency); @@ -406,7 +247,7 @@ WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq, _useCenterFrequencyFlag = useCenterFrequencyFlag; - if(_useCenterFrequencyFlag){ + if(_useCenterFrequencyFlag) { startFreq = (startFreq + centerFreq); stopFreq = (stopFreq + centerFreq); } @@ -419,9 +260,9 @@ WaterfallDisplayPlot::SetFrequencyRange(const double constStartFreq, _startFrequency = startFreq; _stopFrequency = stopFreq; - if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){ + if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)) { double display_units = ceil(log10(units)/2.0); - setAxisScaleDraw(QwtPlot::xBottom, new WaterfallFreqDisplayScaleDraw(display_units)); + setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units)); setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str())); if(reset) { @@ -448,31 +289,35 @@ WaterfallDisplayPlot::GetStopFrequency() const } void -WaterfallDisplayPlot::PlotNewData(const double* dataPoints, +WaterfallDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, const int64_t numDataPoints, const double timePerFFT, const gruel::high_res_timer_type timestamp, const int droppedFrames) { - if(numDataPoints > 0){ - if(numDataPoints != _numPoints){ - _numPoints = numDataPoints; + if(!_stop) { + if(numDataPoints > 0){ + if(numDataPoints != _numPoints){ + _numPoints = numDataPoints; + + Reset(); - Reset(); + for(int i = 0; i < _nplots; i++) { + d_spectrogram[i]->invalidateCache(); + d_spectrogram[i]->itemChanged(); + } - d_spectrogram->invalidateCache(); - d_spectrogram->itemChanged(); + if(isVisible()) { + replot(); + } - if(isVisible()){ - replot(); + _lastReplot = gruel::high_res_timer_now(); } - _lastReplot = gruel::high_res_timer_now(); - } - - if(gruel::high_res_timer_now() - _lastReplot > timePerFFT*gruel::high_res_timer_tps()) { - d_data->addFFTData(dataPoints, numDataPoints, droppedFrames); - d_data->IncrementNumLinesToUpdate(); + for(int i = 0; i < _nplots; i++) { + d_data[i]->addFFTData(dataPoints[i], numDataPoints, droppedFrames); + d_data[i]->IncrementNumLinesToUpdate(); + } QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); timeScale->SetSecondsPerLine(timePerFFT); @@ -481,30 +326,45 @@ WaterfallDisplayPlot::PlotNewData(const double* dataPoints, ((WaterfallZoomer*)_zoomer)->SetSecondsPerLine(timePerFFT); ((WaterfallZoomer*)_zoomer)->SetZeroTime(timestamp); - d_spectrogram->invalidateCache(); - d_spectrogram->itemChanged(); + for(int i = 0; i < _nplots; i++) { + d_spectrogram[i]->invalidateCache(); + d_spectrogram[i]->itemChanged(); + } replot(); - - _lastReplot = gruel::high_res_timer_now(); } } } void +WaterfallDisplayPlot::PlotNewData(const double* dataPoints, + const int64_t numDataPoints, + const double timePerFFT, + const gruel::high_res_timer_type timestamp, + const int droppedFrames) +{ + std::vector<double*> vecDataPoints; + vecDataPoints.push_back((double*)dataPoints); + PlotNewData(vecDataPoints, numDataPoints, timePerFFT, + timestamp, droppedFrames); +} + +void WaterfallDisplayPlot::SetIntensityRange(const double minIntensity, const double maxIntensity) { + for(int i = 0; i < _nplots; i++) { #if QWT_VERSION < 0x060000 - d_data->setRange(QwtDoubleInterval(minIntensity, maxIntensity)); + d_data[i]->setRange(QwtDoubleInterval(minIntensity, maxIntensity)); #else - d_data->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity)); + d_data[i]->setInterval(Qt::ZAxis, QwtInterval(minIntensity, maxIntensity)); #endif - emit UpdatedLowerIntensityLevel(minIntensity); - emit UpdatedUpperIntensityLevel(maxIntensity); + emit UpdatedLowerIntensityLevel(minIntensity); + emit UpdatedUpperIntensityLevel(maxIntensity); - _UpdateIntensityRangeDisplay(); + _UpdateIntensityRangeDisplay(); + } } void @@ -513,8 +373,8 @@ WaterfallDisplayPlot::replot() QwtTimeScaleDraw* timeScale = (QwtTimeScaleDraw*)axisScaleDraw(QwtPlot::yLeft); timeScale->initiateUpdate(); - WaterfallFreqDisplayScaleDraw* freqScale = \ - (WaterfallFreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom); + FreqDisplayScaleDraw* freqScale = \ + (FreqDisplayScaleDraw*)axisScaleDraw(QwtPlot::xBottom); freqScale->initiateUpdate(); // Update the time axis display @@ -534,76 +394,71 @@ WaterfallDisplayPlot::replot() QwtPlot::replot(); } -void -WaterfallDisplayPlot::resizeSlot( QSize *s ) -{ - resize(s->width(), s->height()); -} - int -WaterfallDisplayPlot::GetIntensityColorMapType() const +WaterfallDisplayPlot::GetIntensityColorMapType(int which) const { - return _intensityColorMapType; + return _intensityColorMapType[which]; } void -WaterfallDisplayPlot::SetIntensityColorMapType(const int newType, +WaterfallDisplayPlot::SetIntensityColorMapType(const int which, + const int newType, const QColor lowColor, const QColor highColor) { - if((_intensityColorMapType != newType) || + if((_intensityColorMapType[which] != newType) || ((newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED) && (lowColor.isValid() && highColor.isValid()))){ switch(newType){ case INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR:{ - _intensityColorMapType = newType; + _intensityColorMapType[which] = newType; #if QWT_VERSION < 0x060000 ColorMap_MultiColor colorMap; - d_spectrogram->setColorMap(colorMap); + d_spectrogram[which]->setColorMap(colorMap); #else - d_spectrogram->setColorMap(new ColorMap_MultiColor()); + d_spectrogram[which]->setColorMap(new ColorMap_MultiColor()); #endif break; } case INTENSITY_COLOR_MAP_TYPE_WHITE_HOT:{ - _intensityColorMapType = newType; + _intensityColorMapType[which] = newType; #if QWT_VERSION < 0x060000 ColorMap_WhiteHot colorMap; - d_spectrogram->setColorMap(colorMap); + d_spectrogram[which]->setColorMap(colorMap); #else - d_spectrogram->setColorMap(new ColorMap_WhiteHot()); + d_spectrogram[which]->setColorMap(new ColorMap_WhiteHot()); #endif break; } case INTENSITY_COLOR_MAP_TYPE_BLACK_HOT:{ - _intensityColorMapType = newType; + _intensityColorMapType[which] = newType; #if QWT_VERSION < 0x060000 ColorMap_BlackHot colorMap; - d_spectrogram->setColorMap(colorMap); + d_spectrogram[which]->setColorMap(colorMap); #else - d_spectrogram->setColorMap(new ColorMap_BlackHot()); + d_spectrogram[which]->setColorMap(new ColorMap_BlackHot()); #endif break; } case INTENSITY_COLOR_MAP_TYPE_INCANDESCENT:{ - _intensityColorMapType = newType; + _intensityColorMapType[which] = newType; #if QWT_VERSION < 0x060000 ColorMap_Incandescent colorMap; - d_spectrogram->setColorMap(colorMap); + d_spectrogram[which]->setColorMap(colorMap); #else - d_spectrogram->setColorMap(new ColorMap_Incandescent()); + d_spectrogram[which]->setColorMap(new ColorMap_Incandescent()); #endif break; } case INTENSITY_COLOR_MAP_TYPE_USER_DEFINED:{ _userDefinedLowIntensityColor = lowColor; _userDefinedHighIntensityColor = highColor; - _intensityColorMapType = newType; + _intensityColorMapType[which] = newType; #if QWT_VERSION < 0x060000 ColorMap_UserDefined colorMap(lowColor, highColor); - d_spectrogram->setColorMap(colorMap); + d_spectrogram[which]->setColorMap(colorMap); #else - d_spectrogram->setColorMap(new ColorMap_UserDefined(lowColor, highColor)); + d_spectrogram[which]->setColorMap(new ColorMap_UserDefined(lowColor, highColor)); #endif break; } @@ -633,39 +488,41 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() rightAxis->setTitle("Intensity (dB)"); rightAxis->setColorBarEnabled(true); + for(int i = 0; i < _nplots; i++) { #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()); + rightAxis->setColorMap(d_spectrogram[i]->data()->range(), + d_spectrogram[i]->colorMap()); + setAxisScale(QwtPlot::yRight, + d_spectrogram[i]->data()->range().minValue(), + d_spectrogram[i]->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()); + QwtInterval intv = d_spectrogram[i]->interval(Qt::ZAxis); + switch(_intensityColorMapType[i]) { + 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); + enableAxis(QwtPlot::yRight); - plotLayout()->setAlignCanvasToScales(true); + plotLayout()->setAlignCanvasToScales(true); - // Tell the display to redraw everything - d_spectrogram->invalidateCache(); - d_spectrogram->itemChanged(); + // Tell the display to redraw everything + d_spectrogram[i]->invalidateCache(); + d_spectrogram[i]->itemChanged(); + } // Draw again replot(); @@ -674,22 +531,4 @@ WaterfallDisplayPlot::_UpdateIntensityRangeDisplay() _lastReplot = gruel::high_res_timer_now(); } -void -WaterfallDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) -{ - QPointF point = p; - //fprintf(stderr,"OnPickerPointSelected %f %f\n", point.x(), point.y()); - point.setX(point.x() * _xAxisMultiplier); - emit plotPointSelected(point); -} - -void -WaterfallDisplayPlot::OnPickerPointSelected6(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 /* WATERFALL_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h index d189ca2cbd..adf5278059 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.h +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2008-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,18 +20,15 @@ * Boston, MA 02110-1301, USA. */ -#ifndef WATERFALL_DISPLAY_PLOT_HPP -#define WATERFALL_DISPLAY_PLOT_HPP +#ifndef WATERFALL_DISPLAY_PLOT_H +#define WATERFALL_DISPLAY_PLOT_H #include <stdint.h> #include <cstdio> -#include <qwt_plot.h> +#include <vector> #include <qwt_plot_spectrogram.h> -#include <qwt_plot_zoomer.h> -#include <qwt_plot_panner.h> -#include <qtgui_util.h> -#include <waterfallGlobalData.h> - +#include "DisplayPlot.h" +#include "waterfallGlobalData.h" #include <gruel/high_res_timer.h> #if QWT_VERSION < 0x060000 @@ -40,11 +37,12 @@ #include <qwt_compat.h> #endif -class WaterfallDisplayPlot:public QwtPlot{ +class WaterfallDisplayPlot: public DisplayPlot +{ Q_OBJECT public: - WaterfallDisplayPlot(QWidget*); + WaterfallDisplayPlot(int nplots, QWidget*); virtual ~WaterfallDisplayPlot(); void Reset(); @@ -53,45 +51,34 @@ public: const double, const bool, const double units=1000.0, const std::string &strunits = "kHz"); - double GetStartFrequency()const; - double GetStopFrequency()const; + double GetStartFrequency() const; + double GetStopFrequency() const; - void PlotNewData(const double* dataPoints, const int64_t numDataPoints, - const double timePerFFT, const gruel::high_res_timer_type timestamp, + void PlotNewData(const std::vector<double*> dataPoints, + const int64_t numDataPoints, + const double timePerFFT, + const gruel::high_res_timer_type timestamp, const int droppedFrames); - void SetIntensityRange(const double minIntensity, const double maxIntensity); - - virtual void replot(void); - - int GetIntensityColorMapType()const; - void SetIntensityColorMapType( const int, const QColor, const QColor ); - const QColor GetUserDefinedLowIntensityColor()const; - const QColor GetUserDefinedHighIntensityColor()const; + // to be removed + void PlotNewData(const double* dataPoints, + const int64_t numDataPoints, + const double timePerFFT, + const gruel::high_res_timer_type timestamp, + const int droppedFrames); - enum{ - INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR = 0, - INTENSITY_COLOR_MAP_TYPE_WHITE_HOT = 1, - INTENSITY_COLOR_MAP_TYPE_BLACK_HOT = 2, - INTENSITY_COLOR_MAP_TYPE_INCANDESCENT = 3, - INTENSITY_COLOR_MAP_TYPE_USER_DEFINED = 4 - }; + void SetIntensityRange(const double minIntensity, const double maxIntensity); -public slots: - void resizeSlot( QSize *s ); + void replot(void); - // Because of the preprocessing of slots in QT, these are no - // easily separated by the version check. Make one for each - // version until it's worked out. - void OnPickerPointSelected(const QwtDoublePoint & p); - void OnPickerPointSelected6(const QPointF & p); + int GetIntensityColorMapType(int) const; + void SetIntensityColorMapType(const int, const int, const QColor, const QColor); + const QColor GetUserDefinedLowIntensityColor() const; + const QColor GetUserDefinedHighIntensityColor() const; signals: void UpdatedLowerIntensityLevel(const double); void UpdatedUpperIntensityLevel(const double); - void plotPointSelected(const QPointF p); - -protected: private: void _UpdateIntensityRangeDisplay(); @@ -100,28 +87,21 @@ private: double _stopFrequency; int _xAxisMultiplier; - QwtPlotPanner* _panner; - QwtPlotZoomer* _zoomer; - - QwtDblClickPlotPicker *_picker; - - WaterfallData *d_data; + std::vector<WaterfallData*> d_data; #if QWT_VERSION < 0x060000 - PlotWaterfall *d_spectrogram; + std::vector<PlotWaterfall*> d_spectrogram; #else - QwtPlotSpectrogram *d_spectrogram; + std::vector<QwtPlotSpectrogram*> d_spectrogram; #endif gruel::high_res_timer_type _lastReplot; bool _useCenterFrequencyFlag; - int64_t _numPoints; - - int _intensityColorMapType; + std::vector<int> _intensityColorMapType; QColor _userDefinedLowIntensityColor; QColor _userDefinedHighIntensityColor; }; -#endif /* WATERFALL_DISPLAY_PLOT_HPP */ +#endif /* WATERFALL_DISPLAY_PLOT_H */ diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc new file mode 100644 index 0000000000..b504f7121d --- /dev/null +++ b/gr-qtgui/lib/const_sink_c_impl.cc @@ -0,0 +1,257 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "const_sink_c_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> +#include <fft/fft.h> + +namespace gr { + namespace qtgui { + + const_sink_c::sptr + const_sink_c::make(int size, + const std::string &name, + int nconnections, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new const_sink_c_impl(size, name, nconnections, parent)); + } + + const_sink_c_impl::const_sink_c_impl(int size, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_sync_block("const_sink_c", + gr_make_io_signature(nconnections, nconnections, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_size(size), d_name(name), + d_nconnections(nconnections), d_parent(parent) + { + d_main_gui = NULL; + + d_index = 0; + + for(int i = 0; i < d_nconnections; i++) { + d_residbufs_real.push_back(fft::malloc_double(d_size)); + d_residbufs_imag.push_back(fft::malloc_double(d_size)); + memset(d_residbufs_real[i], 0, d_size*sizeof(double)); + memset(d_residbufs_imag[i], 0, d_size*sizeof(double)); + } + + // Set alignment properties for VOLK + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); + + initialize(); + } + + const_sink_c_impl::~const_sink_c_impl() + { + // d_main_gui is a qwidget destroyed with its parent + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs_real[i]); + fft::free(d_residbufs_imag[i]); + } + } + + void + const_sink_c_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new ConstellationDisplayForm(d_nconnections, d_parent); + d_main_gui->SetNPoints(d_size); + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + const_sink_c_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + const_sink_c_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + const_sink_c_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + const_sink_c_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + const_sink_c_impl::set_title(int which, const std::string &title) + { + d_main_gui->setTitle(which, title.c_str()); + } + + void + const_sink_c_impl::set_color(int which, const std::string &color) + { + d_main_gui->setColor(which, color.c_str()); + } + + void + const_sink_c_impl::set_line_width(int which, int width) + { + d_main_gui->setLineWidth(which, width); + } + + void + const_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + { + d_main_gui->setLineStyle(which, style); + } + + void + const_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(which, marker); + } + + void + const_sink_c_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + const_sink_c_impl::set_nsamps(const int newsize) + { + gruel::scoped_lock lock(d_mutex); + + if(newsize != d_size) { + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs_real[i]); + fft::free(d_residbufs_imag[i]); + d_residbufs_real[i] = fft::malloc_double(newsize); + d_residbufs_imag[i] = fft::malloc_double(newsize); + + memset(d_residbufs_real[i], 0, newsize*sizeof(double)); + memset(d_residbufs_imag[i], 0, newsize*sizeof(double)); + } + + // Set new size and reset buffer index + // (throws away any currently held data, but who cares?) + d_size = newsize; + d_index = 0; + + d_main_gui->SetNPoints(d_size); + } + } + + void + const_sink_c_impl::npoints_resize() + { + int newsize = d_main_gui->GetNPoints(); + set_nsamps(newsize); + } + + int + const_sink_c_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int n=0, j=0, idx=0; + const gr_complex *in = (const gr_complex*)input_items[idx]; + + npoints_resize(); + + for(int i=0; i < noutput_items; i+=d_size) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_size-d_index; + idx = 0; + + // If we have enough input for one full plot, do it + if(datasize >= resid) { + + // Fill up residbufs with d_size number of items + for(n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[idx++]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index], + &d_residbufs_imag[n][d_index], + &in[j], resid); + } + + // Update the plot if its time + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new ConstUpdateEvent(d_residbufs_real, + d_residbufs_imag, + d_size)); + } + + d_index = 0; + j += resid; + } + + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[idx++]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index], + &d_residbufs_imag[n][d_index], + &in[j], datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/const_sink_c_impl.h b/gr-qtgui/lib/const_sink_c_impl.h new file mode 100644 index 0000000000..a17a8793b4 --- /dev/null +++ b/gr-qtgui/lib/const_sink_c_impl.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_CONST_SINK_C_IMPL_H +#define INCLUDED_QTGUI_CONST_SINK_C_IMPL_H + +#include <qtgui/const_sink_c.h> +#include <gruel/high_res_timer.h> +#include <gruel/thread.h> +#include <constellationdisplayform.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API const_sink_c_impl : public const_sink_c + { + private: + void initialize(); + + gruel::mutex d_mutex; + + int d_size; + std::string d_name; + int d_nconnections; + + int d_index; + std::vector<double*> d_residbufs_real; + std::vector<double*> d_residbufs_imag; + + QWidget *d_parent; + ConstellationDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void npoints_resize(); + + public: + const_sink_c_impl(int size, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + ~const_sink_c_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + void set_line_width(int which, int width); + void set_line_style(int which, Qt::PenStyle style); + void set_line_marker(int which, QwtSymbol::Style marker); + void set_nsamps(const int size); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_CONST_SINK_C_IMPL_H */ diff --git a/gr-qtgui/lib/constellationdisplayform.cc b/gr-qtgui/lib/constellationdisplayform.cc new file mode 100644 index 0000000000..98375ebaed --- /dev/null +++ b/gr-qtgui/lib/constellationdisplayform.cc @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cmath> +#include <QMessageBox> +#include <constellationdisplayform.h> +#include <iostream> + +ConstellationDisplayForm::ConstellationDisplayForm(int nplots, QWidget* parent) + : DisplayForm(nplots, parent) +{ + _intValidator = new QIntValidator(this); + _intValidator->setBottom(0); + + _layout = new QGridLayout(this); + _displayPlot = new ConstellationDisplayPlot(nplots, this); + _layout->addWidget(_displayPlot, 0, 0); + setLayout(_layout); + + NPointsMenu *nptsmenu = new NPointsMenu(this); + _menu->addAction(nptsmenu); + connect(nptsmenu, SIGNAL(whichTrigger(int)), + this, SLOT(SetNPoints(const int))); + + Reset(); + + connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onPlotPointSelected(const QPointF))); +} + +ConstellationDisplayForm::~ConstellationDisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + delete _intValidator; +} + +ConstellationDisplayPlot* +ConstellationDisplayForm::getPlot() +{ + return ((ConstellationDisplayPlot*)_displayPlot); +} + +void +ConstellationDisplayForm::newData(const QEvent* updateEvent) +{ + ConstUpdateEvent *tevent = (ConstUpdateEvent*)updateEvent; + const std::vector<double*> realDataPoints = tevent->getRealPoints(); + const std::vector<double*> imagDataPoints = tevent->getImagPoints(); + const uint64_t numDataPoints = tevent->getNumDataPoints(); + + getPlot()->PlotNewData(realDataPoints, + imagDataPoints, + numDataPoints, + d_update_time); +} + +void +ConstellationDisplayForm::customEvent(QEvent * e) +{ + if(e->type() == ConstUpdateEvent::Type()) { + newData(e); + } +} + +int +ConstellationDisplayForm::GetNPoints() const +{ + return d_npoints; +} + +void +ConstellationDisplayForm::SetNPoints(const int npoints) +{ + d_npoints = npoints; +} diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.i b/gr-qtgui/lib/constellationdisplayform.h index ca65708af6..6832bd44cc 100644 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.i +++ b/gr-qtgui/lib/constellationdisplayform.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,17 +20,40 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,probe_density_b); +#ifndef CONSTELLATION_DISPLAY_FORM_H +#define CONSTELLATION_DISPLAY_FORM_H -gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); +#include <spectrumUpdateEvents.h> +#include <ConstellationDisplayPlot.h> +#include <QtGui/QtGui> +#include <vector> -class gr_probe_density_b : public gr_sync_block +#include "displayform.h" + +class ConstellationDisplayForm : public DisplayForm { + Q_OBJECT + public: - double density() const; + ConstellationDisplayForm(int nplots=1, QWidget* parent = 0); + ~ConstellationDisplayForm(); + + ConstellationDisplayPlot* getPlot(); + + int GetNPoints() const; - void set_alpha(double alpha); +public slots: + void customEvent(QEvent * e); + void SetNPoints(const int); + + // add set x/y axis + +private slots: + void newData(const QEvent*); private: - gr_probe_density_b(); + QIntValidator* _intValidator; + int d_npoints; }; + +#endif /* CONSTELLATION_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/displayform.cc b/gr-qtgui/lib/displayform.cc new file mode 100644 index 0000000000..68e1a5c4fd --- /dev/null +++ b/gr-qtgui/lib/displayform.cc @@ -0,0 +1,260 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <displayform.h> +#include <iostream> + +DisplayForm::DisplayForm(int nplots, QWidget* parent) + : QWidget(parent), _nplots(nplots), _systemSpecifiedFlag(false) +{ + // Set the initial plot size + resize(QSize(800, 600)); + + // Set up a grid that can be turned on/off + _grid = new QwtPlotGrid(); + _grid->setPen(QPen(QColor(Qt::gray))); + + // Create a set of actions for the menu + _stop_act = new QAction("Stop", this); + _stop_act->setStatusTip(tr("Start/Stop")); + connect(_stop_act, SIGNAL(triggered()), this, SLOT(setStop())); + _stop_state = false; + + _grid_act = new QAction("Grid On", this); + _grid_act->setStatusTip(tr("Toggle Grid on/off")); + connect(_grid_act, SIGNAL(triggered()), this, SLOT(setGrid())); + _grid_state = false; + + // Create a pop-up menu for manipulating the figure + _menu = new QMenu(this); + _menu->addAction(_stop_act); + _menu->addAction(_grid_act); + + for(int i = 0; i < _nplots; i++) { + _line_title_act.push_back(new LineTitleAction(i, this)); + _line_color_menu.push_back(new LineColorMenu(i, this)); + _line_width_menu.push_back(new LineWidthMenu(i, this)); + _line_style_menu.push_back(new LineStyleMenu(i, this)); + _line_marker_menu.push_back(new LineMarkerMenu(i, this)); + + connect(_line_title_act[i], SIGNAL(whichTrigger(int, const QString&)), + this, SLOT(setTitle(int, const QString&))); + + for(int j = 0; j < _line_color_menu[i]->getNumActions(); j++) { + connect(_line_color_menu[i], SIGNAL(whichTrigger(int, const QString&)), + this, SLOT(setColor(int, const QString&))); + } + + for(int j = 0; j < _line_width_menu[i]->getNumActions(); j++) { + connect(_line_width_menu[i], SIGNAL(whichTrigger(int, int)), + this, SLOT(setLineWidth(int, int))); + } + + for(int j = 0; j < _line_style_menu[i]->getNumActions(); j++) { + connect(_line_style_menu[i], SIGNAL(whichTrigger(int, Qt::PenStyle)), + this, SLOT(setLineStyle(int, Qt::PenStyle))); + } + + for(int j = 0; j < _line_marker_menu[i]->getNumActions(); j++) { + connect(_line_marker_menu[i], SIGNAL(whichTrigger(int, QwtSymbol::Style)), + this, SLOT(setLineMarker(int, QwtSymbol::Style))); + } + + _lines_menu.push_back(new QMenu(tr(""), this)); + _lines_menu[i]->addAction(_line_title_act[i]); + _lines_menu[i]->addMenu(_line_color_menu[i]); + _lines_menu[i]->addMenu(_line_width_menu[i]); + _lines_menu[i]->addMenu(_line_style_menu[i]); + _lines_menu[i]->addMenu(_line_marker_menu[i]); + _menu->addMenu(_lines_menu[i]); + } + + Reset(); + + // Create a timer to update plots at the specified rate + d_displayTimer = new QTimer(this); + connect(d_displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer())); +} + +DisplayForm::~DisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + + d_displayTimer->stop(); + delete d_displayTimer; +} + +void +DisplayForm::resizeEvent( QResizeEvent *e ) +{ + QSize s = size(); + emit _displayPlot->resizeSlot(&s); +} + +void +DisplayForm::mousePressEvent( QMouseEvent * e) +{ + if(e->button() == Qt::RightButton) { + QwtPlotLayout *plt = _displayPlot->plotLayout(); + QRectF cvs = plt->canvasRect(); + + QRect plotrect; + plotrect.setLeft(cvs.x()-plt->spacing()-plt->canvasMargin(0)); + plotrect.setRight(cvs.x()+cvs.width()+plt->spacing()+plt->canvasMargin(0)); + plotrect.setBottom(cvs.y()-plt->spacing()-plt->canvasMargin(0)); + plotrect.setTop(cvs.y()+cvs.width()+plt->spacing()+plt->canvasMargin(0)); + + if(!plotrect.contains(e->pos())) { + if(_stop_state == false) + _stop_act->setText(tr("Stop")); + else + _stop_act->setText(tr("Start")); + + if(_grid_state == false) + _grid_act->setText(tr("Grid On")); + else + _grid_act->setText(tr("Grid Off")); + + // Update the line titles if changed externally + for(int i = 0; i < _nplots; i++) { + _lines_menu[i]->setTitle(_displayPlot->title(i)); + } + _menu->exec(e->globalPos()); + } + } +} + +void +DisplayForm::updateGuiTimer() +{ + _displayPlot->canvas()->update(); +} + +void +DisplayForm::onPlotPointSelected(const QPointF p) +{ + emit plotPointSelected(p, 3); +} + +void +DisplayForm::Reset() +{ +} + + +void +DisplayForm::closeEvent( QCloseEvent *e ) +{ + qApp->processEvents(); + QWidget::closeEvent(e); +} + +void +DisplayForm::setUpdateTime(double t) +{ + d_update_time = t; + d_displayTimer->start(d_update_time); +} + +void +DisplayForm::setTitle(int which, const QString &title) +{ + _displayPlot->setTitle(which, title); +} + +void +DisplayForm::setColor(int which, const QString &color) +{ + _displayPlot->setColor(which, color); + _displayPlot->replot(); +} + +void +DisplayForm::setLineWidth(int which, int width) +{ + _displayPlot->setLineWidth(which, width); + _displayPlot->replot(); +} + +void +DisplayForm::setLineStyle(int which, Qt::PenStyle style) +{ + _displayPlot->setLineStyle(which, style); + _displayPlot->replot(); +} + +void +DisplayForm::setLineMarker(int which, QwtSymbol::Style marker) +{ + _displayPlot->setLineMarker(which, marker); + _displayPlot->replot(); +} + +void +DisplayForm::setStop(bool on) +{ + if(!on) { + // will auto-detach if already attached. + _displayPlot->setStop(false); + _stop_state = false; + } + else { + _displayPlot->setStop(true); + _stop_state = true; + } + _displayPlot->replot(); +} + +void +DisplayForm::setStop() +{ + if(_stop_state == false) + setStop(true); + else + setStop(false); +} + +void +DisplayForm::setGrid(bool on) +{ + if(on) { + // will auto-detach if already attached. + _grid->attach(_displayPlot); + _grid_state = true; + } + else { + _grid->detach(); + _grid_state = false; + } + _displayPlot->replot(); +} + +void +DisplayForm::setGrid() +{ + if(_grid_state == false) + setGrid(true); + else + setGrid(false); +} diff --git a/gr-qtgui/lib/displayform.h b/gr-qtgui/lib/displayform.h new file mode 100644 index 0000000000..82b28c745d --- /dev/null +++ b/gr-qtgui/lib/displayform.h @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef DISPLAY_FORM_H +#define DISPLAY_FORM_H + +#include <spectrumUpdateEvents.h> +#include <QtGui/QtGui> +#include <vector> + +#include <qwt_plot_grid.h> +#include <qwt_plot_layout.h> + +#include "DisplayPlot.h" +#include "form_menus.h" + +class DisplayForm : public QWidget +{ + Q_OBJECT + + public: + DisplayForm(int nplots=1, QWidget* parent = 0); + ~DisplayForm(); + + virtual DisplayPlot* getPlot() = 0; + void Reset(); + +public slots: + void resizeEvent( QResizeEvent * e ); + void mousePressEvent( QMouseEvent * e); + virtual void customEvent( QEvent * e ) = 0; + + void closeEvent( QCloseEvent * e ); + + void setUpdateTime(double t); + + void setTitle(int which, const QString &title); + void setColor(int which, const QString &color); + void setLineWidth(int which, int width); + void setLineStyle(int which, Qt::PenStyle style); + void setLineMarker(int which, QwtSymbol::Style style); + + void setStop(bool on); + void setStop(); + + void setGrid(bool on); + void setGrid(); + +private slots: + virtual void newData(const QEvent*) = 0; + void updateGuiTimer(); + + void onPlotPointSelected(const QPointF p); + +signals: + void plotPointSelected(const QPointF p, int type); + +protected: + int _nplots; + + QGridLayout *_layout; + DisplayPlot* _displayPlot; + bool _systemSpecifiedFlag; + + QwtPlotGrid *_grid; + + QMenu *_menu; + + QAction *_stop_act; + bool _stop_state; + QAction *_grid_act; + bool _grid_state; + + QList<QMenu*> _lines_menu; + QList<LineTitleAction*> _line_title_act; + QList<LineColorMenu*> _line_color_menu; + QList<LineWidthMenu*> _line_width_menu; + QList<LineStyleMenu*> _line_style_menu; + QList<LineMarkerMenu*> _line_marker_menu; + + QTimer *d_displayTimer; + double d_update_time; +}; + +#endif /* DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/form_menus.h b/gr-qtgui/lib/form_menus.h new file mode 100644 index 0000000000..01695f2c46 --- /dev/null +++ b/gr-qtgui/lib/form_menus.h @@ -0,0 +1,882 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FORM_MENUS_H +#define FORM_MENUS_H + +#include <stdexcept> +#include <vector> +#include <QtGui/QtGui> +#include <qwt_symbol.h> +#include <filter/firdes.h> +#include "qtgui_types.h" + +class LineColorMenu: public QMenu +{ + Q_OBJECT + +public: + LineColorMenu(int which, QWidget *parent) + : QMenu("Line Color", parent), d_which(which) + { + d_act.push_back(new QAction("Blue", this)); + d_act.push_back(new QAction("Red", this)); + d_act.push_back(new QAction("Green", this)); + d_act.push_back(new QAction("Black", this)); + d_act.push_back(new QAction("Cyan", this)); + d_act.push_back(new QAction("Magenta", this)); + d_act.push_back(new QAction("Yellow", this)); + d_act.push_back(new QAction("Gray", this)); + d_act.push_back(new QAction("Dark Red", this)); + d_act.push_back(new QAction("Dark Green", this)); + d_act.push_back(new QAction("Dark Blue", this)); + d_act.push_back(new QAction("Dark Gray", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getBlue())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getRed())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getGreen())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getBlack())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getCyan())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(getMagenta())); + connect(d_act[6], SIGNAL(triggered()), this, SLOT(getYellow())); + connect(d_act[7], SIGNAL(triggered()), this, SLOT(getGray())); + connect(d_act[8], SIGNAL(triggered()), this, SLOT(getDarkRed())); + connect(d_act[9], SIGNAL(triggered()), this, SLOT(getDarkGreen())); + connect(d_act[10], SIGNAL(triggered()), this, SLOT(getDarkBlue())); + connect(d_act[11], SIGNAL(triggered()), this, SLOT(getDarkGray())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~LineColorMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("LineColorMenu::getAction: which out of range.\n"); + } + +signals: + void whichTrigger(int which, const QString &name); + +public slots: + void getBlue() { emit whichTrigger(d_which, "blue"); } + void getRed() { emit whichTrigger(d_which, "red"); } + void getGreen() { emit whichTrigger(d_which, "green"); } + void getBlack() { emit whichTrigger(d_which, "black"); } + void getCyan() { emit whichTrigger(d_which, "cyan"); } + void getMagenta() { emit whichTrigger(d_which, "magenta"); } + void getYellow() { emit whichTrigger(d_which, "yellow"); } + void getGray() { emit whichTrigger(d_which, "gray"); } + void getDarkRed() { emit whichTrigger(d_which, "darkred"); } + void getDarkGreen() { emit whichTrigger(d_which, "darkgreen"); } + void getDarkBlue() { emit whichTrigger(d_which, "darkblue"); } + void getDarkGray() { emit whichTrigger(d_which, "darkgray"); } + +private: + QList<QAction *> d_act; + int d_which; +}; + + +/********************************************************************/ + + +class LineWidthMenu: public QMenu +{ + Q_OBJECT + +public: + LineWidthMenu(int which, QWidget *parent) + : QMenu("Line Width", parent), d_which(which) + { + d_act.push_back(new QAction("1", this)); + d_act.push_back(new QAction("2", this)); + d_act.push_back(new QAction("3", this)); + d_act.push_back(new QAction("4", this)); + d_act.push_back(new QAction("5", this)); + d_act.push_back(new QAction("6", this)); + d_act.push_back(new QAction("7", this)); + d_act.push_back(new QAction("8", this)); + d_act.push_back(new QAction("9", this)); + d_act.push_back(new QAction("10", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOne())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getTwo())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getThree())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getFour())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getFive())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(getSix())); + connect(d_act[6], SIGNAL(triggered()), this, SLOT(getSeven())); + connect(d_act[7], SIGNAL(triggered()), this, SLOT(getEight())); + connect(d_act[8], SIGNAL(triggered()), this, SLOT(getNine())); + connect(d_act[9], SIGNAL(triggered()), this, SLOT(getTen())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~LineWidthMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("LineWidthMenu::getAction: which out of range.\n"); + } + +signals: + void whichTrigger(int which, int width); + +public slots: + void getOne() { emit whichTrigger(d_which, 1); } + void getTwo() { emit whichTrigger(d_which, 2); } + void getThree() { emit whichTrigger(d_which, 3); } + void getFour() { emit whichTrigger(d_which, 4); } + void getFive() { emit whichTrigger(d_which, 5); } + void getSix() { emit whichTrigger(d_which, 6); } + void getSeven() { emit whichTrigger(d_which, 7); } + void getEight() { emit whichTrigger(d_which, 8); } + void getNine() { emit whichTrigger(d_which, 9); } + void getTen() { emit whichTrigger(d_which, 10); } + +private: + QList<QAction *> d_act; + int d_which; +}; + + +/********************************************************************/ + + +class LineStyleMenu: public QMenu +{ + Q_OBJECT + +public: + LineStyleMenu(int which, QWidget *parent) + : QMenu("Line Style", parent), d_which(which) + { + d_act.push_back(new QAction("None", this)); + d_act.push_back(new QAction("Solid", this)); + d_act.push_back(new QAction("Dash", this)); + d_act.push_back(new QAction("Dots", this)); + d_act.push_back(new QAction("Dash-Dot", this)); + d_act.push_back(new QAction("Dash-Dot-Dot", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getSolid())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getDash())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getDots())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getDashDot())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(getDashDotDot())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~LineStyleMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("LineStyleMenu::getAction: which out of range.\n"); + } + +signals: + void whichTrigger(int which, Qt::PenStyle); + +public slots: + void getNone() { emit whichTrigger(d_which, Qt::NoPen); } + void getSolid() { emit whichTrigger(d_which, Qt::SolidLine); } + void getDash() { emit whichTrigger(d_which, Qt::DashLine); } + void getDots() { emit whichTrigger(d_which, Qt::DotLine); } + void getDashDot() { emit whichTrigger(d_which, Qt::DashDotLine); } + void getDashDotDot() { emit whichTrigger(d_which, Qt::DashDotDotLine); } + +private: + QList<QAction *> d_act; + int d_which; +}; + + +/********************************************************************/ + + +class LineMarkerMenu: public QMenu +{ + Q_OBJECT + +public: + LineMarkerMenu(int which, QWidget *parent) + : QMenu("Line Marker", parent), d_which(which) + { + d_act.push_back(new QAction("None", this)); + d_act.push_back(new QAction("Circle", this)); + d_act.push_back(new QAction("Rectangle", this)); + d_act.push_back(new QAction("Diamond", this)); + d_act.push_back(new QAction("Triangle", this)); + d_act.push_back(new QAction("Down Triangle", this)); + d_act.push_back(new QAction("Left Triangle", this)); + d_act.push_back(new QAction("Right Triangle", this)); + d_act.push_back(new QAction("Cross", this)); + d_act.push_back(new QAction("X-Cross", this)); + d_act.push_back(new QAction("Horiz. Line", this)); + d_act.push_back(new QAction("Vert. Line", this)); + d_act.push_back(new QAction("Star 1", this)); + d_act.push_back(new QAction("Star 2", this)); + d_act.push_back(new QAction("Hexagon", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getCircle())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getRect())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getDiamond())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getTriangle())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(getDTriangle())); + connect(d_act[6], SIGNAL(triggered()), this, SLOT(getLTriangle())); + connect(d_act[7], SIGNAL(triggered()), this, SLOT(getRTriangle())); + connect(d_act[8], SIGNAL(triggered()), this, SLOT(getCross())); + connect(d_act[9], SIGNAL(triggered()), this, SLOT(getXCross())); + connect(d_act[10], SIGNAL(triggered()), this, SLOT(getHLine())); + connect(d_act[11], SIGNAL(triggered()), this, SLOT(getVLine())); + connect(d_act[12], SIGNAL(triggered()), this, SLOT(getStar1())); + connect(d_act[13], SIGNAL(triggered()), this, SLOT(getStar2())); + connect(d_act[14], SIGNAL(triggered()), this, SLOT(getHexagon())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~LineMarkerMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("LineMarkerMenu::getAction: which out of range.\n"); + } + +signals: + void whichTrigger(int which, QwtSymbol::Style); + +public slots: + void getNone() { emit whichTrigger(d_which, QwtSymbol::NoSymbol); } + void getCircle() { emit whichTrigger(d_which, QwtSymbol::Ellipse); } + void getRect() { emit whichTrigger(d_which, QwtSymbol::Rect); } + void getDiamond() { emit whichTrigger(d_which, QwtSymbol::Diamond); } + void getTriangle() { emit whichTrigger(d_which, QwtSymbol::Triangle); } + void getDTriangle() { emit whichTrigger(d_which, QwtSymbol::DTriangle); } + void getLTriangle() { emit whichTrigger(d_which, QwtSymbol::LTriangle); } + void getRTriangle() { emit whichTrigger(d_which, QwtSymbol::RTriangle); } + void getCross() { emit whichTrigger(d_which, QwtSymbol::Cross); } + void getXCross() { emit whichTrigger(d_which, QwtSymbol::XCross); } + void getHLine() { emit whichTrigger(d_which, QwtSymbol::HLine); } + void getVLine() { emit whichTrigger(d_which, QwtSymbol::VLine); } + void getStar1() { emit whichTrigger(d_which, QwtSymbol::Star1); } + void getStar2() { emit whichTrigger(d_which, QwtSymbol::Star2); } + void getHexagon() { emit whichTrigger(d_which, QwtSymbol::Hexagon); } + +private: + QList<QAction *> d_act; + int d_which; +}; + + +/********************************************************************/ + + +class LineTitleAction: public QAction +{ + Q_OBJECT + +public: + LineTitleAction(int which, QWidget *parent) + : QAction("Line Title", parent), d_which(which) + { + d_diag = new QDialog(parent); + d_diag->setModal(true); + + d_text = new QLineEdit(); + + QGridLayout *layout = new QGridLayout(d_diag); + QPushButton *btn_ok = new QPushButton(tr("OK")); + QPushButton *btn_cancel = new QPushButton(tr("Cancel")); + + layout->addWidget(d_text, 0, 0, 1, 2); + layout->addWidget(btn_ok, 1, 0); + layout->addWidget(btn_cancel, 1, 1); + + connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText())); + connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close())); + + connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag())); + } + + ~LineTitleAction() + {} + +signals: + void whichTrigger(int which, const QString &text); + +public slots: + void getTextDiag() + { + d_diag->exec(); + } + +private slots: + void getText() + { + emit whichTrigger(d_which, d_text->text()); + d_diag->accept(); + } + +private: + int d_which; + + QDialog *d_diag; + QLineEdit *d_text; +}; + + +/********************************************************************/ + + +class OtherAction: public QAction +{ + Q_OBJECT + +public: + OtherAction(QWidget *parent) + : QAction("Other", parent) + { + d_diag = new QDialog(parent); + d_diag->setModal(true); + + d_text = new QLineEdit(); + + QGridLayout *layout = new QGridLayout(d_diag); + QPushButton *btn_ok = new QPushButton(tr("OK")); + QPushButton *btn_cancel = new QPushButton(tr("Cancel")); + + layout->addWidget(d_text, 0, 0, 1, 2); + layout->addWidget(btn_ok, 1, 0); + layout->addWidget(btn_cancel, 1, 1); + + connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText())); + connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close())); + + connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag())); + } + + ~OtherAction() + {} + +signals: + void whichTrigger(const QString &text); + +public slots: + void getTextDiag() + { + d_diag->exec(); + } + +private slots: + void getText() + { + emit whichTrigger(d_text->text()); + d_diag->accept(); + } + +private: + QDialog *d_diag; + QLineEdit *d_text; +}; + +/********************************************************************/ + + +class OtherDualAction: public QAction +{ + Q_OBJECT + +public: + OtherDualAction(QString label0, QString label1, QWidget *parent) + : QAction("Other", parent) + { + d_diag = new QDialog(parent); + d_diag->setModal(true); + + d_text0 = new QLineEdit(); + d_text1 = new QLineEdit(); + + QLabel *_label0 = new QLabel(label0); + QLabel *_label1 = new QLabel(label1); + + QGridLayout *layout = new QGridLayout(d_diag); + QPushButton *btn_ok = new QPushButton(tr("OK")); + QPushButton *btn_cancel = new QPushButton(tr("Cancel")); + + layout->addWidget(_label0, 0, 0, 1, 2); + layout->addWidget(_label1, 1, 0, 1, 2); + + layout->addWidget(d_text0, 0, 1, 1, 2); + layout->addWidget(d_text1, 1, 1, 1, 2); + layout->addWidget(btn_ok, 2, 0); + layout->addWidget(btn_cancel, 2, 1); + + connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText())); + connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close())); + + connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag())); + } + + ~OtherDualAction() + {} + +signals: + void whichTrigger(const QString &text0, const QString &text1); + +public slots: + void getTextDiag() + { + d_diag->exec(); + } + +private slots: + void getText() + { + emit whichTrigger(d_text0->text(), d_text1->text()); + d_diag->accept(); + } + +private: + QDialog *d_diag; + QLineEdit *d_text0; + QLineEdit *d_text1; +}; + + +/********************************************************************/ + + +class FFTSizeMenu: public QMenu +{ + Q_OBJECT + +public: + FFTSizeMenu(QWidget *parent) + : QMenu("FFT Size", parent) + { + d_act.push_back(new QAction("32", this)); + d_act.push_back(new QAction("64", this)); + d_act.push_back(new QAction("128", this)); + d_act.push_back(new QAction("256", this)); + d_act.push_back(new QAction("512", this)); + d_act.push_back(new QAction("1024", this)); + d_act.push_back(new QAction("2048", this)); + d_act.push_back(new QAction("4096", this)); + d_act.push_back(new QAction("8192", this)); + d_act.push_back(new QAction("16384", this)); + d_act.push_back(new QAction("32768", this)); + d_act.push_back(new OtherAction(this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(get05())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(get06())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(get07())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(get08())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(get09())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(get10())); + connect(d_act[6], SIGNAL(triggered()), this, SLOT(get11())); + connect(d_act[7], SIGNAL(triggered()), this, SLOT(get12())); + connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13())); + connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14())); + connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15())); + connect(d_act[11], SIGNAL(whichTrigger(const QString&)), + this, SLOT(getOther(const QString&))); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~FFTSizeMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); + } + + signals: + void whichTrigger(int size); + + public slots: + void get05() { emit whichTrigger(32); } + void get06() { emit whichTrigger(64); } + void get07() { emit whichTrigger(128); } + void get08() { emit whichTrigger(256); } + void get09() { emit whichTrigger(512); } + void get10() { emit whichTrigger(1024); } + void get11() { emit whichTrigger(2048); } + void get12() { emit whichTrigger(4096); } + void get13() { emit whichTrigger(8192); } + void get14() { emit whichTrigger(16384); } + void get15() { emit whichTrigger(32768); } + void getOther(const QString &str) + { + int value = str.toInt(); + emit whichTrigger(value); + } + +private: + QList<QAction *> d_act; + OtherAction *d_other; +}; + + +/********************************************************************/ + + +class FFTAverageMenu: public QMenu +{ + Q_OBJECT + +public: + FFTAverageMenu(QWidget *parent) + : QMenu("FFT Average", parent) + { + d_act.push_back(new QAction("Off", this)); + d_act.push_back(new QAction("High", this)); + d_act.push_back(new QAction("Medium", this)); + d_act.push_back(new QAction("Low", this)); + d_act.push_back(new OtherAction(this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOff())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHigh())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getLow())); + connect(d_act[4], SIGNAL(whichTrigger(const QString&)), + this, SLOT(getOther(const QString&))); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~FFTAverageMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); + } + + signals: + void whichTrigger(float alpha); + + public slots: + void getOff() { emit whichTrigger(1.0); } + void getHigh() { emit whichTrigger(0.05); } + void getMedium() { emit whichTrigger(0.1); } + void getLow() { emit whichTrigger(0.2); } + void getOther(const QString &str) + { + float value = str.toFloat(); + emit whichTrigger(value); + } + +private: + QList<QAction *> d_act; + OtherAction *d_other; +}; + + +/********************************************************************/ + + +class FFTWindowMenu: public QMenu +{ + Q_OBJECT + +public: + FFTWindowMenu(QWidget *parent) + : QMenu("FFT Window", parent) + { + d_act.push_back(new QAction("None", this)); + d_act.push_back(new QAction("Hamming", this)); + d_act.push_back(new QAction("Hann", this)); + d_act.push_back(new QAction("Blackman", this)); + d_act.push_back(new QAction("Blackman-harris", this)); + d_act.push_back(new QAction("Rectangular", this)); + d_act.push_back(new QAction("Kaiser", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHamming())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getHann())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getBlackman())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getBlackmanharris())); + connect(d_act[5], SIGNAL(triggered()), this, SLOT(getRectangular())); + connect(d_act[6], SIGNAL(triggered()), this, SLOT(getKaiser())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } + + ~FFTWindowMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("FFTWindowMenu::getAction: which out of range.\n"); + } + +signals: + void whichTrigger(const gr::filter::firdes::win_type type); + +public slots: + void getNone() { emit whichTrigger(gr::filter::firdes::WIN_NONE); } + void getHamming() { emit whichTrigger(gr::filter::firdes::WIN_HAMMING); } + void getHann() { emit whichTrigger(gr::filter::firdes::WIN_HANN); } + void getBlackman() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN); } + void getBlackmanharris() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN_hARRIS); } + void getRectangular() { emit whichTrigger(gr::filter::firdes::WIN_RECTANGULAR); } + void getKaiser() { emit whichTrigger(gr::filter::firdes::WIN_KAISER); } + +private: + QList<QAction *> d_act; + int d_which; +}; + + +/********************************************************************/ + + +class NPointsMenu: public QAction +{ + Q_OBJECT + +public: + NPointsMenu(QWidget *parent) + : QAction("Number of Points", parent) + { + d_diag = new QDialog(parent); + d_diag->setModal(true); + + d_text = new QLineEdit(); + + QGridLayout *layout = new QGridLayout(d_diag); + QPushButton *btn_ok = new QPushButton(tr("OK")); + QPushButton *btn_cancel = new QPushButton(tr("Cancel")); + + layout->addWidget(d_text, 0, 0, 1, 2); + layout->addWidget(btn_ok, 1, 0); + layout->addWidget(btn_cancel, 1, 1); + + connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText())); + connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close())); + + connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag())); + } + + ~NPointsMenu() + {} + +signals: + void whichTrigger(const int npts); + +public slots: + void getTextDiag() + { + d_diag->show(); + } + +private slots: + void getText() + { + emit whichTrigger(d_text->text().toInt()); + d_diag->accept(); + } + +private: + QDialog *d_diag; + QLineEdit *d_text; +}; + + +/********************************************************************/ + + +class ColorMapMenu: public QMenu +{ + Q_OBJECT + +public: + ColorMapMenu(QWidget *parent) + : QMenu("Color Map", parent) + { + d_act.push_back(new QAction("Multi-Color", this)); + d_act.push_back(new QAction("White Hot", this)); + d_act.push_back(new QAction("Black Hot", this)); + d_act.push_back(new QAction("Incandescent", this)); + d_act.push_back(new QAction("Other", this)); + //d_act.push_back(new OtherDualAction("Min Intensity: ", "Max Intensity: ", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getMultiColor())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getWhiteHot())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getBlackHot())); + connect(d_act[3], SIGNAL(triggered()), this, SLOT(getIncandescent())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getOther())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + + d_max_value = QColor("white"); + d_min_value = QColor("white"); + } + + ~ColorMapMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("ColorMapMenu::getAction: which out of range.\n"); + } + + signals: + void whichTrigger(const int type, const QColor &min_color=QColor(), + const QColor &max_color=QColor()); + + public slots: + void getMultiColor() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); } + void getWhiteHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_WHITE_HOT); } + void getBlackHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_BLACK_HOT); } + void getIncandescent() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_INCANDESCENT); } + //void getOther(const QString &min_str, const QString &max_str) + void getOther() + { + QMessageBox::information(this, "Set low and high intensities", + "In the next windows, select the low and then the high intensity colors.", + QMessageBox::Ok); + d_min_value = QColorDialog::getColor(d_min_value, this); + d_max_value = QColorDialog::getColor(d_max_value, this); + + emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_USER_DEFINED, + d_min_value, d_max_value); + } + +private: + QList<QAction *> d_act; + OtherDualAction *d_other; + QColor d_max_value, d_min_value; +}; + + +/********************************************************************/ + + +#endif /* FORM_MENUS_H */ diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc new file mode 100644 index 0000000000..cf5c989c09 --- /dev/null +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -0,0 +1,376 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "freq_sink_c_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + freq_sink_c::sptr + freq_sink_c::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new freq_sink_c_impl(fftsize, wintype, + fc, bw, name, + nconnections, + parent)); + } + + freq_sink_c_impl::freq_sink_c_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_sync_block("freq_sink_c", + gr_make_io_signature(1, -1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_fftsize(fftsize), d_fftavg(1.0), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_nconnections(nconnections), d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex(d_fftsize, true); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + d_index = 0; + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_complex(d_fftsize)); + d_magbufs.push_back(fft::malloc_double(d_fftsize)); + + memset(d_residbufs[i], 0, d_fftsize*sizeof(gr_complex)); + memset(d_magbufs[i], 0, d_fftsize*sizeof(double)); + } + + buildwindow(); + + initialize(); + } + + freq_sink_c_impl::~freq_sink_c_impl() + { + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + } + delete d_fft; + fft::free(d_fbuf); + } + + void + freq_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + freq_sink_c_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new FreqDisplayForm(d_nconnections, d_parent); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetFFTWindowType(d_wintype); + d_main_gui->SetFrequencyRange(d_center_freq, + d_center_freq - d_bandwidth/2.0, + d_center_freq + d_bandwidth/2.0); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + freq_sink_c_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + freq_sink_c_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + freq_sink_c_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + freq_sink_c_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + freq_sink_c_impl::fft_size() const + { + return d_fftsize; + } + + void + freq_sink_c_impl::set_fft_average(const float fftavg) + { + d_fftavg = fftavg; + d_main_gui->SetFFTAverage(fftavg); + } + + float + freq_sink_c_impl::fft_average() const + { + return d_fftavg; + } + + void + freq_sink_c_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + freq_sink_c_impl::set_fft_power_db(double min, double max) + { + d_main_gui->SetFrequencyAxis(min, max); + } + + void + freq_sink_c_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + freq_sink_c_impl::set_title(int which, const std::string &title) + { + d_main_gui->setTitle(which, title.c_str()); + } + + void + freq_sink_c_impl::set_color(int which, const std::string &color) + { + d_main_gui->setColor(which, color.c_str()); + } + + void + freq_sink_c_impl::set_line_width(int which, int width) + { + d_main_gui->setLineWidth(which, width); + } + + void + freq_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + { + d_main_gui->setLineStyle(which, style); + } + + void + freq_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(which, marker); + } + + void + freq_sink_c_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + freq_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size) + { + if(d_window.size()) { + volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in, + &d_window.front(), size); + } + else { + memcpy(d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size); + } + + d_fft->execute(); // compute the fft + + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); + + // Perform shift operation + unsigned int len = (unsigned int)(floor(size/2.0)); + float *tmp = (float*)malloc(sizeof(float)*len); + memcpy(tmp, &data_out[0], sizeof(float)*len); + memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); + memcpy(&data_out[size - len], tmp, sizeof(float)*len); + free(tmp); + } + + void + freq_sink_c_impl::windowreset() + { + filter::firdes::win_type newwintype; + newwintype = d_main_gui->GetFFTWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + freq_sink_c_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != filter::firdes::WIN_NONE) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + freq_sink_c_impl::fftresize() + { + gruel::scoped_lock lock(d_mutex); + + int newfftsize = d_main_gui->GetFFTSize(); + d_fftavg = d_main_gui->GetFFTAverage(); + + if(newfftsize != d_fftsize) { + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + + d_residbufs[i] = fft::malloc_complex(newfftsize); + d_magbufs[i] = fft::malloc_double(newfftsize); + + memset(d_residbufs[i], 0, newfftsize*sizeof(gr_complex)); + memset(d_magbufs[i], 0, newfftsize*sizeof(double)); + } + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex(d_fftsize, true); + + fft::free(d_fbuf); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + } + } + + int + freq_sink_c_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const gr_complex *in = (const gr_complex*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + + for(int n = 0; n < d_nconnections; n++) { + // Fill up residbuf with d_fftsize number of items + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid); + + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new FreqUpdateEvent(d_magbufs, d_fftsize)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbuf for next time + else { + for(int n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h new file mode 100644 index 0000000000..106e50497d --- /dev/null +++ b/gr-qtgui/lib/freq_sink_c_impl.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H +#define INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H + +#include <qtgui/freq_sink_c.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <gruel/thread.h> +#include <freqdisplayform.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API freq_sink_c_impl : public freq_sink_c + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + gruel::mutex d_mutex; + + int d_fftsize; + float d_fftavg; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + std::vector<gr_complex*> d_residbufs; + std::vector<double*> d_magbufs; + float *d_fbuf; + + QWidget *d_parent; + FreqDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const gr_complex *data_in, int size); + + public: + freq_sink_c_impl(int size, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + ~freq_sink_c_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + void set_fft_average(const float fftavg); + float fft_average() const; + + void set_frequency_range(const double centerfreq, const double bandwidth); + void set_fft_power_db(double min, double max); + + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + void set_line_width(int which, int width); + void set_line_style(int which, Qt::PenStyle style); + void set_line_marker(int which, QwtSymbol::Style marker); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_FREQ_SINK_C_IMPL_H */ diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc new file mode 100644 index 0000000000..2cf43e9994 --- /dev/null +++ b/gr-qtgui/lib/freq_sink_f_impl.cc @@ -0,0 +1,380 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "freq_sink_f_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + freq_sink_f::sptr + freq_sink_f::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new freq_sink_f_impl(fftsize, wintype, + fc, bw, name, + nconnections, + parent)); + } + + freq_sink_f_impl::freq_sink_f_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_sync_block("freq_sink_f", + gr_make_io_signature(1, -1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_fftsize(fftsize), d_fftavg(1.0), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_nconnections(nconnections), d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex(d_fftsize, true); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + d_index = 0; + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_float(d_fftsize)); + d_magbufs.push_back(fft::malloc_double(d_fftsize)); + + memset(d_residbufs[i], 0, d_fftsize*sizeof(float)); + memset(d_magbufs[i], 0, d_fftsize*sizeof(double)); + } + + buildwindow(); + + initialize(); + } + + freq_sink_f_impl::~freq_sink_f_impl() + { + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + } + delete d_fft; + fft::free(d_fbuf); + } + + void + freq_sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + freq_sink_f_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new FreqDisplayForm(d_nconnections, d_parent); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetFFTWindowType(d_wintype); + d_main_gui->SetFrequencyRange(d_center_freq, + d_center_freq - d_bandwidth/2.0, + d_center_freq + d_bandwidth/2.0); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + freq_sink_f_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + freq_sink_f_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + freq_sink_f_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + freq_sink_f_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + freq_sink_f_impl::fft_size() const + { + return d_fftsize; + } + + void + freq_sink_f_impl::set_fft_average(const float fftavg) + { + d_fftavg = fftavg; + d_main_gui->SetFFTAverage(fftavg); + } + + float + freq_sink_f_impl::fft_average() const + { + return d_fftavg; + } + + void + freq_sink_f_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + freq_sink_f_impl::set_fft_power_db(double min, double max) + { + d_main_gui->SetFrequencyAxis(min, max); + } + + void + freq_sink_f_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + freq_sink_f_impl::set_title(int which, const std::string &title) + { + d_main_gui->setTitle(which, title.c_str()); + } + + void + freq_sink_f_impl::set_color(int which, const std::string &color) + { + d_main_gui->setColor(which, color.c_str()); + } + + void + freq_sink_f_impl::set_line_width(int which, int width) + { + d_main_gui->setLineWidth(which, width); + } + + void + freq_sink_f_impl::set_line_style(int which, Qt::PenStyle style) + { + d_main_gui->setLineStyle(which, style); + } + + void + freq_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(which, marker); + } + + + void + freq_sink_f_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + freq_sink_f_impl::fft(float *data_out, const float *data_in, int size) + { + // float to complex conversion + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) + dst[i] = data_in[i]; + + if(d_window.size()) { + volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), dst, + &d_window.front(), size); + } + + d_fft->execute(); // compute the fft + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); + + // Perform shift operation + unsigned int len = (unsigned int)(floor(size/2.0)); + float *tmp = (float*)malloc(sizeof(float)*len); + memcpy(tmp, &data_out[0], sizeof(float)*len); + memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); + memcpy(&data_out[size - len], tmp, sizeof(float)*len); + free(tmp); + } + + void + freq_sink_f_impl::windowreset() + { + gruel::scoped_lock lock(d_mutex); + + filter::firdes::win_type newwintype; + newwintype = d_main_gui->GetFFTWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + freq_sink_f_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != filter::firdes::WIN_NONE) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + freq_sink_f_impl::fftresize() + { + gruel::scoped_lock lock(d_mutex); + + int newfftsize = d_main_gui->GetFFTSize(); + d_fftavg = d_main_gui->GetFFTAverage(); + + if(newfftsize != d_fftsize) { + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + + d_residbufs[i] = fft::malloc_float(newfftsize); + d_magbufs[i] = fft::malloc_double(newfftsize); + + memset(d_residbufs[i], 0, newfftsize*sizeof(float)); + memset(d_magbufs[i], 0, newfftsize*sizeof(double)); + } + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex(d_fftsize, true); + + fft::free(d_fbuf); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + } + } + + int + freq_sink_f_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const float *in = (const float*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + + for(int n = 0; n < d_nconnections; n++) { + // Fill up residbuf with d_fftsize number of items + in = (const float*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid); + + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new FreqUpdateEvent(d_magbufs, d_fftsize)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbuf for next time + else { + for(int n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h new file mode 100644 index 0000000000..a358953629 --- /dev/null +++ b/gr-qtgui/lib/freq_sink_f_impl.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H +#define INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H + +#include <qtgui/freq_sink_f.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <gruel/thread.h> +#include <freqdisplayform.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API freq_sink_f_impl : public freq_sink_f + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + gruel::mutex d_mutex; + + int d_fftsize; + float d_fftavg; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + std::vector<float*> d_residbufs; + std::vector<double*> d_magbufs; + float *d_fbuf; + + QWidget *d_parent; + FreqDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const float *data_in, int size); + + public: + freq_sink_f_impl(int size, int wintype, + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + ~freq_sink_f_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + void set_fft_average(const float fftavg); + float fft_average() const; + + void set_frequency_range(const double centerfreq, const double bandwidth); + void set_fft_power_db(double min, double max); + + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + void set_line_width(int which, int width); + void set_line_style(int which, Qt::PenStyle style); + void set_line_marker(int which, QwtSymbol::Style marker); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_FREQ_SINK_F_IMPL_H */ diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc new file mode 100644 index 0000000000..6f12fe5090 --- /dev/null +++ b/gr-qtgui/lib/freqdisplayform.cc @@ -0,0 +1,162 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cmath> +#include <QMessageBox> +#include <freqdisplayform.h> +#include <iostream> + +FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent) + : DisplayForm(nplots, parent) +{ + _intValidator = new QIntValidator(this); + _intValidator->setBottom(0); + + _layout = new QGridLayout(this); + _displayPlot = new FrequencyDisplayPlot(nplots, this); + _layout->addWidget(_displayPlot, 0, 0); + setLayout(_layout); + + _numRealDataPoints = 1024; + _fftsize = 1024; + _fftavg = 1.0; + + FFTSizeMenu *sizemenu = new FFTSizeMenu(this); + FFTAverageMenu *avgmenu = new FFTAverageMenu(this); + FFTWindowMenu *winmenu = new FFTWindowMenu(this); + _menu->addMenu(sizemenu); + _menu->addMenu(avgmenu); + _menu->addMenu(winmenu); + connect(sizemenu, SIGNAL(whichTrigger(int)), + this, SLOT(SetFFTSize(const int))); + connect(avgmenu, SIGNAL(whichTrigger(float)), + this, SLOT(SetFFTAverage(const float))); + connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), + this, SLOT(SetFFTWindowType(const gr::filter::firdes::win_type))); + + Reset(); + + connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onPlotPointSelected(const QPointF))); +} + +FreqDisplayForm::~FreqDisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + delete _intValidator; +} + +FrequencyDisplayPlot* +FreqDisplayForm::getPlot() +{ + return ((FrequencyDisplayPlot*)_displayPlot); +} + +void +FreqDisplayForm::newData(const QEvent *updateEvent) +{ + FreqUpdateEvent *fevent = (FreqUpdateEvent*)updateEvent; + const std::vector<double*> dataPoints = fevent->getPoints(); + const uint64_t numDataPoints = fevent->getNumDataPoints(); + + getPlot()->PlotNewData(dataPoints, numDataPoints, + 0, 0, 0, d_update_time); +} + +void +FreqDisplayForm::customEvent( QEvent * e) +{ + if(e->type() == FreqUpdateEvent::Type()) { + newData(e); + } +} + +int +FreqDisplayForm::GetFFTSize() const +{ + return _fftsize; +} + +float +FreqDisplayForm::GetFFTAverage() const +{ + return _fftavg; +} + +gr::filter::firdes::win_type +FreqDisplayForm::GetFFTWindowType() const +{ + return _fftwintype; +} + +void +FreqDisplayForm::SetFFTSize(const int newsize) +{ + _fftsize = newsize; +} + +void +FreqDisplayForm::SetFFTAverage(const float newavg) +{ + _fftavg = newavg; + getPlot()->replot(); +} + +void +FreqDisplayForm::SetFFTWindowType(const gr::filter::firdes::win_type newwin) +{ + _fftwintype = newwin; +} + +void +FreqDisplayForm::SetFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency) +{ + double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency)); + + if(fdiff > 0) { + std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"}; + double units10 = floor(log10(fdiff)); + double units3 = std::max(floor(units10 / 3.0), 0.0); + double units = pow(10, (units10-fmod(units10, 3.0))); + int iunit = static_cast<int>(units3); + + _startFrequency = newStartFrequency; + _stopFrequency = newStopFrequency; + double centerFrequency = newCenterFrequency; + + getPlot()->SetFrequencyRange(_startFrequency, + _stopFrequency, + centerFrequency, + true, + units, strunits[iunit]); + } +} + +void +FreqDisplayForm::SetFrequencyAxis(double min, double max) +{ + getPlot()->set_yaxis(min, max); +} diff --git a/gr-qtgui/lib/freqdisplayform.h b/gr-qtgui/lib/freqdisplayform.h new file mode 100644 index 0000000000..ffce317c4f --- /dev/null +++ b/gr-qtgui/lib/freqdisplayform.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FREQ_DISPLAY_FORM_H +#define FREQ_DISPLAY_FORM_H + +#include <spectrumUpdateEvents.h> +#include <FrequencyDisplayPlot.h> +#include <QtGui/QtGui> +#include <vector> +#include <filter/firdes.h> + +#include "displayform.h" + +class FreqDisplayForm : public DisplayForm +{ + Q_OBJECT + + public: + FreqDisplayForm(int nplots=1, QWidget* parent = 0); + ~FreqDisplayForm(); + + FrequencyDisplayPlot* getPlot(); + + int GetFFTSize() const; + float GetFFTAverage() const; + gr::filter::firdes::win_type GetFFTWindowType() const; + +public slots: + void customEvent(QEvent *e); + + void SetFFTSize(const int); + void SetFFTAverage(const float); + void SetFFTWindowType(const gr::filter::firdes::win_type); + + void SetFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency); + void SetFrequencyAxis(double min, double max); + +private slots: + void newData(const QEvent *updateEvent); + +private: + uint64_t _numRealDataPoints; + QIntValidator* _intValidator; + + double _startFrequency; + double _stopFrequency; + + int _fftsize; + float _fftavg; + gr::filter::firdes::win_type _fftwintype; +}; + +#endif /* FREQ_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/qtgui_sink_c.cc b/gr-qtgui/lib/qtgui_sink_c.cc deleted file mode 100644 index de730a8710..0000000000 --- a/gr-qtgui/lib/qtgui_sink_c.cc +++ /dev/null @@ -1,310 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <qtgui_sink_c.h> -#include <gr_io_signature.h> -#include <string.h> - -#include <QTimer> - -qtgui_sink_c_sptr -qtgui_make_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent) -{ - return gnuradio::get_initial_sptr(new qtgui_sink_c (fftsize, wintype, - fc, bw, name, - plotfreq, plotwaterfall, - plottime, plotconst, - parent)); -} - -qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent) - : gr_block ("sink_c", - gr_make_io_signature (1, -1, sizeof(gr_complex)), - gr_make_io_signature (0, 0, 0)), - d_fftsize(fftsize), - d_wintype((gr_firdes::win_type)(wintype)), - d_center_freq(fc), d_bandwidth(bw), d_name(name), - d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), - d_plottime(plottime), d_plotconst(plotconst), - d_parent(parent) -{ - d_main_gui = NULL; - - // Perform fftshift operation; - // this is usually desired when plotting - d_shift = true; - - d_fft = new gri_fft_complex (d_fftsize, true); - - d_index = 0; - d_residbuf = new gr_complex[d_fftsize]; - - buildwindow(); - - initialize(); -} - -qtgui_sink_c::~qtgui_sink_c() -{ - delete d_main_gui; - delete [] d_residbuf; - delete d_fft; -} - -void -qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned int ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); - } -} - -void -qtgui_sink_c::initialize() -{ - if(qApp != NULL) { - d_qApplication = qApp; - } - else { - int argc=0; - char **argv = NULL; - d_qApplication = new QApplication(argc, argv); - } - - if(d_center_freq < 0) { - throw std::runtime_error("qtgui_sink_c: Received bad center frequency.\n"); - } - - uint64_t maxBufferSize = 32768; - d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, - d_center_freq, - -d_bandwidth/2.0, - d_bandwidth/2.0); - - d_main_gui->SetDisplayTitle(d_name); - d_main_gui->SetFFTSize(d_fftsize); - d_main_gui->SetWindowType((int)d_wintype); - - d_main_gui->OpenSpectrumWindow(d_parent, - d_plotfreq, d_plotwaterfall, - d_plottime, d_plotconst); - - // initialize update time to 10 times a second - set_update_time(0.5); - - d_last_update = gruel::high_res_timer_now(); - d_update_active = false; -} - - -void -qtgui_sink_c::exec_() -{ - d_qApplication->exec(); -} - -QWidget* -qtgui_sink_c::qwidget() -{ - return d_main_gui->qwidget(); -} - -PyObject* -qtgui_sink_c::pyqwidget() -{ - PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); - PyObject *retarg = Py_BuildValue("N", w); - return retarg; -} - -void -qtgui_sink_c::set_frequency_range(const double centerfreq, - const double bandwidth) -{ - d_center_freq = centerfreq; - d_bandwidth = bandwidth; - d_main_gui->SetFrequencyRange(d_center_freq, - -d_bandwidth/2.0, - d_bandwidth/2.0); -} - -void -qtgui_sink_c::set_time_domain_axis(double min, double max) -{ - d_main_gui->SetTimeDomainAxis(min, max); -} - -void -qtgui_sink_c::set_constellation_axis(double xmin, double xmax, - double ymin, double ymax) -{ - d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); -} - -void -qtgui_sink_c::set_constellation_pen_size(int size) -{ - d_main_gui->SetConstellationPenSize(size); -} - - -void -qtgui_sink_c::set_frequency_axis(double min, double max) -{ - d_main_gui->SetFrequencyAxis(min, max); -} - -void -qtgui_sink_c::set_update_time(double t) -{ - d_update_time = t * gruel::high_res_timer_tps(); - d_main_gui->SetUpdateTime(t); -} - -void -qtgui_sink_c::fft(const gr_complex *data_in, int size) -{ - if (d_window.size()) { - gr_complex *dst = d_fft->get_inbuf(); - int i; - for (i = 0; i < size; i++) // apply window - dst[i] = data_in[i] * d_window[i]; - } - else { - memcpy (d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size); - } - - d_fft->execute (); // compute the fft -} - -void -qtgui_sink_c::windowreset() -{ - gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType(); - if(d_wintype != newwintype) { - d_wintype = newwintype; - buildwindow(); - } -} - -void -qtgui_sink_c::buildwindow() -{ - d_window.clear(); - if(d_wintype != 0) { - d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76); - } -} - -void -qtgui_sink_c::fftresize() -{ - int newfftsize = d_main_gui->GetFFTSize(); - - if(newfftsize != d_fftsize) { - - // Resize residbuf and replace data - delete [] d_residbuf; - d_residbuf = new gr_complex[newfftsize]; - - // Set new fft size and reset buffer index - // (throws away any currently held data, but who cares?) - d_fftsize = newfftsize; - d_index = 0; - - // Reset window to reflect new size - buildwindow(); - - // Reset FFTW plan for new size - delete d_fft; - d_fft = new gri_fft_complex (d_fftsize, true); - } -} - - -int -qtgui_sink_c::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int j=0; - const gr_complex *in = (const gr_complex*)input_items[0]; - - // Update the FFT size from the application - fftresize(); - windowreset(); - - for(int i=0; i < noutput_items; i+=d_fftsize) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_fftsize-d_index; - - if (!d_update_active && (gruel::high_res_timer_now() - d_last_update) < d_update_time) { - consume_each(noutput_items); - return noutput_items; - } else { - d_last_update = gruel::high_res_timer_now(); - d_update_active = true; - } - - // If we have enough input for one full FFT, do it - if(datasize >= resid) { - const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); - - // Fill up residbuf with d_fftsize number of items - memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid); - d_index = 0; - - j += resid; - fft(d_residbuf, d_fftsize); - - d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize, - NULL, 0, (float*)d_residbuf, d_fftsize, - currentTime, true); - d_update_active = false; - } - // Otherwise, copy what we received into the residbuf for next time - else { - memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*datasize); - d_index += datasize; - j += datasize; - } - } - - consume_each(j); - return j; -} diff --git a/gr-qtgui/lib/qtgui_sink_f.cc b/gr-qtgui/lib/qtgui_sink_f.cc deleted file mode 100644 index a02f89d0ac..0000000000 --- a/gr-qtgui/lib/qtgui_sink_f.cc +++ /dev/null @@ -1,294 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <qtgui_sink_f.h> -#include <gr_io_signature.h> -#include <string.h> - -#include <QTimer> - -qtgui_sink_f_sptr -qtgui_make_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent) -{ - return gnuradio::get_initial_sptr(new qtgui_sink_f (fftsize, wintype, - fc, bw, name, - plotfreq, plotwaterfall, - plottime, plotconst, - parent)); -} - -qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent) - : gr_block ("sink_f", - gr_make_io_signature (1, 1, sizeof(float)), - gr_make_io_signature (0, 0, 0)), - d_fftsize(fftsize), - d_wintype((gr_firdes::win_type)(wintype)), - d_center_freq(fc), d_bandwidth(bw), d_name(name), - d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), - d_plottime(plottime), d_plotconst(plotconst), - d_parent(parent) -{ - d_main_gui = NULL; - - // Perform fftshift operation; - // this is usually desired when plotting - d_shift = true; - - d_fft = new gri_fft_complex (d_fftsize, true); - - d_index = 0; - d_residbuf = new float[d_fftsize]; - - buildwindow(); - - initialize(); -} - -qtgui_sink_f::~qtgui_sink_f() -{ - delete d_main_gui; - delete [] d_residbuf; - delete d_fft; -} - -void -qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned int ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); - } -} - -void -qtgui_sink_f::initialize() -{ - if(qApp != NULL) { - d_qApplication = qApp; - } - else { - int argc; - char **argv = NULL; - d_qApplication = new QApplication(argc, argv); - } - - - uint64_t maxBufferSize = 32768; - d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, - d_center_freq, - -d_bandwidth/2.0, - d_bandwidth/2.0); - d_main_gui->SetDisplayTitle(d_name); - d_main_gui->SetFFTSize(d_fftsize); - d_main_gui->SetWindowType((int)d_wintype); - - d_main_gui->OpenSpectrumWindow(d_parent, - d_plotfreq, d_plotwaterfall, - d_plottime, d_plotconst); - - // initialize update time to 10 times a second - set_update_time(0.1); -} - -void -qtgui_sink_f::exec_() -{ - d_qApplication->exec(); -} - -QWidget* -qtgui_sink_f::qwidget() -{ - return d_main_gui->qwidget(); -} - -PyObject* -qtgui_sink_f::pyqwidget() -{ - PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); - PyObject *retarg = Py_BuildValue("N", w); - return retarg; -} - -void -qtgui_sink_f::set_frequency_range(const double centerfreq, - const double bandwidth) -{ - d_center_freq = centerfreq; - d_bandwidth = bandwidth; - d_main_gui->SetFrequencyRange(d_center_freq, - -d_bandwidth/2.0, - d_bandwidth/2.0); -} - -void -qtgui_sink_f::set_time_domain_axis(double min, double max) -{ - d_main_gui->SetTimeDomainAxis(min, max); -} - -void -qtgui_sink_f::set_constellation_axis(double xmin, double xmax, - double ymin, double ymax) -{ - d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); -} - -void -qtgui_sink_f::set_constellation_pen_size(int size) -{ - d_main_gui->SetConstellationPenSize(size); -} - - -void -qtgui_sink_f::set_frequency_axis(double min, double max) -{ - d_main_gui->SetFrequencyAxis(min, max); -} - -void -qtgui_sink_f::set_update_time(double t) -{ - d_update_time = t; - d_main_gui->SetUpdateTime(d_update_time); -} - -void -qtgui_sink_f::fft(const float *data_in, int size) -{ - if (d_window.size()) { - gr_complex *dst = d_fft->get_inbuf(); - for (int i = 0; i < size; i++) // apply window - dst[i] = data_in[i] * d_window[i]; - } - else { - gr_complex *dst = d_fft->get_inbuf(); - for (int i = 0; i < size; i++) // float to complex conversion - dst[i] = data_in[i]; - } - - d_fft->execute (); // compute the fft -} - -void -qtgui_sink_f::windowreset() -{ - gr_firdes::win_type newwintype = (gr_firdes::win_type)d_main_gui->GetWindowType(); - if(d_wintype != newwintype) { - d_wintype = newwintype; - buildwindow(); - } -} - -void -qtgui_sink_f::buildwindow() -{ - d_window.clear(); - if(d_wintype != 0) { - d_window = gr_firdes::window(d_wintype, d_fftsize, 6.76); - } -} - -void -qtgui_sink_f::fftresize() -{ - int newfftsize = d_main_gui->GetFFTSize(); - - if(newfftsize != d_fftsize) { - - // Resize residbuf and replace data - delete [] d_residbuf; - d_residbuf = new float[newfftsize]; - - // Set new fft size and reset buffer index - // (throws away any currently held data, but who cares?) - d_fftsize = newfftsize; - d_index = 0; - - // Reset window to reflect new size - buildwindow(); - - // Reset FFTW plan for new size - delete d_fft; - d_fft = new gri_fft_complex (d_fftsize, true); - } -} - - -int -qtgui_sink_f::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int j=0; - const float *in = (const float*)input_items[0]; - - // Update the FFT size from the application - fftresize(); - windowreset(); - - for(int i=0; i < noutput_items; i+=d_fftsize) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_fftsize-d_index; - - // If we have enough input for one full FFT, do it - if(datasize >= resid) { - const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); - - // Fill up residbuf with d_fftsize number of items - memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid); - d_index = 0; - - j += resid; - fft(d_residbuf, d_fftsize); - - d_main_gui->UpdateWindow(true, d_fft->get_outbuf(), d_fftsize, - (float*)d_residbuf, d_fftsize, NULL, 0, - currentTime, true); - } - // Otherwise, copy what we received into the residbuf for next time - else { - memcpy(d_residbuf+d_index, &in[j], sizeof(float)*datasize); - d_index += datasize; - j += datasize; - } - } - - consume_each(j); - return j; -} diff --git a/gr-qtgui/lib/qtgui_time_sink_c.cc b/gr-qtgui/lib/qtgui_time_sink_c.cc deleted file mode 100644 index 574fd93ad6..0000000000 --- a/gr-qtgui/lib/qtgui_time_sink_c.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <qtgui_time_sink_c.h> -#include <gr_io_signature.h> -#include <string.h> - -#include <QTimer> - -qtgui_time_sink_c_sptr -qtgui_make_time_sink_c (int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent) -{ - return gnuradio::get_initial_sptr(new qtgui_time_sink_c (size, bw, name, - nconnections, parent)); -} - -qtgui_time_sink_c::qtgui_time_sink_c (int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent) - : gr_sync_block ("time_sink_c", - gr_make_io_signature (nconnections, nconnections, sizeof(gr_complex)), - gr_make_io_signature (0, 0, 0)), - d_size(size), d_bandwidth(bw), d_name(name), - d_nconnections(2*nconnections), d_parent(parent) -{ - d_main_gui = NULL; - - d_index = 0; - - for(int i = 0; i < d_nconnections; i++) { - d_residbufs.push_back(new double[d_size]); - } - - initialize(); - set_output_multiple(d_size); -} - -qtgui_time_sink_c::~qtgui_time_sink_c() -{ - // d_main_gui is a qwidget destroyed with its parent - for(int i = 0; i < d_nconnections; i++) { - delete [] d_residbufs[i]; - } -} - -void -qtgui_time_sink_c::initialize() -{ - if(qApp != NULL) { - d_qApplication = qApp; - } - else { - int argc=0; - char **argv = NULL; - d_qApplication = new QApplication(argc, argv); - } - - d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); - - // initialize update time to 10 times a second - set_update_time(0.1); - d_last_time = 0; -} - - -void -qtgui_time_sink_c::exec_() -{ - d_qApplication->exec(); -} - -QWidget* -qtgui_time_sink_c::qwidget() -{ - return d_main_gui; -} - -PyObject* -qtgui_time_sink_c::pyqwidget() -{ - PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); - PyObject *retarg = Py_BuildValue("N", w); - return retarg; -} - -void -qtgui_time_sink_c::set_time_domain_axis(double min, double max) -{ - d_main_gui->setTimeDomainAxis(min, max); -} - -void -qtgui_time_sink_c::set_update_time(double t) -{ - d_update_time = t; - d_main_gui->setUpdateTime(d_update_time); -} - -void -qtgui_time_sink_c::set_title(int which, const std::string &title) -{ - d_main_gui->setTitle(which, title.c_str()); -} - -void -qtgui_time_sink_c::set_color(int which, const std::string &color) -{ - d_main_gui->setColor(which, color.c_str()); -} - -int -qtgui_time_sink_c::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int n=0, j=0, idx=0; - const gr_complex *in = (const gr_complex*)input_items[idx]; - - for(int i=0; i < noutput_items; i+=d_size) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_size-d_index; - idx = 0; - - // If we have enough input for one full plot, do it - if(datasize >= resid) { - d_current_time = gruel::high_res_timer_now(); - - // Fill up residbufs with d_size number of items - for(n = 0; n < d_nconnections; n+=2) { - in = (const gr_complex*)input_items[idx++]; - for(unsigned int k = 0; k < resid; k++) { - d_residbufs[n][d_index+k] = in[j+k].real(); - d_residbufs[n+1][d_index+k] = in[j+k].imag(); - } - } - - // Update the plot if its time - if(gruel::high_res_timer_now() - d_last_time > d_update_time) { - d_last_time = d_current_time; - d_qApplication->postEvent(d_main_gui, - new TimeUpdateEvent(d_residbufs, d_size)); - } - - d_index = 0; - j += resid; - } - // Otherwise, copy what we received into the residbufs for next time - // because we set the output_multiple, this should never need to be called - else { - assert(0); - for(n = 0; n < d_nconnections; n+=2) { - in = (const gr_complex*)input_items[idx++]; - for(unsigned int k = 0; k < resid; k++) { - d_residbufs[n][d_index+k] = in[j+k].real(); - d_residbufs[n+1][d_index+k] = in[j+k].imag(); - } - } - d_index += datasize; - j += datasize; - } - } - - return noutput_items; -} diff --git a/gr-qtgui/lib/qtgui_time_sink_f.cc b/gr-qtgui/lib/qtgui_time_sink_f.cc deleted file mode 100644 index 09fdf0a92e..0000000000 --- a/gr-qtgui/lib/qtgui_time_sink_f.cc +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <qtgui_time_sink_f.h> -#include <gr_io_signature.h> -#include <string.h> - -#include <QTimer> - -qtgui_time_sink_f_sptr -qtgui_make_time_sink_f (int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent) -{ - return gnuradio::get_initial_sptr(new qtgui_time_sink_f (size, bw, name, - nconnections, parent)); -} - -qtgui_time_sink_f::qtgui_time_sink_f (int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent) - : gr_sync_block ("time_sink_f", - gr_make_io_signature (nconnections, nconnections, sizeof(float)), - gr_make_io_signature (0, 0, 0)), - d_size(size), d_bandwidth(bw), d_name(name), - d_nconnections(nconnections), d_parent(parent) -{ - d_main_gui = NULL; - - d_index = 0; - - for(int i = 0; i < d_nconnections; i++) { - d_residbufs.push_back(new double[d_size]); - } - - initialize(); - set_output_multiple(d_size); -} - -qtgui_time_sink_f::~qtgui_time_sink_f() -{ - // d_main_gui is a qwidget destroyed with its parent - for(int i = 0; i < d_nconnections; i++) { - delete [] d_residbufs[i]; - } -} - -void -qtgui_time_sink_f::initialize() -{ - if(qApp != NULL) { - d_qApplication = qApp; - } - else { - int argc=0; - char **argv = NULL; - d_qApplication = new QApplication(argc, argv); - } - - d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); - - // initialize update time to 10 times a second - set_update_time(0.1); - d_last_time = 0; -} - - -void -qtgui_time_sink_f::exec_() -{ - d_qApplication->exec(); -} - -QWidget* -qtgui_time_sink_f::qwidget() -{ - return d_main_gui; -} - -PyObject* -qtgui_time_sink_f::pyqwidget() -{ - PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); - PyObject *retarg = Py_BuildValue("N", w); - return retarg; -} - -void -qtgui_time_sink_f::set_time_domain_axis(double min, double max) -{ - d_main_gui->setTimeDomainAxis(min, max); -} - -void -qtgui_time_sink_f::set_update_time(double t) -{ - d_update_time = t; - d_main_gui->setUpdateTime(d_update_time); -} - -void -qtgui_time_sink_f::set_title(int which, const std::string &title) -{ - d_main_gui->setTitle(which, title.c_str()); -} - -void -qtgui_time_sink_f::set_color(int which, const std::string &color) -{ - d_main_gui->setColor(which, color.c_str()); -} - -int -qtgui_time_sink_f::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int n=0, j=0, idx=0; - const float *in = (const float*)input_items[idx]; - - for(int i=0; i < noutput_items; i+=d_size) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_size-d_index; - idx = 0; - - // If we have enough input for one full plot, do it - if(datasize >= resid) { - d_current_time = gruel::high_res_timer_now(); - - // Fill up residbufs with d_size number of items - for(n = 0; n < d_nconnections; n++) { - in = (const float*)input_items[idx++]; - for(unsigned int k = 0; k < resid; k++) { - d_residbufs[n][d_index+k] = in[j+k]; - } - } - - // Update the plot if its time - if(gruel::high_res_timer_now() - d_last_time > d_update_time) { - d_last_time = d_current_time; - d_qApplication->postEvent(d_main_gui, - new TimeUpdateEvent(d_residbufs, d_size)); - } - - d_index = 0; - j += resid; - } - // Otherwise, copy what we received into the residbufs for next time - // because we set the output_multiple, this should never need to be called - else { - assert(0); - for(n = 0; n < d_nconnections; n++) { - in = (const float*)input_items[idx++]; - for(unsigned int k = 0; k < resid; k++) { - d_residbufs[n][d_index+k] = in[j+k]; - } - } - d_index += datasize; - j += datasize; - } - } - - return noutput_items; -} diff --git a/gr-qtgui/lib/qtgui_types.h b/gr-qtgui/lib/qtgui_types.h new file mode 100644 index 0000000000..fd5dd6295f --- /dev/null +++ b/gr-qtgui/lib/qtgui_types.h @@ -0,0 +1,196 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef QTGUI_TYPES_H +#define QTGUI_TYPES_H + +#include <qwt_color_map.h> +#include <qwt_scale_draw.h> +#include <gruel/high_res_timer.h> + +class FreqOffsetAndPrecisionClass +{ +public: + FreqOffsetAndPrecisionClass(const int freqPrecision) + { + _frequencyPrecision = freqPrecision; + _centerFrequency = 0; + } + + virtual ~FreqOffsetAndPrecisionClass() + { + } + + virtual unsigned int GetFrequencyPrecision() const + { + return _frequencyPrecision; + } + + virtual void SetFrequencyPrecision(const unsigned int newPrecision) + { + _frequencyPrecision = newPrecision; + } + + virtual double GetCenterFrequency() const + { + return _centerFrequency; + } + + virtual void SetCenterFrequency(const double newFreq) + { + _centerFrequency = newFreq; + } + +protected: + +private: + unsigned int _frequencyPrecision; + double _centerFrequency; +}; + +class TimeScaleData +{ +public: + TimeScaleData() + { + _zeroTime = 0; + _secondsPerLine = 1.0; + } + + virtual ~TimeScaleData() + { + } + + virtual gruel::high_res_timer_type GetZeroTime() const + { + return _zeroTime; + } + + virtual void SetZeroTime(const gruel::high_res_timer_type newTime) + { + _zeroTime = newTime - gruel::high_res_timer_epoch(); + } + + virtual void SetSecondsPerLine(const double newTime) + { + _secondsPerLine = newTime; + } + + virtual double GetSecondsPerLine() const + { + return _secondsPerLine; + } + + +protected: + +private: + gruel::high_res_timer_type _zeroTime; + double _secondsPerLine; + +}; + +/*********************************************************************** + * Text scale widget to provide X (freq) axis text + **********************************************************************/ +class FreqDisplayScaleDraw: public QwtScaleDraw, FreqOffsetAndPrecisionClass +{ +public: + FreqDisplayScaleDraw(const unsigned int precision) + : QwtScaleDraw(), FreqOffsetAndPrecisionClass(precision) + { + } + + virtual QwtText label(double value) const + { + return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision()); + } + + virtual void initiateUpdate(void) + { + invalidateCache(); + } + +protected: + +private: + +}; + +enum{ + INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR = 0, + INTENSITY_COLOR_MAP_TYPE_WHITE_HOT = 1, + INTENSITY_COLOR_MAP_TYPE_BLACK_HOT = 2, + INTENSITY_COLOR_MAP_TYPE_INCANDESCENT = 3, + INTENSITY_COLOR_MAP_TYPE_USER_DEFINED = 4 +}; + +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) + { + } +}; + +#endif //QTGUI_TYPES_H diff --git a/gr-qtgui/lib/qtgui_util.cc b/gr-qtgui/lib/qtgui_util.cc index 543ce1b1c7..70dcb483fb 100644 --- a/gr-qtgui/lib/qtgui_util.cc +++ b/gr-qtgui/lib/qtgui_util.cc @@ -20,53 +20,32 @@ * Boston, MA 02110-1301, USA. */ -#include <qtgui_util.h> +#include <qtgui/utils.h> +#include <QDebug> -#if QWT_VERSION < 0x060000 QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine() +#if QWT_VERSION < 0x060000 : QwtPickerMachine () -{ -} #else -QwtPickerDblClickPointMachine::QwtPickerDblClickPointMachine() : QwtPickerMachine (PointSelection) +#endif { } -#endif QwtPickerDblClickPointMachine::~QwtPickerDblClickPointMachine() { - } #if QWT_VERSION < 0x060000 -QwtPickerMachine::CommandList -QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, - const QEvent *e) -{ - QwtPickerMachine::CommandList 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; -} - +#define CMDLIST_TYPE QwtPickerMachine::CommandList #else - -QList<QwtPickerMachine::Command> +#define CMDLIST_TYPE QList<QwtPickerMachine::Command> +#endif +CMDLIST_TYPE QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, const QEvent *e) { - QList<QwtPickerMachine::Command> cmdList; + CMDLIST_TYPE cmdList; switch(e->type()) { case QEvent::MouseButtonDblClick: if ( eventPattern.mouseMatch(QwtEventPattern::MouseSelect1, @@ -81,7 +60,6 @@ QwtPickerDblClickPointMachine::transition(const QwtEventPattern &eventPattern, } return cmdList; } -#endif QwtDblClickPlotPicker::QwtDblClickPlotPicker(QwtPlotCanvas* canvas) : QwtPlotPicker(canvas) diff --git a/gr-qtgui/lib/sink_c_impl.cc b/gr-qtgui/lib/sink_c_impl.cc new file mode 100644 index 0000000000..29f56a5f39 --- /dev/null +++ b/gr-qtgui/lib/sink_c_impl.cc @@ -0,0 +1,335 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "sink_c_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + sink_c::sptr + sink_c::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new sink_c_impl(fftsize, wintype, + fc, bw, name, + plotfreq, plotwaterfall, + plottime, plotconst, + parent)); + } + + sink_c_impl::sink_c_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent) + : gr_block("sink_c", + gr_make_io_signature(1, -1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_fftsize(fftsize), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), + d_plottime(plottime), d_plotconst(plotconst), + d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex (d_fftsize, true); + + d_index = 0; + d_residbuf = new gr_complex[d_fftsize]; + d_magbuf = new float[d_fftsize]; + + buildwindow(); + + initialize(); + } + + sink_c_impl::~sink_c_impl() + { + delete d_main_gui; + delete [] d_residbuf; + delete [] d_magbuf; + delete d_fft; + } + + void + sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + sink_c_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + if(d_center_freq < 0) { + throw std::runtime_error("sink_c_impl: Received bad center frequency.\n"); + } + + uint64_t maxBufferSize = 32768; + d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, + d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + + d_main_gui->SetDisplayTitle(d_name); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetWindowType((int)d_wintype); + + d_main_gui->OpenSpectrumWindow(d_parent, + d_plotfreq, d_plotwaterfall, + d_plottime, d_plotconst); + + // initialize update time to 10 times a second + set_update_time(0.5); + + d_last_update = gruel::high_res_timer_now(); + d_update_active = false; + } + + void + sink_c_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + sink_c_impl::qwidget() + { + return d_main_gui->qwidget(); + } + + PyObject* + sink_c_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + sink_c_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + sink_c_impl::fft_size() const + { + return d_fftsize; + } + + void + sink_c_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + sink_c_impl::set_fft_power_db(double min, double max) + { + d_main_gui->SetFrequencyAxis(min, max); + } + + /* + void + sink_c_impl::set_time_domain_axis(double min, double max) + { + d_main_gui->SetTimeDomainAxis(min, max); + } + + void + sink_c_impl::set_constellation_axis(double xmin, double xmax, + double ymin, double ymax) + { + d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); + } + + void + sink_c_impl::set_constellation_pen_size(int size) + { + d_main_gui->SetConstellationPenSize(size); + } + */ + + void + sink_c_impl::set_update_time(double t) + { + d_update_time = t * gruel::high_res_timer_tps(); + d_main_gui->SetUpdateTime(t); + } + + void + sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size) + { + if (d_window.size()) { + volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in, + &d_window.front(), size); + } + else { + memcpy (d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size); + } + + d_fft->execute (); // compute the fft + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); +} + + void + sink_c_impl::windowreset() + { + filter::firdes::win_type newwintype; + newwintype = (filter::firdes::win_type)d_main_gui->GetWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + sink_c_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != 0) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + sink_c_impl::fftresize() + { + int newfftsize = d_main_gui->GetFFTSize(); + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + delete [] d_residbuf; + d_residbuf = new gr_complex[newfftsize]; + + delete [] d_magbuf; + d_magbuf = new float[newfftsize]; + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex (d_fftsize, true); + } + } + + int + sink_c_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const gr_complex *in = (const gr_complex*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + if (!d_update_active && (gruel::high_res_timer_now() - d_last_update) < d_update_time) { + consume_each(noutput_items); + return noutput_items; + } + else { + d_last_update = gruel::high_res_timer_now(); + d_update_active = true; + } + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); + + // Fill up residbuf with d_fftsize number of items + memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*resid); + d_index = 0; + + j += resid; + fft(d_magbuf, d_residbuf, d_fftsize); + + d_main_gui->UpdateWindow(true, d_magbuf, d_fftsize, + NULL, 0, (float*)d_residbuf, d_fftsize, + currentTime, true); + d_update_active = false; + } + // Otherwise, copy what we received into the residbuf for next time + else { + memcpy(d_residbuf+d_index, &in[j], sizeof(gr_complex)*datasize); + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/sink_c_impl.h b/gr-qtgui/lib/sink_c_impl.h new file mode 100644 index 0000000000..b201bcd5a2 --- /dev/null +++ b/gr-qtgui/lib/sink_c_impl.h @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_C_IMPL_H +#define INCLUDED_QTGUI_SINK_C_IMPL_H + +#include <qtgui/sink_c.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <SpectrumGUIClass.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API sink_c_impl : public sink_c + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_fftsize; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + gruel::high_res_timer_type d_last_update; + bool d_update_active; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + gr_complex *d_residbuf; + float *d_magbuf; + + bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; + + gruel::high_res_timer_type d_update_time; + + QWidget *d_parent; + SpectrumGUIClass *d_main_gui; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const gr_complex *data_in, int size); + + public: + sink_c_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent); + ~sink_c_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + + void set_frequency_range(const double centerfreq, + const double bandwidth); + void set_fft_power_db(double min, double max); + + //void set_time_domain_axis(double min, double max); + //void set_constellation_axis(double xmin, double xmax, + // double ymin, double ymax); + //void set_constellation_pen_size(int size); + + void set_update_time(double t); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_SINK_C_IMPL_H */ diff --git a/gr-qtgui/lib/sink_f_impl.cc b/gr-qtgui/lib/sink_f_impl.cc new file mode 100644 index 0000000000..580c774c0b --- /dev/null +++ b/gr-qtgui/lib/sink_f_impl.cc @@ -0,0 +1,320 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "sink_f_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + sink_f::sptr + sink_f::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new sink_f_impl(fftsize, wintype, + fc, bw, name, + plotfreq, plotwaterfall, + plottime, plotconst, + parent)); + } + + sink_f_impl::sink_f_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent) + : gr_block("sink_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature (0, 0, 0)), + d_fftsize(fftsize), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_plotfreq(plotfreq), d_plotwaterfall(plotwaterfall), + d_plottime(plottime), d_plotconst(plotconst), + d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex (d_fftsize, true); + + d_index = 0; + d_residbuf = new float[d_fftsize]; + d_magbuf = new float[d_fftsize]; + + buildwindow(); + + initialize(); + } + + sink_f_impl::~sink_f_impl() + { + delete d_main_gui; + delete [] d_residbuf; + delete [] d_magbuf; + delete d_fft; + } + + void + sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + sink_f_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + uint64_t maxBufferSize = 32768; + d_main_gui = new SpectrumGUIClass(maxBufferSize, d_fftsize, + d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + d_main_gui->SetDisplayTitle(d_name); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetWindowType((int)d_wintype); + + d_main_gui->OpenSpectrumWindow(d_parent, + d_plotfreq, d_plotwaterfall, + d_plottime, d_plotconst); + + // initialize update time to 10 times a second + set_update_time(0.1); + } + + void + sink_f_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + sink_f_impl::qwidget() + { + return d_main_gui->qwidget(); + } + + PyObject* + sink_f_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui->qwidget()); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + sink_f_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + sink_f_impl::fft_size() const + { + return d_fftsize; + } + + void + sink_f_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + sink_f_impl::set_fft_power_db(double min, double max) + { + d_main_gui->SetFrequencyAxis(min, max); + } + + /* + void + sink_f_impl::set_time_domain_axis(double min, double max) + { + d_main_gui->SetTimeDomainAxis(min, max); + } + + void + sink_f_impl::set_constellation_axis(double xmin, double xmax, + double ymin, double ymax) + { + d_main_gui->SetConstellationAxis(xmin, xmax, ymin, ymax); + } + + void + sink_f_impl::set_constellation_pen_size(int size) + { + d_main_gui->SetConstellationPenSize(size); + } + */ + + void + sink_f_impl::set_update_time(double t) + { + d_update_time = t; + d_main_gui->SetUpdateTime(d_update_time); + } + + void + sink_f_impl::fft(float *data_out, const float *data_in, int size) + { + if (d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) // apply window + dst[i] = data_in[i] * d_window[i]; + } + else { + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) // float to complex conversion + dst[i] = data_in[i]; + } + + d_fft->execute (); // compute the fft + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); + } + + void + sink_f_impl::windowreset() + { + filter::firdes::win_type newwintype; + newwintype = (filter::firdes::win_type)d_main_gui->GetWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + sink_f_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != 0) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + sink_f_impl::fftresize() + { + int newfftsize = d_main_gui->GetFFTSize(); + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + delete [] d_residbuf; + d_residbuf = new float[newfftsize]; + + delete [] d_magbuf; + d_magbuf = new float[newfftsize]; + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex (d_fftsize, true); + } + } + + int + sink_f_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const float *in = (const float*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + const gruel::high_res_timer_type currentTime = gruel::high_res_timer_now(); + + // Fill up residbuf with d_fftsize number of items + memcpy(d_residbuf+d_index, &in[j], sizeof(float)*resid); + d_index = 0; + + j += resid; + fft(d_magbuf, d_residbuf, d_fftsize); + + d_main_gui->UpdateWindow(true, d_magbuf, d_fftsize, + (float*)d_residbuf, d_fftsize, NULL, 0, + currentTime, true); + } + // Otherwise, copy what we received into the residbuf for next time + else { + memcpy(d_residbuf+d_index, &in[j], sizeof(float)*datasize); + d_index += datasize; + j += datasize; + } + } + + consume_each(j); + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/sink_f_impl.h b/gr-qtgui/lib/sink_f_impl.h new file mode 100644 index 0000000000..93dc46e85f --- /dev/null +++ b/gr-qtgui/lib/sink_f_impl.h @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_SINK_F_IMPL_H +#define INCLUDED_QTGUI_SINK_F_IMPL_H + +#include <qtgui/sink_f.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <SpectrumGUIClass.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API sink_f_impl : public sink_f + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_fftsize; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + float *d_residbuf; + float *d_magbuf; + + bool d_plotfreq, d_plotwaterfall, d_plottime, d_plotconst; + + double d_update_time; + + QWidget *d_parent; + SpectrumGUIClass *d_main_gui; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const float *data_in, int size); + + public: + sink_f_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + bool plotfreq, bool plotwaterfall, + bool plottime, bool plotconst, + QWidget *parent); + ~sink_f_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + + void set_frequency_range(const double centerfreq, + const double bandwidth); + void set_fft_power_db(double min, double max); + + //void set_time_domain_axis(double min, double max); + //void set_constellation_axis(double xmin, double xmax, + // double ymin, double ymax); + //void set_constellation_pen_size(int size); + + void set_update_time(double t); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_SINK_F_IMPL_H */ diff --git a/gr-qtgui/lib/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc index bec39747b8..92dd807147 100644 --- a/gr-qtgui/lib/spectrumUpdateEvents.cc +++ b/gr-qtgui/lib/spectrumUpdateEvents.cc @@ -3,7 +3,7 @@ #include <spectrumUpdateEvents.h> -SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints, +SpectrumUpdateEvent::SpectrumUpdateEvent(const float* fftPoints, const uint64_t numFFTDataPoints, const double* realTimeDomainPoints, const double* imagTimeDomainPoints, @@ -13,7 +13,7 @@ SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints, const bool lastOfMultipleUpdateFlag, const gruel::high_res_timer_type generatedTimestamp, const int droppedFFTFrames) - : QEvent(QEvent::Type(10005)) + : QEvent(QEvent::Type(SpectrumUpdateEventType)) { if(numFFTDataPoints < 1) { _numFFTDataPoints = 1; @@ -29,9 +29,9 @@ SpectrumUpdateEvent::SpectrumUpdateEvent(const std::complex<float>* fftPoints, _numTimeDomainDataPoints = numTimeDomainDataPoints; } - _fftPoints = new std::complex<float>[_numFFTDataPoints]; - _fftPoints[0] = std::complex<float>(0,0); - memcpy(_fftPoints, fftPoints, numFFTDataPoints*sizeof(std::complex<float>)); + _fftPoints = new float[_numFFTDataPoints]; + _fftPoints[0] = 0; + memcpy(_fftPoints, fftPoints, numFFTDataPoints*sizeof(float)); _realDataTimeDomainPoints = new double[_numTimeDomainDataPoints]; memset(_realDataTimeDomainPoints, 0x0, _numTimeDomainDataPoints*sizeof(double)); @@ -60,7 +60,7 @@ SpectrumUpdateEvent::~SpectrumUpdateEvent() delete[] _imagDataTimeDomainPoints; } -const std::complex<float>* +const float* SpectrumUpdateEvent::getFFTPoints() const { return _fftPoints; @@ -121,7 +121,7 @@ SpectrumUpdateEvent::getDroppedFFTFrames() const } SpectrumWindowCaptionEvent::SpectrumWindowCaptionEvent(const QString& newLbl) - : QEvent(QEvent::Type(10008)) + : QEvent(QEvent::Type(SpectrumWindowCaptionEventType)) { _labelString = newLbl; } @@ -137,7 +137,7 @@ SpectrumWindowCaptionEvent::getLabel() } SpectrumWindowResetEvent::SpectrumWindowResetEvent() - : QEvent(QEvent::Type(10009)) + : QEvent(QEvent::Type(SpectrumWindowResetEventType)) { } @@ -148,7 +148,7 @@ SpectrumWindowResetEvent::~SpectrumWindowResetEvent() SpectrumFrequencyRangeEvent::SpectrumFrequencyRangeEvent(const double centerFreq, const double startFreq, const double stopFreq) - : QEvent(QEvent::Type(10010)) + : QEvent(QEvent::Type(SpectrumFrequencyRangeEventType)) { _centerFrequency = centerFreq; _startFrequency = startFreq; @@ -179,10 +179,11 @@ SpectrumFrequencyRangeEvent::GetStopFrequency() const /***************************************************************************/ -#include <iostream> + + TimeUpdateEvent::TimeUpdateEvent(const std::vector<double*> timeDomainPoints, const uint64_t numTimeDomainDataPoints) - : QEvent(QEvent::Type(10005)) + : QEvent(QEvent::Type(SpectrumUpdateEventType)) { if(numTimeDomainDataPoints < 1) { _numTimeDomainDataPoints = 1; @@ -220,4 +221,156 @@ TimeUpdateEvent::getNumTimeDomainDataPoints() const return _numTimeDomainDataPoints; } + +/***************************************************************************/ + + +FreqUpdateEvent::FreqUpdateEvent(const std::vector<double*> dataPoints, + const uint64_t numDataPoints) + : QEvent(QEvent::Type(SpectrumUpdateEventType)) +{ + if(numDataPoints < 1) { + _numDataPoints = 1; + } + else { + _numDataPoints = numDataPoints; + } + + _nplots = dataPoints.size(); + for(size_t i = 0; i < _nplots; i++) { + _dataPoints.push_back(new double[_numDataPoints]); + if(numDataPoints > 0) { + memcpy(_dataPoints[i], dataPoints[i], + _numDataPoints*sizeof(double)); + } + } +} + +FreqUpdateEvent::~FreqUpdateEvent() +{ + for(size_t i = 0; i < _nplots; i++) { + delete[] _dataPoints[i]; + } +} + +const std::vector<double*> +FreqUpdateEvent::getPoints() const +{ + return _dataPoints; +} + +uint64_t +FreqUpdateEvent::getNumDataPoints() const +{ + return _numDataPoints; +} + + +/***************************************************************************/ + + +ConstUpdateEvent::ConstUpdateEvent(const std::vector<double*> realDataPoints, + const std::vector<double*> imagDataPoints, + const uint64_t numDataPoints) + : QEvent(QEvent::Type(SpectrumUpdateEventType)) +{ + if(numDataPoints < 1) { + _numDataPoints = 1; + } + else { + _numDataPoints = numDataPoints; + } + + _nplots = realDataPoints.size(); + for(size_t i = 0; i < _nplots; i++) { + _realDataPoints.push_back(new double[_numDataPoints]); + _imagDataPoints.push_back(new double[_numDataPoints]); + if(numDataPoints > 0) { + memcpy(_realDataPoints[i], realDataPoints[i], + _numDataPoints*sizeof(double)); + memcpy(_imagDataPoints[i], imagDataPoints[i], + _numDataPoints*sizeof(double)); + } + } +} + +ConstUpdateEvent::~ConstUpdateEvent() +{ + for(size_t i = 0; i < _nplots; i++) { + delete[] _realDataPoints[i]; + delete[] _imagDataPoints[i]; + } +} + +const std::vector<double*> +ConstUpdateEvent::getRealPoints() const +{ + return _realDataPoints; +} + +const std::vector<double*> +ConstUpdateEvent::getImagPoints() const +{ + return _imagDataPoints; +} + +uint64_t +ConstUpdateEvent::getNumDataPoints() const +{ + return _numDataPoints; +} + + +/***************************************************************************/ + + +WaterfallUpdateEvent::WaterfallUpdateEvent(const std::vector<double*> dataPoints, + const uint64_t numDataPoints, + const gruel::high_res_timer_type dataTimestamp) + : QEvent(QEvent::Type(SpectrumUpdateEventType)) +{ + if(numDataPoints < 1) { + _numDataPoints = 1; + } + else { + _numDataPoints = numDataPoints; + } + + _nplots = dataPoints.size(); + for(size_t i = 0; i < _nplots; i++) { + _dataPoints.push_back(new double[_numDataPoints]); + if(numDataPoints > 0) { + memcpy(_dataPoints[i], dataPoints[i], + _numDataPoints*sizeof(double)); + } + } + + _dataTimestamp = dataTimestamp; +} + +WaterfallUpdateEvent::~WaterfallUpdateEvent() +{ + for(size_t i = 0; i < _nplots; i++) { + delete[] _dataPoints[i]; + } +} + +const std::vector<double*> +WaterfallUpdateEvent::getPoints() const +{ + return _dataPoints; +} + +uint64_t +WaterfallUpdateEvent::getNumDataPoints() const +{ + return _numDataPoints; +} + +gruel::high_res_timer_type +WaterfallUpdateEvent::getDataTimestamp() const +{ + return _dataTimestamp; +} + #endif /* SPECTRUM_UPDATE_EVENTS_C */ diff --git a/gr-qtgui/lib/spectrumUpdateEvents.h b/gr-qtgui/lib/spectrumUpdateEvents.h index faef0f0875..e663980bc6 100644 --- a/gr-qtgui/lib/spectrumUpdateEvents.h +++ b/gr-qtgui/lib/spectrumUpdateEvents.h @@ -8,10 +8,15 @@ #include <vector> #include <gruel/high_res_timer.h> +static const int SpectrumUpdateEventType = 10005; +static const int SpectrumWindowCaptionEventType = 10008; +static const int SpectrumWindowResetEventType = 10009; +static const int SpectrumFrequencyRangeEventType = 10010; + class SpectrumUpdateEvent:public QEvent{ public: - SpectrumUpdateEvent(const std::complex<float>* fftPoints, + SpectrumUpdateEvent(const float* fftPoints, const uint64_t numFFTDataPoints, const double* realTimeDomainPoints, const double* imagTimeDomainPoints, @@ -24,7 +29,7 @@ public: ~SpectrumUpdateEvent(); - const std::complex<float>* getFFTPoints() const; + const float* getFFTPoints() const; const double* getRealTimeDomainPoints() const; const double* getImagTimeDomainPoints() const; uint64_t getNumFFTDataPoints() const; @@ -38,7 +43,7 @@ public: protected: private: - std::complex<float>* _fftPoints; + float* _fftPoints; double* _realDataTimeDomainPoints; double* _imagDataTimeDomainPoints; uint64_t _numFFTDataPoints; @@ -103,6 +108,9 @@ public: uint64_t getNumTimeDomainDataPoints() const; bool getRepeatDataFlag() const; + static QEvent::Type Type() + { return QEvent::Type(SpectrumUpdateEventType); } + protected: private: @@ -112,4 +120,96 @@ private: }; +/********************************************************************/ + + +class FreqUpdateEvent: public QEvent +{ +public: + FreqUpdateEvent(const std::vector<double*> dataPoints, + const uint64_t numDataPoints); + + ~FreqUpdateEvent(); + + int which() const; + const std::vector<double*> getPoints() const; + uint64_t getNumDataPoints() const; + bool getRepeatDataFlag() const; + + static QEvent::Type Type() + { return QEvent::Type(SpectrumUpdateEventType); } + +protected: + +private: + size_t _nplots; + std::vector<double*> _dataPoints; + uint64_t _numDataPoints; +}; + + +/********************************************************************/ + + +class ConstUpdateEvent: public QEvent +{ +public: + ConstUpdateEvent(const std::vector<double*> realDataPoints, + const std::vector<double*> imagDataPoints, + const uint64_t numDataPoints); + + ~ConstUpdateEvent(); + + int which() const; + const std::vector<double*> getRealPoints() const; + const std::vector<double*> getImagPoints() const; + uint64_t getNumDataPoints() const; + bool getRepeatDataFlag() const; + + static QEvent::Type Type() + { return QEvent::Type(SpectrumUpdateEventType); } + +protected: + +private: + size_t _nplots; + std::vector<double*> _realDataPoints; + std::vector<double*> _imagDataPoints; + uint64_t _numDataPoints; +}; + + +/********************************************************************/ + + +class WaterfallUpdateEvent: public QEvent +{ +public: + WaterfallUpdateEvent(const std::vector<double*> dataPoints, + const uint64_t numDataPoints, + const gruel::high_res_timer_type dataTimestamp); + + ~WaterfallUpdateEvent(); + + int which() const; + const std::vector<double*> getPoints() const; + uint64_t getNumDataPoints() const; + bool getRepeatDataFlag() const; + + gruel::high_res_timer_type getDataTimestamp() const; + + static QEvent::Type Type() + { return QEvent::Type(SpectrumUpdateEventType); } + +protected: + +private: + size_t _nplots; + std::vector<double*> _dataPoints; + uint64_t _numDataPoints; + + gruel::high_res_timer_type _dataTimestamp; +}; + + #endif /* SPECTRUM_UPDATE_EVENTS_H */ diff --git a/gr-qtgui/lib/spectrumdisplayform.cc b/gr-qtgui/lib/spectrumdisplayform.cc index dd9011dbdd..6de6caa1b1 100644 --- a/gr-qtgui/lib/spectrumdisplayform.cc +++ b/gr-qtgui/lib/spectrumdisplayform.cc @@ -24,6 +24,7 @@ #include <QColorDialog> #include <QMessageBox> #include <spectrumdisplayform.h> +#include "qtgui_types.h" SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) : QWidget(parent) @@ -33,10 +34,10 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) _systemSpecifiedFlag = false; _intValidator = new QIntValidator(this); _intValidator->setBottom(0); - _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame); - _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame); + _frequencyDisplayPlot = new FrequencyDisplayPlot(1, FrequencyPlotDisplayFrame); + _waterfallDisplayPlot = new WaterfallDisplayPlot(1, WaterfallPlotDisplayFrame); _timeDomainDisplayPlot = new TimeDomainDisplayPlot(2, TimeDomainDisplayFrame); - _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame); + _constellationDisplayPlot = new ConstellationDisplayPlot(1, ConstellationDisplayFrame); _numRealDataPoints = 1024; _realFFTDataPoints = new double[_numRealDataPoints]; _averagedValues = new double[_numRealDataPoints]; @@ -48,13 +49,11 @@ SpectrumDisplayForm::SpectrumDisplayForm(QWidget* parent) AvgLineEdit->setRange(0, 500); // Set range of Average box value from 0 to 500 MinHoldCheckBox_toggled( false ); MaxHoldCheckBox_toggled( false ); - - WaterfallMaximumIntensityWheel->setRange(-200, 0); - WaterfallMaximumIntensityWheel->setTickCnt(50); - WaterfallMinimumIntensityWheel->setRange(-200, 0); - WaterfallMinimumIntensityWheel->setTickCnt(50); - WaterfallMinimumIntensityWheel->setValue(-200); - + + WaterfallMaximumIntensitySlider->setRange(-200, 0); + WaterfallMinimumIntensitySlider->setRange(-200, 0); + WaterfallMinimumIntensitySlider->setValue(-200); + _peakFrequency = 0; _peakAmplitude = -HUGE_VAL; @@ -137,11 +136,57 @@ SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, } } +/*********************************************************************** + * This is kind of gross because we're combining three operations: + * Conversion from float to double (which is what the plotter wants) + * Finding the peak and mean + * Doing the "FFT shift" to put 0Hz at the center of the plot + * I feel like this might want to be part of the sink block + **********************************************************************/ +static void fftshift_and_sum(double *outFFT, const float *inFFT, uint64_t num_points, double &sum_mean, double &peak_ampl, int &peak_bin) { + const float* inptr = inFFT+num_points/2; + double* outptr = outFFT; + + sum_mean = 0; + peak_ampl = -HUGE_VAL; + peak_bin = 0; + + // Run this twice to perform the fftshift operation on the data here as well + for(uint64_t point = 0; point < num_points/2; point++){ + float pt = (*inptr); + *outptr = pt; + if(*outptr > peak_ampl) { + peak_bin = point; + peak_ampl = *outptr; + } + sum_mean += *outptr; + + inptr++; + outptr++; + } + + // This loop takes the first half of the input data and puts it in the + // second half of the plotted data + inptr = inFFT; + for(uint64_t point = 0; point < num_points/2; point++){ + float pt = (*inptr); + *outptr = pt; + if(*outptr > peak_ampl) { + peak_bin = point; + peak_ampl = *outptr; + } + sum_mean += *outptr; + + inptr++; + outptr++; + } +} + void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent) { //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent); - const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints(); + const float* fftMagDataPoints = spectrumUpdateEvent->getFFTPoints(); const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints(); const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints(); const gruel::high_res_timer_type dataTimestamp = spectrumUpdateEvent->getDataTimestamp(); @@ -158,68 +203,34 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true... ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints); - // Calculate the Magnitude of the complex point - const std::complex<float>* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2; - double* realFFTDataPointsPtr = _realFFTDataPoints; - - double sumMean = 0.0; - double localPeakAmplitude = -HUGE_VAL; - double localPeakFrequency = 0.0; const double fftBinSize = (_stopFrequency-_startFrequency) / static_cast<double>(numFFTDataPoints); - // Run this twice to perform the fftshift operation on the data here as well - std::complex<float> scaleFactor = std::complex<float>((float)numFFTDataPoints); - for(uint64_t point = 0; point < numFFTDataPoints/2; point++){ - std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor; - *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20); - - if(*realFFTDataPointsPtr > localPeakAmplitude) { - localPeakFrequency = static_cast<float>(point) * fftBinSize; - localPeakAmplitude = *realFFTDataPointsPtr; - } - sumMean += *realFFTDataPointsPtr; - - complexDataPointsPtr++; - realFFTDataPointsPtr++; - } - - // This loop takes the first half of the input data and puts it in the - // second half of the plotted data - complexDataPointsPtr = complexDataPoints; - for(uint64_t point = 0; point < numFFTDataPoints/2; point++){ - std::complex<float> pt = (*complexDataPointsPtr) / scaleFactor; - *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20); - - if(*realFFTDataPointsPtr > localPeakAmplitude) { - localPeakFrequency = static_cast<float>(point) * fftBinSize; - localPeakAmplitude = *realFFTDataPointsPtr; - } - sumMean += *realFFTDataPointsPtr; - - complexDataPointsPtr++; - realFFTDataPointsPtr++; - } + //this does the fftshift, conversion to double, and calculation of sum, peak amplitude, peak freq. + double sum_mean, peak_ampl; + int peak_bin; + fftshift_and_sum(_realFFTDataPoints, fftMagDataPoints, numFFTDataPoints, sum_mean, peak_ampl, peak_bin); + double peak_freq = peak_bin * fftBinSize; // Don't update the averaging history if this is repeated data if(!repeatDataFlag){ _AverageHistory(_realFFTDataPoints); // Only use the local info if we are not repeating data - _peakAmplitude = localPeakAmplitude; - _peakFrequency = localPeakFrequency; + _peakAmplitude = peak_ampl; + _peakFrequency = peak_freq; // calculate the spectral mean // +20 because for the comparison below we only want to throw out bins // that are significantly higher (and would, thus, affect the mean more) - const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0; + const double meanAmplitude = (sum_mean / numFFTDataPoints) + 20.0; // now throw out any bins higher than the mean - sumMean = 0.0; + sum_mean = 0.0; uint64_t newNumDataPoints = numFFTDataPoints; for(uint64_t number = 0; number < numFFTDataPoints; number++){ if (_realFFTDataPoints[number] <= meanAmplitude) - sumMean += _realFFTDataPoints[number]; + sum_mean += _realFFTDataPoints[number]; else newNumDataPoints--; } @@ -227,7 +238,7 @@ SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdate if (newNumDataPoints == 0) // in the odd case that all _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal! else - _noiseFloorAmplitude = sumMean / newNumDataPoints; + _noiseFloorAmplitude = sum_mean / newNumDataPoints; } if(lastOfMultipleUpdatesFlag){ @@ -296,26 +307,26 @@ SpectrumDisplayForm::customEvent( QEvent * e) FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex()); } - waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value()); - waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value()); + waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensitySlider->value()); + waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensitySlider->value()); // Clear any previous display Reset(); } - else if(e->type() == 10005){ + else if(e->type() == SpectrumUpdateEventType){ SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e; newFrequencyData(spectrumUpdateEvent); } - else if(e->type() == 10008){ + else if(e->type() == SpectrumWindowCaptionEventType){ setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel()); } - else if(e->type() == 10009){ + else if(e->type() == SpectrumWindowResetEventType){ Reset(); if(_systemSpecifiedFlag){ _system->ResetPendingGUIUpdateEvents(); } } - else if(e->type() == 10010){ + else if(e->type() == SpectrumFrequencyRangeEventType){ _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency(); _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency(); _centerFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency(); @@ -535,7 +546,7 @@ SpectrumDisplayForm::closeEvent( QCloseEvent *e ) qApp->processEvents(); - QWidget::closeEvent(e); + QWidget::closeEvent(e); //equivalent to e->accept() } @@ -558,30 +569,30 @@ SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag ) void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue ) { - if(newValue > WaterfallMinimumIntensityWheel->value()){ + if(newValue > WaterfallMinimumIntensitySlider->value()){ WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0)); } else{ - WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value()); + WaterfallMinimumIntensitySlider->setValue(newValue - 2); } - _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), - WaterfallMaximumIntensityWheel->value()); + _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensitySlider->value(), + WaterfallMaximumIntensitySlider->value()); } void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue ) { - if(newValue < WaterfallMaximumIntensityWheel->value()){ + if(newValue < WaterfallMaximumIntensitySlider->value()){ WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0)); } else{ - WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value()); + WaterfallMaximumIntensitySlider->setValue(newValue + 2); } - _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), - WaterfallMaximumIntensityWheel->value()); + _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensitySlider->value(), + WaterfallMaximumIntensitySlider->value()); } void @@ -597,15 +608,15 @@ void SpectrumDisplayForm::WaterfallAutoScaleBtnCB() { double minimumIntensity = _noiseFloorAmplitude - 5; - if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){ - minimumIntensity = WaterfallMinimumIntensityWheel->minValue(); + if(minimumIntensity < WaterfallMinimumIntensitySlider->minValue()){ + minimumIntensity = WaterfallMinimumIntensitySlider->minValue(); } - WaterfallMinimumIntensityWheel->setValue(minimumIntensity); + WaterfallMinimumIntensitySlider->setValue(minimumIntensity); double maximumIntensity = _peakAmplitude + 10; - if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){ - maximumIntensity = WaterfallMaximumIntensityWheel->maxValue(); + if(maximumIntensity > WaterfallMaximumIntensitySlider->maxValue()){ + maximumIntensity = WaterfallMaximumIntensitySlider->maxValue(); } - WaterfallMaximumIntensityWheel->setValue(maximumIntensity); + WaterfallMaximumIntensitySlider->setValue(maximumIntensity); waterfallMaximumIntensityChangedCB(maximumIntensity); } @@ -614,7 +625,7 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType ) { QColor lowIntensityColor; QColor highIntensityColor; - if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){ + if(newType == INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){ // Select the Low Intensity Color lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor(); if(!lowIntensityColor.isValid()){ @@ -632,7 +643,7 @@ SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType ) highIntensityColor = QColorDialog::getColor(highIntensityColor, this); } - _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor); + _waterfallDisplayPlot->SetIntensityColorMapType(0, newType, lowIntensityColor, highIntensityColor); } void diff --git a/gr-qtgui/lib/spectrumdisplayform.ui b/gr-qtgui/lib/spectrumdisplayform.ui index 049d4ffeb4..9b06f44f0d 100644 --- a/gr-qtgui/lib/spectrumdisplayform.ui +++ b/gr-qtgui/lib/spectrumdisplayform.ui @@ -177,13 +177,13 @@ <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> - <verstretch>0</verstretch> + <verstretch>1</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>617</width> - <height>400</height> + <width>320</width> + <height>200</height> </size> </property> <property name="sizeIncrement"> @@ -283,7 +283,7 @@ </property> <property name="sizeHint" stdset="0"> <size> - <width>200</width> + <width>100</width> <height>20</height> </size> </property> @@ -304,7 +304,7 @@ <widget class="QLabel" name="textLabel1"> <property name="maximumSize"> <size> - <width>100</width> + <width>130</width> <height>16777215</height> </size> </property> @@ -317,10 +317,10 @@ </widget> </item> <item row="0" column="2"> - <widget class="QwtWheel" name="WaterfallMaximumIntensityWheel"> + <widget class="QwtSlider" name="WaterfallMaximumIntensitySlider"> <property name="minimumSize"> <size> - <width>200</width> + <width>50</width> <height>0</height> </size> </property> @@ -328,20 +328,11 @@ <bool>true</bool> </property> <property name="focusPolicy"> - <enum>Qt::WheelFocus</enum> + <enum>Qt::ClickFocus</enum> </property> <property name="valid"> <bool>true</bool> </property> - <property name="totalAngle"> - <double>200.000000000000000</double> - </property> - <property name="viewAngle"> - <double>20.000000000000000</double> - </property> - <property name="mass"> - <double>0.000000000000000</double> - </property> </widget> </item> <item row="0" column="3"> @@ -364,8 +355,8 @@ <widget class="QFrame" name="WaterfallPlotDisplayFrame"> <property name="minimumSize"> <size> - <width>617</width> - <height>338</height> + <width>320</width> + <height>200</height> </size> </property> <property name="frameShape"> @@ -377,24 +368,21 @@ </widget> </item> <item row="2" column="2"> - <widget class="QwtWheel" name="WaterfallMinimumIntensityWheel"> + <widget class="QwtSlider" name="WaterfallMinimumIntensitySlider"> <property name="minimumSize"> <size> - <width>200</width> + <width>50</width> <height>0</height> </size> </property> <property name="valid"> <bool>true</bool> </property> - <property name="totalAngle"> - <double>200.000000000000000</double> - </property> - <property name="viewAngle"> - <double>20.000000000000000</double> + <property name="mouseTracking"> + <bool>true</bool> </property> - <property name="mass"> - <double>0.000000000000000</double> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> </property> </widget> </item> @@ -476,8 +464,8 @@ <widget class="QFrame" name="TimeDomainDisplayFrame"> <property name="minimumSize"> <size> - <width>617</width> - <height>404</height> + <width>320</width> + <height>200</height> </size> </property> <property name="frameShape"> @@ -499,8 +487,8 @@ <widget class="QFrame" name="ConstellationDisplayFrame"> <property name="minimumSize"> <size> - <width>617</width> - <height>406</height> + <width>320</width> + <height>200</height> </size> </property> <property name="frameShape"> @@ -520,18 +508,18 @@ <layoutdefault spacing="6" margin="11"/> <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> <customwidgets> - <customwidget> - <class>QwtWheel</class> + <customwidget> + <class>QwtSlider</class> <extends>QWidget</extends> - <header>qwt_wheel.h</header> - </customwidget> + <header>qwt_slider.h</header> + </customwidget> </customwidgets> <tabstops> <tabstop>SpectrumTypeTab</tabstop> <tabstop>UseRFFrequenciesCheckBox</tabstop> <tabstop>FFTSizeComboBox</tabstop> - <tabstop>WaterfallMaximumIntensityWheel</tabstop> - <tabstop>WaterfallMinimumIntensityWheel</tabstop> + <tabstop>WaterfallMaximumIntensitySlider</tabstop> + <tabstop>WaterfallMinimumIntensitySlider</tabstop> </tabstops> <includes> <include location="global">SpectrumGUIClass.h</include> @@ -540,7 +528,7 @@ <include location="global">TimeDomainDisplayPlot.h</include> <include location="global">qvalidator.h</include> <include location="global">vector</include> - <include location="local">qwt_wheel.h</include> + <include location="local">qwt_slider.h</include> </includes> <resources/> <connections> @@ -641,7 +629,7 @@ </hints> </connection> <connection> - <sender>WaterfallMaximumIntensityWheel</sender> + <sender>WaterfallMaximumIntensitySlider</sender> <signal>valueChanged(double)</signal> <receiver>SpectrumDisplayForm</receiver> <slot>waterfallMaximumIntensityChangedCB(double)</slot> @@ -657,7 +645,7 @@ </hints> </connection> <connection> - <sender>WaterfallMinimumIntensityWheel</sender> + <sender>WaterfallMinimumIntensitySlider</sender> <signal>valueChanged(double)</signal> <receiver>SpectrumDisplayForm</receiver> <slot>waterfallMinimumIntensityChangedCB(double)</slot> diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc new file mode 100644 index 0000000000..83ab76eb6e --- /dev/null +++ b/gr-qtgui/lib/time_sink_c_impl.cc @@ -0,0 +1,256 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "time_sink_c_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> +#include <fft/fft.h> + +namespace gr { + namespace qtgui { + + time_sink_c::sptr + time_sink_c::make(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new time_sink_c_impl(size, bw, name, nconnections, parent)); + } + + time_sink_c_impl::time_sink_c_impl(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_sync_block("time_sink_c", + gr_make_io_signature(nconnections, nconnections, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_size(size), d_bandwidth(bw), d_name(name), + d_nconnections(2*nconnections), d_parent(parent) + { + d_main_gui = NULL; + + d_index = 0; + + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_double(d_size)); + memset(d_residbufs[i], 0, d_size*sizeof(double)); + } + + // Set alignment properties for VOLK + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); + + initialize(); + } + + time_sink_c_impl::~time_sink_c_impl() + { + // d_main_gui is a qwidget destroyed with its parent + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + } + } + + void + time_sink_c_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); + d_main_gui->SetNPoints(d_size); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + time_sink_c_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + time_sink_c_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + time_sink_c_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + time_sink_c_impl::set_time_domain_axis(double min, double max) + { + d_main_gui->setTimeDomainAxis(min, max); + } + + void + time_sink_c_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + time_sink_c_impl::set_title(int which, const std::string &title) + { + d_main_gui->setTitle(which, title.c_str()); + } + + void + time_sink_c_impl::set_color(int which, const std::string &color) + { + d_main_gui->setColor(which, color.c_str()); + } + + void + time_sink_c_impl::set_line_width(int which, int width) + { + d_main_gui->setLineWidth(which, width); + } + + void + time_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + { + d_main_gui->setLineStyle(which, style); + } + + void + time_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(which, marker); + } + + void + time_sink_c_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + time_sink_c_impl::set_nsamps(const int newsize) + { + gruel::scoped_lock lock(d_mutex); + + if(newsize != d_size) { + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + d_residbufs[i] = fft::malloc_double(newsize); + + memset(d_residbufs[i], 0, newsize*sizeof(double)); + } + + // Set new size and reset buffer index + // (throws away any currently held data, but who cares?) + d_size = newsize; + d_index = 0; + + d_main_gui->SetNPoints(d_size); + } + } + + void + time_sink_c_impl::npoints_resize() + { + int newsize = d_main_gui->GetNPoints(); + set_nsamps(newsize); + } + + int + time_sink_c_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int n=0, j=0, idx=0; + const gr_complex *in = (const gr_complex*)input_items[idx]; + + npoints_resize(); + + for(int i=0; i < noutput_items; i+=d_size) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_size-d_index; + idx = 0; + + // If we have enough input for one full plot, do it + if(datasize >= resid) { + + // Fill up residbufs with d_size number of items + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx++]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], + &d_residbufs[n+1][d_index], + &in[j], resid); + } + + // Update the plot if its time + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new TimeUpdateEvent(d_residbufs, d_size)); + } + + d_index = 0; + j += resid; + } + + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx++]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], + &d_residbufs[n+1][d_index], + &in[j], datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h new file mode 100644 index 0000000000..0cace14890 --- /dev/null +++ b/gr-qtgui/lib/time_sink_c_impl.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_C_IMPL_H +#define INCLUDED_QTGUI_TIME_SINK_C_IMPL_H + +#include <qtgui/time_sink_c.h> +#include <timedisplayform.h> +#include <gruel/thread.h> +#include <gruel/high_res_timer.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API time_sink_c_impl : public time_sink_c + { + private: + void initialize(); + + gruel::mutex d_mutex; + + int d_size; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + int d_index; + std::vector<double*> d_residbufs; + + QWidget *d_parent; + TimeDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void npoints_resize(); + + public: + time_sink_c_impl(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + ~time_sink_c_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_time_domain_axis(double min, double max); + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + void set_line_width(int which, int width); + void set_line_style(int which, Qt::PenStyle style); + void set_line_marker(int which, QwtSymbol::Style marker); + void set_nsamps(const int size); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_TIME_SINK_C_IMPL_H */ diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc new file mode 100644 index 0000000000..4b965b648c --- /dev/null +++ b/gr-qtgui/lib/time_sink_f_impl.cc @@ -0,0 +1,254 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "time_sink_f_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> +#include <fft/fft.h> + +namespace gr { + namespace qtgui { + + time_sink_f::sptr + time_sink_f::make(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new time_sink_f_impl(size, bw, name, nconnections, parent)); + } + + time_sink_f_impl::time_sink_f_impl(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent) + : gr_sync_block("time_sink_f", + gr_make_io_signature(nconnections, nconnections, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_size(size), d_bandwidth(bw), d_name(name), + d_nconnections(nconnections), d_parent(parent) + { + d_main_gui = NULL; + + d_index = 0; + + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_double(d_size)); + memset(d_residbufs[i], 0, d_size*sizeof(double)); + } + + // Set alignment properties for VOLK + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); + + initialize(); + } + + time_sink_f_impl::~time_sink_f_impl() + { + // d_main_gui is a qwidget destroyed with its parent + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + } + } + + void + time_sink_f_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new TimeDisplayForm(d_nconnections, d_parent); + d_main_gui->SetNPoints(d_size); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + time_sink_f_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + time_sink_f_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + time_sink_f_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + time_sink_f_impl::set_time_domain_axis(double min, double max) + { + d_main_gui->setTimeDomainAxis(min, max); + } + + void + time_sink_f_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + time_sink_f_impl::set_title(int which, const std::string &title) + { + d_main_gui->setTitle(which, title.c_str()); + } + + void + time_sink_f_impl::set_color(int which, const std::string &color) + { + d_main_gui->setColor(which, color.c_str()); + } + + void + time_sink_f_impl::set_line_width(int which, int width) + { + d_main_gui->setLineWidth(which, width); + } + + void + time_sink_f_impl::set_line_style(int which, Qt::PenStyle style) + { + d_main_gui->setLineStyle(which, style); + } + + void + time_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(which, marker); + } + + void + time_sink_f_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + time_sink_f_impl::set_nsamps(const int newsize) + { + gruel::scoped_lock lock(d_mutex); + + if(newsize != d_size) { + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + d_residbufs[i] = fft::malloc_double(newsize); + + memset(d_residbufs[i], 0, newsize*sizeof(double)); + } + + // Set new size and reset buffer index + // (throws away any currently held data, but who cares?) + d_size = newsize; + d_index = 0; + + d_main_gui->SetNPoints(d_size); + } + } + + void + time_sink_f_impl::npoints_resize() + { + int newsize = d_main_gui->GetNPoints(); + set_nsamps(newsize); + } + + int + time_sink_f_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int n=0, j=0, idx=0; + const float *in = (const float*)input_items[idx]; + + npoints_resize(); + + for(int i=0; i < noutput_items; i+=d_size) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_size-d_index; + idx = 0; + + // If we have enough input for one full plot, do it + if(datasize >= resid) { + + // Fill up residbufs with d_size number of items + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx++]; + volk_32f_convert_64f_u(&d_residbufs[n][d_index], + &in[j], resid); + } + + // Update the plot if its time + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new TimeUpdateEvent(d_residbufs, d_size)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbufs for next time + // because we set the output_multiple, this should never need to be called + else { + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx++]; + volk_32f_convert_64f_u(&d_residbufs[n][d_index], + &in[j], datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h new file mode 100644 index 0000000000..69c07fbdab --- /dev/null +++ b/gr-qtgui/lib/time_sink_f_impl.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TIME_SINK_F_IMPL_H +#define INCLUDED_QTGUI_TIME_SINK_F_IMPL_H + +#include <qtgui/time_sink_f.h> +#include <timedisplayform.h> +#include <gruel/thread.h> +#include <gruel/high_res_timer.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API time_sink_f_impl : public time_sink_f + { + private: + void initialize(); + + gruel::mutex d_mutex; + + int d_size; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + int d_index; + std::vector<double*> d_residbufs; + + QWidget *d_parent; + TimeDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void npoints_resize(); + + public: + time_sink_f_impl(int size, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); + ~time_sink_f_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_time_domain_axis(double min, double max); + void set_update_time(double t); + void set_title(int which, const std::string &title); + void set_color(int which, const std::string &color); + void set_line_width(int which, int width); + void set_line_style(int which, Qt::PenStyle style); + void set_line_marker(int which, QwtSymbol::Style marker); + void set_nsamps(const int newsize); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_TIME_SINK_F_IMPL_H */ diff --git a/gr-qtgui/lib/timedisplayform.cc b/gr-qtgui/lib/timedisplayform.cc index c650cd3eb0..3d94d20094 100644 --- a/gr-qtgui/lib/timedisplayform.cc +++ b/gr-qtgui/lib/timedisplayform.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -21,34 +21,30 @@ */ #include <cmath> -#include <QColorDialog> #include <QMessageBox> #include <timedisplayform.h> #include <iostream> TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) - : QWidget(parent) + : DisplayForm(nplots, parent) { - _systemSpecifiedFlag = false; _intValidator = new QIntValidator(this); _intValidator->setBottom(0); _layout = new QGridLayout(this); - _timeDomainDisplayPlot = new TimeDomainDisplayPlot(nplots, this); - _layout->addWidget(_timeDomainDisplayPlot, 0, 0); - - _numRealDataPoints = 1024; - + _displayPlot = new TimeDomainDisplayPlot(nplots, this); + _layout->addWidget(_displayPlot, 0, 0); setLayout(_layout); - Reset(); + NPointsMenu *nptsmenu = new NPointsMenu(this); + _menu->addAction(nptsmenu); + connect(nptsmenu, SIGNAL(whichTrigger(int)), + this, SLOT(SetNPoints(const int))); - // Create a timer to update plots at the specified rate - displayTimer = new QTimer(this); - connect(displayTimer, SIGNAL(timeout()), this, SLOT(updateGuiTimer())); + Reset(); - connect(_timeDomainDisplayPlot, SIGNAL(plotPointSelected(const QPointF)), - this, SLOT(onTimePlotPointSelected(const QPointF))); + connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onPlotPointSelected(const QPointF))); } TimeDisplayForm::~TimeDisplayForm() @@ -57,57 +53,32 @@ TimeDisplayForm::~TimeDisplayForm() // Don't worry about deleting Display Plots - they are deleted when parents are deleted delete _intValidator; - - displayTimer->stop(); - delete displayTimer; } -void -TimeDisplayForm::newData( const TimeUpdateEvent* spectrumUpdateEvent) +TimeDomainDisplayPlot* +TimeDisplayForm::getPlot() { - const std::vector<double*> timeDomainDataPoints = spectrumUpdateEvent->getTimeDomainPoints(); - const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints(); - - _timeDomainDisplayPlot->PlotNewData(timeDomainDataPoints, - numTimeDomainDataPoints, - d_update_time); + return ((TimeDomainDisplayPlot*)_displayPlot); } void -TimeDisplayForm::resizeEvent( QResizeEvent *e ) +TimeDisplayForm::newData(const QEvent* updateEvent) { - QSize s = size(); - emit _timeDomainDisplayPlot->resizeSlot(&s); -} + TimeUpdateEvent *tevent = (TimeUpdateEvent*)updateEvent; + const std::vector<double*> dataPoints = tevent->getTimeDomainPoints(); + const uint64_t numDataPoints = tevent->getNumTimeDomainDataPoints(); -void -TimeDisplayForm::customEvent( QEvent * e) -{ - if(e->type() == 10005) { - TimeUpdateEvent* timeUpdateEvent = (TimeUpdateEvent*)e; - newData(timeUpdateEvent); - } - //else if(e->type() == 10008){ - //setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel()); - //} - //else if(e->type() == 10009){ - //Reset(); - //if(_systemSpecifiedFlag){ - // _system->ResetPendingGUIUpdateEvents(); - //} - //} -} - -void -TimeDisplayForm::updateGuiTimer() -{ - _timeDomainDisplayPlot->canvas()->update(); + getPlot()->PlotNewData(dataPoints, + numDataPoints, + d_update_time); } void -TimeDisplayForm::onTimePlotPointSelected(const QPointF p) +TimeDisplayForm::customEvent(QEvent * e) { - emit plotPointSelected(p, 3); + if(e->type() == TimeUpdateEvent::Type()) { + newData(e); + } } void @@ -126,52 +97,26 @@ TimeDisplayForm::setFrequencyRange(const double newCenterFrequency, _startFrequency = newStartFrequency; _stopFrequency = newStopFrequency; - - _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency, - units, strtime[iunit]); + + getPlot()->SetSampleRate(_stopFrequency - _startFrequency, + units, strtime[iunit]); } } void -TimeDisplayForm::Reset() -{ -} - - -void -TimeDisplayForm::closeEvent( QCloseEvent *e ) -{ - //if(_systemSpecifiedFlag){ - // _system->SetWindowOpenFlag(false); - //} - - qApp->processEvents(); - - QWidget::closeEvent(e); -} - -void TimeDisplayForm::setTimeDomainAxis(double min, double max) { - _timeDomainDisplayPlot->setYaxis(min, max); -} - -void -TimeDisplayForm::setUpdateTime(double t) -{ - d_update_time = t; - // QTimer class takes millisecond input - displayTimer->start(d_update_time*1000); + getPlot()->setYaxis(min, max); } -void -TimeDisplayForm::setTitle(int which, QString title) +int +TimeDisplayForm::GetNPoints() const { - _timeDomainDisplayPlot->setTitle(which, title); + return d_npoints; } void -TimeDisplayForm::setColor(int which, QString color) +TimeDisplayForm::SetNPoints(const int npoints) { - _timeDomainDisplayPlot->setColor(which, color); + d_npoints = npoints; } diff --git a/gr-qtgui/lib/timedisplayform.h b/gr-qtgui/lib/timedisplayform.h index dd3f62a83f..806fc4053f 100644 --- a/gr-qtgui/lib/timedisplayform.h +++ b/gr-qtgui/lib/timedisplayform.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,17 +24,13 @@ #define TIME_DISPLAY_FORM_H #include <spectrumUpdateEvents.h> -#include <FrequencyDisplayPlot.h> -#include <WaterfallDisplayPlot.h> #include <TimeDomainDisplayPlot.h> -#include <ConstellationDisplayPlot.h> -#include <QtGui/QApplication> -#include <QtGui/QGridLayout> -#include <QValidator> -#include <QTimer> +#include <QtGui/QtGui> #include <vector> -class TimeDisplayForm : public QWidget +#include "displayform.h" + +class TimeDisplayForm : public DisplayForm { Q_OBJECT @@ -42,44 +38,29 @@ class TimeDisplayForm : public QWidget TimeDisplayForm(int nplots=1, QWidget* parent = 0); ~TimeDisplayForm(); - void Reset(); + TimeDomainDisplayPlot* getPlot(); + + int GetNPoints() const; public slots: - void resizeEvent( QResizeEvent * e ); - void customEvent( QEvent * e ); - void setFrequencyRange( const double newCenterFrequency, - const double newStartFrequency, - const double newStopFrequency ); - void closeEvent( QCloseEvent * e ); + void customEvent(QEvent * e); + void setFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency); void setTimeDomainAxis(double min, double max); - - void setUpdateTime(double t); - - void setTitle(int which, QString title); - void setColor(int which, QString color); + void SetNPoints(const int); private slots: - void newData( const TimeUpdateEvent* ); - void updateGuiTimer(); - - void onTimePlotPointSelected(const QPointF p); - -signals: - void plotPointSelected(const QPointF p, int type); + void newData(const QEvent*); private: - uint64_t _numRealDataPoints; QIntValidator* _intValidator; - QGridLayout *_layout; - TimeDomainDisplayPlot* _timeDomainDisplayPlot; - bool _systemSpecifiedFlag; double _startFrequency; double _stopFrequency; - QTimer *displayTimer; - double d_update_time; + int d_npoints; }; #endif /* TIME_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc new file mode 100644 index 0000000000..0611d37974 --- /dev/null +++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc @@ -0,0 +1,366 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "waterfall_sink_c_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + waterfall_sink_c::sptr + waterfall_sink_c::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new waterfall_sink_c_impl(fftsize, wintype, + fc, bw, name, + parent)); + } + + waterfall_sink_c_impl::waterfall_sink_c_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent) + : gr_sync_block("waterfall_sink_c", + gr_make_io_signature(1, -1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_fftsize(fftsize), d_fftavg(1.0), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_nconnections(1), d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex(d_fftsize, true); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + d_index = 0; + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_complex(d_fftsize)); + d_magbufs.push_back(fft::malloc_double(d_fftsize)); + memset(d_residbufs[i], 0, d_fftsize*sizeof(float)); + memset(d_magbufs[i], 0, d_fftsize*sizeof(double)); + } + + buildwindow(); + + initialize(); + } + + waterfall_sink_c_impl::~waterfall_sink_c_impl() + { + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + } + delete d_fft; + fft::free(d_fbuf); + } + + void + waterfall_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + waterfall_sink_c_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetFFTWindowType(d_wintype); + d_main_gui->SetFrequencyRange(d_center_freq, + d_center_freq - d_bandwidth/2.0, + d_center_freq + d_bandwidth/2.0); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + waterfall_sink_c_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + waterfall_sink_c_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + waterfall_sink_c_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + waterfall_sink_c_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + waterfall_sink_c_impl::fft_size() const + { + return d_fftsize; + } + + void + waterfall_sink_c_impl::set_fft_average(const float fftavg) + { + d_fftavg = fftavg; + d_main_gui->SetFFTAverage(fftavg); + } + + float + waterfall_sink_c_impl::fft_average() const + { + return d_fftavg; + } + + void + waterfall_sink_c_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + waterfall_sink_c_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + waterfall_sink_c_impl::set_title(const std::string &title) + { + d_main_gui->setTitle(0, title.c_str()); + } + + void + waterfall_sink_c_impl::set_color(const std::string &color) + { + d_main_gui->setColor(0, color.c_str()); + } + + void + waterfall_sink_c_impl::set_line_width(int width) + { + d_main_gui->setLineWidth(0, width); + } + + void + waterfall_sink_c_impl::set_line_style(Qt::PenStyle style) + { + d_main_gui->setLineStyle(0, style); + } + + void + waterfall_sink_c_impl::set_line_marker(QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(0, marker); + } + + void + waterfall_sink_c_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + waterfall_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size) + { + if(d_window.size()) { + volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), data_in, &d_window.front(), size); + } + else { + memcpy(d_fft->get_inbuf(), data_in, sizeof(gr_complex)*size); + } + + d_fft->execute(); // compute the fft + + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); + + // Perform shift operation + unsigned int len = (unsigned int)(floor(size/2.0)); + float *tmp = (float*)malloc(sizeof(float)*len); + memcpy(tmp, &data_out[0], sizeof(float)*len); + memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); + memcpy(&data_out[size - len], tmp, sizeof(float)*len); + free(tmp); + } + + void + waterfall_sink_c_impl::windowreset() + { + filter::firdes::win_type newwintype; + newwintype = d_main_gui->GetFFTWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + waterfall_sink_c_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != filter::firdes::WIN_NONE) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + waterfall_sink_c_impl::fftresize() + { + int newfftsize = d_main_gui->GetFFTSize(); + d_fftavg = d_main_gui->GetFFTAverage(); + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + + d_residbufs[i] = fft::malloc_complex(newfftsize); + d_magbufs[i] = fft::malloc_double(newfftsize); + + memset(d_residbufs[i], 0, newfftsize*sizeof(gr_complex)); + memset(d_magbufs[i], 0, newfftsize*sizeof(double)); + } + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex(d_fftsize, true); + + fft::free(d_fbuf); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + } + } + + int + waterfall_sink_c_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const gr_complex *in = (const gr_complex*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + + for(int n = 0; n < d_nconnections; n++) { + // Fill up residbuf with d_fftsize number of items + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid); + + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new WaterfallUpdateEvent(d_magbufs, + d_fftsize, + d_last_time)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbuf for next time + else { + for(int n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h new file mode 100644 index 0000000000..b51b1e66eb --- /dev/null +++ b/gr-qtgui/lib/waterfall_sink_c_impl.h @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H +#define INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H + +#include <qtgui/waterfall_sink_c.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <gruel/thread.h> +#include <waterfalldisplayform.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API waterfall_sink_c_impl : public waterfall_sink_c + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_fftsize; + float d_fftavg; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + std::vector<gr_complex*> d_residbufs; + std::vector<double*> d_magbufs; + float *d_fbuf; + + QWidget *d_parent; + WaterfallDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const gr_complex *data_in, int size); + + public: + waterfall_sink_c_impl(int size, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent=NULL); + ~waterfall_sink_c_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + void set_fft_average(const float fftavg); + float fft_average() const; + + void set_frequency_range(const double centerfreq, const double bandwidth); + + void set_update_time(double t); + void set_title(const std::string &title); + void set_color(const std::string &color); + void set_line_width(int width); + void set_line_style(Qt::PenStyle style); + void set_line_marker(QwtSymbol::Style marker); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_WATERFALL_SINK_C_IMPL_H */ diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc new file mode 100644 index 0000000000..3fdb2b795a --- /dev/null +++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc @@ -0,0 +1,368 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "waterfall_sink_f_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { + namespace qtgui { + + waterfall_sink_f::sptr + waterfall_sink_f::make(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent) + { + return gnuradio::get_initial_sptr + (new waterfall_sink_f_impl(fftsize, wintype, + fc, bw, name, + parent)); + } + + waterfall_sink_f_impl::waterfall_sink_f_impl(int fftsize, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent) + : gr_sync_block("waterfall_sink_f", + gr_make_io_signature(1, -1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_fftsize(fftsize), d_fftavg(1.0), + d_wintype((filter::firdes::win_type)(wintype)), + d_center_freq(fc), d_bandwidth(bw), d_name(name), + d_nconnections(1), d_parent(parent) + { + d_main_gui = NULL; + + // Perform fftshift operation; + // this is usually desired when plotting + d_shift = true; + + d_fft = new fft::fft_complex(d_fftsize, true); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + d_index = 0; + for(int i = 0; i < d_nconnections; i++) { + d_residbufs.push_back(fft::malloc_float(d_fftsize)); + d_magbufs.push_back(fft::malloc_double(d_fftsize)); + memset(d_residbufs[i], 0, d_fftsize*sizeof(float)); + memset(d_magbufs[i], 0, d_fftsize*sizeof(double)); + } + + buildwindow(); + + initialize(); + } + + waterfall_sink_f_impl::~waterfall_sink_f_impl() + { + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + } + delete d_fft; + fft::free(d_fbuf); + } + + void + waterfall_sink_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = std::min(d_fftsize, 8191); + } + } + + void + waterfall_sink_f_impl::initialize() + { + if(qApp != NULL) { + d_qApplication = qApp; + } + else { + int argc=0; + char **argv = NULL; + d_qApplication = new QApplication(argc, argv); + } + + d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent); + d_main_gui->SetFFTSize(d_fftsize); + d_main_gui->SetFFTWindowType(d_wintype); + d_main_gui->SetFrequencyRange(d_center_freq, + d_center_freq - d_bandwidth/2.0, + d_center_freq + d_bandwidth/2.0); + + // initialize update time to 10 times a second + set_update_time(0.1); + d_last_time = 0; + } + + void + waterfall_sink_f_impl::exec_() + { + d_qApplication->exec(); + } + + QWidget* + waterfall_sink_f_impl::qwidget() + { + return d_main_gui; + } + + PyObject* + waterfall_sink_f_impl::pyqwidget() + { + PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui); + PyObject *retarg = Py_BuildValue("N", w); + return retarg; + } + + void + waterfall_sink_f_impl::set_fft_size(const int fftsize) + { + d_fftsize = fftsize; + d_main_gui->SetFFTSize(fftsize); + } + + int + waterfall_sink_f_impl::fft_size() const + { + return d_fftsize; + } + + void + waterfall_sink_f_impl::set_fft_average(const float fftavg) + { + d_fftavg = fftavg; + d_main_gui->SetFFTAverage(fftavg); + } + + float + waterfall_sink_f_impl::fft_average() const + { + return d_fftavg; + } + + void + waterfall_sink_f_impl::set_frequency_range(const double centerfreq, + const double bandwidth) + { + d_center_freq = centerfreq; + d_bandwidth = bandwidth; + d_main_gui->SetFrequencyRange(d_center_freq, + -d_bandwidth/2.0, + d_bandwidth/2.0); + } + + void + waterfall_sink_f_impl::set_update_time(double t) + { + //convert update time to ticks + gruel::high_res_timer_type tps = gruel::high_res_timer_tps(); + d_update_time = t * tps; + d_main_gui->setUpdateTime(t); + } + + void + waterfall_sink_f_impl::set_title(const std::string &title) + { + d_main_gui->setTitle(0, title.c_str()); + } + + void + waterfall_sink_f_impl::set_color(const std::string &color) + { + d_main_gui->setColor(0, color.c_str()); + } + + void + waterfall_sink_f_impl::set_line_width(int width) + { + d_main_gui->setLineWidth(0, width); + } + + void + waterfall_sink_f_impl::set_line_style(Qt::PenStyle style) + { + d_main_gui->setLineStyle(0, style); + } + + void + waterfall_sink_f_impl::set_line_marker(QwtSymbol::Style marker) + { + d_main_gui->setLineMarker(0, marker); + } + + void + waterfall_sink_f_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + void + waterfall_sink_f_impl::fft(float *data_out, const float *data_in, int size) + { + // float to complex conversion + gr_complex *dst = d_fft->get_inbuf(); + for (int i = 0; i < size; i++) + dst[i] = data_in[i]; + + if(d_window.size()) { + volk_32fc_32f_multiply_32fc_a(d_fft->get_inbuf(), dst, + &d_window.front(), size); + } + + d_fft->execute(); // compute the fft + + volk_32fc_s32f_x2_power_spectral_density_32f_a(data_out, d_fft->get_outbuf(), + size, 1.0, size); + + // Perform shift operation + unsigned int len = (unsigned int)(floor(size/2.0)); + float *tmp = (float*)malloc(sizeof(float)*len); + memcpy(tmp, &data_out[0], sizeof(float)*len); + memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); + memcpy(&data_out[size - len], tmp, sizeof(float)*len); + free(tmp); + } + + void + waterfall_sink_f_impl::windowreset() + { + filter::firdes::win_type newwintype; + newwintype = d_main_gui->GetFFTWindowType(); + if(d_wintype != newwintype) { + d_wintype = newwintype; + buildwindow(); + } + } + + void + waterfall_sink_f_impl::buildwindow() + { + d_window.clear(); + if(d_wintype != filter::firdes::WIN_NONE) { + d_window = filter::firdes::window(d_wintype, d_fftsize, 6.76); + } + } + + void + waterfall_sink_f_impl::fftresize() + { + int newfftsize = d_fftsize; + + if(newfftsize != d_fftsize) { + + // Resize residbuf and replace data + for(int i = 0; i < d_nconnections; i++) { + fft::free(d_residbufs[i]); + fft::free(d_magbufs[i]); + + d_residbufs[i] = fft::malloc_float(newfftsize); + d_magbufs[i] = fft::malloc_double(newfftsize); + + memset(d_residbufs[i], 0, newfftsize*sizeof(float)); + memset(d_magbufs[i], 0, newfftsize*sizeof(double)); + } + + // Set new fft size and reset buffer index + // (throws away any currently held data, but who cares?) + d_fftsize = newfftsize; + d_index = 0; + + // Reset window to reflect new size + buildwindow(); + + // Reset FFTW plan for new size + delete d_fft; + d_fft = new fft::fft_complex(d_fftsize, true); + + fft::free(d_fbuf); + d_fbuf = fft::malloc_float(d_fftsize); + memset(d_fbuf, 0, d_fftsize*sizeof(float)); + } + } + + int + waterfall_sink_f_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int j=0; + const float *in = (const float*)input_items[0]; + + // Update the FFT size from the application + fftresize(); + windowreset(); + + for(int i=0; i < noutput_items; i+=d_fftsize) { + unsigned int datasize = noutput_items - i; + unsigned int resid = d_fftsize-d_index; + + // If we have enough input for one full FFT, do it + if(datasize >= resid) { + + for(int n = 0; n < d_nconnections; n++) { + // Fill up residbuf with d_fftsize number of items + in = (const float*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*resid); + + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + if(gruel::high_res_timer_now() - d_last_time > d_update_time) { + d_last_time = gruel::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new WaterfallUpdateEvent(d_magbufs, + d_fftsize, + d_last_time)); + } + + d_index = 0; + j += resid; + } + // Otherwise, copy what we received into the residbuf for next time + else { + for(int n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[n]; + memcpy(d_residbufs[n]+d_index, &in[j], sizeof(float)*datasize); + } + d_index += datasize; + j += datasize; + } + } + + return j; + } + + } /* namespace qtgui */ +} /* namespace gr */ diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h new file mode 100644 index 0000000000..684e1dfb03 --- /dev/null +++ b/gr-qtgui/lib/waterfall_sink_f_impl.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H +#define INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H + + +#include <qtgui/waterfall_sink_f.h> +#include <filter/firdes.h> +#include <fft/fft.h> +#include <gruel/high_res_timer.h> +#include <gruel/thread.h> +#include <waterfalldisplayform.h> + +namespace gr { + namespace qtgui { + + class QTGUI_API waterfall_sink_f_impl : public waterfall_sink_f + { + private: + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + void initialize(); + + int d_fftsize; + float d_fftavg; + filter::firdes::win_type d_wintype; + std::vector<float> d_window; + double d_center_freq; + double d_bandwidth; + std::string d_name; + int d_nconnections; + + bool d_shift; + fft::fft_complex *d_fft; + + int d_index; + std::vector<float*> d_residbufs; + std::vector<double*> d_magbufs; + float *d_fbuf; + + QWidget *d_parent; + WaterfallDisplayForm *d_main_gui; + + gruel::high_res_timer_type d_update_time; + gruel::high_res_timer_type d_last_time; + + void windowreset(); + void buildwindow(); + void fftresize(); + void fft(float *data_out, const float *data_in, int size); + + public: + waterfall_sink_f_impl(int size, int wintype, + double fc, double bw, + const std::string &name, + QWidget *parent=NULL); + ~waterfall_sink_f_impl(); + + void exec_(); + QWidget* qwidget(); + PyObject* pyqwidget(); + + void set_fft_size(const int fftsize); + int fft_size() const; + void set_fft_average(const float fftavg); + float fft_average() const; + + void set_frequency_range(const double centerfreq, const double bandwidth); + + void set_update_time(double t); + void set_title(const std::string &title); + void set_color(const std::string &color); + void set_line_width(int width); + void set_line_style(Qt::PenStyle style); + void set_line_marker(QwtSymbol::Style marker); + + void set_size(int width, int height); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_WATERFALL_SINK_F_IMPL_H */ diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc new file mode 100644 index 0000000000..1a69e97d10 --- /dev/null +++ b/gr-qtgui/lib/waterfalldisplayform.cc @@ -0,0 +1,205 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cmath> +#include <QColorDialog> +#include <QMessageBox> +#include <waterfalldisplayform.h> +#include <iostream> + +WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent) + : DisplayForm(nplots, parent) +{ + _intValidator = new QIntValidator(this); + _intValidator->setBottom(0); + + _layout = new QGridLayout(this); + _displayPlot = new WaterfallDisplayPlot(nplots, this); + _layout->addWidget(_displayPlot, 0, 0); + setLayout(_layout); + + _numRealDataPoints = 1024; + _fftsize = 1024; + _fftavg = 1.0; + + _min_val = 1000; + _max_val = -1000; + + QAction *autoscale_act = new QAction("Auto Scale", this); + autoscale_act->setStatusTip(tr("Autoscale intensity range")); + connect(autoscale_act, SIGNAL(triggered()), this, SLOT(AutoScale())); + + FFTSizeMenu *sizemenu = new FFTSizeMenu(this); + FFTAverageMenu *avgmenu = new FFTAverageMenu(this); + FFTWindowMenu *winmenu = new FFTWindowMenu(this); + ColorMapMenu *colormenu = new ColorMapMenu(this); + _menu->addMenu(sizemenu); + _menu->addMenu(avgmenu); + _menu->addMenu(winmenu); + _menu->addMenu(colormenu); + _menu->addAction(autoscale_act); + connect(sizemenu, SIGNAL(whichTrigger(int)), + this, SLOT(SetFFTSize(const int))); + connect(avgmenu, SIGNAL(whichTrigger(float)), + this, SLOT(SetFFTAverage(const float))); + connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), + this, SLOT(SetFFTWindowType(const gr::filter::firdes::win_type))); + connect(colormenu, SIGNAL(whichTrigger(const int, const QColor&, const QColor&)), + this, SLOT(SetColorMap(const int, const QColor&, const QColor&))); + + Reset(); + + connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), + this, SLOT(onPlotPointSelected(const QPointF))); +} + +WaterfallDisplayForm::~WaterfallDisplayForm() +{ + // Qt deletes children when parent is deleted + + // Don't worry about deleting Display Plots - they are deleted when parents are deleted + delete _intValidator; +} + +WaterfallDisplayPlot* +WaterfallDisplayForm::getPlot() +{ + return ((WaterfallDisplayPlot*)_displayPlot); +} + +void +WaterfallDisplayForm::newData(const QEvent *updateEvent) +{ + WaterfallUpdateEvent *event = (WaterfallUpdateEvent*)updateEvent; + const std::vector<double*> dataPoints = event->getPoints(); + const uint64_t numDataPoints = event->getNumDataPoints(); + const gruel::high_res_timer_type dataTimestamp = event->getDataTimestamp(); + + _min_val = 1000; + _max_val = -1000; + for(size_t i=0; i < dataPoints.size(); i++) { + double *min_val = std::min_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]); + double *max_val = std::max_element(&dataPoints[i][0], &dataPoints[i][numDataPoints-1]); + if(*min_val < _min_val) + _min_val = *min_val; + if(*max_val > _max_val) + _max_val = *max_val; + } + + getPlot()->PlotNewData(dataPoints, numDataPoints, + d_update_time, dataTimestamp, 0); +} + +void +WaterfallDisplayForm::customEvent( QEvent * e) +{ + if(e->type() == WaterfallUpdateEvent::Type()) { + newData(e); + } +} + +int +WaterfallDisplayForm::GetFFTSize() const +{ + return _fftsize; +} + +float +WaterfallDisplayForm::GetFFTAverage() const +{ + return _fftavg; +} + +gr::filter::firdes::win_type +WaterfallDisplayForm::GetFFTWindowType() const +{ + return _fftwintype; +} + +void +WaterfallDisplayForm::SetFFTSize(const int newsize) +{ + _fftsize = newsize; +} + +void +WaterfallDisplayForm::SetFFTAverage(const float newavg) +{ + _fftavg = newavg; +} + +void +WaterfallDisplayForm::SetFFTWindowType(const gr::filter::firdes::win_type newwin) +{ + _fftwintype = newwin; +} + +void +WaterfallDisplayForm::SetFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency) +{ + double fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency)); + + if(fdiff > 0) { + std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"}; + double units10 = floor(log10(fdiff)); + double units3 = std::max(floor(units10 / 3.0), 0.0); + double units = pow(10, (units10-fmod(units10, 3.0))); + int iunit = static_cast<int>(units3); + + _startFrequency = newStartFrequency; + _stopFrequency = newStopFrequency; + double centerFrequency = newCenterFrequency; + + getPlot()->SetFrequencyRange(_startFrequency, + _stopFrequency, + centerFrequency, + true, + units, strunits[iunit]); + } +} + +void +WaterfallDisplayForm::SetColorMap(const int newType, + const QColor lowColor, + const QColor highColor) +{ + getPlot()->SetIntensityColorMapType(0, newType, + lowColor, highColor); +} + +void +WaterfallDisplayForm::SetIntensityRange(const double minIntensity, + const double maxIntensity) +{ + getPlot()->SetIntensityRange(minIntensity, maxIntensity); +} + +void +WaterfallDisplayForm::AutoScale() +{ + double min_int = _min_val - 5; + double max_int = _max_val + 10; + + getPlot()->SetIntensityRange(min_int, max_int); +} diff --git a/gr-qtgui/lib/waterfalldisplayform.h b/gr-qtgui/lib/waterfalldisplayform.h new file mode 100644 index 0000000000..46e0d815e0 --- /dev/null +++ b/gr-qtgui/lib/waterfalldisplayform.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WATERFALL_DISPLAY_FORM_H +#define WATERFALL_DISPLAY_FORM_H + +#include <spectrumUpdateEvents.h> +#include <WaterfallDisplayPlot.h> +#include <QtGui/QtGui> +#include <vector> +#include <filter/firdes.h> + +#include "displayform.h" + +class WaterfallDisplayForm : public DisplayForm +{ + Q_OBJECT + + public: + WaterfallDisplayForm(int nplots=1, QWidget* parent = 0); + ~WaterfallDisplayForm(); + + WaterfallDisplayPlot* getPlot(); + + int GetFFTSize() const; + float GetFFTAverage() const; + gr::filter::firdes::win_type GetFFTWindowType() const; + +public slots: + void customEvent(QEvent *e); + + void SetFFTSize(const int); + void SetFFTAverage(const float); + void SetFFTWindowType(const gr::filter::firdes::win_type); + + void SetFrequencyRange(const double newCenterFrequency, + const double newStartFrequency, + const double newStopFrequency); + + void SetIntensityRange(const double minIntensity, + const double maxIntensity); + + void SetColorMap(const int newType, + const QColor lowColor, + const QColor highColor); + + void AutoScale(); + +private slots: + void newData(const QEvent *updateEvent); + +private: + uint64_t _numRealDataPoints; + QIntValidator* _intValidator; + + double _startFrequency; + double _stopFrequency; + + int _fftsize; + float _fftavg; + gr::filter::firdes::win_type _fftwintype; + + double _min_val; + double _max_val; +}; + +#endif /* WATERFALL_DISPLAY_FORM_H */ diff --git a/gr-qtgui/python/__init__.py b/gr-qtgui/python/__init__.py index c7024e4f72..82e36597be 100644 --- a/gr-qtgui/python/__init__.py +++ b/gr-qtgui/python/__init__.py @@ -27,4 +27,4 @@ sinks. # The presence of this file turns this directory into a Python package from qtgui_swig import * -import qtgui_swig as qtgui # to preserve the old interface +#import qtgui_swig as qtgui # to preserve the old interface diff --git a/gr-qtgui/python/qa_qtgui.py b/gr-qtgui/python/qa_qtgui.py index 562706701a..eb402a2084 100755 --- a/gr-qtgui/python/qa_qtgui.py +++ b/gr-qtgui/python/qa_qtgui.py @@ -21,7 +21,7 @@ # from gnuradio import gr, gr_unittest -import qtgui_swig +import qtgui_swig as qtgui class test_qtgui(gr_unittest.TestCase): @@ -31,18 +31,41 @@ class test_qtgui(gr_unittest.TestCase): def tearDown (self): self.tb = None - def test01 (self): - # Test to make sure we can instantiate the sink - self.qtsnk = qtgui_swig.sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS, - 0, 1, "Test", - True, True, True, True) + # Tests to make sure we can instantiate the sink + def test01(self): + self.qtsnk = qtgui.sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test", + True, True, True, True) - def test02 (self): - # Test to make sure we can instantiate the sink - self.qtsnk = qtgui_swig.sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS, - 0, 1, "Test", - True, True, True, True) + def test02(self): + self.qtsnk = qtgui.sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test", + True, True, True, True) + def test03(self): + self.qtsnk = qtgui.time_sink_c(1024, 1, "Test", 1) + + def test04(self): + self.qtsnk = qtgui.time_sink_f(1024, 1, "Test", 1) + + def test05(self): + self.qtsnk = qtgui.freq_sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test", 1) + + def test06(self): + self.qtsnk = qtgui.freq_sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test", 1) + + def test07(self): + self.qtsnk = qtgui.waterfall_sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test") + + def test08(self): + self.qtsnk = qtgui.waterfall_sink_f(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + 0, 1, "Test") + + def test09(self): + self.qtsnk = qtgui.const_sink_c(1024, "Test", 1) if __name__ == '__main__': gr_unittest.run(test_qtgui, "test_qtgui.xml") diff --git a/gr-qtgui/swig/CMakeLists.txt b/gr-qtgui/swig/CMakeLists.txt index e84035b9f7..74545f4cfe 100644 --- a/gr-qtgui/swig/CMakeLists.txt +++ b/gr-qtgui/swig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -28,6 +28,7 @@ set(GR_SWIG_TARGET_DEPS core_swig) set(GR_SWIG_INCLUDE_DIRS ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} ${GR_QTGUI_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} ${QWT_INCLUDE_DIRS} ) @@ -46,10 +47,6 @@ GR_SWIG_INSTALL( install(FILES qtgui_swig.i - qtgui_sink_c.i - qtgui_sink_f.i - qtgui_time_sink_c.i - qtgui_time_sink_f.i ${CMAKE_CURRENT_BINARY_DIR}/qtgui_swig_doc.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "qtgui_swig" diff --git a/gr-qtgui/swig/qtgui_sink_c.i b/gr-qtgui/swig/qtgui_sink_c.i deleted file mode 100644 index 65e7d1c82b..0000000000 --- a/gr-qtgui/swig/qtgui_sink_c.i +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include "gnuradio.i" - -%{ -#include <qtgui_sink_c.h> -%} - -GR_SWIG_BLOCK_MAGIC(qtgui,sink_c) - -qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc=0, double bw=1.0, - const std::string &name="Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plottime=true, bool plotconst=true, - QWidget *parent=NULL); - -class qtgui_sink_c : public gr_block -{ -private: - friend qtgui_sink_c_sptr qtgui_make_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - qtgui_sink_c (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_frequency_axis(double min, double max); - void set_constellation_pen_size(int size); - void set_update_time(double t); -}; diff --git a/gr-qtgui/swig/qtgui_sink_f.i b/gr-qtgui/swig/qtgui_sink_f.i deleted file mode 100644 index b07eaa9ec8..0000000000 --- a/gr-qtgui/swig/qtgui_sink_f.i +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include "gnuradio.i" - -%{ -#include <qtgui_sink_f.h> -%} - -GR_SWIG_BLOCK_MAGIC(qtgui,sink_f) - -qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc=0, double bw=0.0, - const std::string &name="Display", - bool plotfreq=true, bool plotwaterfall=true, - bool plottime=true, bool plotconst=false, - QWidget *parent=NULL); - -class qtgui_sink_f : public gr_block -{ -private: - friend qtgui_sink_f_sptr qtgui_make_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - qtgui_sink_f (int fftsize, int wintype, - double fc, double bw, - const std::string &name, - bool plotfreq, bool plotwaterfall, - bool plottime, bool plotconst, - QWidget *parent); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_frequency_range(const double centerfreq, - const double bandwidth); - void set_time_domain_axis(double min, double max); - void set_constellation_axis(double xmin, double xmax, - double ymin, double ymax); - void set_frequency_axis(double min, double max); - void set_constellation_pen_size(int size); - void set_update_time(double t); -}; diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i index 0d77e22da8..9821ccf440 100644 --- a/gr-qtgui/swig/qtgui_swig.i +++ b/gr-qtgui/swig/qtgui_swig.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2011 Free Software Foundation, Inc. + * Copyright 2008,2009,2011,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,19 +20,41 @@ * Boston, MA 02110-1301, USA. */ +#define QTGUI_API + %include "gnuradio.i" //load generated python docstrings %include "qtgui_swig_doc.i" %{ -#include "qtgui_sink_c.h" -#include "qtgui_sink_f.h" -#include "qtgui_time_sink_c.h" -#include "qtgui_time_sink_f.h" +#include "qtgui/sink_c.h" +#include "qtgui/sink_f.h" +#include "qtgui/time_sink_c.h" +#include "qtgui/time_sink_f.h" +#include "qtgui/freq_sink_c.h" +#include "qtgui/freq_sink_f.h" +#include "qtgui/const_sink_c.h" +#include "qtgui/waterfall_sink_c.h" +#include "qtgui/waterfall_sink_f.h" %} -%include "qtgui_sink_c.i" -%include "qtgui_sink_f.i" -%include "qtgui_time_sink_c.i" -%include "qtgui_time_sink_f.i" +%include "qtgui/sink_c.h" +%include "qtgui/sink_f.h" +%include "qtgui/time_sink_c.h" +%include "qtgui/time_sink_f.h" +%include "qtgui/freq_sink_c.h" +%include "qtgui/freq_sink_f.h" +%include "qtgui/const_sink_c.h" +%include "qtgui/waterfall_sink_c.h" +%include "qtgui/waterfall_sink_f.h" + +GR_SWIG_BLOCK_MAGIC2(qtgui, sink_c); +GR_SWIG_BLOCK_MAGIC2(qtgui, sink_f); +GR_SWIG_BLOCK_MAGIC2(qtgui, time_sink_c); +GR_SWIG_BLOCK_MAGIC2(qtgui, time_sink_f); +GR_SWIG_BLOCK_MAGIC2(qtgui, freq_sink_c); +GR_SWIG_BLOCK_MAGIC2(qtgui, freq_sink_f); +GR_SWIG_BLOCK_MAGIC2(qtgui, const_sink_c); +GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_c); +GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_f); diff --git a/gr-qtgui/swig/qtgui_time_sink_c.i b/gr-qtgui/swig/qtgui_time_sink_c.i deleted file mode 100644 index b78ca5386b..0000000000 --- a/gr-qtgui/swig/qtgui_time_sink_c.i +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include "gnuradio.i" - -%{ -#include <qtgui_time_sink_c.h> -%} - -GR_SWIG_BLOCK_MAGIC(qtgui,time_sink_c) - -qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, - const std::string &name, - int nconnections=1, - QWidget *parent=NULL); - -class qtgui_time_sink_c : public gr_sync_block -{ -private: - friend qtgui_time_sink_c_sptr qtgui_make_time_sink_c(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent); - qtgui_time_sink_c(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent=NULL); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_time_domain_axis(double min, double max); - void set_update_time(double t); - void set_title(int which, const std::string &title); - void set_color(int which, const std::string &color); -}; diff --git a/gr-qtgui/swig/qtgui_time_sink_f.i b/gr-qtgui/swig/qtgui_time_sink_f.i deleted file mode 100644 index 9d59f93643..0000000000 --- a/gr-qtgui/swig/qtgui_time_sink_f.i +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include "gnuradio.i" - -%{ -#include <qtgui_time_sink_f.h> -%} - -GR_SWIG_BLOCK_MAGIC(qtgui,time_sink_f) - -qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, - const std::string &name, - int nconnections=1, - QWidget *parent=NULL); - -class qtgui_time_sink_f : public gr_sync_block -{ -private: - friend qtgui_time_sink_f_sptr qtgui_make_time_sink_f(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent); - qtgui_time_sink_f(int size, double bw, - const std::string &name, - int nconnections, - QWidget *parent=NULL); - -public: - void exec_(); - PyObject* pyqwidget(); - - void set_time_domain_axis(double min, double max); - void set_update_time(double t); - void set_title(int which, const std::string &title); - void set_color(int which, const std::string &color); -}; diff --git a/gr-trellis/doc/gr-trellis.xml b/gr-trellis/doc/gr-trellis.xml index 4657dab384..58aa74d409 100644 --- a/gr-trellis/doc/gr-trellis.xml +++ b/gr-trellis/doc/gr-trellis.xml @@ -587,7 +587,7 @@ outputs a sequence of D numbers ci1,ci2,...,ciD representing the coordianates of the constellation symbol c_i with i=y_k. </para> <programlisting> - 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + 20 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) </programlisting> <para> @@ -804,7 +804,7 @@ L being the channel length. This is sufficient to drive the initial and final st 23 packet[i] = 0 24 packet[len(packet)-i-1] = 0 25 src = gr.vector_source_s(packet,False) - 26 mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + 26 mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) </programlisting> diff --git a/gr-trellis/doc/test_tcm.py b/gr-trellis/doc/test_tcm.py index 8c046d697b..3a285e27a2 100644 --- a/gr-trellis/doc/test_tcm.py +++ b/gr-trellis/doc/test_tcm.py @@ -17,7 +17,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/doc/test_tcm.py.xml b/gr-trellis/doc/test_tcm.py.xml index b5074cb2f4..a4c541e38a 100644 --- a/gr-trellis/doc/test_tcm.py.xml +++ b/gr-trellis/doc/test_tcm.py.xml @@ -19,7 +19,7 @@ 17 src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts 18 s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality 19 enc = trellis.encoder_ss(f,0) # initial state = 0 - 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + 20 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) 21 22 # CHANNEL 23 add = gr.add_ff() diff --git a/gr-trellis/doc/test_viterbi_equalization1.py b/gr-trellis/doc/test_viterbi_equalization1.py index 5967384cf9..c9c897fe2e 100755 --- a/gr-trellis/doc/test_viterbi_equalization1.py +++ b/gr-trellis/doc/test_viterbi_equalization1.py @@ -23,7 +23,7 @@ def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constel packet[i] = 0 packet[len(packet)-i-1] = 0 src = gr.vector_source_s(packet,False) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/doc/test_viterbi_equalization1.py.xml b/gr-trellis/doc/test_viterbi_equalization1.py.xml index 27605870e8..751633a618 100644 --- a/gr-trellis/doc/test_viterbi_equalization1.py.xml +++ b/gr-trellis/doc/test_viterbi_equalization1.py.xml @@ -25,7 +25,7 @@ 23 packet[i] = 0 24 packet[len(packet)-i-1] = 0 25 src = gr.vector_source_s(packet,False) - 26 mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + 26 mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) 27 28 # CHANNEL 29 isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_cpm.py b/gr-trellis/src/examples/python/test_cpm.py index 5342e57e82..7503a458b1 100755 --- a/gr-trellis/src/examples/python/test_cpm.py +++ b/gr-trellis/src/examples/python/test_cpm.py @@ -89,7 +89,7 @@ def run_test(seed,blocksize): # Blocks ################################################## random_source_x_0 = gr.vector_source_b(data.tolist(), False) - gr_chunks_to_symbols_xx_0 = gr.chunks_to_symbols_bf((-1, 1), 1) + digital_chunks_to_symbols_xx_0 = digital.chunks_to_symbols_bf((-1, 1), 1) gr_interp_fir_filter_xxx_0 = gr.interp_fir_filter_fff(Q, p) gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(2*math.pi*h*(1.0/Q)) @@ -111,8 +111,8 @@ def run_test(seed,blocksize): ################################################## # Connections ################################################## - tb.connect((random_source_x_0, 0), (gr_chunks_to_symbols_xx_0, 0)) - tb.connect((gr_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0)) + tb.connect((random_source_x_0, 0), (digital_chunks_to_symbols_xx_0, 0)) + tb.connect((digital_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0)) tb.connect((gr_interp_fir_filter_xxx_0, 0), (gr_frequency_modulator_fc_0, 0)) tb.connect((gr_frequency_modulator_fc_0, 0), (gr_add_vxx_0, 0)) tb.connect((gr_noise_source_x_0, 0), (gr_add_vxx_0, 1)) diff --git a/gr-trellis/src/examples/python/test_pccc_turbo1.py b/gr-trellis/src/examples/python/test_pccc_turbo1.py index 0655b972de..abc0e1d01f 100755 --- a/gr-trellis/src/examples/python/test_pccc_turbo1.py +++ b/gr-trellis/src/examples/python/test_pccc_turbo1.py @@ -20,7 +20,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, #src = gr.vector_source_s([0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],False) enc = trellis.pccc_encoder_ss(fo,0,fi,0,interleaver,K) code = gr.vector_sink_s() - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_hard.py b/gr-trellis/src/examples/python/test_sccc_hard.py index 4eeb94a12d..397ebf0871 100755 --- a/gr-trellis/src/examples/python/test_sccc_hard.py +++ b/gr-trellis/src/examples/python/test_sccc_hard.py @@ -19,7 +19,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_soft.py b/gr-trellis/src/examples/python/test_sccc_soft.py index 10c28419a8..b1ffaae748 100755 --- a/gr-trellis/src/examples/python/test_sccc_soft.py +++ b/gr-trellis/src/examples/python/test_sccc_soft.py @@ -22,7 +22,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo.py b/gr-trellis/src/examples/python/test_sccc_turbo.py index 762a93ba51..e8054a08b2 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo.py @@ -61,7 +61,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo1.py b/gr-trellis/src/examples/python/test_sccc_turbo1.py index 187a75185f..ef5d32f588 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo1.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo1.py @@ -17,7 +17,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo2.py b/gr-trellis/src/examples/python/test_sccc_turbo2.py index dff1ba93c3..942572676d 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo2.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo2.py @@ -17,7 +17,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_tcm.py b/gr-trellis/src/examples/python/test_tcm.py index a7d6a02d04..eff93f5b4e 100755 --- a/gr-trellis/src/examples/python/test_tcm.py +++ b/gr-trellis/src/examples/python/test_tcm.py @@ -24,7 +24,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): #b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_tcm_bit.py b/gr-trellis/src/examples/python/test_tcm_bit.py index 7f69c0e294..1a89d06a89 100755 --- a/gr-trellis/src/examples/python/test_tcm_bit.py +++ b/gr-trellis/src/examples/python/test_tcm_bit.py @@ -25,7 +25,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL diff --git a/gr-trellis/src/examples/python/test_tcm_combined.py b/gr-trellis/src/examples/python/test_tcm_combined.py index d98e36e27d..a46444e32b 100755 --- a/gr-trellis/src/examples/python/test_tcm_combined.py +++ b/gr-trellis/src/examples/python/test_tcm_combined.py @@ -18,7 +18,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL diff --git a/gr-trellis/src/examples/python/test_tcm_parallel.py b/gr-trellis/src/examples/python/test_tcm_parallel.py index 0372351aad..72fb8cf3bf 100755 --- a/gr-trellis/src/examples/python/test_tcm_parallel.py +++ b/gr-trellis/src/examples/python/test_tcm_parallel.py @@ -19,7 +19,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): s2fsmi=gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality s2p = gr.stream_to_streams(gr.sizeof_short,P) # serial to parallel enc = trellis.encoder_ss(f,0) # initiali state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add=[] diff --git a/gr-trellis/src/examples/python/test_turbo_equalization.py b/gr-trellis/src/examples/python/test_turbo_equalization.py index 18bfb022a9..d97f3f2c29 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization.py @@ -59,7 +59,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,tot_constellat inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the innner FSM) - mod = gr.chunks_to_symbols_sf(tot_constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_turbo_equalization1.py b/gr-trellis/src/examples/python/test_turbo_equalization1.py index 17ad430235..da1132d38c 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization1.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization1.py @@ -61,7 +61,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensiona src = gr.vector_source_s(packet,False) enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_turbo_equalization2.py b/gr-trellis/src/examples/python/test_turbo_equalization2.py index 5a6c77e9d4..886240efac 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization2.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization2.py @@ -59,7 +59,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensiona src = gr.vector_source_s(packet,False) enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_viterbi_equalization.py b/gr-trellis/src/examples/python/test_viterbi_equalization.py index 9f3f7e3911..00d54620b2 100755 --- a/gr-trellis/src/examples/python/test_viterbi_equalization.py +++ b/gr-trellis/src/examples/python/test_viterbi_equalization.py @@ -16,7 +16,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,tot_constellation,N0,seed): s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the FSM) - mod = gr.chunks_to_symbols_sf(tot_constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_viterbi_equalization1.py b/gr-trellis/src/examples/python/test_viterbi_equalization1.py index 90eb4790e5..caf99ff581 100755 --- a/gr-trellis/src/examples/python/test_viterbi_equalization1.py +++ b/gr-trellis/src/examples/python/test_viterbi_equalization1.py @@ -22,7 +22,7 @@ def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constel packet[i] = 0 packet[len(packet)-i-1] = 0 src = gr.vector_source_s(packet,False) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/python/qa_trellis.py b/gr-trellis/src/python/qa_trellis.py index fcc651ec6d..935459a3c7 100755 --- a/gr-trellis/src/python/qa_trellis.py +++ b/gr-trellis/src/python/qa_trellis.py @@ -114,7 +114,7 @@ class trellis_tb(gr.top_block): s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol, gr.GR_MSB_FIRST) # initial FSM state = 0 enc = trellis.encoder_ss(f, 0) - mod = gr.chunks_to_symbols_sc(constellation.points(), 1) + mod = digital_swig.chunks_to_symbols_sc(constellation.points(), 1) # CHANNEL add = gr.add_cc() diff --git a/gr-wavelet/CMakeLists.txt b/gr-wavelet/CMakeLists.txt index 555c326d11..a488c47e91 100644 --- a/gr-wavelet/CMakeLists.txt +++ b/gr-wavelet/CMakeLists.txt @@ -37,7 +37,7 @@ GR_REGISTER_COMPONENT("gr-wavelet" ENABLE_GR_WAVELET GR_SET_GLOBAL(GR_WAVELET_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/lib - ${CMAKE_CURRENT_SOURCE_DIR}/include/wavelet + ${CMAKE_CURRENT_SOURCE_DIR}/include ) ######################################################################## diff --git a/gr-wavelet/include/wavelet/CMakeLists.txt b/gr-wavelet/include/wavelet/CMakeLists.txt index a37a3b0cd8..43c1603d15 100644 --- a/gr-wavelet/include/wavelet/CMakeLists.txt +++ b/gr-wavelet/include/wavelet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,11 +21,11 @@ # Install header files ######################################################################## install(FILES - wavelet_api.h - wavelet_squash_ff.h - wavelet_wavelet_ff.h - wavelet_wvps_ff.h - DESTINATION ${GR_INCLUDE_DIR}/gnuradio + api.h + squash_ff.h + wavelet_ff.h + wvps_ff.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/wavelet COMPONENT "wavelet_devel" ) diff --git a/gr-wavelet/include/wavelet/wavelet_api.h b/gr-wavelet/include/wavelet/api.h index 68b2c04d78..68b2c04d78 100644 --- a/gr-wavelet/include/wavelet/wavelet_api.h +++ b/gr-wavelet/include/wavelet/api.h diff --git a/gr-wavelet/include/wavelet/wavelet_squash_ff.h b/gr-wavelet/include/wavelet/squash_ff.h index a9d1c12812..4d1aeb3c3c 100644 --- a/gr-wavelet/include/wavelet/wavelet_squash_ff.h +++ b/gr-wavelet/include/wavelet/squash_ff.h @@ -23,24 +23,29 @@ #ifndef INCLUDED_WAVELET_SQUASH_FF_H #define INCLUDED_WAVELET_SQUASH_FF_H -#include <wavelet_api.h> +#include <wavelet/api.h> #include <gr_sync_block.h> -class wavelet_squash_ff; -typedef boost::shared_ptr<wavelet_squash_ff> wavelet_squash_ff_sptr; +namespace gr { + namespace wavelet { -WAVELET_API wavelet_squash_ff_sptr wavelet_make_squash_ff(const std::vector<float> &igrid, - const std::vector<float> &ogrid); + class WAVELET_API squash_ff : virtual public gr_sync_block + { + public: + + // gr::wavelet::squash_ff::sptr + typedef boost::shared_ptr<squash_ff> sptr; + + /*! + * \brief implements cheap resampling of spectrum directly from + * spectral points, using gsl interpolation + * \ingroup misc + */ + static WAVELET_API sptr make(const std::vector<float> &igrid, + const std::vector<float> &ogrid); + }; -/*! - * \brief implements cheap resampling of spectrum directly from - * spectral points, using gsl interpolation - * \ingroup misc - */ - -class WAVELET_API wavelet_squash_ff : virtual public gr_sync_block -{ - // No public API methods visible -}; + } /* namespace wavelet */ +} /* namespace gr */ #endif diff --git a/gr-wavelet/include/wavelet/wavelet_wavelet_ff.h b/gr-wavelet/include/wavelet/wavelet_ff.h index 7d60dbdad1..71e959f88a 100644 --- a/gr-wavelet/include/wavelet/wavelet_wavelet_ff.h +++ b/gr-wavelet/include/wavelet/wavelet_ff.h @@ -19,28 +19,33 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_WAVELET_WAVELET_FF_H #define INCLUDED_WAVELET_WAVELET_FF_H -#include <wavelet_api.h> +#include <wavelet/api.h> #include <gr_sync_block.h> -class wavelet_wavelet_ff; -typedef boost::shared_ptr<wavelet_wavelet_ff> wavelet_wavelet_ff_sptr; +namespace gr { + namespace wavelet { -WAVELET_API wavelet_wavelet_ff_sptr -wavelet_make_wavelet_ff(int size = 1024, - int order = 20, - bool forward = true); + class WAVELET_API wavelet_ff : virtual public gr_sync_block + { + public: -/*! - * \brief compute wavelet transform using gsl routines - * \ingroup wavelet_blk - */ + // gr::wavelet::wavelet_ff:sptr + typedef boost::shared_ptr<wavelet_ff> sptr; + + /*! + * \brief compute wavelet transform using gsl routines + * \ingroup wavelet_blk + */ + static WAVELET_API sptr make(int size = 1024, + int order = 20, + bool forward = true); + }; -class WAVELET_API wavelet_wavelet_ff : virtual public gr_sync_block -{ - // No public API methods visible -}; + } /* namespace wavelet */ +} /* namespace gr */ #endif /* INCLUDED_WAVELET_WAVELET_FF_H */ diff --git a/gr-wavelet/include/wavelet/wavelet_wvps_ff.h b/gr-wavelet/include/wavelet/wvps_ff.h index 4e2889b52a..8b955db65f 100644 --- a/gr-wavelet/include/wavelet/wavelet_wvps_ff.h +++ b/gr-wavelet/include/wavelet/wvps_ff.h @@ -23,22 +23,29 @@ #ifndef INCLUDED_WAVELET_WVPS_FF_H #define INCLUDED_WAVELET_WVPS_FF_H -#include <wavelet_api.h> +#include <wavelet/api.h> #include <gr_sync_decimator.h> class wavelet_wvps_ff; -typedef boost::shared_ptr<wavelet_wvps_ff> wavelet_wvps_ff_sptr; -WAVELET_API wavelet_wvps_ff_sptr -wavelet_make_wvps_ff(int ilen); +namespace gr { + namespace wavelet { -/*! - * \brief computes the Wavelet Power Spectrum from a set of wavelet coefficients - * \ingroup wavelet_blk - */ -class WAVELET_API wavelet_wvps_ff : virtual public gr_sync_block -{ - // No public API methods visible -}; + class WAVELET_API wvps_ff : virtual public gr_sync_block + { + public: + + // gr::wavelet::wvps_ff::sptr + typedef boost::shared_ptr<wvps_ff> sptr; + + /*! + * \brief computes the Wavelet Power Spectrum from a set of wavelet coefficients + * \ingroup wavelet_blk + */ + static WAVELET_API sptr make(int ilen); + }; + + } /* namespace wavelet */ +} /* namespace gr */ #endif /* INCLUDED_WAVELET_WVPS_FF_H */ diff --git a/gr-wavelet/lib/CMakeLists.txt b/gr-wavelet/lib/CMakeLists.txt index 9594f6a6ac..2d4382b765 100644 --- a/gr-wavelet/lib/CMakeLists.txt +++ b/gr-wavelet/lib/CMakeLists.txt @@ -38,9 +38,9 @@ add_definitions(${GSL_DEFINITIONS}) # Setup library ######################################################################## list(APPEND gr_wavelet_sources - wavelet_squash_ff_impl.cc - wavelet_wavelet_ff_impl.cc - wavelet_wvps_ff_impl.cc + squash_ff_impl.cc + wavelet_ff_impl.cc + wvps_ff_impl.cc ) list(APPEND wavelet_libs diff --git a/gr-wavelet/lib/squash_ff_impl.cc b/gr-wavelet/lib/squash_ff_impl.cc new file mode 100644 index 0000000000..081ac900f5 --- /dev/null +++ b/gr-wavelet/lib/squash_ff_impl.cc @@ -0,0 +1,98 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdexcept> +#include <squash_ff_impl.h> +#include <gr_io_signature.h> + +// expect input vector of igrid.size y-values, +// produce output vector of ogrid.size y-values + +namespace gr { + namespace wavelet { + + squash_ff::sptr squash_ff::make(const std::vector<float> &igrid, + const std::vector<float> &ogrid) + { + return gnuradio::get_initial_sptr(new squash_ff_impl(igrid, ogrid)); + } + + squash_ff_impl::squash_ff_impl(const std::vector<float> &igrid, + const std::vector<float> &ogrid) + : gr_sync_block("squash_ff", + gr_make_io_signature(1, 1, sizeof(float) * igrid.size()), + gr_make_io_signature(1, 1, sizeof(float) * ogrid.size())) + { + d_inum = igrid.size(); + d_onum = ogrid.size(); + d_igrid = (double *) malloc(d_inum * sizeof(double)); + d_iwork = (double *) malloc(d_inum * sizeof(double)); + d_ogrid = (double *) malloc(d_onum * sizeof(double)); + for (unsigned int i = 0; i < d_inum; i++) + d_igrid[i] = igrid[i]; + for (unsigned int i = 0; i < d_onum; i++) + d_ogrid[i] = ogrid[i]; + + d_accel = gsl_interp_accel_alloc(); + d_spline = gsl_spline_alloc(gsl_interp_cspline, d_inum); // FIXME check w/ Frank + } + + squash_ff_impl::~squash_ff_impl() + { + free((char *) d_igrid); + free((char *) d_iwork); + free((char *) d_ogrid); + gsl_interp_accel_free(d_accel); + gsl_spline_free(d_spline); + } + + int + squash_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int count = 0; count < noutput_items; count++) { + + for (unsigned int i = 0; i < d_inum; i++) + d_iwork[i] = in[i]; + + gsl_spline_init(d_spline, d_igrid, d_iwork, d_inum); + + for (unsigned int i = 0; i < d_onum; i++) + out[i] = gsl_spline_eval(d_spline, d_ogrid[i], d_accel); + + in += d_inum; + out += d_onum; + } + + return noutput_items; + } + + } /* namespace wavelet */ +} /* namespace gr */ diff --git a/gr-wavelet/lib/wavelet_squash_ff_impl.h b/gr-wavelet/lib/squash_ff_impl.h index dac50ddf2a..b6ddb45363 100644 --- a/gr-wavelet/lib/wavelet_squash_ff_impl.h +++ b/gr-wavelet/lib/squash_ff_impl.h @@ -23,36 +23,38 @@ #ifndef INCLUDED_WAVELET_SQUASH_FF_IMPL_H #define INCLUDED_WAVELET_SQUASH_FF_IMPL_H -#include <wavelet_api.h> -#include <wavelet_squash_ff.h> +#include <wavelet/api.h> +#include <wavelet/squash_ff.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_interp.h> #include <gsl/gsl_spline.h> -class WAVELET_API wavelet_squash_ff_impl : public wavelet_squash_ff -{ - size_t d_inum; - size_t d_onum; - double *d_igrid; - double *d_iwork; - double *d_ogrid; - - gsl_interp_accel *d_accel; - gsl_spline *d_spline; - - wavelet_squash_ff_impl(const std::vector<float> &igrid, - const std::vector<float> &ogrid); - - friend WAVELET_API wavelet_squash_ff_sptr - wavelet_make_squash_ff(const std::vector<float> &igrid, - const std::vector<float> &ogrid); - - public: - ~wavelet_squash_ff_impl(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; +namespace gr { + namespace wavelet { + + class WAVELET_API squash_ff_impl : public squash_ff + { + size_t d_inum; + size_t d_onum; + double *d_igrid; + double *d_iwork; + double *d_ogrid; + + gsl_interp_accel *d_accel; + gsl_spline *d_spline; + + public: + squash_ff_impl(const std::vector<float> &igrid, + const std::vector<float> &ogrid); + + ~squash_ff_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace wavelet */ +} /* namespace gr */ #endif /* INCLUDED_WAVELET_WAVELET_FF_IMPL_H */ diff --git a/gr-wavelet/lib/wavelet_ff_impl.cc b/gr-wavelet/lib/wavelet_ff_impl.cc new file mode 100644 index 0000000000..73fc8c5440 --- /dev/null +++ b/gr-wavelet/lib/wavelet_ff_impl.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the tewavelet of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdexcept> +#include <wavelet_ff_impl.h> +#include <gr_io_signature.h> + +#include <stdio.h> + +// NB in this version, only Daubechies wavelets +// order is wavelet length, even, 2...20 + +namespace gr { + namespace wavelet { + + wavelet_ff::sptr wavelet_ff::make(int size, + int order, + bool forward) + { + return gnuradio::get_initial_sptr(new wavelet_ff_impl(size, order, forward)); + } + + wavelet_ff_impl::wavelet_ff_impl(int size, + int order, + bool forward) + : gr_sync_block("wavelet_ff", + gr_make_io_signature(1, 1, size * sizeof(float)), + gr_make_io_signature(1, 1, size * sizeof(float))), + d_size(size), + d_order(order), + d_forward(forward) + { + d_wavelet = gsl_wavelet_alloc(gsl_wavelet_daubechies, d_order); + if (d_wavelet == NULL) + throw std::runtime_error("can't allocate wavelet"); + d_workspace = gsl_wavelet_workspace_alloc(d_size); + if (d_workspace == NULL) + throw std::runtime_error("can't allocate wavelet workspace"); + d_temp = (double *) malloc(d_size*sizeof(double)); + if (d_workspace == NULL) + throw std::runtime_error("can't allocate wavelet double conversion temp"); + } + + wavelet_ff_impl::~wavelet_ff_impl() + { + gsl_wavelet_free(d_wavelet); + gsl_wavelet_workspace_free(d_workspace); + free((char *) d_temp); + } + + int + wavelet_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int count = 0; count < noutput_items; count++) { + for (int i = 0; i < d_size; i++) + d_temp[i] = in[i]; + + if (d_forward) + gsl_wavelet_transform_forward(d_wavelet, + d_temp, + 1, + d_size, + d_workspace); + else + gsl_wavelet_transform_inverse(d_wavelet, + d_temp, + 1, + d_size, + d_workspace); + + for (int i = 0; i < d_size; i++) + out[i] = d_temp[i]; + + in += d_size; + out += d_size; + } + + return noutput_items; + } + + } /* namespace wavelet */ +} /* namespace gr */ diff --git a/gr-wavelet/lib/wavelet_wavelet_ff_impl.h b/gr-wavelet/lib/wavelet_ff_impl.h index dc33a4184e..bec3935f33 100644 --- a/gr-wavelet/lib/wavelet_wavelet_ff_impl.h +++ b/gr-wavelet/lib/wavelet_ff_impl.h @@ -22,34 +22,35 @@ #ifndef INCLUDED_WAVELET_WAVELET_FF_IMPL_H #define INCLUDED_WAVELET_WAVELET_FF_IMPL_H -#include <wavelet_wavelet_ff.h> +#include <wavelet/wavelet_ff.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_wavelet.h> -class WAVELET_API wavelet_wavelet_ff_impl : public wavelet_wavelet_ff -{ - int d_size; - int d_order; - bool d_forward; - gsl_wavelet *d_wavelet; - gsl_wavelet_workspace *d_workspace; - double *d_temp; - - friend WAVELET_API wavelet_wavelet_ff_sptr - wavelet_make_wavelet_ff(int size, - int order, - bool forward); - - wavelet_wavelet_ff_impl(int size, - int order, - bool forward); - -public: - ~wavelet_wavelet_ff_impl(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; +namespace gr { + namespace wavelet { + + class WAVELET_API wavelet_ff_impl : public wavelet_ff + { + int d_size; + int d_order; + bool d_forward; + gsl_wavelet *d_wavelet; + gsl_wavelet_workspace *d_workspace; + double *d_temp; + + public: + wavelet_ff_impl(int size, + int order, + bool forward); + + ~wavelet_ff_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace wavelet */ +} /* namespace gr */ #endif /* INCLUDED_WAVELET_WAVELET_FF_IMPL_H */ diff --git a/gr-wavelet/lib/wavelet_squash_ff_impl.cc b/gr-wavelet/lib/wavelet_squash_ff_impl.cc deleted file mode 100644 index 89494a9c39..0000000000 --- a/gr-wavelet/lib/wavelet_squash_ff_impl.cc +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdexcept> -#include <wavelet_squash_ff_impl.h> -#include <gr_io_signature.h> - -// expect input vector of igrid.size y-values, -// produce output vector of ogrid.size y-values - -wavelet_squash_ff_sptr -wavelet_make_squash_ff(const std::vector<float> &igrid, - const std::vector<float> &ogrid) -{ - return gnuradio::get_initial_sptr(new wavelet_squash_ff_impl(igrid, ogrid)); -} - -wavelet_squash_ff_impl::wavelet_squash_ff_impl(const std::vector<float> &igrid, - const std::vector<float> &ogrid) - : gr_sync_block("squash_ff", - gr_make_io_signature(1, 1, sizeof(float) * igrid.size()), - gr_make_io_signature(1, 1, sizeof(float) * ogrid.size())) -{ - d_inum = igrid.size(); - d_onum = ogrid.size(); - d_igrid = (double *) malloc(d_inum * sizeof(double)); - d_iwork = (double *) malloc(d_inum * sizeof(double)); - d_ogrid = (double *) malloc(d_onum * sizeof(double)); - for (unsigned int i = 0; i < d_inum; i++) - d_igrid[i] = igrid[i]; - for (unsigned int i = 0; i < d_onum; i++) - d_ogrid[i] = ogrid[i]; - - d_accel = gsl_interp_accel_alloc(); - d_spline = gsl_spline_alloc(gsl_interp_cspline, d_inum); // FIXME check w/ Frank -} - -wavelet_squash_ff_impl::~wavelet_squash_ff_impl() -{ - free((char *) d_igrid); - free((char *) d_iwork); - free((char *) d_ogrid); - gsl_interp_accel_free(d_accel); - gsl_spline_free(d_spline); -} - -int -wavelet_squash_ff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - for (int count = 0; count < noutput_items; count++) { - - for (unsigned int i = 0; i < d_inum; i++) - d_iwork[i] = in[i]; - - gsl_spline_init(d_spline, d_igrid, d_iwork, d_inum); - - for (unsigned int i = 0; i < d_onum; i++) - out[i] = gsl_spline_eval(d_spline, d_ogrid[i], d_accel); - - in += d_inum; - out += d_onum; - } - - return noutput_items; -} diff --git a/gr-wavelet/lib/wavelet_wavelet_ff_impl.cc b/gr-wavelet/lib/wavelet_wavelet_ff_impl.cc deleted file mode 100644 index ccc1a6d8f7..0000000000 --- a/gr-wavelet/lib/wavelet_wavelet_ff_impl.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the tewavelet of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdexcept> -#include <wavelet_wavelet_ff_impl.h> -#include <gr_io_signature.h> - -#include <stdio.h> - -// NB in this version, only Daubechies wavelets -// order is wavelet length, even, 2...20 - -wavelet_wavelet_ff_sptr -wavelet_make_wavelet_ff(int size, - int order, - bool forward) -{ - return gnuradio::get_initial_sptr(new wavelet_wavelet_ff_impl(size, order, forward)); -} - -wavelet_wavelet_ff_impl::wavelet_wavelet_ff_impl(int size, int order, bool forward) - : gr_sync_block("wavelet_ff", - gr_make_io_signature(1, 1, size * sizeof(float)), - gr_make_io_signature(1, 1, size * sizeof(float))), - d_size(size), - d_order(order), - d_forward(forward) -{ - d_wavelet = gsl_wavelet_alloc(gsl_wavelet_daubechies, d_order); - if (d_wavelet == NULL) - throw std::runtime_error("can't allocate wavelet"); - d_workspace = gsl_wavelet_workspace_alloc(d_size); - if (d_workspace == NULL) - throw std::runtime_error("can't allocate wavelet workspace"); - d_temp = (double *) malloc(d_size*sizeof(double)); - if (d_workspace == NULL) - throw std::runtime_error("can't allocate wavelet double conversion temp"); -} - -wavelet_wavelet_ff_impl::~wavelet_wavelet_ff_impl() -{ - gsl_wavelet_free(d_wavelet); - gsl_wavelet_workspace_free(d_workspace); - free((char *) d_temp); -} - -int -wavelet_wavelet_ff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - for (int count = 0; count < noutput_items; count++) { - for (int i = 0; i < d_size; i++) - d_temp[i] = in[i]; - - if (d_forward) - gsl_wavelet_transform_forward(d_wavelet, - d_temp, - 1, - d_size, - d_workspace); - else - gsl_wavelet_transform_inverse(d_wavelet, - d_temp, - 1, - d_size, - d_workspace); - - for (int i = 0; i < d_size; i++) - out[i] = d_temp[i]; - - in += d_size; - out += d_size; - } - - return noutput_items; -} diff --git a/gr-wavelet/lib/wavelet_wvps_ff_impl.cc b/gr-wavelet/lib/wavelet_wvps_ff_impl.cc deleted file mode 100644 index b86859b0ae..0000000000 --- a/gr-wavelet/lib/wavelet_wvps_ff_impl.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <wavelet_wvps_ff_impl.h> -#include <gr_io_signature.h> -#include <string.h> - -static int -ceil_log2(int k) -{ - int m = 0; - for (int n = k-1; n > 0; n >>= 1) m++; - return m; -} - -wavelet_wvps_ff_sptr -wavelet_make_wvps_ff(int ilen) -{ - return gnuradio::get_initial_sptr(new wavelet_wvps_ff_impl(ilen)); -} - -wavelet_wvps_ff_impl::wavelet_wvps_ff_impl(int ilen) - : gr_sync_block("wvps_ff", - gr_make_io_signature(1, 1, sizeof(float) * ilen), - gr_make_io_signature(1, 1, sizeof(float) * ceil_log2(ilen))), - d_ilen(ilen), d_olen(ceil_log2(ilen)) -{ -} - -// input vector assumed to be output from gsl wavelet computation - -int -wavelet_wvps_ff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - for (int count = 0; count < noutput_items; count++) { - - // any power? - - if (in[0] == 0.0) { - for (int i = 0; i < d_olen; i++) - out[i] = 0.0; - - } else { - - // get power normalization from 0-th wavelet coefficient - - float scl = 1.0/(in[0]*in[0]); - int k = 1; - - // sum powers over sequences of bins, - // sequence lengths in increasing powers of 2 - - for (int e = 0; e < d_olen; e++) { - int m = 01<<e; - float sum = 0.0; - - for (int l = 0; l < m; l++) - sum += (in[k+l]*in[k+l]); - - out[e] = scl*sum; - k += m; - } - } - - in += d_ilen; - out += d_olen; - } - - return noutput_items; -} diff --git a/gr-wavelet/lib/wvps_ff_impl.cc b/gr-wavelet/lib/wvps_ff_impl.cc new file mode 100644 index 0000000000..6e886bff4e --- /dev/null +++ b/gr-wavelet/lib/wvps_ff_impl.cc @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <wvps_ff_impl.h> +#include <gr_io_signature.h> +#include <string.h> + +namespace gr { + namespace wavelet { + + static int + ceil_log2(int k) + { + int m = 0; + for (int n = k-1; n > 0; n >>= 1) m++; + return m; + } + + wvps_ff::sptr wvps_ff::make(int ilen) + { + return gnuradio::get_initial_sptr(new wvps_ff_impl(ilen)); + } + + wvps_ff_impl::wvps_ff_impl(int ilen) + : gr_sync_block("wvps_ff", + gr_make_io_signature(1, 1, sizeof(float) * ilen), + gr_make_io_signature(1, 1, sizeof(float) * ceil_log2(ilen))), + d_ilen(ilen), d_olen(ceil_log2(ilen)) + { + } + + // input vector assumed to be output from gsl wavelet computation + + int + wvps_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int count = 0; count < noutput_items; count++) { + + // any power? + + if (in[0] == 0.0) { + for (int i = 0; i < d_olen; i++) + out[i] = 0.0; + + } else { + + // get power normalization from 0-th wavelet coefficient + + float scl = 1.0/(in[0]*in[0]); + int k = 1; + + // sum powers over sequences of bins, + // sequence lengths in increasing powers of 2 + + for (int e = 0; e < d_olen; e++) { + int m = 01<<e; + float sum = 0.0; + + for (int l = 0; l < m; l++) + sum += (in[k+l]*in[k+l]); + + out[e] = scl*sum; + k += m; + } + } + + in += d_ilen; + out += d_olen; + } + + return noutput_items; + } + + } /* namespace wavelet */ +} /* namespace gr */ diff --git a/gr-wavelet/lib/wavelet_wvps_ff_impl.h b/gr-wavelet/lib/wvps_ff_impl.h index 553469fde9..ab64395d24 100644 --- a/gr-wavelet/lib/wavelet_wvps_ff_impl.h +++ b/gr-wavelet/lib/wvps_ff_impl.h @@ -23,22 +23,25 @@ #ifndef INCLUDED_WAVELET_WVPS_FF_IMPL_H #define INCLUDED_WAVELET_WVPS_FF_IMPL_H -#include <wavelet_wvps_ff.h> +#include <wavelet/wvps_ff.h> -class WAVELET_API wavelet_wvps_ff_impl : public wavelet_wvps_ff -{ - int d_ilen; - int d_olen; +namespace gr { + namespace wavelet { - friend WAVELET_API wavelet_wvps_ff_sptr - wavelet_make_wvps_ff(int ilen); + class WAVELET_API wvps_ff_impl : public wvps_ff + { + int d_ilen; + int d_olen; - wavelet_wvps_ff_impl(int ilen); + public: + wvps_ff_impl(int ilen); - public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace wavelet */ +}/* namespace gr */ #endif /* INCLUDED_WAVELET_WVPS_FF_IMPL_H */ diff --git a/gr-wavelet/swig/wavelet_swig.i b/gr-wavelet/swig/wavelet_swig.i index b04efc508d..40fe3f9b5e 100644 --- a/gr-wavelet/swig/wavelet_swig.i +++ b/gr-wavelet/swig/wavelet_swig.i @@ -28,21 +28,15 @@ %include "wavelet_swig_doc.i" %{ -#include "wavelet_squash_ff.h" -#include "wavelet_wavelet_ff.h" -#include "wavelet_wvps_ff.h" +#include "wavelet/squash_ff.h" +#include "wavelet/wavelet_ff.h" +#include "wavelet/wvps_ff.h" %} -%include "wavelet_squash_ff.h" -%include "wavelet_wavelet_ff.h" -%include "wavelet_wvps_ff.h" +%include "wavelet/squash_ff.h" +%include "wavelet/wavelet_ff.h" +%include "wavelet/wvps_ff.h" -GR_SWIG_BLOCK_MAGIC(wavelet,squash_ff); -wavelet_squash_ff_sptr wavelet_make_squash_ff(const std::vector<float> &igrid, - const std::vector<float> &ogrid); - -GR_SWIG_BLOCK_MAGIC(wavelet,wavelet_ff); -wavelet_wavelet_ff_sptr wavelet_make_wavelet_ff(int size, int order, bool forward); - -GR_SWIG_BLOCK_MAGIC(wavelet,wvps_ff); -wavelet_wvps_ff_sptr wavelet_make_wvps_ff(int ilen); +GR_SWIG_BLOCK_MAGIC2(wavelet, squash_ff); +GR_SWIG_BLOCK_MAGIC2(wavelet, wavelet_ff); +GR_SWIG_BLOCK_MAGIC2(wavelet, wvps_ff); diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 3b5491a745..a23518a3c4 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -13,7 +13,6 @@ <block>gr_noise_source_x</block> <block>gr_vector_source_x</block> <block>random_source_x</block> - <block>gr_glfsr_source_x</block> <block>gr_null_source</block> <block>gr_file_source</block> <block>blks2_tcp_source</block> @@ -118,8 +117,6 @@ <block>gr_packed_to_unpacked_xx</block> <block>gr_unpack_k_bits_bb</block> <block>gr_pack_k_bits_bb</block> - <block>gr_chunks_to_symbols_xx</block> - <block>gr_map_bb</block> </cat> <cat> <name>Synchronizers</name> @@ -131,9 +128,7 @@ <block>gr_pll_freqdet_cf</block> <block>gr_pll_refout_cc</block> - <block>gr_pn_correlator_cc</block> <block>gr_simple_correlator</block> - <block>gr_simple_framer</block> <block>blks2_packet_decoder</block> <block>blks2_packet_encoder</block> @@ -200,11 +195,6 @@ <block>gr_quadrature_demod_cf</block> <block>gr_cpfsk_bc</block> - <block>gr_diff_phasor_cc</block> - - <block>gr_diff_encoder_bb</block> - <block>gr_diff_decoder_bb</block> - <block>blks2_wfm_tx</block> <block>blks2_wfm_rcv</block> <block>blks2_wfm_rcv_pll</block> @@ -227,15 +217,8 @@ <block>gr_decode_ccsds_27_fb</block> </cat> <cat> - <name>Line Coding</name> - <block>gr_scrambler_bb</block> - <block>gr_descrambler_bb</block> - <block>gr_additive_scrambler_bb</block> - </cat> - <cat> <name>Probes</name> <block>gr_probe_avg_mag_sqrd_x</block> - <block>gr_probe_density_b</block> <block>gr_probe_signal_f</block> </cat> <cat> diff --git a/grc/blocks/gr_additive_scrambler_bb.xml b/grc/blocks/gr_additive_scrambler_bb.xml deleted file mode 100644 index a15d6eefbe..0000000000 --- a/grc/blocks/gr_additive_scrambler_bb.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -## Additive Scrambler -################################################### - --> -<block> - <name>Additive Scrambler</name> - <key>gr_additive_scrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.additive_scrambler_bb($mask, $seed, $len, $count)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <param> - <name>Count</name> - <key>count</key> - <value>0</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_chunks_to_symbols.xml b/grc/blocks/gr_chunks_to_symbols.xml deleted file mode 100644 index e9da38e9a5..0000000000 --- a/grc/blocks/gr_chunks_to_symbols.xml +++ /dev/null @@ -1,77 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Chunks to Symbols -################################################### - --> -<block> - <name>Chunks to Symbols</name> - <key>gr_chunks_to_symbols_xx</key> - <import>from gnuradio import gr</import> - <make>gr.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension)</make> - <param> - <name>Input Type</name> - <key>in_type</key> - <type>enum</type> - <option> - <name>Int</name> - <key>int</key> - <opt>fcn:i</opt> - </option> - <option> - <name>Short</name> - <key>short</key> - <opt>fcn:s</opt> - </option> - <option> - <name>Byte</name> - <key>byte</key> - <opt>fcn:b</opt> - </option> - </param> - <param> - <name>Output Type</name> - <key>out_type</key> - <type>enum</type> - <option> - <name>Complex</name> - <key>complex</key> - <opt>fcn:c</opt> - <opt>table:complex_vector</opt> - </option> - <option> - <name>Float</name> - <key>float</key> - <opt>fcn:f</opt> - <opt>table:real_vector</opt> - </option> - </param> - <param> - <name>Symbol Table</name> - <key>symbol_table</key> - <type>$out_type.table</type> - </param> - <param> - <name>Dimension</name> - <key>dimension</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Num Ports</name> - <key>num_ports</key> - <value>1</value> - <type>int</type> - </param> - <check>$num_ports > 0</check> - <sink> - <name>in</name> - <type>$in_type</type> - <nports>$num_ports</nports> - </sink> - <source> - <name>out</name> - <type>$out_type</type> - <nports>$num_ports</nports> - </source> -</block> diff --git a/grc/blocks/gr_descrambler_bb.xml b/grc/blocks/gr_descrambler_bb.xml deleted file mode 100644 index 5cfbcc203e..0000000000 --- a/grc/blocks/gr_descrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Descrambler -################################################### - --> -<block> - <name>Descrambler</name> - <key>gr_descrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.descrambler_bb($mask, $seed, $len)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_diff_decoder_bb.xml b/grc/blocks/gr_diff_decoder_bb.xml deleted file mode 100644 index ea7cf17343..0000000000 --- a/grc/blocks/gr_diff_decoder_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Differential Decoder -################################################### - --> -<block> - <name>Differential Decoder</name> - <key>gr_diff_decoder_bb</key> - <import>from gnuradio import gr</import> - <make>gr.diff_decoder_bb($modulus)</make> - <param> - <name>Modulus</name> - <key>modulus</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_diff_encoder_bb.xml b/grc/blocks/gr_diff_encoder_bb.xml deleted file mode 100644 index 21241eac22..0000000000 --- a/grc/blocks/gr_diff_encoder_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Differential Encoder -################################################### - --> -<block> - <name>Differential Encoder</name> - <key>gr_diff_encoder_bb</key> - <import>from gnuradio import gr</import> - <make>gr.diff_encoder_bb($modulus)</make> - <param> - <name>Modulus</name> - <key>modulus</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_diff_phasor_cc.xml b/grc/blocks/gr_diff_phasor_cc.xml deleted file mode 100644 index 2b2d7e372c..0000000000 --- a/grc/blocks/gr_diff_phasor_cc.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Differential Phasor -################################################### - --> -<block> - <name>Differential Phasor</name> - <key>gr_diff_phasor_cc</key> - <import>from gnuradio import gr</import> - <make>gr.diff_phasor_cc()</make> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/gr_glfsr_source_x.xml b/grc/blocks/gr_glfsr_source_x.xml deleted file mode 100644 index 88fb66797b..0000000000 --- a/grc/blocks/gr_glfsr_source_x.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##GLFSR Source -################################################### - --> -<block> - <name>GLFSR Source</name> - <key>gr_glfsr_source_x</key> - <import>from gnuradio import gr</import> - <make>gr.glfsr_source_$(type.fcn)($degree, $repeat, $mask, $seed)</make> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>Float</name> - <key>float</key> - <opt>fcn:f</opt> - </option> - <option> - <name>Byte</name> - <key>byte</key> - <opt>fcn:b</opt> - </option> - </param> - <param> - <name>Degree</name> - <key>degree</key> - <type>int</type> - </param> - <param> - <name>Repeat</name> - <key>repeat</key> - <type>enum</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Mask</name> - <key>mask</key> - <type>int</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <type>int</type> - </param> - <source> - <name>out</name> - <type>$type</type> - </source> -</block> diff --git a/grc/blocks/gr_map_bb.xml b/grc/blocks/gr_map_bb.xml deleted file mode 100644 index 20d6bd2b44..0000000000 --- a/grc/blocks/gr_map_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Map -################################################### - --> -<block> - <name>Map</name> - <key>gr_map_bb</key> - <import>from gnuradio import gr</import> - <make>gr.map_bb($map)</make> - <param> - <name>Map</name> - <key>map</key> - <type>int_vector</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_pn_correlator_cc.xml b/grc/blocks/gr_pn_correlator_cc.xml deleted file mode 100644 index 094f46cdfd..0000000000 --- a/grc/blocks/gr_pn_correlator_cc.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##PN Correlator -################################################### - --> -<block> - <name>PN Correlator</name> - <key>gr_pn_correlator_cc</key> - <import>from gnuradio import gr</import> - <make>gr.pn_correlator_cc($degree, $mask, $seed)</make> - <param> - <name>Degree</name> - <key>degree</key> - <type>int</type> - </param> - <param> - <name>Mask</name> - <key>mask</key> - <type>int</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/gr_probe_density_b.xml b/grc/blocks/gr_probe_density_b.xml deleted file mode 100644 index 3a91256aa5..0000000000 --- a/grc/blocks/gr_probe_density_b.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Probe Density -################################################### - --> -<block> - <name>Probe Density</name> - <key>gr_probe_density_b</key> - <import>from gnuradio import gr</import> - <make>gr.probe_density_b($alpha)</make> - <callback>set_alpha($alpha)</callback> - <param> - <name>Alpha</name> - <key>alpha</key> - <value>1</value> - <type>real</type> - </param> - <param> - <name>Probe Rate</name> - <key>probe_rate</key> - <value>10</value> - <type>real</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <doc> -Available functions to probe: density() - -Use with the function probe block. - </doc> -</block> diff --git a/grc/blocks/gr_scrambler_bb.xml b/grc/blocks/gr_scrambler_bb.xml deleted file mode 100644 index d079c4015f..0000000000 --- a/grc/blocks/gr_scrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Descrambler -################################################### - --> -<block> - <name>Scrambler</name> - <key>gr_scrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.scrambler_bb($mask, $seed, $len)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_simple_framer.xml b/grc/blocks/gr_simple_framer.xml deleted file mode 100644 index 2a0295c417..0000000000 --- a/grc/blocks/gr_simple_framer.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Simple Framer -################################################### - --> -<block> - <name>Simple Framer</name> - <key>gr_simple_framer</key> - <import>from gnuradio import gr</import> - <make>gr.simple_framer($payload_bytesize)</make> - <param> - <name>Payload Byte Size</name> - <key>payload_bytesize</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/grc_gnuradio/blks2/packet.py b/grc/grc_gnuradio/blks2/packet.py index e39f55c841..494afa986a 100644 --- a/grc/grc_gnuradio/blks2/packet.py +++ b/grc/grc_gnuradio/blks2/packet.py @@ -1,4 +1,4 @@ -# Copyright 2008, 2009 Free Software Foundation, Inc. +# Copyright 2008, 2009, 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -158,7 +158,7 @@ class packet_decoder(gr.hier_block2): #blocks msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY correlator = digital.correlate_access_code_bb(self._access_code, self._threshold) - framer_sink = gr.framer_sink_1(msgq) + framer_sink = digital.framer_sink_1(msgq) #initialize hier2 gr.hier_block2.__init__( self, diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 17feb01f65..6e504815a6 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -77,6 +77,9 @@ class $(class_name)(gr.top_block, Qt.QWidget): self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) + self.settings = Qt.QSettings("GNU Radio", "$class_name") + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + #elif $generate_options == 'no_gui' class $(class_name)(gr.top_block): @@ -191,6 +194,16 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) #end for ######################################################## +# QT sink close method reimplementation +######################################################## +#if $generate_options == 'qt_gui' + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "$class_name") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() +#end if + +######################################################## ##Create Callbacks ## Write a set method for this variable that calls the callbacks ######################################################## @@ -262,6 +275,7 @@ if __name__ == '__main__': tb.show() qapp.exec_() tb.stop() + tb = None #to clean up Qt widgets #elif $generate_options == 'no_gui' tb = $(class_name)($(', '.join($params_eq_list))) #set $run_options = $flow_graph.get_option('run_options') diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc index 648f4d878a..d35d90deea 100644 --- a/volk/apps/volk_profile.cc +++ b/volk/apps/volk_profile.cc @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc_u, 1e-4, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32fc_deinterleave_32f_x2_a, 1e-4, 0, 204600, 1000, &results); VOLK_PROFILE(volk_32fc_deinterleave_64f_x2_a, 1e-4, 0, 204600, 1000, &results); + VOLK_PROFILE(volk_32fc_deinterleave_64f_x2_u, 1e-4, 0, 204600, 1000, &results); VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i_a, 0, 32768, 204600, 10000, &results); VOLK_PROFILE(volk_32fc_deinterleave_imag_32f_a, 1e-4, 0, 204600, 5000, &results); VOLK_PROFILE(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 204600, 5000, &results); diff --git a/volk/include/volk/volk_32fc_deinterleave_64f_x2_u.h b/volk/include/volk/volk_32fc_deinterleave_64f_x2_u.h new file mode 100644 index 0000000000..feed54be8c --- /dev/null +++ b/volk/include/volk/volk_32fc_deinterleave_64f_x2_u.h @@ -0,0 +1,78 @@ +#ifndef INCLUDED_volk_32fc_deinterleave_64f_x2_u_H +#define INCLUDED_volk_32fc_deinterleave_64f_x2_u_H + +#include <inttypes.h> +#include <stdio.h> + +#ifdef LV_HAVE_SSE2 +#include <emmintrin.h> +/*! + \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_64f_x2_u_sse2(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + + const float* complexVectorPtr = (float*)complexVector; + double* iBufferPtr = iBuffer; + double* qBufferPtr = qBuffer; + + const unsigned int halfPoints = num_points / 2; + __m128 cplxValue, fVal; + __m128d dVal; + + for(;number < halfPoints; number++){ + + cplxValue = _mm_loadu_ps(complexVectorPtr); + complexVectorPtr += 4; + + // Arrange in i1i2i1i2 format + fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(2,0,2,0)); + dVal = _mm_cvtps_pd(fVal); + _mm_storeu_pd(iBufferPtr, dVal); + + // Arrange in q1q2q1q2 format + fVal = _mm_shuffle_ps(cplxValue, cplxValue, _MM_SHUFFLE(3,1,3,1)); + dVal = _mm_cvtps_pd(fVal); + _mm_storeu_pd(qBufferPtr, dVal); + + iBufferPtr += 2; + qBufferPtr += 2; + } + + number = halfPoints * 2; + for(; number < num_points; number++){ + *iBufferPtr++ = *complexVectorPtr++; + *qBufferPtr++ = *complexVectorPtr++; + } +} +#endif /* LV_HAVE_SSE */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Deinterleaves the lv_32fc_t vector into double I & Q vector data + \param complexVector The complex input vector + \param iBuffer The I buffer output data + \param qBuffer The Q buffer output data + \param num_points The number of complex data values to be deinterleaved +*/ +static inline void volk_32fc_deinterleave_64f_x2_u_generic(double* iBuffer, double* qBuffer, const lv_32fc_t* complexVector, unsigned int num_points){ + unsigned int number = 0; + const float* complexVectorPtr = (float*)complexVector; + double* iBufferPtr = iBuffer; + double* qBufferPtr = qBuffer; + + for(number = 0; number < num_points; number++){ + *iBufferPtr++ = (double)*complexVectorPtr++; + *qBufferPtr++ = (double)*complexVectorPtr++; + } +} +#endif /* LV_HAVE_GENERIC */ + + + + +#endif /* INCLUDED_volk_32fc_deinterleave_64f_x2_u_H */ diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index 2e41c25daf..9b7d9da5e3 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -33,8 +33,10 @@ VOLK_RUN_TESTS(volk_32fc_s32f_atan2_32f_a, 1e-4, 10.0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_x2_conjugate_dot_prod_32fc_u, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_32f_x2_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_64f_x2_a, 1e-4, 0, 20460, 1); +VOLK_RUN_TESTS(volk_32fc_deinterleave_64f_x2_u, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_s32f_deinterleave_real_16i_a, 0, 32768, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 20460, 1); +VOLK_RUN_TESTS(volk_32fc_deinterleave_imag_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_real_64f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 2046000, 1); VOLK_RUN_TESTS(volk_32fc_32f_dot_prod_32fc_a, 1e-4, 0, 204600, 1); |